Commit 06315375 authored by Adrian Holovaty's avatar Adrian Holovaty
Browse files

Fixed #7420 -- Abstracted some more database options into DatabaseFeatures --...

Fixed #7420 -- Abstracted some more database options into DatabaseFeatures -- supports_usecs, time_field_needs_date, interprets_empty_strings_as_nulls and date_field_supports_time_value -- and changed various hard-coded 'if DATABASE_BACKEND == oracle' statements to use the new options. Thanks to ramiro for the patch

git-svn-id: http://code.djangoproject.com/svn/django/trunk@7643 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 57311b59
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -52,6 +52,10 @@ class BaseDatabaseFeatures(object):
    uses_custom_query_class = False
    empty_fetchmany_value = []
    update_can_self_select = True
    supports_usecs = True
    time_field_needs_date = False
    interprets_empty_strings_as_nulls = False
    date_field_supports_time_value = True

class BaseDatabaseOperations(object):
    """
@@ -266,3 +270,8 @@ class BaseDatabaseOperations(object):
        tablespaces.
        """
        return None

    def prep_for_like_query(self, x):
        """Prepares a value for use in a LIKE query."""
        from django.utils.encoding import smart_unicode
        return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    inline_fk_references = False
    empty_fetchmany_value = ()
    update_can_self_select = False
    supports_usecs = False

class DatabaseOperations(BaseDatabaseOperations):
    def date_extract_sql(self, lookup_type, field_name):
+1 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    inline_fk_references = False
    empty_fetchmany_value = ()
    update_can_self_select = False
    supports_usecs = False

class DatabaseOperations(BaseDatabaseOperations):
    def date_extract_sql(self, lookup_type, field_name):
+3 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    supports_tablespaces = True
    uses_case_insensitive_names = True
    uses_custom_query_class = True
    time_field_needs_date = True
    interprets_empty_strings_as_nulls = True
    date_field_supports_time_value = False

class DatabaseOperations(BaseDatabaseOperations):
    def autoinc_sql(self, table, column):
+16 −16
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ try:
except ImportError:
    from django.utils import _decimal as decimal    # for Python 2.3

from django.db import get_creation_module
from django.db import connection, get_creation_module
from django.db.models import signals
from django.db.models.query_utils import QueryWrapper
from django.dispatch import dispatcher
@@ -33,9 +33,6 @@ HORIZONTAL, VERTICAL = 1, 2
BLANK_CHOICE_DASH = [("", "---------")]
BLANK_CHOICE_NONE = [("", "None")]

# prepares a value for use in a LIKE query
prep_for_like_query = lambda x: smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")

# returns the <ul> class for a given radio_admin value
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')

@@ -97,7 +94,7 @@ class Field(object):
        self.blank, self.null = blank, null
        # Oracle treats the empty string ('') as null, so coerce the null
        # option whenever '' is a possible value.
        if self.empty_strings_allowed and settings.DATABASE_ENGINE == 'oracle':
        if self.empty_strings_allowed and connection.features.interprets_empty_strings_as_nulls:
            self.null = True
        self.core, self.rel, self.default = core, rel, default
        self.editable = editable
@@ -235,13 +232,13 @@ class Field(object):
        elif lookup_type in ('range', 'in'):
            return value
        elif lookup_type in ('contains', 'icontains'):
            return ["%%%s%%" % prep_for_like_query(value)]
            return ["%%%s%%" % connection.ops.prep_for_like_query(value)]
        elif lookup_type == 'iexact':
            return [prep_for_like_query(value)]
            return [connection.ops.prep_for_like_query(value)]
        elif lookup_type in ('startswith', 'istartswith'):
            return ["%s%%" % prep_for_like_query(value)]
            return ["%s%%" % connection.ops.prep_for_like_query(value)]
        elif lookup_type in ('endswith', 'iendswith'):
            return ["%%%s" % prep_for_like_query(value)]
            return ["%%%s" % connection.ops.prep_for_like_query(value)]
        elif lookup_type == 'isnull':
            return []
        elif lookup_type == 'year':
@@ -252,9 +249,12 @@ class Field(object):
            if settings.DATABASE_ENGINE == 'sqlite3':
                first = '%s-01-01'
                second = '%s-12-31 23:59:59.999999'
            elif settings.DATABASE_ENGINE == 'oracle' and self.get_internal_type() == 'DateField':
            elif not connection.features.date_field_supports_time_value and self.get_internal_type() == 'DateField':
                first = '%s-01-01'
                second = '%s-12-31'
            elif not connection.features.supports_usecs:
                first = '%s-01-01 00:00:00'
                second = '%s-12-31 23:59:59.99'
            else:
                first = '%s-01-01 00:00:00'
                second = '%s-12-31 23:59:59.999999'
@@ -271,7 +271,7 @@ class Field(object):
            if callable(self.default):
                return self.default()
            return force_unicode(self.default, strings_only=True)
        if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'):
        if not self.empty_strings_allowed or (self.null and not connection.features.interprets_empty_strings_as_nulls):
            return None
        return ""

@@ -629,7 +629,7 @@ class DateTimeField(DateField):
        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' and hasattr(value, 'microsecond'):
            if not connection.features.supports_usecs and hasattr(value, 'microsecond'):
                value = value.replace(microsecond=0)
            value = smart_unicode(value)
        return Field.get_db_prep_save(self, value)
@@ -1071,7 +1071,7 @@ class TimeField(Field):
        return "TimeField"

    def get_db_prep_lookup(self, lookup_type, value):
        if settings.DATABASE_ENGINE == 'oracle':
        if connection.features.time_field_needs_date:
            # Oracle requires a date in order to parse.
            def prep(value):
                if isinstance(value, datetime.time):
@@ -1098,9 +1098,9 @@ class TimeField(Field):
        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' and hasattr(value, 'microsecond'):
            if not connection.features.supports_usecs and hasattr(value, 'microsecond'):
                value = value.replace(microsecond=0)
            if settings.DATABASE_ENGINE == 'oracle':
            if connection.features.time_field_needs_date:
                # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.
                if isinstance(value, datetime.time):
                    value = datetime.datetime(1900, 1, 1, value.hour, value.minute,