Ticket #1990: django_oracle_release-0.95-v2.patch
File django_oracle_release-0.95-v2.patch, 20.3 KB (added by , 18 years ago) |
---|
-
db/models/base.py
171 171 record_exists = True 172 172 if pk_set: 173 173 # Determine whether a record with the primary key already exists. 174 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \ 175 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 174 lim = settings.DATABASE_ENGINE != 'oracle' and ' LIMIT 1' or '' 175 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s %s" % \ 176 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column), lim), [pk_val]) 176 177 # If it does already exist, do an UPDATE. 177 178 if cursor.fetchone(): 178 179 db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] -
db/models/fields/__init__.py
158 158 159 159 def get_db_prep_save(self, value): 160 160 "Returns field's value prepared for saving into a database." 161 # Oracle treats empty strings ('') the same as NULLs. 162 # To get around this wart, we need to change it to something else... 163 if settings.DATABASE_ENGINE == 'oracle' and value == '': 164 value = ' ' 161 165 return value 162 166 163 167 def get_db_prep_lookup(self, lookup_type, value): … … 446 450 def get_db_prep_save(self, value): 447 451 # Casts dates into string format for entry into database. 448 452 if value is not None: 449 value = value.strftime('%Y-%m-%d') 453 if settings.DATABASE_ENGINE != 'oracle': 454 #Oracle does not need a string conversion 455 value = value.strftime('%Y-%m-%d') 450 456 return Field.get_db_prep_save(self, value) 451 457 452 458 def get_manipulator_field_objs(self): … … 476 482 def get_db_prep_save(self, value): 477 483 # Casts dates into string format for entry into database. 478 484 if value is not None: 479 # MySQL will throw a warning if microseconds are given, because it485 # MySQL/Oracle will throw a warning if microseconds are given, because it 480 486 # doesn't support microseconds. 481 if settings.DATABASE_ENGINE == 'mysql'and hasattr(value, 'microsecond'):487 if (settings.DATABASE_ENGINE == 'mysql' or settings.DATABASE_ENGINE=='oracle') and hasattr(value, 'microsecond'): 482 488 value = value.replace(microsecond=0) 483 489 value = str(value) 484 490 return Field.get_db_prep_save(self, value) 485 491 486 492 def get_db_prep_lookup(self, lookup_type, value): 493 # Oracle will throw an error if microseconds are given, because it 494 # doesn't support microseconds. 495 if (settings.DATABASE_ENGINE=='oracle') and hasattr(value, 'microsecond'): 496 value = value.replace(microsecond=0) 487 497 if lookup_type == 'range': 488 498 value = [str(v) for v in value] 489 499 else: … … 511 521 def flatten_data(self,follow, obj = None): 512 522 val = self._get_val_from_obj(obj) 513 523 date_field, time_field = self.get_manipulator_field_names('') 514 return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''), 515 time_field: (val is not None and val.strftime("%H:%M:%S") or '')} 524 #cx_Oracle does not support strftime 525 if (settings.DATABASE_ENGINE=='oracle'): 526 return {date_field: (val is not None or ''), 527 time_field: (val is not None or '')} 528 else: 529 return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''), 530 time_field: (val is not None and val.strftime("%H:%M:%S") or '')} 516 531 517 532 class EmailField(CharField): 518 533 def __init__(self, *args, **kwargs): … … 744 759 # doesn't support microseconds. 745 760 if settings.DATABASE_ENGINE == 'mysql': 746 761 value = value.replace(microsecond=0) 747 value = str(value) 762 value = str(value) 763 elif settings.DATABASE_ENGINE == 'oracle': 764 value = value.replace(microsecond=0) 765 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. 766 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, value.second) 767 else: 768 value = str(value) 748 769 return Field.get_db_prep_save(self, value) 749 770 750 771 def get_manipulator_field_objs(self): -
db/models/query.py
3 3 from django.db.models import signals 4 4 from django.dispatch import dispatcher 5 5 from django.utils.datastructures import SortedDict 6 from django.conf import settings 6 7 import operator 7 8 import re 8 9 … … 168 169 extra_select = self._select.items() 169 170 170 171 cursor = connection.cursor() 171 select, sql, params = self._get_sql_clause() 172 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 172 173 full_query = None 174 if (settings.DATABASE_ENGINE == 'oracle'): 175 select, sql, params, full_query = self._get_sql_clause() 176 else: 177 select, sql, params = self._get_sql_clause() 178 179 if not full_query: 180 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 181 else: 182 cursor.execute(full_query, params) 173 183 fill_cache = self._select_related 174 184 index_end = len(self.model._meta.fields) 175 185 while 1: … … 192 202 counter._offset = None 193 203 counter._limit = None 194 204 counter._select_related = False 195 select, sql, params = counter._get_sql_clause() 205 if (settings.DATABASE_ENGINE == 'oracle'): 206 select, sql, params, full_query = counter._get_sql_clause() 207 else: 208 select, sql, params = counter._get_sql_clause() 196 209 cursor = connection.cursor() 197 210 if self._distinct: 198 211 id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table), … … 501 514 sql.append("ORDER BY " + ", ".join(order_by)) 502 515 503 516 # LIMIT and OFFSET clauses 504 if self._limit is not None: 505 sql.append("%s " % backend.get_limit_offset_sql(self._limit, self._offset)) 517 if (settings.DATABASE_ENGINE != 'oracle'): 518 if self._limit is not None: 519 sql.append("%s " % backend.get_limit_offset_sql(self._limit, self._offset)) 520 else: 521 assert self._offset is None, "'offset' is not allowed without 'limit'" 522 523 return select, " ".join(sql), params 506 524 else: 507 assert self._offset is None, "'offset' is not allowed without 'limit'" 525 # To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query. 526 select_clause = ",".join(select) 527 distinct = (self._distinct and "DISTINCT " or "") 508 528 509 return select, " ".join(sql), params 529 if order_by: 530 order_by_clause = " OVER (ORDER BY %s )" % (", ".join(order_by)) 531 else: 532 #Oracle's row_number() function always requires an order-by clause. 533 #So we need to define a default order-by, since none was provided. 534 order_by_clause = " OVER (ORDER BY %s.%s)" % \ 535 (backend.quote_name(opts.db_table), 536 backend.quote_name(opts.fields[0].db_column or opts.fields[0].column)) 537 # limit_and_offset_clause 538 offset = self._offset and int(self._offset) or 0 539 limit = self._limit and int(self._limit) or None 540 limit_and_offset_clause = '' 541 if limit: 542 limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % (offset, limit+offset) 543 elif offset: 544 limit_and_offset_clause = "WHERE rn > %s" % (offset) 510 545 546 if len(limit_and_offset_clause) > 0: 547 full_query = """SELECT * FROM 548 (SELECT %s 549 %s, 550 ROW_NUMBER() %s AS rn 551 %s 552 ) 553 %s 554 """ % (distinct, select_clause, order_by_clause, " ".join(sql), limit_and_offset_clause) 555 else: 556 full_query = None 557 558 return select, " ".join(sql), params, full_query 511 559 class ValuesQuerySet(QuerySet): 512 560 def iterator(self): 513 561 # select_related and select aren't supported in values(). … … 523 571 field_names = [f.attname for f in self.model._meta.fields] 524 572 525 573 cursor = connection.cursor() 526 select, sql, params = self._get_sql_clause()574 select, sql, params, full_query = self._get_sql_clause() 527 575 select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 528 576 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 529 577 while 1: … … 636 684 if table_prefix.endswith('.'): 637 685 table_prefix = backend.quote_name(table_prefix[:-1])+'.' 638 686 field_name = backend.quote_name(field_name) 687 #put some oracle exceptions here 688 if lookup_type == "icontains" and settings.DATABASE_ENGINE == 'oracle': 689 return 'lower(%s%s) %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 639 690 try: 640 691 return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 641 692 except KeyError: … … 667 718 Helper function that recursively populates the select, tables and where (in 668 719 place) for select_related queries. 669 720 """ 721 from django.db.models.fields import AutoField 670 722 qn = backend.quote_name 671 723 for f in opts.fields: 672 724 if f.rel and not f.null: … … 680 732 cache_tables_seen.append(db_table) 681 733 where.append('%s.%s = %s.%s' % \ 682 734 (qn(old_prefix), qn(f.column), qn(db_table), qn(f.rel.get_related_field().column))) 683 select.extend(['%s.%s' % (qn(db_table), qn(f2.column)) for f2 in f.rel.to._meta.fields]) 735 if settings.DATABASE_ENGINE == 'oracle': 736 select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields if not isinstance(f2, AutoField)]) 737 else: 738 select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields]) 684 739 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) 685 740 686 741 def parse_lookup(kwarg_items, opts): -
db/backends/oracle/base.py
39 39 else: 40 40 conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) 41 41 self.connection = Database.connect(conn_string) 42 # set oracle date to ansi date format 43 cursor = self.connection.cursor() 44 cursor.execute("alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'") 45 cursor.close() 42 46 return FormatStylePlaceholderCursor(self.connection) 43 47 44 48 def _commit(self): … … 67 71 def execute(self, query, params=None): 68 72 if params is None: params = [] 69 73 query = self.convert_arguments(query, len(params)) 70 return Database.Cursor.execute(self, query, params) 74 # cx can not execute the query with the closing ';' 75 if query.endswith(';') : 76 query = query[0:len(query)-1] 77 print query 78 print params 79 return Database.Cursor.execute(self, query, params) 71 80 72 81 def executemany(self, query, params=None): 73 82 if params is None: params = [] 74 83 query = self.convert_arguments(query, len(params[0])) 84 # cx can not execute the query with the closing ';' 85 if query.endswith(';') : 86 query = query[0:len(query)-1] 75 87 return Database.Cursor.executemany(self, query, params) 76 88 77 89 def convert_arguments(self, query, num_params): -
core/management.py
6 6 import os, re, shutil, sys, textwrap 7 7 from optparse import OptionParser 8 8 from django.utils import termcolors 9 from django.conf import settings 9 10 10 11 # For Python 2.3 11 12 if not hasattr(__builtins__, 'set'): … … 83 84 84 85 def get_sql_create(app): 85 86 "Returns a list of the CREATE TABLE SQL statements for the given app." 86 from django.db import get_creation_module, models87 from django.db import models,get_creation_module, backend 87 88 data_types = get_creation_module().DATA_TYPES 88 89 89 90 if not data_types: … … 157 158 field_output.append(style.SQL_KEYWORD('UNIQUE')) 158 159 if f.primary_key: 159 160 field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) 161 if (settings.DATABASE_ENGINE == 'oracle') and f.unique and f.primary_key: 162 # Suppress UNIQUE/PRIMARY KEY for Oracle (ORA-02259) 163 field_output.remove(style.SQL_KEYWORD('UNIQUE')) 160 164 if f.rel: 161 165 if f.rel.to in known_models: 162 166 field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \ … … 181 185 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 182 186 full_statement.append(');') 183 187 final_output.append('\n'.join(full_statement)) 188 189 # To simulate auto-incrementing primary keys in Oracle -- creating primary tables 190 if (settings.DATABASE_ENGINE == 'oracle') & (opts.has_auto_field): 191 sequence_statement = 'CREATE SEQUENCE %s_sq;' % opts.db_table 192 final_output.append(sequence_statement) 193 trigger_statement = '' + \ 194 'CREATE OR REPLACE trigger %s_tr\n' % opts.db_table + \ 195 ' before insert on %s\n' % backend.quote_name(opts.db_table) + \ 196 ' for each row\n' + \ 197 ' when (new.id is NULL)\n' + \ 198 ' begin\n' + \ 199 ' select %s_sq.NEXTVAL into :new.id from DUAL;\n' % opts.db_table + \ 200 ' end;\n' 201 final_output.append(trigger_statement) 184 202 203 185 204 return final_output, pending_references 186 205 187 206 def _get_sql_for_pending_references(model, pending_references): … … 208 227 r_name += '_%s' % reference_names[r_name] 209 228 else: 210 229 reference_names[r_name] = 0 211 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \ 212 (backend.quote_name(r_table), r_name, 213 backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col))) 230 # if constraint name size is over 29 char and db is oracle, chop it 231 if settings.DATABASE_ENGINE == 'oracle' and len(r_name) > 29: 232 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \ 233 (backend.quote_name(r_table), r_name[0:29], 234 backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col))) 235 else: 236 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \ 237 (backend.quote_name(r_table), r_name, 238 backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col))) 214 239 del pending_references[model] 215 240 return final_output 216 241 … … 248 273 style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())))) 249 274 table_output.append(');') 250 275 final_output.append('\n'.join(table_output)) 276 # To simulate auto-incrementing primary keys in Oracle -- creating m2m tables 277 if (settings.DATABASE_ENGINE == 'oracle'): 278 m_table = f.m2m_db_table() 279 sequence_statement = 'CREATE SEQUENCE %s_sq;' % m_table 280 final_output.append(sequence_statement) 281 trigger_statement = '' + \ 282 'CREATE OR REPLACE trigger %s_tr\n' % m_table + \ 283 ' before insert on %s\n' % backend.quote_name(m_table) + \ 284 ' for each row\n' + \ 285 ' when (new.id is NULL)\n' + \ 286 ' begin\n' + \ 287 ' select %s_sq.NEXTVAL into :new.id from DUAL;\n' % m_table + \ 288 ' end;\n' 289 final_output.append(trigger_statement) 251 290 return final_output 252 291 253 292 def get_sql_delete(app): … … 471 510 sql.extend(_get_sql_for_pending_references(model, pending_references)) 472 511 print "Creating table %s" % model._meta.db_table 473 512 for statement in sql: 474 cursor.execute(statement) 513 # go on if one table could not be created 514 try: 515 cursor.execute(statement) 516 except Exception, e: 517 print statement 518 print e 475 519 table_list.append(model._meta.db_table) 476 520 477 521 for model in model_list: … … 480 524 if sql: 481 525 print "Creating many-to-many tables for %s model" % model.__name__ 482 526 for statement in sql: 483 cursor.execute(statement) 527 try: 528 cursor.execute(statement) 529 except Exception, e: 530 print statement 531 print e 484 532 485 533 transaction.commit_unless_managed() 486 534 … … 1281 1329 if not mod_list: 1282 1330 parser.print_usage_and_exit() 1283 1331 if action not in NO_SQL_TRANSACTION: 1284 print style.SQL_KEYWORD("BEGIN;") 1332 if settings.DATABASE_ENGINE != 'oracle': 1333 print style.SQL_KEYWORD("BEGIN;") 1285 1334 for mod in mod_list: 1286 1335 output = action_mapping[action](mod) 1287 1336 if output: 1288 1337 print '\n'.join(output) 1289 1338 if action not in NO_SQL_TRANSACTION: 1290 print style.SQL_KEYWORD("COMMIT;") 1339 if settings.DATABASE_ENGINE != 'oracle': 1340 print style.SQL_KEYWORD("COMMIT;") 1291 1341 1292 1342 def execute_manager(settings_mod, argv=None): 1293 1343 # Add this project to sys.path so that it's importable in the conventional -
contrib/sessions/models.py
51 51 session_key = models.CharField(_('session key'), maxlength=40, primary_key=True) 52 52 session_data = models.TextField(_('session data')) 53 53 expire_date = models.DateTimeField(_('expire date')) 54 54 55 objects = SessionManager() 55 56 class Meta: 56 57 db_table = 'django_session' -
contrib/admin/models.py
16 16 action_time = models.DateTimeField(_('action time'), auto_now=True) 17 17 user = models.ForeignKey(User) 18 18 content_type = models.ForeignKey(ContentType, blank=True, null=True) 19 object_id = models.TextField(_('object id'), blank=True, null=True) 19 #changed for Oracle support 20 object_id = models.CharField(_('object id'), maxlength=200, blank=True, null=True) 20 21 object_repr = models.CharField(_('object repr'), maxlength=200) 21 22 action_flag = models.PositiveSmallIntegerField(_('action flag')) 22 23 change_message = models.TextField(_('change message'), blank=True)