Author: bouldersprinters
Date: 2007-03-14 16:34:23 -0500 (Wed, 14 Mar 2007)
New Revision: 4728

Added:
   django/branches/boulder-oracle-sprint/docs/databases.txt
Removed:
   django/branches/boulder-oracle-sprint/django/db/backends/ado_mssql/query.py
   django/branches/boulder-oracle-sprint/django/db/backends/dummy/query.py
   django/branches/boulder-oracle-sprint/django/db/backends/mysql/query.py
   django/branches/boulder-oracle-sprint/django/db/backends/oracle/query.py
   django/branches/boulder-oracle-sprint/django/db/backends/postgresql/query.py
   
django/branches/boulder-oracle-sprint/django/db/backends/postgresql_psycopg2/query.py
   django/branches/boulder-oracle-sprint/django/db/backends/sqlite3/query.py
Modified:
   django/branches/boulder-oracle-sprint/django/db/__init__.py
   django/branches/boulder-oracle-sprint/django/db/backends/mysql/base.py
   django/branches/boulder-oracle-sprint/django/db/backends/mysql/client.py
   django/branches/boulder-oracle-sprint/django/db/backends/oracle/base.py
   django/branches/boulder-oracle-sprint/django/db/models/fields/__init__.py
   django/branches/boulder-oracle-sprint/django/db/models/query.py
   django/branches/boulder-oracle-sprint/tests/modeltests/many_to_one/models.py
   
django/branches/boulder-oracle-sprint/tests/regressiontests/serializers_regress/tests.py
Log:
boulder-oracle-sprint: Refactored backend query.py modules away to reduce some 
extra diffs 
with the trunk.


Modified: django/branches/boulder-oracle-sprint/django/db/__init__.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/__init__.py 2007-03-14 
20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/__init__.py 2007-03-14 
21:34:23 UTC (rev 4728)
@@ -23,20 +23,12 @@
     else:
         raise # If there's some other error, this must be an error in Django 
itself.
 
-def backend_module_accessor(module_name):
-    def accessor():
-        full_name = 'django.db.backends.%s.%s' % (settings.DATABASE_ENGINE, 
module_name)
-        return __import__(full_name, {}, {}, [''])
-    return accessor
+get_introspection_module = lambda: 
__import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, 
{}, {}, [''])
+get_creation_module = lambda: __import__('django.db.backends.%s.creation' % 
settings.DATABASE_ENGINE, {}, {}, [''])
+get_query_module = lambda: __import__('django.db.backends.%s.query' % 
settings.DATABASE_ENGINE, {}, {}, [''])
+runshell = lambda: __import__('django.db.backends.%s.client' % 
settings.DATABASE_ENGINE, {}, {}, ['']).runshell()
 
-get_introspection_module = backend_module_accessor("introspection")
-get_creation_module = backend_module_accessor("creation")
-get_query_module = backend_module_accessor("query")
-get_client_module = backend_module_accessor("client")
-runshell = lambda: get_client_module().runshell()
-
 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
-
 DatabaseError = backend.DatabaseError
 
 # Register an event that closes the database connection

Deleted: 
django/branches/boulder-oracle-sprint/django/db/backends/ado_mssql/query.py
===================================================================

Deleted: django/branches/boulder-oracle-sprint/django/db/backends/dummy/query.py
===================================================================

Modified: django/branches/boulder-oracle-sprint/django/db/backends/mysql/base.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/backends/mysql/base.py      
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/backends/mysql/base.py      
2007-03-14 21:34:23 UTC (rev 4728)
@@ -10,6 +10,9 @@
 except ImportError, e:
     from django.core.exceptions import ImproperlyConfigured
     raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
+if Database.version_info < (1,2,1,'final',2):
+    raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % 
MySQLdb.__version__
+
 from MySQLdb.converters import conversions
 from MySQLdb.constants import FIELD_TYPE
 import types
@@ -17,11 +20,14 @@
 
 DatabaseError = Database.DatabaseError
 
+# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime
+# module for time-related columns; older versions could have used mx.DateTime
+# or strings if there were no datetime module. However, MySQLdb still returns
+# TIME columns as timedelta -- they are more like timedelta in terms of actual
+# behavior as they are signed and include days -- and Django expects time, so
+# we still need to override that.
 django_conversions = conversions.copy()
 django_conversions.update({
-    types.BooleanType: util.rev_typecast_boolean,
-    FIELD_TYPE.DATETIME: util.typecast_timestamp,
-    FIELD_TYPE.DATE: util.typecast_date,
     FIELD_TYPE.TIME: util.typecast_time,
 })
 
@@ -31,32 +37,13 @@
 # http://dev.mysql.com/doc/refman/5.0/en/news.html .
 server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
 
-# This is an extra debug layer over MySQL queries, to display warnings.
-# It's only used when DEBUG=True.
-class MysqlDebugWrapper:
-    def __init__(self, cursor):
-        self.cursor = cursor
+# MySQLdb-1.2.1 and newer automatically makes use of SHOW WARNINGS on
+# MySQL-4.1 and newer, so the MysqlDebugWrapper is unnecessary. Since the
+# point is to raise Warnings as exceptions, this can be done with the Python
+# warning module, and this is setup when the connection is created, and the
+# standard util.CursorDebugWrapper can be used. Also, using sql_mode
+# TRADITIONAL will automatically cause most warnings to be treated as errors.
 
-    def execute(self, sql, params=()):
-        try:
-            return self.cursor.execute(sql, params)
-        except Database.Warning, w:
-            self.cursor.execute("SHOW WARNINGS")
-            raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
-
-    def executemany(self, sql, param_list):
-        try:
-            return self.cursor.executemany(sql, param_list)
-        except Database.Warning, w:
-            self.cursor.execute("SHOW WARNINGS")
-            raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
-
-    def __getattr__(self, attr):
-        if self.__dict__.has_key(attr):
-            return self.__dict__[attr]
-        else:
-            return getattr(self.cursor, attr)
-
 try:
     # Only exists in Python 2.4+
     from threading import local
@@ -83,28 +70,31 @@
 
     def cursor(self):
         from django.conf import settings
+        from warnings import filterwarnings
         if not self._valid_connection():
             kwargs = {
-                'user': settings.DATABASE_USER,
-                'db': settings.DATABASE_NAME,
-                'passwd': settings.DATABASE_PASSWORD,
                 'conv': django_conversions,
             }
+            if settings.DATABASE_USER:
+                kwargs['user'] = settings.DATABASE_USER
+            if settings.DATABASE_NAME:
+                kwargs['db'] = settings.DATABASE_NAME
+            if settings.DATABASE_PASSWORD:
+                kwargs['passwd'] = settings.DATABASE_PASSWORD
             if settings.DATABASE_HOST.startswith('/'):
                 kwargs['unix_socket'] = settings.DATABASE_HOST
-            else:
+            elif settings.DATABASE_HOST:
                 kwargs['host'] = settings.DATABASE_HOST
             if settings.DATABASE_PORT:
                 kwargs['port'] = int(settings.DATABASE_PORT)
             kwargs.update(self.options)
             self.connection = Database.connect(**kwargs)
             cursor = self.connection.cursor()
-            if self.connection.get_server_info() >= '4.1':
-                cursor.execute("SET NAMES 'utf8'")
         else:
             cursor = self.connection.cursor()
         if settings.DEBUG:
-            return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
+            filterwarnings("error", category=Database.Warning)
+            return util.CursorDebugWrapper(cursor, self)
         return cursor
 
     def _commit(self):

Modified: 
django/branches/boulder-oracle-sprint/django/db/backends/mysql/client.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/backends/mysql/client.py    
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/backends/mysql/client.py    
2007-03-14 21:34:23 UTC (rev 4728)
@@ -3,12 +3,25 @@
 
 def runshell():
     args = ['']
-    args += ["--user=%s" % settings.DATABASE_USER]
-    if settings.DATABASE_PASSWORD:
-        args += ["--password=%s" % settings.DATABASE_PASSWORD]
-    if settings.DATABASE_HOST:
-        args += ["--host=%s" % settings.DATABASE_HOST]
-    if settings.DATABASE_PORT:
-        args += ["--port=%s" % settings.DATABASE_PORT]
-    args += [settings.DATABASE_NAME]
+    db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
+    user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
+    passwd = settings.DATABASE_OPTIONS.get('passwd', 
settings.DATABASE_PASSWORD)
+    host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST)
+    port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT)
+    defaults_file = settings.DATABASE_OPTIONS.get('read_default_file')
+    # Seems to be no good way to set sql_mode with CLI
+    
+    if defaults_file:
+        args += ["--defaults-file=%s" % defaults_file]
+    if user:
+        args += ["--user=%s" % user]
+    if passwd:
+        args += ["--password=%s" % passwd]
+    if host:
+        args += ["--host=%s" % host]
+    if port:
+        args += ["--port=%s" % port]
+    if db:
+        args += [db]
+
     os.execvp('mysql', args)

Deleted: django/branches/boulder-oracle-sprint/django/db/backends/mysql/query.py
===================================================================

Modified: 
django/branches/boulder-oracle-sprint/django/db/backends/oracle/base.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/backends/oracle/base.py     
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/backends/oracle/base.py     
2007-03-14 21:34:23 UTC (rev 4728)
@@ -11,7 +11,10 @@
 except ImportError, e:
     from django.core.exceptions import ImproperlyConfigured
     raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e
+import datetime
+from django.utils.datastructures import SortedDict
 
+
 DatabaseError = Database.Error
 
 try:
@@ -227,6 +230,201 @@
     drop_sequence_sql = 'DROP SEQUENCE %s;' % sq_name
     return drop_sequence_sql
 
+def get_query_set_class(DefaultQuerySet):
+    "Create a custom QuerySet class for Oracle."
+
+    from django.db import backend, connection
+
+    class OracleQuerySet(DefaultQuerySet):
+
+        def iterator(self):
+            "Performs the SELECT database lookup of this QuerySet."
+
+            from django.db.models.query import get_cached_row
+
+            # self._select is a dictionary, and dictionaries' key order is
+            # undefined, so we convert it to a list of tuples.
+            extra_select = self._select.items()
+
+            full_query = None
+
+            select, sql, params, full_query = 
self._get_sql_clause(get_full_query=True)
+            if not full_query:
+                full_query = "SELECT %s%s\n%s" % \
+                             ((self._distinct and "DISTINCT " or ""),
+                              ', '.join(select), sql)
+
+            cursor = connection.cursor()
+            cursor.execute(full_query, params)
+
+            fill_cache = self._select_related
+            index_end = len(self.model._meta.fields)
+
+            # so here's the logic;
+            # 1. retrieve each row in turn
+            # 2. convert NCLOBs
+
+            def resolve_cols(row):
+                for field in row:
+                    if isinstance(field, Database.LOB):
+                        yield str(field)
+                    # cx_Oracle returns datetime.datetime objects for DATE
+                    # columns, but Django wants a datetime.date.
+                    # A workaround is to return a date if time fields are 0.
+                    # A safer fix would involve either patching cx_Oracle,
+                    # or checking the Model here, neither of which is good.
+                    elif isinstance(field, datetime.datetime) and \
+                        field.hour == field.minute == field.second == 
field.microsecond == 0:
+                        yield field.date()
+                    else:
+                        yield field
+
+            for unresolved_row in cursor:
+                row = list(resolve_cols(unresolved_row))
+                if fill_cache:
+                    obj, index_end = get_cached_row(self.model, row, 0)
+                else:
+                    obj = self.model(*row[:index_end])
+                for i, k in enumerate(extra_select):
+                    setattr(obj, k[0], row[index_end+i])
+                yield obj
+
+        def _get_sql_clause(self, get_full_query=False):
+            from django.db.models.query import fill_table_cache, \
+                handle_legacy_orderlist, orderfield2column
+
+            opts = self.model._meta
+
+            # Construct the fundamental parts of the query: SELECT X FROM Y 
WHERE Z.
+            select = ["%s.%s" % (backend.quote_name(opts.db_table), 
backend.quote_name(f.column)) for f in opts.fields]
+            tables = [quote_only_if_word(t) for t in self._tables]
+            joins = SortedDict()
+            where = self._where[:]
+            params = self._params[:]
+
+            # Convert self._filters into SQL.
+            joins2, where2, params2 = self._filters.get_sql(opts)
+            joins.update(joins2)
+            where.extend(where2)
+            params.extend(params2)
+
+            # Add additional tables and WHERE clauses based on select_related.
+            if self._select_related:
+                fill_table_cache(opts, select, tables, where, opts.db_table, 
[opts.db_table])
+
+            # Add any additional SELECTs.
+            if self._select:
+                select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), 
backend.quote_name(s[0])) for s in self._select.items()])
+
+            # Start composing the body of the SQL statement.
+            sql = [" FROM", backend.quote_name(opts.db_table)]
+
+            # Compose the join dictionary into SQL describing the joins.
+            if joins:
+                sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, 
alias, condition)
+                                for (alias, (table, join_type, condition)) in 
joins.items()]))
+
+            # Compose the tables clause into SQL.
+            if tables:
+                sql.append(", " + ", ".join(tables))
+
+            # Compose the where clause into SQL.
+            if where:
+                sql.append(where and "WHERE " + " AND ".join(where))
+
+            # ORDER BY clause
+            order_by = []
+            if self._order_by is not None:
+                ordering_to_use = self._order_by
+            else:
+                ordering_to_use = opts.ordering
+            for f in handle_legacy_orderlist(ordering_to_use):
+                if f == '?': # Special case.
+                    order_by.append(backend.get_random_function_sql())
+                else:
+                    if f.startswith('-'):
+                        col_name = f[1:]
+                        order = "DESC"
+                    else:
+                        col_name = f
+                        order = "ASC"
+                    if "." in col_name:
+                        table_prefix, col_name = col_name.split('.', 1)
+                        table_prefix = backend.quote_name(table_prefix) + '.'
+                    else:
+                        # Use the database table as a column prefix if it 
wasn't given,
+                        # and if the requested column isn't a custom SELECT.
+                        if "." not in col_name and col_name not in 
(self._select or ()):
+                            table_prefix = backend.quote_name(opts.db_table) + 
'.'
+                        else:
+                            table_prefix = ''
+                    order_by.append('%s%s %s' % (table_prefix, 
backend.quote_name(orderfield2column(col_name, opts)), order))
+            if order_by:
+                sql.append("ORDER BY " + ", ".join(order_by))
+
+            # Look for column name collisions in the select elements
+            # and fix them with an AS alias.  This allows us to do a
+            # SELECT * later in the paging query.
+            cols = [clause.split('.')[-1] for clause in select]
+            for index, col in enumerate(cols):
+                if cols.count(col) > 1:
+                    col = '%s%d' % (col.replace('"', ''), index)
+                    cols[index] = col
+                    select[index] = '%s AS %s' % (select[index], col)
+
+            # LIMIT and OFFSET clauses
+            # To support limits and offsets, Oracle requires some funky 
rewriting of an otherwise normal looking query.
+            select_clause = ",".join(select)
+            distinct = (self._distinct and "DISTINCT " or "")
+
+            if order_by:
+                order_by_clause = " OVER (ORDER BY %s )" % (", 
".join(order_by))
+            else:
+                #Oracle's row_number() function always requires an order-by 
clause.
+                #So we need to define a default order-by, since none was 
provided.
+                order_by_clause = " OVER (ORDER BY %s.%s)" % \
+                    (backend.quote_name(opts.db_table),
+                    backend.quote_name(opts.fields[0].db_column or 
opts.fields[0].column))
+            # limit_and_offset_clause
+            if self._limit is None:
+                assert self._offset is None, "'offset' is not allowed without 
'limit'"
+
+            if self._offset is not None:
+                offset = int(self._offset)
+            else:
+                offset = 0
+            if self._limit is not None:
+                limit = int(self._limit)
+            else:
+                limit = None
+
+            limit_and_offset_clause = ''
+            if limit is not None:
+                limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % 
(offset, limit+offset)
+            elif offset:
+                limit_and_offset_clause = "WHERE rn > %s" % (offset)
+
+            if len(limit_and_offset_clause) > 0:
+                fmt = \
+"""SELECT * FROM
+  (SELECT %s%s,
+          ROW_NUMBER()%s AS rn
+   %s)
+%s"""
+                full_query = fmt % (distinct, select_clause,
+                                    order_by_clause, ' '.join(sql).strip(),
+                                    limit_and_offset_clause)
+            else:
+                full_query = None
+
+            if get_full_query:
+                return select, " ".join(sql), params, full_query
+            else:
+                return select, " ".join(sql), params
+
+    return OracleQuerySet
+
+
 OPERATOR_MAPPING = {
     'exact': '= %s',
     'iexact': "LIKE %s ESCAPE '\\'",

Deleted: 
django/branches/boulder-oracle-sprint/django/db/backends/oracle/query.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/backends/oracle/query.py    
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/backends/oracle/query.py    
2007-03-14 21:34:23 UTC (rev 4728)
@@ -1,194 +0,0 @@
-import datetime
-from django.db import backend, connection
-from django.utils.datastructures import SortedDict
-import cx_Oracle as Database
-
-
-def get_query_set_class(DefaultQuerySet):
-    "Create a custom QuerySet class for Oracle."
-
-    class OracleQuerySet(DefaultQuerySet):
-
-        def iterator(self):
-            "Performs the SELECT database lookup of this QuerySet."
-
-            from django.db.models.query import get_cached_row
-
-            # self._select is a dictionary, and dictionaries' key order is
-            # undefined, so we convert it to a list of tuples.
-            extra_select = self._select.items()
-
-            full_query = None
-
-            select, sql, params, full_query = self._get_sql_clause()
-            if not full_query:
-                full_query = "SELECT %s%s\n%s" % \
-                             ((self._distinct and "DISTINCT " or ""),
-                              ', '.join(select), sql)
-
-            cursor = connection.cursor()
-            cursor.execute(full_query, params)
-
-            fill_cache = self._select_related
-            index_end = len(self.model._meta.fields)
-
-            # so here's the logic;
-            # 1. retrieve each row in turn
-            # 2. convert NCLOBs
-
-            def resolve_cols(row):
-                for field in row:
-                    if isinstance(field, Database.LOB):
-                        yield str(field)
-                    # cx_Oracle returns datetime.datetime objects for DATE
-                    # columns, but Django wants a datetime.date.
-                    # A workaround is to return a date if time fields are 0.
-                    # A safer fix would involve either patching cx_Oracle,
-                    # or checking the Model here, neither of which is good.
-                    elif isinstance(field, datetime.datetime) and \
-                        field.hour == field.minute == field.second == 
field.microsecond == 0:
-                        yield field.date()
-                    else:
-                        yield field
-
-            for unresolved_row in cursor:
-                row = list(resolve_cols(unresolved_row))
-                if fill_cache:
-                    obj, index_end = get_cached_row(self.model, row, 0)
-                else:
-                    obj = self.model(*row[:index_end])
-                for i, k in enumerate(extra_select):
-                    setattr(obj, k[0], row[index_end+i])
-                yield obj
-
-        def _get_sql_clause(self):
-            from django.db.models.query import fill_table_cache, \
-                handle_legacy_orderlist, orderfield2column
-
-            opts = self.model._meta
-
-            # Construct the fundamental parts of the query: SELECT X FROM Y 
WHERE Z.
-            select = ["%s.%s" % (backend.quote_name(opts.db_table), 
backend.quote_name(f.column)) for f in opts.fields]
-            tables = [quote_only_if_word(t) for t in self._tables]
-            joins = SortedDict()
-            where = self._where[:]
-            params = self._params[:]
-
-            # Convert self._filters into SQL.
-            joins2, where2, params2 = self._filters.get_sql(opts)
-            joins.update(joins2)
-            where.extend(where2)
-            params.extend(params2)
-
-            # Add additional tables and WHERE clauses based on select_related.
-            if self._select_related:
-                fill_table_cache(opts, select, tables, where, opts.db_table, 
[opts.db_table])
-
-            # Add any additional SELECTs.
-            if self._select:
-                select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), 
backend.quote_name(s[0])) for s in self._select.items()])
-
-            # Start composing the body of the SQL statement.
-            sql = [" FROM", backend.quote_name(opts.db_table)]
-
-            # Compose the join dictionary into SQL describing the joins.
-            if joins:
-                sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, 
alias, condition)
-                                for (alias, (table, join_type, condition)) in 
joins.items()]))
-
-            # Compose the tables clause into SQL.
-            if tables:
-                sql.append(", " + ", ".join(tables))
-
-            # Compose the where clause into SQL.
-            if where:
-                sql.append(where and "WHERE " + " AND ".join(where))
-
-            # ORDER BY clause
-            order_by = []
-            if self._order_by is not None:
-                ordering_to_use = self._order_by
-            else:
-                ordering_to_use = opts.ordering
-            for f in handle_legacy_orderlist(ordering_to_use):
-                if f == '?': # Special case.
-                    order_by.append(backend.get_random_function_sql())
-                else:
-                    if f.startswith('-'):
-                        col_name = f[1:]
-                        order = "DESC"
-                    else:
-                        col_name = f
-                        order = "ASC"
-                    if "." in col_name:
-                        table_prefix, col_name = col_name.split('.', 1)
-                        table_prefix = backend.quote_name(table_prefix) + '.'
-                    else:
-                        # Use the database table as a column prefix if it 
wasn't given,
-                        # and if the requested column isn't a custom SELECT.
-                        if "." not in col_name and col_name not in 
(self._select or ()):
-                            table_prefix = backend.quote_name(opts.db_table) + 
'.'
-                        else:
-                            table_prefix = ''
-                    order_by.append('%s%s %s' % (table_prefix, 
backend.quote_name(orderfield2column(col_name, opts)), order))
-            if order_by:
-                sql.append("ORDER BY " + ", ".join(order_by))
-
-            # Look for column name collisions in the select elements
-            # and fix them with an AS alias.  This allows us to do a
-            # SELECT * later in the paging query.
-            cols = [clause.split('.')[-1] for clause in select]
-            for index, col in enumerate(cols):
-                if cols.count(col) > 1:
-                    col = '%s%d' % (col.replace('"', ''), index)
-                    cols[index] = col
-                    select[index] = '%s AS %s' % (select[index], col)
-
-            # LIMIT and OFFSET clauses
-            # To support limits and offsets, Oracle requires some funky 
rewriting of an otherwise normal looking query.
-            select_clause = ",".join(select)
-            distinct = (self._distinct and "DISTINCT " or "")
-
-            if order_by:
-                order_by_clause = " OVER (ORDER BY %s )" % (", 
".join(order_by))
-            else:
-                #Oracle's row_number() function always requires an order-by 
clause.
-                #So we need to define a default order-by, since none was 
provided.
-                order_by_clause = " OVER (ORDER BY %s.%s)" % \
-                    (backend.quote_name(opts.db_table),
-                    backend.quote_name(opts.fields[0].db_column or 
opts.fields[0].column))
-            # limit_and_offset_clause
-            if self._limit is None:
-                assert self._offset is None, "'offset' is not allowed without 
'limit'"
-
-            if self._offset is not None:
-                offset = int(self._offset)
-            else:
-                offset = 0
-            if self._limit is not None:
-                limit = int(self._limit)
-            else:
-                limit = None
-
-            limit_and_offset_clause = ''
-            if limit is not None:
-                limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % 
(offset, limit+offset)
-            elif offset:
-                limit_and_offset_clause = "WHERE rn > %s" % (offset)
-
-            if len(limit_and_offset_clause) > 0:
-                fmt = \
-"""SELECT * FROM
-  (SELECT %s%s,
-          ROW_NUMBER()%s AS rn
-   %s)
-%s"""
-                full_query = fmt % (distinct, select_clause,
-                                    order_by_clause, ' '.join(sql).strip(),
-                                    limit_and_offset_clause)
-            else:
-                full_query = None
-
-            return select, " ".join(sql), params, full_query
-
-    return OracleQuerySet

Deleted: 
django/branches/boulder-oracle-sprint/django/db/backends/postgresql/query.py
===================================================================

Deleted: 
django/branches/boulder-oracle-sprint/django/db/backends/postgresql_psycopg2/query.py
===================================================================

Deleted: 
django/branches/boulder-oracle-sprint/django/db/backends/sqlite3/query.py
===================================================================

Modified: 
django/branches/boulder-oracle-sprint/django/db/models/fields/__init__.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/models/fields/__init__.py   
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/models/fields/__init__.py   
2007-03-14 21:34:23 UTC (rev 4728)
@@ -846,7 +846,7 @@
         if value is not None:
             # MySQL will throw a warning if microseconds are given, because it
             # doesn't support microseconds.
-            if settings.DATABASE_ENGINE == 'mysql':
+            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 
'microsecond'):
                 value = value.replace(microsecond=0)
                 value = str(value)
             elif settings.DATABASE_ENGINE == 'oracle':

Modified: django/branches/boulder-oracle-sprint/django/db/models/query.py
===================================================================
--- django/branches/boulder-oracle-sprint/django/db/models/query.py     
2007-03-14 20:43:43 UTC (rev 4727)
+++ django/branches/boulder-oracle-sprint/django/db/models/query.py     
2007-03-14 21:34:23 UTC (rev 4728)
@@ -169,7 +169,7 @@
     def iterator(self):
         "Performs the SELECT database lookup of this QuerySet."
         try:
-            select, sql, params, full_query = self._get_sql_clause()
+            select, sql, params = self._get_sql_clause()
         except EmptyResultSet:
             raise StopIteration
 
@@ -218,7 +218,7 @@
         counter._limit = None
 
         try:
-            select, sql, params, full_query = counter._get_sql_clause()
+            select, sql, params = counter._get_sql_clause()
         except EmptyResultSet:
             return 0
 
@@ -548,12 +548,11 @@
         else:
             assert self._offset is None, "'offset' is not allowed without 
'limit'"
 
-        return select, " ".join(sql), params, None
+        return select, " ".join(sql), params
 
 # 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)
+if hasattr(backend, 'get_query_set_class'):
+    QuerySet = backend.get_query_set_class(_QuerySet)
 else:
     QuerySet = _QuerySet
 
@@ -566,7 +565,7 @@
 
     def iterator(self):
         try:
-            select, sql, params, full_query = self._get_sql_clause()
+            select, sql, params = self._get_sql_clause()
         except EmptyResultSet:
             raise StopIteration
 
@@ -601,7 +600,7 @@
             self._where.append('%s.%s IS NOT NULL' % \
                 (backend.quote_name(self.model._meta.db_table), 
backend.quote_name(self._field.column)))
         try:
-            select, sql, params, full_query = self._get_sql_clause()
+            select, sql, params = self._get_sql_clause()
         except EmptyResultSet:
             raise StopIteration
 

Copied: django/branches/boulder-oracle-sprint/docs/databases.txt (from rev 
4727, django/trunk/docs/databases.txt)
===================================================================
--- django/branches/boulder-oracle-sprint/docs/databases.txt                    
        (rev 0)
+++ django/branches/boulder-oracle-sprint/docs/databases.txt    2007-03-14 
21:34:23 UTC (rev 4728)
@@ -0,0 +1,162 @@
+===============================
+Notes About Supported Databases
+===============================
+
+Django attempts to support as many features as possible on all databases.
+However, since not all database servers are identical, there is obviously
+going to be some variations. This file describes some of the
+features that might relevant to Django usage. It is not intended as a
+replacement for server-specific documentation or reference manuals.
+
+MySQL Notes
+===========
+
+Django expects the database to support transactions, referential integrity,
+and Unicode support (UTF-8 encoding). Fortunately MySQL_ has all these
+features as available as far back as 3.23. While it may be possible to use
+3.23 or 4.0, you will probably have less trouble if you use 4.1 or 5.0.
+
+MySQL-4.1
+---------
+
+MySQL-4.1_ has greatly improved support for character sets. It is possible to
+set different default character sets on the database, table, and column.
+Previous versions have only a server-wide character set setting. It's also the
+first version where the character set can be changed on the fly. 4.1 also has
+support for views, but these are not currently used by Django.
+
+MySQL-5.0
+---------
+
+MySQL-5.0_ adds the ``information_schema`` database, which contains detailed
+data on all database schema. This is used for Django's ``inspectdb`` feature,
+when it is available. 5.0 also has support for stored procedures, but these
+are not currently used by Django.
+
+.. _MySQL: http://www.mysql.com/
+.. _MySQL-4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html
+.. _MySQL-5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html
+
+Storage Engines
+---------------
+
+MySQL has several `storage engines`_ (previously called table types). You can
+change the default storage engine in the server configuration.
+
+The default one is MyISAM_. The main drawback of MyISAM is that it does not
+currently have support for transactions or foreign keys. On the plus side, it
+is currently the only engine that supports full-text indexing and searching.
+
+The InnoDB_ engine is fully transactional and supports foreign key references.
+
+The BDB_ engine, like InnoDB, is also fully transactional and supports foreign
+key references. However, it's use seems to be somewhat deprecated.
+
+`Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon.
+For now, InnoDB is probably your best choice.
+
+.. _storage engines: 
http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html
+.. _MyISAM: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html
+.. _BDB: http://dev.mysql.com/doc/refman/5.0/en/bdb-storage-engine.html
+.. _InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb.html
+.. _Other storage engines: 
http://dev.mysql.com/doc/refman/5.1/en/storage-engines-other.html
+.. _SolidDB: http://forge.mysql.com/projects/view.php?id=139
+.. _Falcon: http://dev.mysql.com/doc/falcon/en/index.html
+
+MySQLdb
+-------
+
+`MySQLdb`_ is the Python interface to MySQL. 1.2.1 is the first version which
+has support for MySQL-4.1 and newer. If you are trying to use an older version
+of MySQL, then 1.2.0 *may* work for you.
+
+.. _MySQLdb: http://sourceforge.net/projects/mysql-python
+
+Creating your database
+~~~~~~~~~~~~~~~~~~~~~~
+
+You can `create your database`_ using the command-line tools and this SQL::
+
+  CREATE DATABASE <dbname> CHARACTER SET utf8;
+  
+This ensures all tables and columns will use utf8 by default.
+  
+.. _create your database: 
http://dev.mysql.com/doc/refman/5.0/en/create-database.html
+
+Connecting to the database
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Refer to the `settings documentation`_.
+
+Connection settings are used in this order:
+
+ 1. ``DATABASE_OPTIONS``
+ 2. ``DATABASE_NAME``, ``DATABASE_USER``, ``DATABASE_PASSWORD``, 
``DATABASE_HOST``,
+    ``DATABASE_PORT``
+ 3. MySQL option files.
+
+In other words, if you set the name of the database in ``DATABASE_OPTIONS``,
+this will take precedence over ``DATABASE_NAME``, which would override
+anything in a `MySQL option file`_.
+
+Here's a sample configuration which uses a MySQL option file::
+
+  # settings.py
+  DATABASE_ENGINE = "mysql"
+  DATABASE_OPTIONS = {
+      'read_default_file': '/path/to/my.cnf',
+      }
+      
+  # my.cnf
+  [client]
+  database = DATABASE_NAME
+  user = DATABASE_USER
+  passwd = DATABASE_PASSWORD
+  default-character-set = utf8
+
+There are several other MySQLdb connection options which may be useful, such
+as ``ssl``, ``use_unicode``, ``init_command``, and ``sql_mode``; consult the
+`MySQLdb documentation`_ for more details.
+  
+.. _settings documentation: 
http://www.djangoproject.com/documentation/settings/#database-engine
+.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
+.. _MySQLdb documentation: http://mysql-python.sourceforge.net/
+
+Creating your tables
+~~~~~~~~~~~~~~~~~~~~
+
+When Django generates the schema, it doesn't specify a storage engine, so they
+will be created with whatever default `storage engine`__ your database server
+is configured for. The easiest solution is to set your database server's 
default
+storage engine to the desired engine.
+
+__ `storage engines`_
+
+If you are using a hosting service and can't change your server's default
+storage engine, you have a couple of options.
+
+After the tables is created, all that is needed to convert it to a new storage
+engine (such as InnoDB) is::
+  
+  ALTER TABLE <tablename> ENGINE=INNODB;
+
+With a lot of tables, this can be tedious.
+
+Another option is to use the ``init_command`` option for MySQLdb prior to
+creating your tables::
+
+  DATABASE_OPTIONS = {
+      ...
+      "init_command": "SET storage_engine=INNODB",
+      ...
+      }
+
+This sets the default storage engine upon connecting to the database. After
+your tables are set up and running in production, you should remove this
+option.
+
+Another method for changing the storage engine is described in
+AlterModelOnSyncDB_.
+
+.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB
+

Modified: 
django/branches/boulder-oracle-sprint/tests/modeltests/many_to_one/models.py
===================================================================
--- 
django/branches/boulder-oracle-sprint/tests/modeltests/many_to_one/models.py    
    2007-03-14 20:43:43 UTC (rev 4727)
+++ 
django/branches/boulder-oracle-sprint/tests/modeltests/many_to_one/models.py    
    2007-03-14 21:34:23 UTC (rev 4728)
@@ -146,7 +146,7 @@
 
 # The underlying query only makes one join when a related table is referenced 
twice.
 >>> query = Article.objects.filter(reporter__first_name__exact='John', 
 >>> reporter__last_name__exact='Smith')
->>> null, sql, null, null = query._get_sql_clause()
+>>> null, sql, null = query._get_sql_clause()
 >>> sql.count('INNER JOIN')
 1
 

Modified: 
django/branches/boulder-oracle-sprint/tests/regressiontests/serializers_regress/tests.py
===================================================================
--- 
django/branches/boulder-oracle-sprint/tests/regressiontests/serializers_regress/tests.py
    2007-03-14 20:43:43 UTC (rev 4727)
+++ 
django/branches/boulder-oracle-sprint/tests/regressiontests/serializers_regress/tests.py
    2007-03-14 21:34:23 UTC (rev 4728)
@@ -54,7 +54,7 @@
 def data_compare(testcase, pk, klass, data):
     instance = klass.objects.get(id=pk)
     testcase.assertEqual(data, instance.data, 
-                         "Objects with PK=%d not equal; expected '%s', got 
'%s'" % (pk,data,instance.data))
+                         "Objects with PK=%d not equal; expected '%s' (%s), 
got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data)))
 
 def fk_compare(testcase, pk, klass, data):
     instance = klass.objects.get(id=pk)


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to