Kaydet (Commit) 38b5d7f2 authored tarafından Adrian Holovaty's avatar Adrian Holovaty

Began implementing BaseDatabaseOperations class for every database backend. This…

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
üst 7c41b19c
......@@ -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)
......
......@@ -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
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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))
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment