mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Implemented BaseDatabaseFeatures and changed all code to access it -- connection.features.foo instead of backend.foo
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5974 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -34,7 +34,7 @@ class Command(NoArgsCommand): | ||||
|         # Get a list of all existing database tables, | ||||
|         # so we know what needs to be added. | ||||
|         table_list = table_list() | ||||
|         if backend.uses_case_insensitive_names: | ||||
|         if connection.features.uses_case_insensitive_names: | ||||
|             table_name_converter = str.upper | ||||
|         else: | ||||
|             table_name_converter = lambda x: x | ||||
|   | ||||
| @@ -15,12 +15,12 @@ def table_list(): | ||||
|  | ||||
| def installed_models(table_list): | ||||
|     "Returns a set of all models that are installed, given a list of existing table names." | ||||
|     from django.db import backend, models | ||||
|     from django.db import connection, models | ||||
|     all_models = [] | ||||
|     for app in models.get_apps(): | ||||
|         for model in models.get_models(app): | ||||
|             all_models.append(model) | ||||
|     if backend.uses_case_insensitive_names: | ||||
|     if connection.features.uses_case_insensitive_names: | ||||
|         converter = lambda x: x.upper() | ||||
|     else: | ||||
|         converter = lambda x: x | ||||
| @@ -110,7 +110,7 @@ def sql_delete(app, style): | ||||
|         table_names = introspection.get_table_list(cursor) | ||||
|     else: | ||||
|         table_names = [] | ||||
|     if backend.uses_case_insensitive_names: | ||||
|     if connection.features.uses_case_insensitive_names: | ||||
|         table_name_converter = str.upper | ||||
|     else: | ||||
|         table_name_converter = lambda x: x | ||||
| @@ -138,7 +138,7 @@ def sql_delete(app, style): | ||||
|             # Drop the table now | ||||
|             output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), | ||||
|                 style.SQL_TABLE(qn(model._meta.db_table)))) | ||||
|             if backend.supports_constraints and model in references_to_delete: | ||||
|             if connection.features.supports_constraints and model in references_to_delete: | ||||
|                 for rel_class, f in references_to_delete[model]: | ||||
|                     table = rel_class._meta.db_table | ||||
|                     col = f.column | ||||
| @@ -232,11 +232,11 @@ def sql_model_create(model, style, known_models=set()): | ||||
|         field_output = [style.SQL_FIELD(qn(f.column)), | ||||
|             style.SQL_COLTYPE(col_type)] | ||||
|         field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or ''))) | ||||
|         if f.unique and (not f.primary_key or backend.allows_unique_and_pk): | ||||
|         if f.unique and (not f.primary_key or connection.features.allows_unique_and_pk): | ||||
|             field_output.append(style.SQL_KEYWORD('UNIQUE')) | ||||
|         if f.primary_key: | ||||
|             field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) | ||||
|         if tablespace and backend.supports_tablespaces and (f.unique or f.primary_key) and backend.autoindexes_primary_keys: | ||||
|         if tablespace and connection.features.supports_tablespaces and (f.unique or f.primary_key) and connection.features.autoindexes_primary_keys: | ||||
|             # We must specify the index tablespace inline, because we | ||||
|             # won't be generating a CREATE INDEX statement for this field. | ||||
|             field_output.append(connection.ops.tablespace_sql(tablespace, inline=True)) | ||||
| @@ -264,7 +264,7 @@ def sql_model_create(model, style, known_models=set()): | ||||
|     for i, line in enumerate(table_output): # Combine and add commas. | ||||
|         full_statement.append('    %s%s' % (line, i < len(table_output)-1 and ',' or '')) | ||||
|     full_statement.append(')') | ||||
|     if opts.db_tablespace and backend.supports_tablespaces: | ||||
|     if opts.db_tablespace and connection.features.supports_tablespaces: | ||||
|         full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace)) | ||||
|     full_statement.append(';') | ||||
|     final_output.append('\n'.join(full_statement)) | ||||
| @@ -287,7 +287,7 @@ def sql_for_pending_references(model, style, pending_references): | ||||
|  | ||||
|     qn = connection.ops.quote_name | ||||
|     final_output = [] | ||||
|     if backend.supports_constraints: | ||||
|     if connection.features.supports_constraints: | ||||
|         opts = model._meta | ||||
|         if model in pending_references: | ||||
|             for rel_class, f in pending_references[model]: | ||||
| @@ -316,7 +316,7 @@ def many_to_many_sql_for_model(model, style): | ||||
|     for f in opts.many_to_many: | ||||
|         if not isinstance(f.rel, generic.GenericRel): | ||||
|             tablespace = f.db_tablespace or opts.db_tablespace | ||||
|             if tablespace and backend.supports_tablespaces and backend.autoindexes_primary_keys: | ||||
|             if tablespace and connection.features.supports_tablespaces and connection.features.autoindexes_primary_keys: | ||||
|                 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace, inline=True) | ||||
|             else: | ||||
|                 tablespace_sql = '' | ||||
| @@ -347,7 +347,7 @@ def many_to_many_sql_for_model(model, style): | ||||
|                 style.SQL_FIELD(qn(f.m2m_reverse_name())), | ||||
|                 tablespace_sql)) | ||||
|             table_output.append(')') | ||||
|             if opts.db_tablespace and backend.supports_tablespaces: | ||||
|             if opts.db_tablespace and connection.features.supports_tablespaces: | ||||
|                 # f.db_tablespace is only for indices, so ignore its value here. | ||||
|                 table_output.append(connection.ops.tablespace_sql(opts.db_tablespace)) | ||||
|             table_output.append(';') | ||||
| @@ -395,10 +395,10 @@ def sql_indexes_for_model(model, style): | ||||
|  | ||||
|     qn = connection.ops.quote_name | ||||
|     for f in model._meta.fields: | ||||
|         if f.db_index and not ((f.primary_key or f.unique) and backend.autoindexes_primary_keys): | ||||
|         if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): | ||||
|             unique = f.unique and 'UNIQUE ' or '' | ||||
|             tablespace = f.db_tablespace or model._meta.db_tablespace | ||||
|             if tablespace and backend.supports_tablespaces: | ||||
|             if tablespace and connection.features.supports_tablespaces: | ||||
|                 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace) | ||||
|             else: | ||||
|                 tablespace_sql = '' | ||||
|   | ||||
| @@ -39,6 +39,16 @@ class BaseDatabaseWrapper(local): | ||||
|         from django.db.backends import util | ||||
|         return util.CursorDebugWrapper(cursor, self) | ||||
|  | ||||
| class BaseDatabaseFeatures(object): | ||||
|     allows_group_by_ordinal = True | ||||
|     allows_unique_and_pk = True | ||||
|     autoindexes_primary_keys = True | ||||
|     needs_datetime_string_cast = True | ||||
|     needs_upper_for_iops = False | ||||
|     supports_constraints = True | ||||
|     supports_tablespaces = False | ||||
|     uses_case_insensitive_names = False | ||||
|  | ||||
| class BaseDatabaseOperations(object): | ||||
|     """ | ||||
|     This class encapsulates all backend-specific differences, such as the way | ||||
|   | ||||
| @@ -4,7 +4,7 @@ ADO MSSQL database backend for Django. | ||||
| Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/ | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util | ||||
| try: | ||||
|     import adodbapi as Database | ||||
| except ImportError, e: | ||||
| @@ -48,6 +48,9 @@ def variantToPython(variant, adType): | ||||
|     return res | ||||
| Database.convertVariantToPython = variantToPython | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     supports_tablespaces = True | ||||
|  | ||||
| class DatabaseOperations(BaseDatabaseOperations): | ||||
|     def date_extract_sql(self, lookup_type, field_name): | ||||
|         return "DATEPART(%s, %s)" % (lookup_type, field_name) | ||||
| @@ -79,6 +82,7 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|         return "ON %s" % self.quote_name(tablespace) | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def _cursor(self, settings): | ||||
| @@ -93,15 +97,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|             self.connection = Database.connect(conn_string) | ||||
|         return self.connection.cursor() | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = True | ||||
| needs_datetime_string_cast = True | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = True | ||||
| supports_tablespaces = True | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| OPERATOR_MAPPING = { | ||||
|     'exact': '= %s', | ||||
|     'iexact': 'LIKE %s', | ||||
|   | ||||
| @@ -21,12 +21,13 @@ class DatabaseError(Exception): | ||||
| class IntegrityError(DatabaseError): | ||||
|     pass | ||||
|  | ||||
| class DatabaseOperations(object): | ||||
| class ComplainOnGetattr(object): | ||||
|     def __getattr__(self, *args, **kwargs): | ||||
|         complain() | ||||
|  | ||||
| class DatabaseWrapper(object): | ||||
|     ops = DatabaseOperations() | ||||
|     ops = ComplainOnGetattr() | ||||
|     features = ComplainOnGetattr() | ||||
|     cursor = complain | ||||
|     _commit = complain | ||||
|     _rollback = ignore | ||||
| @@ -37,7 +38,4 @@ class DatabaseWrapper(object): | ||||
|     def close(self): | ||||
|         pass # close() | ||||
|  | ||||
| supports_constraints = False | ||||
| supports_tablespaces = False | ||||
|  | ||||
| OPERATOR_MAPPING = {} | ||||
|   | ||||
| @@ -4,7 +4,7 @@ MySQL database backend for Django. | ||||
| Requires MySQLdb: http://sourceforge.net/projects/mysql-python | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util | ||||
| try: | ||||
|     import MySQLdb as Database | ||||
| except ImportError, e: | ||||
| @@ -53,6 +53,9 @@ server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})') | ||||
| # standard util.CursorDebugWrapper can be used. Also, using sql_mode | ||||
| # TRADITIONAL will automatically cause most warnings to be treated as errors. | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     autoindexes_primary_keys = False | ||||
|  | ||||
| class DatabaseOperations(BaseDatabaseOperations): | ||||
|     def date_extract_sql(self, lookup_type, field_name): | ||||
|         # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html | ||||
| @@ -116,6 +119,7 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|             return [] | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def __init__(self, **kwargs): | ||||
| @@ -175,15 +179,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|             self.server_version = tuple([int(x) for x in m.groups()]) | ||||
|         return self.server_version | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = False | ||||
| needs_datetime_string_cast = True     # MySQLdb requires a typecast for dates | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = True | ||||
| supports_tablespaces = False | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| OPERATOR_MAPPING = { | ||||
|     'exact': '= %s', | ||||
|     'iexact': 'LIKE %s', | ||||
|   | ||||
| @@ -4,7 +4,7 @@ MySQL database backend for Django. | ||||
| Requires MySQLdb: http://sourceforge.net/projects/mysql-python | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util | ||||
| from django.utils.encoding import force_unicode | ||||
| try: | ||||
|     import MySQLdb as Database | ||||
| @@ -63,6 +63,9 @@ class MysqlDebugWrapper: | ||||
|         else: | ||||
|             return getattr(self.cursor, attr) | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     autoindexes_primary_keys = False | ||||
|  | ||||
| class DatabaseOperations(BaseDatabaseOperations): | ||||
|     def date_extract_sql(self, lookup_type, field_name): | ||||
|         # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html | ||||
| @@ -126,6 +129,7 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|             return [] | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def __init__(self, **kwargs): | ||||
| @@ -194,15 +198,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|             self.server_version = tuple([int(x) for x in m.groups()]) | ||||
|         return self.server_version | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = False | ||||
| needs_datetime_string_cast = True     # MySQLdb requires a typecast for dates | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = True | ||||
| supports_tablespaces = False | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| OPERATOR_MAPPING = { | ||||
|     'exact': '= %s', | ||||
|     'iexact': 'LIKE %s', | ||||
|   | ||||
| @@ -4,7 +4,7 @@ Oracle database backend for Django. | ||||
| Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util | ||||
| from django.utils.datastructures import SortedDict | ||||
| from django.utils.encoding import smart_str, force_unicode | ||||
| import datetime | ||||
| @@ -21,6 +21,14 @@ except ImportError, e: | ||||
| DatabaseError = Database.Error | ||||
| IntegrityError = Database.IntegrityError | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     allows_group_by_ordinal = False | ||||
|     allows_unique_and_pk = False        # Suppress UNIQUE/PK for Oracle (ORA-02259) | ||||
|     needs_datetime_string_cast = False | ||||
|     needs_upper_for_iops = True | ||||
|     supports_tablespaces = True | ||||
|     uses_case_insensitive_names = True | ||||
|  | ||||
| class DatabaseOperations(BaseDatabaseOperations): | ||||
|     def autoinc_sql(self, table): | ||||
|         # To simulate auto-incrementing primary keys in Oracle, we have to | ||||
| @@ -128,6 +136,7 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|         return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace)) | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def _valid_connection(self): | ||||
| @@ -151,15 +160,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|         cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'") | ||||
|         return cursor | ||||
|  | ||||
| allows_group_by_ordinal = False | ||||
| allows_unique_and_pk = False        # Suppress UNIQUE/PK for Oracle (ORA-02259) | ||||
| autoindexes_primary_keys = True | ||||
| needs_datetime_string_cast = False | ||||
| needs_upper_for_iops = True | ||||
| supports_constraints = True | ||||
| supports_tablespaces = True | ||||
| uses_case_insensitive_names = True | ||||
|  | ||||
| class FormatStylePlaceholderCursor(Database.Cursor): | ||||
|     """ | ||||
|     Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" | ||||
|   | ||||
| @@ -5,7 +5,7 @@ Requires psycopg 1: http://initd.org/projects/psycopg1 | ||||
| """ | ||||
|  | ||||
| from django.utils.encoding import smart_str, smart_unicode | ||||
| from django.db.backends import BaseDatabaseWrapper, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, util | ||||
| from django.db.backends.postgresql.operations import DatabaseOperations | ||||
| try: | ||||
|     import psycopg as Database | ||||
| @@ -56,7 +56,11 @@ class UnicodeCursorWrapper(object): | ||||
|         else: | ||||
|             return getattr(self.cursor, attr) | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     pass # This backend uses all the defaults. | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def _cursor(self, settings): | ||||
| @@ -87,15 +91,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|             self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')] | ||||
|         return cursor | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = True | ||||
| needs_datetime_string_cast = True | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = True | ||||
| supports_tablespaces = False | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| def typecast_string(s): | ||||
|     """ | ||||
|     Cast all returned strings to unicode strings. | ||||
|   | ||||
| @@ -4,7 +4,7 @@ PostgreSQL database backend for Django. | ||||
| Requires psycopg 2: http://initd.org/projects/psycopg2 | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures | ||||
| from django.db.backends.postgresql.operations import DatabaseOperations | ||||
| try: | ||||
|     import psycopg2 as Database | ||||
| @@ -18,7 +18,11 @@ IntegrityError = Database.IntegrityError | ||||
|  | ||||
| psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     needs_datetime_string_cast = False | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def _cursor(self, settings): | ||||
| @@ -49,15 +53,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|             self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')] | ||||
|         return cursor | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = True | ||||
| needs_datetime_string_cast = False | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = True | ||||
| supports_tablespaces = False | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| OPERATOR_MAPPING = { | ||||
|     'exact': '= %s', | ||||
|     'iexact': 'ILIKE %s', | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| SQLite3 backend for django.  Requires pysqlite2 (http://pysqlite.org/). | ||||
| """ | ||||
|  | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||
| from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util | ||||
| try: | ||||
|     try: | ||||
|         from sqlite3 import dbapi2 as Database | ||||
| @@ -34,6 +34,9 @@ Database.register_converter("TIMESTAMP", util.typecast_timestamp) | ||||
| Database.register_converter("decimal", util.typecast_decimal) | ||||
| Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal) | ||||
|  | ||||
| class DatabaseFeatures(BaseDatabaseFeatures): | ||||
|     supports_constraints = False | ||||
|  | ||||
| class DatabaseOperations(BaseDatabaseOperations): | ||||
|     def date_extract_sql(self, lookup_type, field_name): | ||||
|         # sqlite doesn't support extract, so we fake it with the user-defined | ||||
| @@ -70,6 +73,7 @@ class DatabaseOperations(BaseDatabaseOperations): | ||||
|         return sql | ||||
|  | ||||
| class DatabaseWrapper(BaseDatabaseWrapper): | ||||
|     features = DatabaseFeatures() | ||||
|     ops = DatabaseOperations() | ||||
|  | ||||
|     def _cursor(self, settings): | ||||
| @@ -111,15 +115,6 @@ class SQLiteCursorWrapper(Database.Cursor): | ||||
|     def convert_query(self, query, num_params): | ||||
|         return query % tuple("?" * num_params) | ||||
|  | ||||
| allows_group_by_ordinal = True | ||||
| allows_unique_and_pk = True | ||||
| autoindexes_primary_keys = True | ||||
| needs_datetime_string_cast = True | ||||
| needs_upper_for_iops = False | ||||
| supports_constraints = False | ||||
| supports_tablespaces = False | ||||
| uses_case_insensitive_names = False | ||||
|  | ||||
| def _sqlite_extract(lookup_type, dt): | ||||
|     try: | ||||
|         dt = util.typecast_timestamp(dt) | ||||
|   | ||||
| @@ -651,7 +651,7 @@ class DateQuerySet(QuerySet): | ||||
|         table_name = qn(self.model._meta.db_table) | ||||
|         field_name = qn(self._field.column) | ||||
|  | ||||
|         if backend.allows_group_by_ordinal: | ||||
|         if connection.features.allows_group_by_ordinal: | ||||
|             group_by = '1' | ||||
|         else: | ||||
|             group_by = connection.ops.date_trunc_sql(self._kind, '%s.%s' % (table_name, field_name)) | ||||
| @@ -663,7 +663,7 @@ class DateQuerySet(QuerySet): | ||||
|         cursor.execute(sql, params) | ||||
|  | ||||
|         has_resolve_columns = hasattr(self, 'resolve_columns') | ||||
|         needs_datetime_string_cast = backend.needs_datetime_string_cast | ||||
|         needs_datetime_string_cast = connection.features.needs_datetime_string_cast | ||||
|         dates = [] | ||||
|         # It would be better to use self._field here instead of DateTimeField(), | ||||
|         # but in Oracle that will result in a list of datetime.date instead of | ||||
| @@ -796,7 +796,7 @@ def get_where_clause(lookup_type, table_prefix, field_name, value, db_type): | ||||
|     else: | ||||
|         field_cast_sql = '%s%s' | ||||
|     field_sql = field_cast_sql % (table_prefix, field_name) | ||||
|     if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops: | ||||
|     if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and connection.features.needs_upper_for_iops: | ||||
|         format = 'UPPER(%s) %s' | ||||
|     else: | ||||
|         format = '%s %s' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user