mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refactored get_query_set_class() to DatabaseOperations.query_set_class(). Also added BaseDatabaseFeatures.uses_custom_queryset. Refs #5106
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5976 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -48,6 +48,7 @@ class BaseDatabaseFeatures(object): | |||||||
|     supports_constraints = True |     supports_constraints = True | ||||||
|     supports_tablespaces = False |     supports_tablespaces = False | ||||||
|     uses_case_insensitive_names = False |     uses_case_insensitive_names = False | ||||||
|  |     uses_custom_queryset = False | ||||||
|  |  | ||||||
| class BaseDatabaseOperations(object): | class BaseDatabaseOperations(object): | ||||||
|     """ |     """ | ||||||
| @@ -144,6 +145,15 @@ class BaseDatabaseOperations(object): | |||||||
|         """ |         """ | ||||||
|         return 'DEFAULT' |         return 'DEFAULT' | ||||||
|  |  | ||||||
|  |     def query_set_class(self, DefaultQuerySet): | ||||||
|  |         """ | ||||||
|  |         Given the default QuerySet class, returns a custom QuerySet class | ||||||
|  |         to use for this backend. Returns None if a custom QuerySet isn't used. | ||||||
|  |         See also BaseDatabaseFeatures.uses_custom_queryset, which regulates | ||||||
|  |         whether this method is called at all. | ||||||
|  |         """ | ||||||
|  |         return None | ||||||
|  |  | ||||||
|     def quote_name(self, name): |     def quote_name(self, name): | ||||||
|         """ |         """ | ||||||
|         Returns a quoted version of the given table, index or column name. Does |         Returns a quoted version of the given table, index or column name. Does | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): | |||||||
|     needs_upper_for_iops = True |     needs_upper_for_iops = True | ||||||
|     supports_tablespaces = True |     supports_tablespaces = True | ||||||
|     uses_case_insensitive_names = True |     uses_case_insensitive_names = True | ||||||
|  |     uses_custom_queryset = True | ||||||
|  |  | ||||||
| class DatabaseOperations(BaseDatabaseOperations): | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|     def autoinc_sql(self, table): |     def autoinc_sql(self, table): | ||||||
| @@ -78,192 +79,7 @@ class DatabaseOperations(BaseDatabaseOperations): | |||||||
|     def max_name_length(self): |     def max_name_length(self): | ||||||
|         return 30 |         return 30 | ||||||
|  |  | ||||||
|     def quote_name(self, name): |     def query_set_class(self, DefaultQuerySet): | ||||||
|         # SQL92 requires delimited (quoted) names to be case-sensitive.  When |  | ||||||
|         # not quoted, Oracle has case-insensitive behavior for identifiers, but |  | ||||||
|         # always defaults to uppercase. |  | ||||||
|         # We simplify things by making Oracle identifiers always uppercase. |  | ||||||
|         if not name.startswith('"') and not name.endswith('"'): |  | ||||||
|             name = '"%s"' % util.truncate_name(name.upper(), DatabaseOperations().max_name_length()) |  | ||||||
|         return name.upper() |  | ||||||
|  |  | ||||||
|     def random_function_sql(self): |  | ||||||
|         return "DBMS_RANDOM.RANDOM" |  | ||||||
|  |  | ||||||
|     def sql_flush(self, style, tables, sequences): |  | ||||||
|         # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', |  | ||||||
|         # 'TRUNCATE z;'... style SQL statements |  | ||||||
|         if tables: |  | ||||||
|             # Oracle does support TRUNCATE, but it seems to get us into |  | ||||||
|             # FK referential trouble, whereas DELETE FROM table works. |  | ||||||
|             sql = ['%s %s %s;' % \ |  | ||||||
|                     (style.SQL_KEYWORD('DELETE'), |  | ||||||
|                      style.SQL_KEYWORD('FROM'), |  | ||||||
|                      style.SQL_FIELD(self.quote_name(table)) |  | ||||||
|                      ) for table in tables] |  | ||||||
|             # Since we've just deleted all the rows, running our sequence |  | ||||||
|             # ALTER code will reset the sequence to 0. |  | ||||||
|             for sequence_info in sequences: |  | ||||||
|                 table_name = sequence_info['table'] |  | ||||||
|                 seq_name = get_sequence_name(table_name) |  | ||||||
|                 query = _get_sequence_reset_sql() % {'sequence': seq_name, 'table': self.quote_name(table_name)} |  | ||||||
|                 sql.append(query) |  | ||||||
|             return sql |  | ||||||
|         else: |  | ||||||
|             return [] |  | ||||||
|  |  | ||||||
|     def sequence_reset_sql(self, style, model_list): |  | ||||||
|         from django.db import models |  | ||||||
|         output = [] |  | ||||||
|         query = _get_sequence_reset_sql() |  | ||||||
|         for model in model_list: |  | ||||||
|             for f in model._meta.fields: |  | ||||||
|                 if isinstance(f, models.AutoField): |  | ||||||
|                     sequence_name = get_sequence_name(model._meta.db_table) |  | ||||||
|                     output.append(query % {'sequence':sequence_name, |  | ||||||
|                                            'table':model._meta.db_table}) |  | ||||||
|                     break # Only one AutoField is allowed per model, so don't bother continuing. |  | ||||||
|             for f in model._meta.many_to_many: |  | ||||||
|                 sequence_name = get_sequence_name(f.m2m_db_table()) |  | ||||||
|                 output.append(query % {'sequence':sequence_name, |  | ||||||
|                                        'table':f.m2m_db_table()}) |  | ||||||
|         return output |  | ||||||
|  |  | ||||||
|     def start_transaction_sql(self): |  | ||||||
|         return '' |  | ||||||
|  |  | ||||||
|     def tablespace_sql(self, tablespace, inline=False): |  | ||||||
|         return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace)) |  | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): |  | ||||||
|     features = DatabaseFeatures() |  | ||||||
|     ops = DatabaseOperations() |  | ||||||
|  |  | ||||||
|     def _valid_connection(self): |  | ||||||
|         return self.connection is not None |  | ||||||
|  |  | ||||||
|     def _cursor(self, settings): |  | ||||||
|         if not self._valid_connection(): |  | ||||||
|             if len(settings.DATABASE_HOST.strip()) == 0: |  | ||||||
|                 settings.DATABASE_HOST = 'localhost' |  | ||||||
|             if len(settings.DATABASE_PORT.strip()) != 0: |  | ||||||
|                 dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME) |  | ||||||
|                 self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn, **self.options) |  | ||||||
|             else: |  | ||||||
|                 conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) |  | ||||||
|                 self.connection = Database.connect(conn_string, **self.options) |  | ||||||
|         cursor = FormatStylePlaceholderCursor(self.connection) |  | ||||||
|         # Default arraysize of 1 is highly sub-optimal. |  | ||||||
|         cursor.arraysize = 100 |  | ||||||
|         # Set oracle date to ansi date format. |  | ||||||
|         cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'") |  | ||||||
|         cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'") |  | ||||||
|         return cursor |  | ||||||
|  |  | ||||||
| class FormatStylePlaceholderCursor(Database.Cursor): |  | ||||||
|     """ |  | ||||||
|     Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" |  | ||||||
|     style. This fixes it -- but note that if you want to use a literal "%s" in |  | ||||||
|     a query, you'll need to use "%%s". |  | ||||||
|  |  | ||||||
|     We also do automatic conversion between Unicode on the Python side and |  | ||||||
|     UTF-8 -- for talking to Oracle -- in here. |  | ||||||
|     """ |  | ||||||
|     charset = 'utf-8' |  | ||||||
|  |  | ||||||
|     def _rewrite_args(self, query, params=None): |  | ||||||
|         if params is None: |  | ||||||
|             params = [] |  | ||||||
|         else: |  | ||||||
|             params = self._format_params(params) |  | ||||||
|         args = [(':arg%d' % i) for i in range(len(params))] |  | ||||||
|         query = smart_str(query, self.charset) % tuple(args) |  | ||||||
|         # cx_Oracle wants no trailing ';' for SQL statements.  For PL/SQL, it |  | ||||||
|         # it does want a trailing ';' but not a trailing '/'.  However, these |  | ||||||
|         # characters must be included in the original query in case the query |  | ||||||
|         # is being passed to SQL*Plus. |  | ||||||
|         if query.endswith(';') or query.endswith('/'): |  | ||||||
|             query = query[:-1] |  | ||||||
|         return query, params |  | ||||||
|  |  | ||||||
|     def _format_params(self, params): |  | ||||||
|         if isinstance(params, dict): |  | ||||||
|             result = {} |  | ||||||
|             charset = self.charset |  | ||||||
|             for key, value in params.items(): |  | ||||||
|                 result[smart_str(key, charset)] = smart_str(value, charset) |  | ||||||
|             return result |  | ||||||
|         else: |  | ||||||
|             return tuple([smart_str(p, self.charset, True) for p in params]) |  | ||||||
|  |  | ||||||
|     def execute(self, query, params=None): |  | ||||||
|         query, params = self._rewrite_args(query, params) |  | ||||||
|         return Database.Cursor.execute(self, query, params) |  | ||||||
|  |  | ||||||
|     def executemany(self, query, params=None): |  | ||||||
|         query, params = self._rewrite_args(query, params) |  | ||||||
|         return Database.Cursor.executemany(self, query, params) |  | ||||||
|  |  | ||||||
|     def fetchone(self): |  | ||||||
|         return to_unicode(Database.Cursor.fetchone(self)) |  | ||||||
|  |  | ||||||
|     def fetchmany(self, size=None): |  | ||||||
|         if size is None: |  | ||||||
|             size = self.arraysize |  | ||||||
|         return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchmany(self, size)]) |  | ||||||
|  |  | ||||||
|     def fetchall(self): |  | ||||||
|         return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchall(self)]) |  | ||||||
|  |  | ||||||
| def to_unicode(s): |  | ||||||
|     """ |  | ||||||
|     Convert strings to Unicode objects (and return all other data types |  | ||||||
|     unchanged). |  | ||||||
|     """ |  | ||||||
|     if isinstance(s, basestring): |  | ||||||
|         return force_unicode(s) |  | ||||||
|     return s |  | ||||||
|  |  | ||||||
| def get_field_cast_sql(db_type): |  | ||||||
|     if db_type.endswith('LOB'): |  | ||||||
|         return "DBMS_LOB.SUBSTR(%s%s)" |  | ||||||
|     else: |  | ||||||
|         return "%s%s" |  | ||||||
|  |  | ||||||
| def get_drop_sequence(table): |  | ||||||
|     return "DROP SEQUENCE %s;" % DatabaseOperations().quote_name(get_sequence_name(table)) |  | ||||||
|  |  | ||||||
| def _get_sequence_reset_sql(): |  | ||||||
|     # TODO: colorize this SQL code with style.SQL_KEYWORD(), etc. |  | ||||||
|     return """ |  | ||||||
|         DECLARE |  | ||||||
|             startvalue integer; |  | ||||||
|             cval integer; |  | ||||||
|         BEGIN |  | ||||||
|             LOCK TABLE %(table)s IN SHARE MODE; |  | ||||||
|             SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s; |  | ||||||
|             SELECT %(sequence)s.nextval INTO cval FROM dual; |  | ||||||
|             cval := startvalue - cval; |  | ||||||
|             IF cval != 0 THEN |  | ||||||
|                 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s MINVALUE 0 INCREMENT BY '||cval; |  | ||||||
|                 SELECT %(sequence)s.nextval INTO cval FROM dual; |  | ||||||
|                 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s INCREMENT BY 1'; |  | ||||||
|             END IF; |  | ||||||
|             COMMIT; |  | ||||||
|         END; |  | ||||||
|         /""" |  | ||||||
|  |  | ||||||
| def get_sequence_name(table): |  | ||||||
|     name_length = DatabaseOperations().max_name_length() - 3 |  | ||||||
|     return '%s_SQ' % util.truncate_name(table, name_length).upper() |  | ||||||
|  |  | ||||||
| def get_trigger_name(table): |  | ||||||
|     name_length = DatabaseOperations().max_name_length() - 3 |  | ||||||
|     return '%s_TR' % util.truncate_name(table, name_length).upper() |  | ||||||
|  |  | ||||||
| def get_query_set_class(DefaultQuerySet): |  | ||||||
|     "Create a custom QuerySet class for Oracle." |  | ||||||
|  |  | ||||||
|         from django.db import connection |         from django.db import connection | ||||||
|         from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word |         from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word | ||||||
|  |  | ||||||
| @@ -500,6 +316,188 @@ def get_query_set_class(DefaultQuerySet): | |||||||
|  |  | ||||||
|         return OracleQuerySet |         return OracleQuerySet | ||||||
|  |  | ||||||
|  |     def quote_name(self, name): | ||||||
|  |         # SQL92 requires delimited (quoted) names to be case-sensitive.  When | ||||||
|  |         # not quoted, Oracle has case-insensitive behavior for identifiers, but | ||||||
|  |         # always defaults to uppercase. | ||||||
|  |         # We simplify things by making Oracle identifiers always uppercase. | ||||||
|  |         if not name.startswith('"') and not name.endswith('"'): | ||||||
|  |             name = '"%s"' % util.truncate_name(name.upper(), DatabaseOperations().max_name_length()) | ||||||
|  |         return name.upper() | ||||||
|  |  | ||||||
|  |     def random_function_sql(self): | ||||||
|  |         return "DBMS_RANDOM.RANDOM" | ||||||
|  |  | ||||||
|  |     def sql_flush(self, style, tables, sequences): | ||||||
|  |         # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', | ||||||
|  |         # 'TRUNCATE z;'... style SQL statements | ||||||
|  |         if tables: | ||||||
|  |             # Oracle does support TRUNCATE, but it seems to get us into | ||||||
|  |             # FK referential trouble, whereas DELETE FROM table works. | ||||||
|  |             sql = ['%s %s %s;' % \ | ||||||
|  |                     (style.SQL_KEYWORD('DELETE'), | ||||||
|  |                      style.SQL_KEYWORD('FROM'), | ||||||
|  |                      style.SQL_FIELD(self.quote_name(table)) | ||||||
|  |                      ) for table in tables] | ||||||
|  |             # Since we've just deleted all the rows, running our sequence | ||||||
|  |             # ALTER code will reset the sequence to 0. | ||||||
|  |             for sequence_info in sequences: | ||||||
|  |                 table_name = sequence_info['table'] | ||||||
|  |                 seq_name = get_sequence_name(table_name) | ||||||
|  |                 query = _get_sequence_reset_sql() % {'sequence': seq_name, 'table': self.quote_name(table_name)} | ||||||
|  |                 sql.append(query) | ||||||
|  |             return sql | ||||||
|  |         else: | ||||||
|  |             return [] | ||||||
|  |  | ||||||
|  |     def sequence_reset_sql(self, style, model_list): | ||||||
|  |         from django.db import models | ||||||
|  |         output = [] | ||||||
|  |         query = _get_sequence_reset_sql() | ||||||
|  |         for model in model_list: | ||||||
|  |             for f in model._meta.fields: | ||||||
|  |                 if isinstance(f, models.AutoField): | ||||||
|  |                     sequence_name = get_sequence_name(model._meta.db_table) | ||||||
|  |                     output.append(query % {'sequence':sequence_name, | ||||||
|  |                                            'table':model._meta.db_table}) | ||||||
|  |                     break # Only one AutoField is allowed per model, so don't bother continuing. | ||||||
|  |             for f in model._meta.many_to_many: | ||||||
|  |                 sequence_name = get_sequence_name(f.m2m_db_table()) | ||||||
|  |                 output.append(query % {'sequence':sequence_name, | ||||||
|  |                                        'table':f.m2m_db_table()}) | ||||||
|  |         return output | ||||||
|  |  | ||||||
|  |     def start_transaction_sql(self): | ||||||
|  |         return '' | ||||||
|  |  | ||||||
|  |     def tablespace_sql(self, tablespace, inline=False): | ||||||
|  |         return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace)) | ||||||
|  |  | ||||||
|  | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     features = DatabaseFeatures() | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|  |     def _valid_connection(self): | ||||||
|  |         return self.connection is not None | ||||||
|  |  | ||||||
|  |     def _cursor(self, settings): | ||||||
|  |         if not self._valid_connection(): | ||||||
|  |             if len(settings.DATABASE_HOST.strip()) == 0: | ||||||
|  |                 settings.DATABASE_HOST = 'localhost' | ||||||
|  |             if len(settings.DATABASE_PORT.strip()) != 0: | ||||||
|  |                 dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME) | ||||||
|  |                 self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn, **self.options) | ||||||
|  |             else: | ||||||
|  |                 conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) | ||||||
|  |                 self.connection = Database.connect(conn_string, **self.options) | ||||||
|  |         cursor = FormatStylePlaceholderCursor(self.connection) | ||||||
|  |         # Default arraysize of 1 is highly sub-optimal. | ||||||
|  |         cursor.arraysize = 100 | ||||||
|  |         # Set oracle date to ansi date format. | ||||||
|  |         cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'") | ||||||
|  |         cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'") | ||||||
|  |         return cursor | ||||||
|  |  | ||||||
|  | class FormatStylePlaceholderCursor(Database.Cursor): | ||||||
|  |     """ | ||||||
|  |     Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" | ||||||
|  |     style. This fixes it -- but note that if you want to use a literal "%s" in | ||||||
|  |     a query, you'll need to use "%%s". | ||||||
|  |  | ||||||
|  |     We also do automatic conversion between Unicode on the Python side and | ||||||
|  |     UTF-8 -- for talking to Oracle -- in here. | ||||||
|  |     """ | ||||||
|  |     charset = 'utf-8' | ||||||
|  |  | ||||||
|  |     def _rewrite_args(self, query, params=None): | ||||||
|  |         if params is None: | ||||||
|  |             params = [] | ||||||
|  |         else: | ||||||
|  |             params = self._format_params(params) | ||||||
|  |         args = [(':arg%d' % i) for i in range(len(params))] | ||||||
|  |         query = smart_str(query, self.charset) % tuple(args) | ||||||
|  |         # cx_Oracle wants no trailing ';' for SQL statements.  For PL/SQL, it | ||||||
|  |         # it does want a trailing ';' but not a trailing '/'.  However, these | ||||||
|  |         # characters must be included in the original query in case the query | ||||||
|  |         # is being passed to SQL*Plus. | ||||||
|  |         if query.endswith(';') or query.endswith('/'): | ||||||
|  |             query = query[:-1] | ||||||
|  |         return query, params | ||||||
|  |  | ||||||
|  |     def _format_params(self, params): | ||||||
|  |         if isinstance(params, dict): | ||||||
|  |             result = {} | ||||||
|  |             charset = self.charset | ||||||
|  |             for key, value in params.items(): | ||||||
|  |                 result[smart_str(key, charset)] = smart_str(value, charset) | ||||||
|  |             return result | ||||||
|  |         else: | ||||||
|  |             return tuple([smart_str(p, self.charset, True) for p in params]) | ||||||
|  |  | ||||||
|  |     def execute(self, query, params=None): | ||||||
|  |         query, params = self._rewrite_args(query, params) | ||||||
|  |         return Database.Cursor.execute(self, query, params) | ||||||
|  |  | ||||||
|  |     def executemany(self, query, params=None): | ||||||
|  |         query, params = self._rewrite_args(query, params) | ||||||
|  |         return Database.Cursor.executemany(self, query, params) | ||||||
|  |  | ||||||
|  |     def fetchone(self): | ||||||
|  |         return to_unicode(Database.Cursor.fetchone(self)) | ||||||
|  |  | ||||||
|  |     def fetchmany(self, size=None): | ||||||
|  |         if size is None: | ||||||
|  |             size = self.arraysize | ||||||
|  |         return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchmany(self, size)]) | ||||||
|  |  | ||||||
|  |     def fetchall(self): | ||||||
|  |         return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchall(self)]) | ||||||
|  |  | ||||||
|  | def to_unicode(s): | ||||||
|  |     """ | ||||||
|  |     Convert strings to Unicode objects (and return all other data types | ||||||
|  |     unchanged). | ||||||
|  |     """ | ||||||
|  |     if isinstance(s, basestring): | ||||||
|  |         return force_unicode(s) | ||||||
|  |     return s | ||||||
|  |  | ||||||
|  | def get_field_cast_sql(db_type): | ||||||
|  |     if db_type.endswith('LOB'): | ||||||
|  |         return "DBMS_LOB.SUBSTR(%s%s)" | ||||||
|  |     else: | ||||||
|  |         return "%s%s" | ||||||
|  |  | ||||||
|  | def get_drop_sequence(table): | ||||||
|  |     return "DROP SEQUENCE %s;" % DatabaseOperations().quote_name(get_sequence_name(table)) | ||||||
|  |  | ||||||
|  | def _get_sequence_reset_sql(): | ||||||
|  |     # TODO: colorize this SQL code with style.SQL_KEYWORD(), etc. | ||||||
|  |     return """ | ||||||
|  |         DECLARE | ||||||
|  |             startvalue integer; | ||||||
|  |             cval integer; | ||||||
|  |         BEGIN | ||||||
|  |             LOCK TABLE %(table)s IN SHARE MODE; | ||||||
|  |             SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s; | ||||||
|  |             SELECT %(sequence)s.nextval INTO cval FROM dual; | ||||||
|  |             cval := startvalue - cval; | ||||||
|  |             IF cval != 0 THEN | ||||||
|  |                 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s MINVALUE 0 INCREMENT BY '||cval; | ||||||
|  |                 SELECT %(sequence)s.nextval INTO cval FROM dual; | ||||||
|  |                 EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s INCREMENT BY 1'; | ||||||
|  |             END IF; | ||||||
|  |             COMMIT; | ||||||
|  |         END; | ||||||
|  |         /""" | ||||||
|  |  | ||||||
|  | def get_sequence_name(table): | ||||||
|  |     name_length = DatabaseOperations().max_name_length() - 3 | ||||||
|  |     return '%s_SQ' % util.truncate_name(table, name_length).upper() | ||||||
|  |  | ||||||
|  | def get_trigger_name(table): | ||||||
|  |     name_length = DatabaseOperations().max_name_length() - 3 | ||||||
|  |     return '%s_TR' % util.truncate_name(table, name_length).upper() | ||||||
|  |  | ||||||
| OPERATOR_MAPPING = { | OPERATOR_MAPPING = { | ||||||
|     'exact': '= %s', |     'exact': '= %s', | ||||||
|   | |||||||
| @@ -564,9 +564,9 @@ class _QuerySet(object): | |||||||
|  |  | ||||||
|         return select, " ".join(sql), params |         return select, " ".join(sql), params | ||||||
|  |  | ||||||
| # Use the backend's QuerySet class if it defines one, otherwise use _QuerySet. | # Use the backend's QuerySet class if it defines one. Otherwise, use _QuerySet. | ||||||
| if hasattr(backend, 'get_query_set_class'): | if connection.features.uses_custom_queryset: | ||||||
|     QuerySet = backend.get_query_set_class(_QuerySet) |     QuerySet = connection.ops.query_set_class(_QuerySet) | ||||||
| else: | else: | ||||||
|     QuerySet = _QuerySet |     QuerySet = _QuerySet | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user