mirror of https://github.com/django/django.git
Fixed #21844: Move quote_parameter off of Operations and rename
This commit is contained in:
parent
5cc0555603
commit
42607a9e33
|
@ -975,15 +975,6 @@ class BaseDatabaseOperations(object):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('subclasses of BaseDatabaseOperations may require a quote_name() method')
|
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):
|
def random_function_sql(self):
|
||||||
"""
|
"""
|
||||||
Returns an SQL expression that returns a random value.
|
Returns an SQL expression that returns a random value.
|
||||||
|
|
|
@ -311,11 +311,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
return name # Quoting once is enough.
|
return name # Quoting once is enough.
|
||||||
return "`%s`" % name
|
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):
|
def random_function_sql(self):
|
||||||
return 'RAND()'
|
return 'RAND()'
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
|
|
||||||
sql_create_pk = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)"
|
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"
|
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)
|
||||||
|
|
|
@ -326,16 +326,6 @@ WHEN (new.%(col_name)s IS NULL)
|
||||||
name = name.replace('%', '%%')
|
name = name.replace('%', '%%')
|
||||||
return name.upper()
|
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):
|
def random_function_sql(self):
|
||||||
return "DBMS_RANDOM.RANDOM"
|
return "DBMS_RANDOM.RANDOM"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import copy
|
import copy
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from django.utils import six
|
||||||
from django.db.backends.schema import BaseDatabaseSchemaEditor
|
from django.db.backends.schema import BaseDatabaseSchemaEditor
|
||||||
from django.db.utils import DatabaseError
|
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_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s"
|
||||||
sql_delete_table = "DROP TABLE %(table)s CASCADE CONSTRAINTS"
|
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):
|
def delete_model(self, model):
|
||||||
# Run superclass action
|
# Run superclass action
|
||||||
super(DatabaseSchemaEditor, self).delete_model(model)
|
super(DatabaseSchemaEditor, self).delete_model(model)
|
||||||
|
@ -92,4 +104,4 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
return self.normalize_name(for_name + "_" + suffix)
|
return self.normalize_name(for_name + "_" + suffix)
|
||||||
|
|
||||||
def prepare_default(self, value):
|
def prepare_default(self, value):
|
||||||
return self.connection.ops.quote_parameter(value)
|
return self.quote_value(value)
|
||||||
|
|
|
@ -98,11 +98,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
return name # Quoting once is enough.
|
return name # Quoting once is enough.
|
||||||
return '"%s"' % name
|
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):
|
def set_time_zone_sql(self):
|
||||||
return "SET TIME ZONE %s"
|
return "SET TIME ZONE %s"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,11 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
||||||
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
|
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):
|
def _alter_column_type_sql(self, table, column, type):
|
||||||
"""
|
"""
|
||||||
Makes ALTER TYPE with SERIAL make sense.
|
Makes ALTER TYPE with SERIAL make sense.
|
||||||
|
|
|
@ -89,7 +89,7 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
# Log the command we're running, then run it
|
# Log the command we're running, then run it
|
||||||
logger.debug("%s; (params %r)" % (sql, params))
|
logger.debug("%s; (params %r)" % (sql, params))
|
||||||
if self.collect_sql:
|
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:
|
else:
|
||||||
with self.connection.cursor() as cursor:
|
with self.connection.cursor() as cursor:
|
||||||
cursor.execute(sql, params)
|
cursor.execute(sql, params)
|
||||||
|
@ -166,6 +166,16 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
default = default()
|
default = default()
|
||||||
return 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
|
# Actions
|
||||||
|
|
||||||
def create_model(self, model):
|
def create_model(self, model):
|
||||||
|
|
|
@ -215,25 +215,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
return name # Quoting once is enough.
|
return name # Quoting once is enough.
|
||||||
return '"%s"' % name
|
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):
|
def no_limit_value(self):
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.utils import six
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
from django.db.backends.schema import BaseDatabaseSchemaEditor
|
from django.db.backends.schema import BaseDatabaseSchemaEditor
|
||||||
from django.db.models.fields.related import ManyToManyField
|
from django.db.models.fields.related import ManyToManyField
|
||||||
|
@ -8,6 +9,25 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
sql_delete_table = "DROP TABLE %(table)s"
|
sql_delete_table = "DROP TABLE %(table)s"
|
||||||
sql_create_inline_fk = "REFERENCES %(to_table)s (%(to_column)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):
|
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
|
Shortcut to transform a model from old_model into new_model
|
||||||
|
@ -31,7 +51,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
body[field.name] = field
|
body[field.name] = field
|
||||||
# If there's a default, insert it into the copy map
|
# If there's a default, insert it into the copy map
|
||||||
if field.has_default():
|
if field.has_default():
|
||||||
mapping[field.column] = self.connection.ops.quote_parameter(
|
mapping[field.column] = self.quote_value(
|
||||||
field.get_default()
|
field.get_default()
|
||||||
)
|
)
|
||||||
# Add in any altered fields
|
# Add in any altered fields
|
||||||
|
|
Loading…
Reference in New Issue