Commit 9cc6cfc4 authored by Andrew Godwin's avatar Andrew Godwin
Browse files

Fix Oracle's default handling and schema-prepared-statement issue

parent ac45f9c9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -654,6 +654,12 @@ class BaseDatabaseFeatures(object):
    # supported by the Python driver
    supports_paramstyle_pyformat = True

    # Does the backend require literal defaults, rather than parameterised ones?
    requires_literal_defaults = False

    # Does the backend require a connection reset after each material schema change?
    connection_persists_old_columns = False

    def __init__(self, connection):
        self.connection = connection

+2 −0
Original line number Diff line number Diff line
@@ -94,6 +94,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    supports_combined_alters = False
    max_index_name_length = 30
    nulls_order_largest = True
    requires_literal_defaults = True
    connection_persists_old_columns = True


class DatabaseOperations(BaseDatabaseOperations):
+12 −0
Original line number Diff line number Diff line
import copy
import datetime
from django.utils import six
from django.db.backends.schema import BaseDatabaseSchemaEditor
from django.db.utils import DatabaseError

@@ -89,3 +91,13 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
        """
        suffix = hex(hash(for_name)).upper()[1:]
        return self.normalize_name(for_name + "_" + suffix)

    def prepare_default(self, value):
        if isinstance(value, (datetime.date, datetime.time, datetime.datetime)):
            return "'%s'" % value
        elif isinstance(value, six.string_types):
            return repr(value)
        elif isinstance(value, bool):
            return "1" if value else "0"
        else:
            return str(value)
+42 −9
Original line number Diff line number Diff line
@@ -116,6 +116,12 @@ class BaseDatabaseSchemaEditor(object):
        # If we were told to include a default value, do so
        default_value = self.effective_default(field)
        if include_default and default_value is not None:
            if self.connection.features.requires_literal_defaults:
                # Some databases can't take defaults as a parameter (oracle)
                # If this is the case, the individual schema backend should
                # implement prepare_default
                sql += " DEFAULT %s" % self.prepare_default(default_value)
            else:
                sql += " DEFAULT %s"
                params += [default_value]
        # Oracle treats the empty string ('') as null, so coerce the null
@@ -135,6 +141,12 @@ class BaseDatabaseSchemaEditor(object):
        # Return the sql
        return sql, params

    def prepare_default(self, value):
        """
        Only used for backends which have requires_literal_defaults feature
        """
        raise NotImplementedError()

    def effective_default(self, field):
        """
        Returns a field's effective database default value
@@ -385,6 +397,9 @@ class BaseDatabaseSchemaEditor(object):
                    "to_column": self.quote_name(to_column),
                }
            )
        # Reset connection if required
        if self.connection.features.connection_persists_old_columns:
            self.connection.close()

    def remove_field(self, model, field):
        """
@@ -405,6 +420,9 @@ class BaseDatabaseSchemaEditor(object):
            "column": self.quote_name(field.column),
        }
        self.execute(sql)
        # Reset connection if required
        if self.connection.features.connection_persists_old_columns:
            self.connection.close()

    def alter_field(self, model, old_field, new_field, strict=False):
        """
@@ -522,6 +540,18 @@ class BaseDatabaseSchemaEditor(object):
                    },
                    [],
                ))
            else:
                if self.connection.features.requires_literal_defaults:
                    # Some databases can't take defaults as a parameter (oracle)
                    # If this is the case, the individual schema backend should
                    # implement prepare_default
                    actions.append((
                        self.sql_alter_column_default % {
                            "column": self.quote_name(new_field.column),
                            "default": self.prepare_default(new_default),
                        },
                        [],
                    ))
                else:
                    actions.append((
                        self.sql_alter_column_default % {
@@ -628,6 +658,9 @@ class BaseDatabaseSchemaEditor(object):
                    "check": new_db_params['check'],
                }
            )
        # Reset connection if required
        if self.connection.features.connection_persists_old_columns:
            self.connection.close()

    def _alter_many_to_many(self, model, old_field, new_field, strict):
        """