summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2007-08-20 02:20:33 +0000
committerAdrian Holovaty <adrian@holovaty.com>2007-08-20 02:20:33 +0000
commit1a8f9b2b97d2549fe28c2d9090fece3f29f029fa (patch)
tree15e79fab23561c33d7c4a2647c77e8a39b5f367b /django/db
parent4f8225051246fb4c1560bbba77a4ead18bc22828 (diff)
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
Diffstat (limited to 'django/db')
-rw-r--r--django/db/backends/__init__.py10
-rw-r--r--django/db/backends/ado_mssql/base.py15
-rw-r--r--django/db/backends/dummy/base.py8
-rw-r--r--django/db/backends/mysql/base.py15
-rw-r--r--django/db/backends/mysql_old/base.py15
-rw-r--r--django/db/backends/oracle/base.py20
-rw-r--r--django/db/backends/postgresql/base.py15
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py15
-rw-r--r--django/db/backends/sqlite3/base.py15
-rw-r--r--django/db/models/query.py6
10 files changed, 56 insertions, 78 deletions
diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index 632dd36639..2415d453ce 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -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
diff --git a/django/db/backends/ado_mssql/base.py b/django/db/backends/ado_mssql/base.py
index fe7daaf765..60109b7226 100644
--- a/django/db/backends/ado_mssql/base.py
+++ b/django/db/backends/ado_mssql/base.py
@@ -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',
diff --git a/django/db/backends/dummy/base.py b/django/db/backends/dummy/base.py
index 94fa3e1c23..671c9d7291 100644
--- a/django/db/backends/dummy/base.py
+++ b/django/db/backends/dummy/base.py
@@ -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 = {}
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 1501508b4c..079bf36eb0 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -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',
diff --git a/django/db/backends/mysql_old/base.py b/django/db/backends/mysql_old/base.py
index 296a576e26..e4ff1c64b2 100644
--- a/django/db/backends/mysql_old/base.py
+++ b/django/db/backends/mysql_old/base.py
@@ -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',
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index 842efde35c..f4f602ff0d 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -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"
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index 094670cbc6..755a34231c 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -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.
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index 87b41877a6..0bcfd46ac4 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -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',
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 96f88dfa17..2ffdefa73e 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -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)
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 8cf4510622..767942c6a5 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -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'