Ticket #1990: django_oracle_rev2977.patch
File django_oracle_rev2977.patch, 15.3 KB (added by , 18 years ago) |
---|
-
db/models/base.py
157 157 record_exists = True 158 158 if pk_set: 159 159 # Determine whether a record with the primary key already exists. 160 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \ 161 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 160 lim = settings.DATABASE_ENGINE != 'oracle' and ' LIMIT 1' or '' 161 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s %s" % \ 162 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column), lim), [pk_val]) 162 163 # If it does already exist, do an UPDATE. 163 164 if cursor.fetchone(): 164 165 db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks] -
db/models/fields/__init__.py
409 409 return datetime.date(*time.strptime(value, '%Y-%m-%d')[:3]) 410 410 411 411 def get_db_prep_lookup(self, lookup_type, value): 412 if lookup_type == 'range': 413 value = [str(v) for v in value] 414 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne'): 415 value = value.strftime('%Y-%m-%d') 412 # Oracle driver can deal with datetime.time objects natively 413 # and doesn't need to convert to string 414 if settings.DATABASE_ENGINE == 'oracle': 415 if lookup_type == 'range': 416 value = [str(v) for v in value] 417 #elif lookup_type == 'day': 418 # value = int(value) 419 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne'): 420 if type(value) == str: 421 pattern = r'^\d\d\d\d-\d\d-\d\d$' # "YYYY-MM-DD" 422 from re import search 423 if search(pattern, value) != None: 424 year, month, day = map(int, value.split('-')) 425 value = datetime.date(year, month, day) 426 else: 427 value = value 416 428 else: 417 value = str(value) 429 if lookup_type == 'range': 430 value = [str(v) for v in value] 431 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne'): 432 value = value.strftime('%Y-%m-%d') 433 else: 434 value = str(value) 418 435 return Field.get_db_prep_lookup(self, lookup_type, value) 419 436 420 437 def pre_save(self, value, add): … … 440 457 def get_db_prep_save(self, value): 441 458 # Casts dates into string format for entry into database. 442 459 if value is not None: 443 value = value.strftime('%Y-%m-%d') 460 if settings.DATABASE_ENGINE != 'oracle': 461 #Oracle does not need a string conversion 462 value = value.strftime('%Y-%m-%d') 444 463 return Field.get_db_prep_save(self, value) 445 464 446 465 def get_manipulator_field_objs(self): … … 473 492 # MySQL will throw a warning if microseconds are given, because it 474 493 # doesn't support microseconds. 475 494 if settings.DATABASE_ENGINE == 'mysql': 495 value = str(value.replace(microsecond=0)) 496 # Oracle will choke if microseconds are given... 497 elif settings.DATABASE_ENGINE == 'oracle': 476 498 value = value.replace(microsecond=0) 477 value = str(value)478 499 return Field.get_db_prep_save(self, value) 479 500 480 501 def get_db_prep_lookup(self, lookup_type, value): 481 if lookup_type == 'range': 482 value = [str(v) for v in value] 502 # Oracle driver can deal with datetime.time objects natively 503 # and doesn't need to convert to string 504 if settings.DATABASE_ENGINE == 'oracle': 505 if lookup_type == 'range': 506 value = [v for v in value] 507 else: 508 value = value 483 509 else: 484 value = str(value) 510 if lookup_type == 'range': 511 value = [str(v) for v in value] 512 else: 513 value = str(value) 485 514 return Field.get_db_prep_lookup(self, lookup_type, value) 486 515 487 516 def get_manipulator_field_objs(self): … … 735 764 # doesn't support microseconds. 736 765 if settings.DATABASE_ENGINE == 'mysql': 737 766 value = value.replace(microsecond=0) 738 value = str(value) 767 value = str(value) 768 elif settings.DATABASE_ENGINE == 'oracle': 769 value = value.replace(microsecond=0) 770 else: 771 value = str(value) 739 772 return Field.get_db_prep_save(self, value) 740 773 741 774 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 7 8 import operator 8 9 … … 156 157 extra_select = self._select.items() 157 158 158 159 cursor = connection.cursor() 159 select, sql, params = self._get_sql_clause() 160 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 160 select, sql, params, full_query = self._get_sql_clause() 161 if not full_query: 162 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 163 else: 164 cursor.execute(full_query, params) 161 165 fill_cache = self._select_related 162 166 index_end = len(self.model._meta.fields) 163 167 while 1: … … 180 184 counter._offset = None 181 185 counter._limit = None 182 186 counter._select_related = False 183 select, sql, params = counter._get_sql_clause()187 select, sql, params, full_query = counter._get_sql_clause() 184 188 cursor = connection.cursor() 185 189 if self._distinct: 186 190 id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table), … … 455 459 if order_by: 456 460 sql.append("ORDER BY " + ", ".join(order_by)) 457 461 458 # LIMIT and OFFSET clauses 459 if self._limit is not None: 460 sql.append("%s " % backend.get_limit_offset_sql(self._limit, self._offset)) 462 463 464 if (settings.DATABASE_ENGINE != 'oracle'): 465 # LIMIT and OFFSET clauses 466 if self._limit is not None: 467 sql.append("%s " % backend.get_limit_offset_sql(self._limit, self._offset)) 468 else: 469 assert self._offset is None, "'offset' is not allowed without 'limit'" 470 471 return select, " ".join(sql), params, None 472 461 473 else: 462 assert self._offset is None, "'offset' is not allowed without 'limit'" 474 # To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query. 475 select_clause = ",".join(select) 476 distinct = (self._distinct and "DISTINCT " or "") 477 478 if order_by: 479 order_by_clause = " OVER (ORDER BY %s )" % (", ".join(order_by)) 480 else: 481 #Oracle's row_number() function always requires an order-by clause. 482 #So we need to define a default order-by, since none was provided. 483 order_by_clause = " OVER (ORDER BY %s.%s)" % \ 484 (backend.quote_name(opts.db_table), 485 backend.quote_name(opts.fields[0].db_column or opts.fields[0].column)) 486 487 # limit_and_offset_clause 488 offset = self._offset and int(self._offset) or 0 489 limit = self._limit and int(self._limit) or None 490 limit_and_offset_clause = '' 491 if limit: 492 limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % (offset, limit+offset) 493 elif offset: 494 limit_and_offset_clause = "WHERE rn > %s" % (offset) 495 496 if len(limit_and_offset_clause) > 0: 497 full_query = """SELECT * FROM 498 (SELECT %s 499 %s, 500 ROW_NUMBER() %s AS rn 501 %s 502 ) 503 %s 504 """ % (distinct, select_clause, order_by_clause, " ".join(sql), limit_and_offset_clause) 505 else: 506 full_query = None 507 508 return select, " ".join(sql), params, full_query 463 509 464 return select, " ".join(sql), params 465 510 466 511 class ValuesQuerySet(QuerySet): 467 512 def iterator(self): 468 513 # select_related and select aren't supported in values(). … … 478 523 field_names = [f.attname for f in self.model._meta.fields] 479 524 480 525 cursor = connection.cursor() 481 select, sql, params = self._get_sql_clause()526 select, sql, params, full_query = self._get_sql_clause() 482 527 select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 483 528 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 484 529 while 1: … … 500 545 if self._field.null: 501 546 self._where.append('%s.%s IS NOT NULL' % \ 502 547 (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 503 select, sql, params = self._get_sql_clause()548 select, sql, params, full_query = self._get_sql_clause() 504 549 sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ 505 550 (backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table), 506 551 backend.quote_name(self._field.column))), sql, self._order) … … 589 634 if table_prefix.endswith('.'): 590 635 table_prefix = backend.quote_name(table_prefix[:-1])+'.' 591 636 field_name = backend.quote_name(field_name) 637 638 #put some oracle exceptions here 639 if lookup_type == "icontains" and settings.DATABASE_ENGINE == 'oracle': 640 return 'lower(%s%s) %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 641 592 642 try: 593 643 return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 594 644 except KeyError: … … 618 668 Helper function that recursively populates the select, tables and where (in 619 669 place) for fill-cache queries. 620 670 """ 671 from django.db.models.fields import AutoField 621 672 for f in opts.fields: 622 673 if f.rel and not f.null: 623 674 db_table = f.rel.to._meta.db_table … … 631 682 where.append('%s.%s = %s.%s' % \ 632 683 (backend.quote_name(old_prefix), backend.quote_name(f.column), 633 684 backend.quote_name(db_table), backend.quote_name(f.rel.get_related_field().column))) 634 select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields]) 685 if settings.DATABASE_ENGINE == 'oracle': 686 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)]) 687 else: 688 select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields]) 635 689 fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) 636 690 637 691 def parse_lookup(kwarg_items, opts): -
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, models 87 from django.db import get_creation_module, models, backend 87 88 data_types = get_creation_module().DATA_TYPES 88 89 89 90 if not data_types: … … 110 111 final_output.extend(_get_sql_for_pending_references(klass, pending_references)) 111 112 # Keep track of the fact that we've created the table for this model. 112 113 models_output.add(klass) 113 114 115 opts = klass._meta 116 if (settings.DATABASE_ENGINE == 'oracle') & (opts.has_auto_field): 117 # To simulate auto-incrementing primary keys in Oracle 118 sequence_statement = 'CREATE SEQUENCE %s_sq;' % opts.db_table 119 final_output.append(sequence_statement) 120 trigger_statement = '' + \ 121 'CREATE OR REPLACE trigger %s_tr\n' % opts.db_table + \ 122 ' before insert on %s\n' % backend.quote_name(opts.db_table) + \ 123 ' for each row\n' + \ 124 ' when (new.id is NULL)\n' + \ 125 ' begin\n' + \ 126 ' select %s_sq.NEXTVAL into :new.id from DUAL;\n' % opts.db_table + \ 127 ' end;\n' + \ 128 ' /' 129 final_output.append(trigger_statement) 130 114 131 # Create the many-to-many join tables. 115 132 for klass in app_models: 116 133 final_output.extend(_get_many_to_many_sql_for_model(klass)) … … 1202 1219 if not mod_list: 1203 1220 parser.print_usage_and_exit() 1204 1221 if action not in NO_SQL_TRANSACTION: 1205 print style.SQL_KEYWORD("BEGIN;") 1222 if settings.DATABASE_ENGINE != 'oracle': 1223 print style.SQL_KEYWORD("BEGIN;") 1206 1224 for mod in mod_list: 1207 1225 output = action_mapping[action](mod) 1208 1226 if output: 1209 1227 print '\n'.join(output) 1210 1228 if action not in NO_SQL_TRANSACTION: 1211 print style.SQL_KEYWORD("COMMIT;") 1229 if settings.DATABASE_ENGINE != 'oracle': 1230 print style.SQL_KEYWORD("COMMIT;") 1212 1231 1213 1232 def execute_manager(settings_mod): 1214 1233 # Add this project to sys.path so that it's importable in the conventional -
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) 21 # object_id = models.TextField(_('object id'), blank=True, null=True) 20 22 object_repr = models.CharField(_('object repr'), maxlength=200) 21 23 action_flag = models.PositiveSmallIntegerField(_('action flag')) 22 24 change_message = models.TextField(_('change message'), blank=True)