summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-02-09 12:41:55 +0000
committerAndrew Godwin <andrew@aeracode.org>2014-02-09 12:42:26 +0000
commit42607a9e33e63639d1da2166b9a2f85c691e07ae (patch)
tree29ef996e81955c8973023ef74ddc3054b70ce5f4
parent5cc0555603167c7532b7b714e2672687da8f106e (diff)
Fixed #21844: Move quote_parameter off of Operations and rename
-rw-r--r--django/db/backends/__init__.py9
-rw-r--r--django/db/backends/mysql/base.py5
-rw-r--r--django/db/backends/mysql/schema.py5
-rw-r--r--django/db/backends/oracle/base.py10
-rw-r--r--django/db/backends/oracle/schema.py14
-rw-r--r--django/db/backends/postgresql_psycopg2/operations.py5
-rw-r--r--django/db/backends/postgresql_psycopg2/schema.py5
-rw-r--r--django/db/backends/schema.py12
-rw-r--r--django/db/backends/sqlite3/base.py19
-rw-r--r--django/db/backends/sqlite3/schema.py22
10 files changed, 55 insertions, 51 deletions
diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index c0a82460cf..48f448b58f 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -975,15 +975,6 @@ class BaseDatabaseOperations(object):
"""
raise NotImplementedError('subclasses of BaseDatabaseOperations may require a quote_name() method')
- def quote_parameter(self, value):
- """
- Returns a quoted version of the value so it's safe to use in an SQL
- string. This should NOT be used to prepare SQL statements to send to
- the database; it is meant for outputting SQL statements to a file
- or the console for later execution by a developer/DBA.
- """
- raise NotImplementedError()
-
def random_function_sql(self):
"""
Returns an SQL expression that returns a random value.
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index d35d7a3888..e79f980e21 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -311,11 +311,6 @@ class DatabaseOperations(BaseDatabaseOperations):
return name # Quoting once is enough.
return "`%s`" % name
- def quote_parameter(self, value):
- # Inner import to allow module to fail to load gracefully
- import MySQLdb.converters
- return MySQLdb.escape(value, MySQLdb.converters.conversions)
-
def random_function_sql(self):
return 'RAND()'
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
index dc74b2db2a..3d544f14cc 100644
--- a/django/db/backends/mysql/schema.py
+++ b/django/db/backends/mysql/schema.py
@@ -24,3 +24,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_create_pk = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)"
sql_delete_pk = "ALTER TABLE %(table)s DROP PRIMARY KEY"
+
+ def quote_value(self, value):
+ # Inner import to allow module to fail to load gracefully
+ import MySQLdb.converters
+ return MySQLdb.escape(value, MySQLdb.converters.conversions)
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index b86cc03446..f549663497 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -326,16 +326,6 @@ WHEN (new.%(col_name)s IS NULL)
name = name.replace('%', '%%')
return name.upper()
- def quote_parameter(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)
-
def random_function_sql(self):
return "DBMS_RANDOM.RANDOM"
diff --git a/django/db/backends/oracle/schema.py b/django/db/backends/oracle/schema.py
index 1733fc0690..447c0a231f 100644
--- a/django/db/backends/oracle/schema.py
+++ b/django/db/backends/oracle/schema.py
@@ -1,5 +1,7 @@
import copy
+import datetime
+from django.utils import six
from django.db.backends.schema import BaseDatabaseSchemaEditor
from django.db.utils import DatabaseError
@@ -15,6 +17,16 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s"
sql_delete_table = "DROP TABLE %(table)s CASCADE CONSTRAINTS"
+ def quote_value(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)
+
def delete_model(self, model):
# Run superclass action
super(DatabaseSchemaEditor, self).delete_model(model)
@@ -92,4 +104,4 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
return self.normalize_name(for_name + "_" + suffix)
def prepare_default(self, value):
- return self.connection.ops.quote_parameter(value)
+ return self.quote_value(value)
diff --git a/django/db/backends/postgresql_psycopg2/operations.py b/django/db/backends/postgresql_psycopg2/operations.py
index b9496868b0..9285e6eeca 100644
--- a/django/db/backends/postgresql_psycopg2/operations.py
+++ b/django/db/backends/postgresql_psycopg2/operations.py
@@ -98,11 +98,6 @@ class DatabaseOperations(BaseDatabaseOperations):
return name # Quoting once is enough.
return '"%s"' % name
- def quote_parameter(self, value):
- # Inner import so backend fails nicely if it's not present
- import psycopg2
- return psycopg2.extensions.adapt(value)
-
def set_time_zone_sql(self):
return "SET TIME ZONE %s"
diff --git a/django/db/backends/postgresql_psycopg2/schema.py b/django/db/backends/postgresql_psycopg2/schema.py
index 946f39d586..ceb446c13a 100644
--- a/django/db/backends/postgresql_psycopg2/schema.py
+++ b/django/db/backends/postgresql_psycopg2/schema.py
@@ -7,6 +7,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
+ def quote_value(self, value):
+ # Inner import so backend fails nicely if it's not present
+ import psycopg2
+ return psycopg2.extensions.adapt(value)
+
def _alter_column_type_sql(self, table, column, type):
"""
Makes ALTER TYPE with SERIAL make sense.
diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py
index 4a3d7fe46c..638ae08436 100644
--- a/django/db/backends/schema.py
+++ b/django/db/backends/schema.py
@@ -89,7 +89,7 @@ class BaseDatabaseSchemaEditor(object):
# Log the command we're running, then run it
logger.debug("%s; (params %r)" % (sql, params))
if self.collect_sql:
- self.collected_sql.append((sql % tuple(map(self.connection.ops.quote_parameter, params))) + ";")
+ self.collected_sql.append((sql % tuple(map(self.quote_value, params))) + ";")
else:
with self.connection.cursor() as cursor:
cursor.execute(sql, params)
@@ -166,6 +166,16 @@ class BaseDatabaseSchemaEditor(object):
default = default()
return default
+ def quote_value(self, value):
+ """
+ Returns a quoted version of the value so it's safe to use in an SQL
+ string. This is not safe against injection from user code; it is
+ intended only for use in making SQL scripts or preparing default values
+ for particularly tricky backends (defaults are not user-defined, though,
+ so this is safe).
+ """
+ raise NotImplementedError()
+
# Actions
def create_model(self, model):
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 2adfbacaa9..3bb85e042d 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -215,25 +215,6 @@ class DatabaseOperations(BaseDatabaseOperations):
return name # Quoting once is enough.
return '"%s"' % name
- def quote_parameter(self, value):
- # Inner import to allow nice failure for backend if not present
- import _sqlite3
- try:
- value = _sqlite3.adapt(value)
- except _sqlite3.ProgrammingError:
- pass
- # Manual emulation of SQLite parameter quoting
- if isinstance(value, type(True)):
- return str(int(value))
- elif isinstance(value, six.integer_types):
- return str(value)
- elif isinstance(value, six.string_types):
- return '"%s"' % six.text_type(value)
- elif value is None:
- return "NULL"
- else:
- raise ValueError("Cannot quote parameter value %r" % value)
-
def no_limit_value(self):
return -1
diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py
index b6680e730d..279ac4b203 100644
--- a/django/db/backends/sqlite3/schema.py
+++ b/django/db/backends/sqlite3/schema.py
@@ -1,3 +1,4 @@
+from django.utils import six
from django.apps.registry import Apps
from django.db.backends.schema import BaseDatabaseSchemaEditor
from django.db.models.fields.related import ManyToManyField
@@ -8,6 +9,25 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_delete_table = "DROP TABLE %(table)s"
sql_create_inline_fk = "REFERENCES %(to_table)s (%(to_column)s)"
+ def quote_value(self, value):
+ # Inner import to allow nice failure for backend if not present
+ import _sqlite3
+ try:
+ value = _sqlite3.adapt(value)
+ except _sqlite3.ProgrammingError:
+ pass
+ # Manual emulation of SQLite parameter quoting
+ if isinstance(value, type(True)):
+ return str(int(value))
+ elif isinstance(value, six.integer_types):
+ return str(value)
+ elif isinstance(value, six.string_types):
+ return '"%s"' % six.text_type(value)
+ elif value is None:
+ return "NULL"
+ else:
+ raise ValueError("Cannot quote parameter value %r" % value)
+
def _remake_table(self, model, create_fields=[], delete_fields=[], alter_fields=[], rename_fields=[], override_uniques=None):
"""
Shortcut to transform a model from old_model into new_model
@@ -31,7 +51,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
body[field.name] = field
# If there's a default, insert it into the copy map
if field.has_default():
- mapping[field.column] = self.connection.ops.quote_parameter(
+ mapping[field.column] = self.quote_value(
field.get_default()
)
# Add in any altered fields