mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Began implementing BaseDatabaseOperations class for every database backend. This class will be used to hold the database-specific methods that currently live at the module level in each backend. Only autoinc_sql() has been implemented so far.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5950 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -213,7 +213,7 @@ def sql_model_create(model, style, known_models=set()): | |||||||
|     Returns the SQL required to create a single model, as a tuple of: |     Returns the SQL required to create a single model, as a tuple of: | ||||||
|         (list_of_sql, pending_references_dict) |         (list_of_sql, pending_references_dict) | ||||||
|     """ |     """ | ||||||
|     from django.db import backend, models |     from django.db import backend, connection, models | ||||||
|  |  | ||||||
|     opts = model._meta |     opts = model._meta | ||||||
|     final_output = [] |     final_output = [] | ||||||
| @@ -267,9 +267,9 @@ def sql_model_create(model, style, known_models=set()): | |||||||
|     full_statement.append(';') |     full_statement.append(';') | ||||||
|     final_output.append('\n'.join(full_statement)) |     final_output.append('\n'.join(full_statement)) | ||||||
|  |  | ||||||
|     if opts.has_auto_field and hasattr(backend, 'get_autoinc_sql'): |     if opts.has_auto_field: | ||||||
|         # Add any extra SQL needed to support auto-incrementing primary keys |         # Add any extra SQL needed to support auto-incrementing primary keys. | ||||||
|         autoinc_sql = backend.get_autoinc_sql(opts.db_table) |         autoinc_sql = connection.ops.autoinc_sql(opts.db_table) | ||||||
|         if autoinc_sql: |         if autoinc_sql: | ||||||
|             for stmt in autoinc_sql: |             for stmt in autoinc_sql: | ||||||
|                 final_output.append(stmt) |                 final_output.append(stmt) | ||||||
|   | |||||||
| @@ -6,6 +6,10 @@ except ImportError: | |||||||
|     from django.utils._threading_local import local |     from django.utils._threading_local import local | ||||||
|  |  | ||||||
| class BaseDatabaseWrapper(local): | class BaseDatabaseWrapper(local): | ||||||
|  |     """ | ||||||
|  |     Represents a database connection. | ||||||
|  |     """ | ||||||
|  |     ops = None | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
|         self.connection = None |         self.connection = None | ||||||
|         self.queries = [] |         self.queries = [] | ||||||
| @@ -34,3 +38,18 @@ class BaseDatabaseWrapper(local): | |||||||
|     def make_debug_cursor(self, cursor): |     def make_debug_cursor(self, cursor): | ||||||
|         from django.db.backends import util |         from django.db.backends import util | ||||||
|         return util.CursorDebugWrapper(cursor, self) |         return util.CursorDebugWrapper(cursor, self) | ||||||
|  |  | ||||||
|  | class BaseDatabaseOperations(object): | ||||||
|  |     """ | ||||||
|  |     This class encapsulates all backend-specific differences, such as the way | ||||||
|  |     a backend performs ordering or calculates the ID of a recently-inserted | ||||||
|  |     row. | ||||||
|  |     """ | ||||||
|  |     def autoinc_sql(self, table): | ||||||
|  |         """ | ||||||
|  |         Returns any SQL needed to support auto-incrementing primary keys, or | ||||||
|  |         None if no SQL is necessary. | ||||||
|  |  | ||||||
|  |         This SQL is executed when a table is created. | ||||||
|  |         """ | ||||||
|  |         return None | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ ADO MSSQL database backend for Django. | |||||||
| Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/ | Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/ | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| try: | try: | ||||||
|     import adodbapi as Database |     import adodbapi as Database | ||||||
| except ImportError, e: | except ImportError, e: | ||||||
| @@ -48,7 +48,12 @@ def variantToPython(variant, adType): | |||||||
|     return res |     return res | ||||||
| Database.convertVariantToPython = variantToPython | Database.convertVariantToPython = variantToPython | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def _cursor(self, settings): |     def _cursor(self, settings): | ||||||
|         if self.connection is None: |         if self.connection is None: | ||||||
|             if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '': |             if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '': | ||||||
| @@ -130,9 +135,6 @@ def get_start_transaction_sql(): | |||||||
| def get_tablespace_sql(tablespace, inline=False): | def get_tablespace_sql(tablespace, inline=False): | ||||||
|     return "ON %s" % quote_name(tablespace) |     return "ON %s" % quote_name(tablespace) | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """Return a list of SQL statements required to remove all data from |     """Return a list of SQL statements required to remove all data from | ||||||
|     all tables in the database (without actually removing the tables |     all tables in the database (without actually removing the tables | ||||||
|   | |||||||
| @@ -21,7 +21,12 @@ class DatabaseError(Exception): | |||||||
| class IntegrityError(DatabaseError): | class IntegrityError(DatabaseError): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper: | class DatabaseOperations(object): | ||||||
|  |     def __getattr__(self, *args, **kwargs): | ||||||
|  |         complain() | ||||||
|  |  | ||||||
|  | class DatabaseWrapper(object): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|     cursor = complain |     cursor = complain | ||||||
|     _commit = complain |     _commit = complain | ||||||
|     _rollback = ignore |     _rollback = ignore | ||||||
| @@ -50,7 +55,6 @@ get_drop_foreignkey_sql = complain | |||||||
| get_pk_default_value = complain | get_pk_default_value = complain | ||||||
| get_max_name_length = ignore | get_max_name_length = ignore | ||||||
| get_start_transaction_sql = complain | get_start_transaction_sql = complain | ||||||
| get_autoinc_sql = complain |  | ||||||
| get_sql_flush = complain | get_sql_flush = complain | ||||||
| get_sql_sequence_reset = complain | get_sql_sequence_reset = complain | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ MySQL database backend for Django. | |||||||
| Requires MySQLdb: http://sourceforge.net/projects/mysql-python | Requires MySQLdb: http://sourceforge.net/projects/mysql-python | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| try: | try: | ||||||
|     import MySQLdb as Database |     import MySQLdb as Database | ||||||
| except ImportError, e: | except ImportError, e: | ||||||
| @@ -53,7 +53,12 @@ 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 | # standard util.CursorDebugWrapper can be used. Also, using sql_mode | ||||||
| # TRADITIONAL will automatically cause most warnings to be treated as errors. | # TRADITIONAL will automatically cause most warnings to be treated as errors. | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
|         super(DatabaseWrapper, self).__init__(**kwargs) |         super(DatabaseWrapper, self).__init__(**kwargs) | ||||||
|         self.server_version = None |         self.server_version = None | ||||||
| @@ -181,9 +186,6 @@ def get_max_name_length(): | |||||||
| def get_start_transaction_sql(): | def get_start_transaction_sql(): | ||||||
|     return "BEGIN;" |     return "BEGIN;" | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """Return a list of SQL statements required to remove all data from |     """Return a list of SQL statements required to remove all data from | ||||||
|     all tables in the database (without actually removing the tables |     all tables in the database (without actually removing the tables | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ MySQL database backend for Django. | |||||||
| Requires MySQLdb: http://sourceforge.net/projects/mysql-python | Requires MySQLdb: http://sourceforge.net/projects/mysql-python | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| from django.utils.encoding import force_unicode | from django.utils.encoding import force_unicode | ||||||
| try: | try: | ||||||
|     import MySQLdb as Database |     import MySQLdb as Database | ||||||
| @@ -63,7 +63,12 @@ class MysqlDebugWrapper: | |||||||
|         else: |         else: | ||||||
|             return getattr(self.cursor, attr) |             return getattr(self.cursor, attr) | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
|         super(DatabaseWrapper, self).__init__(**kwargs) |         super(DatabaseWrapper, self).__init__(**kwargs) | ||||||
|         self.server_version = None |         self.server_version = None | ||||||
| @@ -200,9 +205,6 @@ def get_max_name_length(): | |||||||
| def get_start_transaction_sql(): | def get_start_transaction_sql(): | ||||||
|     return "BEGIN;" |     return "BEGIN;" | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """Return a list of SQL statements required to remove all data from |     """Return a list of SQL statements required to remove all data from | ||||||
|     all tables in the database (without actually removing the tables |     all tables in the database (without actually removing the tables | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ Oracle database backend for Django. | |||||||
| Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ | Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| from django.utils.datastructures import SortedDict | from django.utils.datastructures import SortedDict | ||||||
| from django.utils.encoding import smart_str, force_unicode | from django.utils.encoding import smart_str, force_unicode | ||||||
| import datetime | import datetime | ||||||
| @@ -21,7 +21,26 @@ except ImportError, e: | |||||||
| DatabaseError = Database.Error | DatabaseError = Database.Error | ||||||
| IntegrityError = Database.IntegrityError | IntegrityError = Database.IntegrityError | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     def autoinc_sql(self, table): | ||||||
|  |         # To simulate auto-incrementing primary keys in Oracle, we have to | ||||||
|  |         # create a sequence and a trigger. | ||||||
|  |         sq_name = get_sequence_name(table) | ||||||
|  |         tr_name = get_trigger_name(table) | ||||||
|  |         sequence_sql = 'CREATE SEQUENCE %s;' % sq_name | ||||||
|  |         trigger_sql = """ | ||||||
|  |             CREATE OR REPLACE TRIGGER %s | ||||||
|  |             BEFORE INSERT ON %s | ||||||
|  |             FOR EACH ROW | ||||||
|  |             WHEN (new.id IS NULL) | ||||||
|  |                 BEGIN | ||||||
|  |                     SELECT %s.nextval INTO :new.id FROM dual; | ||||||
|  |                 END;/""" % (tr_name, quote_name(table), sq_name) | ||||||
|  |         return sequence_sql, trigger_sql | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def _valid_connection(self): |     def _valid_connection(self): | ||||||
|         return self.connection is not None |         return self.connection is not None | ||||||
|  |  | ||||||
| @@ -187,22 +206,6 @@ def get_start_transaction_sql(): | |||||||
| def get_tablespace_sql(tablespace, inline=False): | def get_tablespace_sql(tablespace, inline=False): | ||||||
|     return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), quote_name(tablespace)) |     return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), quote_name(tablespace)) | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     # To simulate auto-incrementing primary keys in Oracle, we have to |  | ||||||
|     # create a sequence and a trigger. |  | ||||||
|     sq_name = get_sequence_name(table) |  | ||||||
|     tr_name = get_trigger_name(table) |  | ||||||
|     sequence_sql = 'CREATE SEQUENCE %s;' % sq_name |  | ||||||
|     trigger_sql = """CREATE OR REPLACE TRIGGER %s |  | ||||||
|   BEFORE INSERT ON %s |  | ||||||
|   FOR EACH ROW |  | ||||||
|   WHEN (new.id IS NULL) |  | ||||||
|     BEGIN |  | ||||||
|       SELECT %s.nextval INTO :new.id FROM dual; |  | ||||||
|     END; |  | ||||||
|     /""" % (tr_name, quote_name(table), sq_name) |  | ||||||
|     return sequence_sql, trigger_sql |  | ||||||
|  |  | ||||||
| def get_drop_sequence(table): | def get_drop_sequence(table): | ||||||
|     return "DROP SEQUENCE %s;" % quote_name(get_sequence_name(table)) |     return "DROP SEQUENCE %s;" % quote_name(get_sequence_name(table)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ Requires psycopg 1: http://initd.org/projects/psycopg1 | |||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.utils.encoding import smart_str, smart_unicode | from django.utils.encoding import smart_str, smart_unicode | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| try: | try: | ||||||
|     import psycopg as Database |     import psycopg as Database | ||||||
| except ImportError, e: | except ImportError, e: | ||||||
| @@ -57,7 +57,12 @@ class UnicodeCursorWrapper(object): | |||||||
|  |  | ||||||
| postgres_version = None | postgres_version = None | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def _cursor(self, settings): |     def _cursor(self, settings): | ||||||
|         set_tz = False |         set_tz = False | ||||||
|         if self.connection is None: |         if self.connection is None: | ||||||
| @@ -157,9 +162,6 @@ def get_max_name_length(): | |||||||
| def get_start_transaction_sql(): | def get_start_transaction_sql(): | ||||||
|     return "BEGIN;" |     return "BEGIN;" | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """Return a list of SQL statements required to remove all data from |     """Return a list of SQL statements required to remove all data from | ||||||
|     all tables in the database (without actually removing the tables |     all tables in the database (without actually removing the tables | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ PostgreSQL database backend for Django. | |||||||
| Requires psycopg 2: http://initd.org/projects/psycopg2 | Requires psycopg 2: http://initd.org/projects/psycopg2 | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| try: | try: | ||||||
|     import psycopg2 as Database |     import psycopg2 as Database | ||||||
|     import psycopg2.extensions |     import psycopg2.extensions | ||||||
| @@ -19,7 +19,12 @@ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) | |||||||
|  |  | ||||||
| postgres_version = None | postgres_version = None | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def _cursor(self, settings): |     def _cursor(self, settings): | ||||||
|         set_tz = False |         set_tz = False | ||||||
|         if self.connection is None: |         if self.connection is None: | ||||||
| @@ -111,9 +116,6 @@ def get_max_name_length(): | |||||||
| def get_start_transaction_sql(): | def get_start_transaction_sql(): | ||||||
|     return "BEGIN;" |     return "BEGIN;" | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """Return a list of SQL statements required to remove all data from |     """Return a list of SQL statements required to remove all data from | ||||||
|     all tables in the database (without actually removing the tables |     all tables in the database (without actually removing the tables | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| SQLite3 backend for django.  Requires pysqlite2 (http://pysqlite.org/). | SQLite3 backend for django.  Requires pysqlite2 (http://pysqlite.org/). | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.db.backends import BaseDatabaseWrapper, util | from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util | ||||||
| try: | try: | ||||||
|     try: |     try: | ||||||
|         from sqlite3 import dbapi2 as Database |         from sqlite3 import dbapi2 as Database | ||||||
| @@ -34,7 +34,12 @@ Database.register_converter("TIMESTAMP", util.typecast_timestamp) | |||||||
| Database.register_converter("decimal", util.typecast_decimal) | Database.register_converter("decimal", util.typecast_decimal) | ||||||
| Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal) | Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal) | ||||||
|  |  | ||||||
|  | class DatabaseOperations(BaseDatabaseOperations): | ||||||
|  |     pass | ||||||
|  |  | ||||||
| class DatabaseWrapper(BaseDatabaseWrapper): | class DatabaseWrapper(BaseDatabaseWrapper): | ||||||
|  |     ops = DatabaseOperations() | ||||||
|  |  | ||||||
|     def _cursor(self, settings): |     def _cursor(self, settings): | ||||||
|         if self.connection is None: |         if self.connection is None: | ||||||
|             kwargs = { |             kwargs = { | ||||||
| @@ -143,9 +148,6 @@ def get_max_name_length(): | |||||||
| def get_start_transaction_sql(): | def get_start_transaction_sql(): | ||||||
|     return "BEGIN;" |     return "BEGIN;" | ||||||
|  |  | ||||||
| def get_autoinc_sql(table): |  | ||||||
|     return None |  | ||||||
|  |  | ||||||
| def get_sql_flush(style, tables, sequences): | def get_sql_flush(style, tables, sequences): | ||||||
|     """ |     """ | ||||||
|     Return a list of SQL statements required to remove all data from |     Return a list of SQL statements required to remove all data from | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user