summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-08-23 12:07:55 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-08-23 12:07:55 +0100
commit9cc6cfc4057e07b73a1d72a1177d568362b0c517 (patch)
treeaf7e7cda1256f590a48a36f8fe37b5bef612e16c
parentac45f9c9c5b5f64556c95d458368185298d21042 (diff)
Fix Oracle's default handling and schema-prepared-statement issue
-rw-r--r--django/db/backends/__init__.py6
-rw-r--r--django/db/backends/oracle/base.py2
-rw-r--r--django/db/backends/oracle/schema.py12
-rw-r--r--django/db/backends/schema.py51
4 files changed, 62 insertions, 9 deletions
diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index 8d3c09ab1a..6274d5bc55 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -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
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index e6435a9e96..a363c09001 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -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):
diff --git a/django/db/backends/oracle/schema.py b/django/db/backends/oracle/schema.py
index c78294cad5..18d67b254f 100644
--- a/django/db/backends/oracle/schema.py
+++ b/django/db/backends/oracle/schema.py
@@ -1,4 +1,6 @@
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)
diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py
index 7beae7417a..64098499f6 100644
--- a/django/db/backends/schema.py
+++ b/django/db/backends/schema.py
@@ -116,8 +116,14 @@ 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:
- sql += " DEFAULT %s"
- params += [default_value]
+ 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
# option whenever '' is a possible value.
if (field.empty_strings_allowed and not field.primary_key and
@@ -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):
"""
@@ -523,13 +541,25 @@ class BaseDatabaseSchemaEditor(object):
[],
))
else:
- actions.append((
- self.sql_alter_column_default % {
- "column": self.quote_name(new_field.column),
- "default": "%s",
- },
- [new_default],
- ))
+ 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 % {
+ "column": self.quote_name(new_field.column),
+ "default": "%s",
+ },
+ [new_default],
+ ))
# Nullability change?
if old_field.null != new_field.null:
if new_field.null:
@@ -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):
"""