From 495abe00951ceb9787d7f36590f71aa14c973d3d Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 19 Sep 2018 15:27:40 -0400 Subject: [PATCH] Refs #29198 -- Fixed migrate --plan crash if RunSQL uses a list or tuple. Also fixed test failures if sqlparse isn't installed. --- django/core/management/commands/migrate.py | 2 +- tests/migrations/test_commands.py | 42 +++++++++++-------- .../test_migrations_plan/0002_second.py | 2 +- .../test_migrations_plan/0003_third.py | 2 +- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py index 68aa52bb4a..f28816fcee 100644 --- a/django/core/management/commands/migrate.py +++ b/django/core/management/commands/migrate.py @@ -344,7 +344,7 @@ class Command(BaseCommand): action = 'IRREVERSIBLE' is_error = True else: - action = action.replace('\n', '') + action = str(action).replace('\n', '') is_error = False if action: action = ' -> ' + action diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index aee89ed912..268e180697 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -20,6 +20,11 @@ from .models import UnicodeModel, UnserializableModel from .routers import TestRouter from .test_base import MigrationTestBase +try: + import sqlparse +except ImportError: + sqlparse = None + class MigrateTests(MigrationTestBase): """ @@ -311,10 +316,10 @@ class MigrateTests(MigrationTestBase): ' Raw Python operation -> Grow salamander tail.\n' 'migrations.0002_second\n' ' Create model Book\n' - ' Raw SQL operation -> SELECT * FROM migrations_book\n' + " Raw SQL operation -> ['SELECT * FROM migrations_book']\n" 'migrations.0003_third\n' ' Create model Author\n' - ' Raw SQL operation -> SELECT * FROM migrations_author\n', + " Raw SQL operation -> ['SELECT * FROM migrations_author']\n", out.getvalue() ) # Migrate to the third migration. @@ -334,10 +339,10 @@ class MigrateTests(MigrationTestBase): 'Planned operations:\n' 'migrations.0003_third\n' ' Undo Create model Author\n' - ' Raw SQL operation -> SELECT * FROM migrations_book\n' + " Raw SQL operation -> ['SELECT * FROM migrations_book']\n" 'migrations.0002_second\n' ' Undo Create model Book\n' - ' Raw SQL operation -> SELECT * FROM migrations_salamander\n', + " Raw SQL operation -> ['SELECT * FROM migrations_salamand…\n", out.getvalue() ) out = io.StringIO() @@ -349,20 +354,23 @@ class MigrateTests(MigrationTestBase): ' Raw SQL operation -> SELECT * FROM migrations_author WHE…\n', out.getvalue() ) - # Migrate to the fourth migration. - call_command('migrate', 'migrations', '0004', verbosity=0) - out = io.StringIO() # Show the plan when an operation is irreversible. - call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True) - self.assertEqual( - 'Planned operations:\n' - 'migrations.0004_fourth\n' - ' Raw SQL operation -> IRREVERSIBLE\n', - out.getvalue() - ) - # Cleanup by unmigrating everything: fake the irreversible, then - # migrate all to zero. - call_command('migrate', 'migrations', '0003', fake=True, verbosity=0) + # Migration 0004's RunSQL uses a SQL string instead of a list, so + # sqlparse may be required for splitting. + if sqlparse or not connection.features.requires_sqlparse_for_splitting: + # Migrate to the fourth migration. + call_command('migrate', 'migrations', '0004', verbosity=0) + out = io.StringIO() + call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True) + self.assertEqual( + 'Planned operations:\n' + 'migrations.0004_fourth\n' + ' Raw SQL operation -> IRREVERSIBLE\n', + out.getvalue() + ) + # Cleanup by unmigrating everything: fake the irreversible, then + # migrate all to zero. + call_command('migrate', 'migrations', '0003', fake=True, verbosity=0) call_command('migrate', 'migrations', 'zero', verbosity=0) @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_empty"}) diff --git a/tests/migrations/test_migrations_plan/0002_second.py b/tests/migrations/test_migrations_plan/0002_second.py index e8aeec880b..2fc9ea6933 100644 --- a/tests/migrations/test_migrations_plan/0002_second.py +++ b/tests/migrations/test_migrations_plan/0002_second.py @@ -15,6 +15,6 @@ class Migration(migrations.Migration): ('id', models.AutoField(primary_key=True)), ], ), - migrations.RunSQL('SELECT * FROM migrations_book', 'SELECT * FROM migrations_salamander') + migrations.RunSQL(['SELECT * FROM migrations_book'], ['SELECT * FROM migrations_salamander']) ] diff --git a/tests/migrations/test_migrations_plan/0003_third.py b/tests/migrations/test_migrations_plan/0003_third.py index d045a91448..6d17e217ec 100644 --- a/tests/migrations/test_migrations_plan/0003_third.py +++ b/tests/migrations/test_migrations_plan/0003_third.py @@ -15,5 +15,5 @@ class Migration(migrations.Migration): ('id', models.AutoField(primary_key=True)), ], ), - migrations.RunSQL('SELECT * FROM migrations_author', 'SELECT * FROM migrations_book') + migrations.RunSQL(['SELECT * FROM migrations_author'], ['SELECT * FROM migrations_book']) ]