summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorBoulder Sprinters <boulder-sprinters@djangoproject.com>2006-11-17 06:20:35 +0000
committerBoulder Sprinters <boulder-sprinters@djangoproject.com>2006-11-17 06:20:35 +0000
commit1b0d6b942c39bf0f5105be2d47e6e844e43a2659 (patch)
tree1f4e6a6d3bb7bdaa91ff554d4858354c19bc2b07 /django/db
parente146dd75d94a944009d4a1639906b7ae424be448 (diff)
downloaddjango-1b0d6b942c39bf0f5105be2d47e6e844e43a2659.tar.gz
boulder-oracle-sprint: Refactored all Oracle references outside django.db into the
backend. git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@4082 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db')
-rw-r--r--django/db/backends/ado_mssql/base.py9
-rw-r--r--django/db/backends/mysql/base.py9
-rw-r--r--django/db/backends/oracle/base.py24
-rw-r--r--django/db/backends/postgresql/base.py9
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py9
-rw-r--r--django/db/backends/sqlite3/base.py9
-rw-r--r--django/db/models/query.py51
7 files changed, 90 insertions, 30 deletions
diff --git a/django/db/backends/ado_mssql/base.py b/django/db/backends/ado_mssql/base.py
index ad1f6dd60f..33800980a8 100644
--- a/django/db/backends/ado_mssql/base.py
+++ b/django/db/backends/ado_mssql/base.py
@@ -87,6 +87,9 @@ class DatabaseWrapper(local):
self.connection.close()
self.connection = None
+allows_group_by_ordinal = True
+allows_unique_and_pk = True
+returns_dates_as_strings = False
supports_constraints = True
uses_case_insensitive_names = False
@@ -116,6 +119,9 @@ def get_date_trunc_sql(lookup_type, field_name):
if lookup_type=='day':
return "Convert(datetime, Convert(varchar(12), %s))" % field_name
+def get_datetime_cast_sql():
+ return None
+
def get_limit_offset_sql(limit, offset=None):
# TODO: This is a guess. Make sure this is correct.
sql = "LIMIT %s" % limit
@@ -138,6 +144,9 @@ def get_pk_default_value():
def get_max_name_length():
return None
+def get_autoinc_sql(table):
+ return None
+
OPERATOR_MAPPING = {
'exact': '= %s',
'iexact': 'LIKE %s',
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 0dd73ac51a..e5756dc4b0 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -130,6 +130,9 @@ class DatabaseWrapper(local):
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
+returns_dates_as_strings = True # MySQLdb requires a typecast for dates
supports_constraints = True
uses_case_insensitive_names = False
@@ -164,6 +167,9 @@ def get_date_trunc_sql(lookup_type, field_name):
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
return sql
+def get_datetime_cast_sql():
+ return None
+
def get_limit_offset_sql(limit, offset=None):
sql = "LIMIT "
if offset and offset != 0:
@@ -185,6 +191,9 @@ def get_pk_default_value():
def get_max_name_length():
return 64;
+def get_autoinc_sql(table):
+ return None
+
OPERATOR_MAPPING = {
'exact': '= %s',
'iexact': 'LIKE %s',
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index 5831ca47da..4e6314d32e 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -59,6 +59,9 @@ class DatabaseWrapper(local):
self.connection.close()
self.connection = None
+allows_group_by_ordinal = False
+allows_unique_and_pk = False # Suppress UNIQUE/PK for Oracle (ORA-02259)
+returns_dates_as_strings = False
supports_constraints = True
uses_case_insensitive_names = True
@@ -118,6 +121,9 @@ def get_date_trunc_sql(lookup_type, field_name):
sql = "TRUNC(%s, '%s')" % (field_name, lookup_type)
return sql
+def get_datetime_cast_sql():
+ return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS')"
+
def get_limit_offset_sql(limit, offset=None):
# Limits and offset are too complicated to be handled here.
# Instead, they are handled in django/db/backends/oracle/query.py.
@@ -138,11 +144,27 @@ def get_pk_default_value():
def get_max_name_length():
return 30
+def get_autoinc_sql(table):
+ # To simulate auto-incrementing primary keys in Oracle, we have to
+ # create a sequence and a trigger.
+ name_length = get_max_name_length() - 3
+ sq_name = '%s_sq' % util.truncate_name(table, name_length)
+ tr_name = '%s_tr' % util.truncate_name(table, name_length)
+ 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;\n""" % (tr_name, quote_name(table), sq_name)
+ return sequence_sql, trigger_sql
+
OPERATOR_MAPPING = {
'exact': '= %s',
'iexact': "LIKE %s ESCAPE '\\'",
'contains': "LIKE %s ESCAPE '\\'",
- 'icontains': "LIKE %s ESCAPE '\\'",
+ 'icontains': "LIKE LOWER(%s) ESCAPE '\\'",
'gt': '> %s',
'gte': '>= %s',
'lt': '< %s',
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index 1fba77a550..fd3ef87c45 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -61,6 +61,9 @@ class DatabaseWrapper(local):
self.connection.close()
self.connection = None
+allows_group_by_ordinal = True
+allows_unique_and_pk = True
+returns_dates_as_strings = False
supports_constraints = True
uses_case_insensitive_names = False
@@ -95,6 +98,9 @@ def get_date_trunc_sql(lookup_type, field_name):
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
+def get_datetime_cast_sql():
+ return None
+
def get_limit_offset_sql(limit, offset=None):
sql = "LIMIT %s" % limit
if offset and offset != 0:
@@ -116,6 +122,9 @@ def get_pk_default_value():
def get_max_name_length():
return None
+def get_autoinc_sql(table):
+ return None
+
# Register these custom typecasts, because Django expects dates/times to be
# in Python's native (standard-library) datetime/time format, whereas psycopg
# use mx.DateTime by default.
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index bfbb7616db..b2722d8d99 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -62,6 +62,9 @@ class DatabaseWrapper(local):
self.connection.close()
self.connection = None
+allows_group_by_ordinal = True
+allows_unique_and_pk = True
+returns_dates_as_strings = False
supports_constraints = True
uses_case_insensitive_names = True
@@ -88,6 +91,9 @@ def get_date_trunc_sql(lookup_type, field_name):
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
+def get_datetime_cast_sql():
+ return None
+
def get_limit_offset_sql(limit, offset=None):
sql = "LIMIT %s" % limit
if offset and offset != 0:
@@ -109,6 +115,9 @@ def get_pk_default_value():
def get_max_name_length():
return None
+def get_autoinc_sql(table):
+ return None
+
OPERATOR_MAPPING = {
'exact': '= %s',
'iexact': 'ILIKE %s',
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index cc27bb0a1c..c92e83a6ad 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -98,6 +98,9 @@ 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
+returns_dates_as_strings = True
supports_constraints = False
uses_case_insensitive_names = False
@@ -131,6 +134,9 @@ def get_date_trunc_sql(lookup_type, field_name):
# sqlite doesn't support DATE_TRUNC, so we fake it as above.
return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name)
+def get_datetime_cast_sql():
+ return None
+
def get_limit_offset_sql(limit, offset=None):
sql = "LIMIT %s" % limit
if offset and offset != 0:
@@ -152,6 +158,9 @@ def get_pk_default_value():
def get_max_name_length():
return None
+def get_autoinc_sql(table):
+ return None
+
def _sqlite_date_trunc(lookup_type, dt):
try:
dt = util.typecast_timestamp(dt)
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 847906fd26..53a17c23d7 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1,5 +1,4 @@
-from django import db
-from django.db import backend, connection, transaction
+from django.db import backend, connection, get_query_module, transaction
from django.db.models.fields import DateField, FieldDoesNotExist
from django.db.models import signals
from django.dispatch import dispatcher
@@ -509,13 +508,12 @@ class _QuerySet(object):
else:
assert self._offset is None, "'offset' is not allowed without 'limit'"
- return select, " ".join(sql), params
+ return select, " ".join(sql), params, None
-# Check to see if the DB backend would like to define its own QuerySet class
-# and otherwise use the default.
-backend_query_module = db.get_query_module()
-if hasattr(backend_query_module, "get_query_set_class"):
- QuerySet = db.get_query_module().get_query_set_class(_QuerySet)
+# Use the backend's QuerySet class if it defines one, otherwise use _QuerySet.
+backend_query_module = get_query_module()
+if hasattr(backend_query_module, 'get_query_set_class'):
+ QuerySet = backend_query_module.get_query_set_class(_QuerySet)
else:
QuerySet = _QuerySet
@@ -561,21 +559,18 @@ class DateQuerySet(QuerySet):
field_name = backend.quote_name(self._field.column)
date_trunc_sql = backend.get_date_trunc_sql(self._kind,
'%s.%s' % (table_name, field_name))
- fmt = 'SELECT %s %s GROUP BY %s ORDER BY 1 %s'
-
- if settings.DATABASE_ENGINE == 'oracle':
- sql = fmt % (date_trunc_sql, sql, date_trunc_sql, self._order)
- cursor = connection.cursor()
- cursor.execute(sql, params)
- return [row[0] for row in cursor.fetchall()]
+ if backend.allows_group_by_ordinal:
+ group_by = '1'
else:
- sql = fmt % (date_trunc_sql, sql, 1, self._order_by)
- cursor = connection.cursor()
- cursor.execute(sql, params)
- # We have to manually run typecast_timestamp(str()) on the results, because
- # MySQL doesn't automatically cast the result of date functions as datetime
- # objects -- MySQL returns the values as strings, instead.
+ group_by = date_trunc_sql
+ fmt = 'SELECT %s %s GROUP BY %s ORDER BY 1 %s'
+ stmt = fmt % (date_trunc_sql, sql, group_by, self._order)
+ cursor = connection.cursor()
+ cursor.execute(stmt, params)
+ if backend.returns_dates_as_strings:
return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
+ else:
+ return [row[0] for row in cursor.fetchall()]
def _clone(self, klass=None, **kwargs):
c = super(DateQuerySet, self)._clone(klass, **kwargs)
@@ -657,15 +652,13 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
if table_prefix.endswith('.'):
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
field_name = backend.quote_name(field_name)
- # TODO: move this into django.db.backends.oracle somehow
- if settings.DATABASE_ENGINE == 'oracle':
- if lookup_type == 'icontains':
- return 'lower(%s%s) %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s'))
- elif type(value) == datetime.datetime:
- return "%s%s %s" % (table_prefix, field_name,
- (backend.OPERATOR_MAPPING[lookup_type] % "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS')"))
+ if type(value) == datetime.datetime and backend.get_datetime_cast_sql():
+ cast_sql = backend.get_datetime_cast_sql()
+ else:
+ cast_sql = '%s'
try:
- return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s'))
+ return '%s%s %s' % (table_prefix, field_name,
+ backend.OPERATOR_MAPPING[lookup_type] % cast_sql)
except KeyError:
pass
if lookup_type == 'in':