[1.7.x] Fixed #23426 -- Don't require double percent sign in RunSQL without parameters
Backport of b9a670b227
from master
This commit is contained in:
parent
cc74d8e02e
commit
ae14c75014
|
@ -66,14 +66,14 @@ class RunSQL(Operation):
|
||||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
statements = schema_editor.connection.ops.prepare_sql_script(self.sql)
|
statements = schema_editor.connection.ops.prepare_sql_script(self.sql)
|
||||||
for statement in statements:
|
for statement in statements:
|
||||||
schema_editor.execute(statement)
|
schema_editor.execute(statement, params=None)
|
||||||
|
|
||||||
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
if self.reverse_sql is None:
|
if self.reverse_sql is None:
|
||||||
raise NotImplementedError("You cannot reverse this operation")
|
raise NotImplementedError("You cannot reverse this operation")
|
||||||
statements = schema_editor.connection.ops.prepare_sql_script(self.reverse_sql)
|
statements = schema_editor.connection.ops.prepare_sql_script(self.reverse_sql)
|
||||||
for statement in statements:
|
for statement in statements:
|
||||||
schema_editor.execute(statement)
|
schema_editor.execute(statement, params=None)
|
||||||
|
|
||||||
def describe(self):
|
def describe(self):
|
||||||
return "Raw SQL operation"
|
return "Raw SQL operation"
|
||||||
|
|
|
@ -192,6 +192,11 @@ operation here so that the autodetector still has an up-to-date state of the
|
||||||
model (otherwise, when you next run ``makemigrations``, it won't see any
|
model (otherwise, when you next run ``makemigrations``, it won't see any
|
||||||
operation that adds that field and so will try to run it again).
|
operation that adds that field and so will try to run it again).
|
||||||
|
|
||||||
|
.. versionchanged:: 1.7.1
|
||||||
|
|
||||||
|
If you want to include literal percent signs in the query you don't need to
|
||||||
|
double them anymore.
|
||||||
|
|
||||||
.. _sqlparse: https://pypi.python.org/pypi/sqlparse
|
.. _sqlparse: https://pypi.python.org/pypi/sqlparse
|
||||||
|
|
||||||
RunPython
|
RunPython
|
||||||
|
|
|
@ -67,3 +67,6 @@ Bugfixes
|
||||||
:meth:`~django.contrib.admin.InlineModelAdmin.get_min_num()` hooks to
|
:meth:`~django.contrib.admin.InlineModelAdmin.get_min_num()` hooks to
|
||||||
:class:`~django.contrib.contenttypes.admin.GenericInlineModelAdmin`
|
:class:`~django.contrib.contenttypes.admin.GenericInlineModelAdmin`
|
||||||
(:ticket:`23539`).
|
(:ticket:`23539`).
|
||||||
|
|
||||||
|
* Made ``migrations.RunSQL`` no longer require percent sign escaping. This is
|
||||||
|
now consistent with ``cursor.execute()`` (:ticket:`23426`).
|
||||||
|
|
|
@ -1156,10 +1156,18 @@ class OperationTests(OperationTestBase):
|
||||||
# Create the operation
|
# Create the operation
|
||||||
operation = migrations.RunSQL(
|
operation = migrations.RunSQL(
|
||||||
# Use a multi-line string with a comment to test splitting on SQLite and MySQL respectively
|
# Use a multi-line string with a comment to test splitting on SQLite and MySQL respectively
|
||||||
"CREATE TABLE i_love_ponies (id int, special_thing int);\n"
|
"CREATE TABLE i_love_ponies (id int, special_thing varchar(15));\n"
|
||||||
"INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 42); -- this is magic!\n"
|
"INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 'i love ponies'); -- this is magic!\n"
|
||||||
"INSERT INTO i_love_ponies (id, special_thing) VALUES (2, 51);\n",
|
"INSERT INTO i_love_ponies (id, special_thing) VALUES (2, 'i love django');\n"
|
||||||
|
"UPDATE i_love_ponies SET special_thing = 'Ponies' WHERE special_thing LIKE '%%ponies';"
|
||||||
|
"UPDATE i_love_ponies SET special_thing = 'Django' WHERE special_thing LIKE '%django';",
|
||||||
|
|
||||||
|
# Run delete queries to test for parameter substitution failure
|
||||||
|
# reported in #23426
|
||||||
|
"DELETE FROM i_love_ponies WHERE special_thing LIKE '%Django%';"
|
||||||
|
"DELETE FROM i_love_ponies WHERE special_thing LIKE '%%Ponies%%';"
|
||||||
"DROP TABLE i_love_ponies",
|
"DROP TABLE i_love_ponies",
|
||||||
|
|
||||||
state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
|
state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
|
||||||
)
|
)
|
||||||
self.assertEqual(operation.describe(), "Raw SQL operation")
|
self.assertEqual(operation.describe(), "Raw SQL operation")
|
||||||
|
@ -1177,6 +1185,10 @@ class OperationTests(OperationTestBase):
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
|
cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
|
||||||
self.assertEqual(cursor.fetchall()[0][0], 2)
|
self.assertEqual(cursor.fetchall()[0][0], 2)
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Django'")
|
||||||
|
self.assertEqual(cursor.fetchall()[0][0], 1)
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM i_love_ponies WHERE special_thing = 'Ponies'")
|
||||||
|
self.assertEqual(cursor.fetchall()[0][0], 1)
|
||||||
# And test reversal
|
# And test reversal
|
||||||
self.assertTrue(operation.reversible)
|
self.assertTrue(operation.reversible)
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
|
|
Loading…
Reference in New Issue