mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #21844: Move quote_parameter off of Operations and rename
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user