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:
Adrian Holovaty 2007-08-19 22:29:57 +00:00
parent 7c41b19c8a
commit 38b5d7f23d
10 changed files with 85 additions and 47 deletions

View File

@ -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:
(list_of_sql, pending_references_dict)
"""
from django.db import backend, models
from django.db import backend, connection, models
opts = model._meta
final_output = []
@ -267,9 +267,9 @@ def sql_model_create(model, style, known_models=set()):
full_statement.append(';')
final_output.append('\n'.join(full_statement))
if opts.has_auto_field and hasattr(backend, 'get_autoinc_sql'):
# Add any extra SQL needed to support auto-incrementing primary keys
autoinc_sql = backend.get_autoinc_sql(opts.db_table)
if opts.has_auto_field:
# Add any extra SQL needed to support auto-incrementing primary keys.
autoinc_sql = connection.ops.autoinc_sql(opts.db_table)
if autoinc_sql:
for stmt in autoinc_sql:
final_output.append(stmt)

View File

@ -6,6 +6,10 @@ except ImportError:
from django.utils._threading_local import local
class BaseDatabaseWrapper(local):
"""
Represents a database connection.
"""
ops = None
def __init__(self, **kwargs):
self.connection = None
self.queries = []
@ -34,3 +38,18 @@ class BaseDatabaseWrapper(local):
def make_debug_cursor(self, cursor):
from django.db.backends import util
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

View File

@ -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, util
from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util
try:
import adodbapi as Database
except ImportError, e:
@ -48,7 +48,12 @@ def variantToPython(variant, adType):
return res
Database.convertVariantToPython = variantToPython
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def _cursor(self, settings):
if self.connection is None:
if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '':
@ -130,9 +135,6 @@ def get_start_transaction_sql():
def get_tablespace_sql(tablespace, inline=False):
return "ON %s" % quote_name(tablespace)
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables

View File

@ -21,7 +21,12 @@ class DatabaseError(Exception):
class IntegrityError(DatabaseError):
pass
class DatabaseWrapper:
class DatabaseOperations(object):
def __getattr__(self, *args, **kwargs):
complain()
class DatabaseWrapper(object):
ops = DatabaseOperations()
cursor = complain
_commit = complain
_rollback = ignore
@ -50,7 +55,6 @@ get_drop_foreignkey_sql = complain
get_pk_default_value = complain
get_max_name_length = ignore
get_start_transaction_sql = complain
get_autoinc_sql = complain
get_sql_flush = complain
get_sql_sequence_reset = complain

View File

@ -4,7 +4,7 @@ MySQL database backend for Django.
Requires MySQLdb: http://sourceforge.net/projects/mysql-python
"""
from django.db.backends import BaseDatabaseWrapper, util
from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util
try:
import MySQLdb as Database
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
# TRADITIONAL will automatically cause most warnings to be treated as errors.
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def __init__(self, **kwargs):
super(DatabaseWrapper, self).__init__(**kwargs)
self.server_version = None
@ -181,9 +186,6 @@ def get_max_name_length():
def get_start_transaction_sql():
return "BEGIN;"
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables

View File

@ -4,7 +4,7 @@ MySQL database backend for Django.
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
try:
import MySQLdb as Database
@ -63,7 +63,12 @@ class MysqlDebugWrapper:
else:
return getattr(self.cursor, attr)
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def __init__(self, **kwargs):
super(DatabaseWrapper, self).__init__(**kwargs)
self.server_version = None
@ -200,9 +205,6 @@ def get_max_name_length():
def get_start_transaction_sql():
return "BEGIN;"
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables

View File

@ -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, util
from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util
from django.utils.datastructures import SortedDict
from django.utils.encoding import smart_str, force_unicode
import datetime
@ -21,7 +21,26 @@ except ImportError, e:
DatabaseError = Database.Error
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):
ops = DatabaseOperations()
def _valid_connection(self):
return self.connection is not None
@ -187,22 +206,6 @@ def get_start_transaction_sql():
def get_tablespace_sql(tablespace, inline=False):
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):
return "DROP SEQUENCE %s;" % quote_name(get_sequence_name(table))

View File

@ -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, BaseDatabaseOperations, util
try:
import psycopg as Database
except ImportError, e:
@ -57,7 +57,12 @@ class UnicodeCursorWrapper(object):
postgres_version = None
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def _cursor(self, settings):
set_tz = False
if self.connection is None:
@ -157,9 +162,6 @@ def get_max_name_length():
def get_start_transaction_sql():
return "BEGIN;"
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables

View File

@ -4,7 +4,7 @@ PostgreSQL database backend for Django.
Requires psycopg 2: http://initd.org/projects/psycopg2
"""
from django.db.backends import BaseDatabaseWrapper, util
from django.db.backends import BaseDatabaseWrapper, BaseDatabaseOperations, util
try:
import psycopg2 as Database
import psycopg2.extensions
@ -19,7 +19,12 @@ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
postgres_version = None
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def _cursor(self, settings):
set_tz = False
if self.connection is None:
@ -111,9 +116,6 @@ def get_max_name_length():
def get_start_transaction_sql():
return "BEGIN;"
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables

View File

@ -2,7 +2,7 @@
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:
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_adapter(decimal.Decimal, util.rev_typecast_decimal)
class DatabaseOperations(BaseDatabaseOperations):
pass
class DatabaseWrapper(BaseDatabaseWrapper):
ops = DatabaseOperations()
def _cursor(self, settings):
if self.connection is None:
kwargs = {
@ -143,9 +148,6 @@ def get_max_name_length():
def get_start_transaction_sql():
return "BEGIN;"
def get_autoinc_sql(table):
return None
def get_sql_flush(style, tables, sequences):
"""
Return a list of SQL statements required to remove all data from