Python django.db.migrations.RunSQL() Examples

The following are 15 code examples for showing how to use django.db.migrations.RunSQL(). These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.

You may check out the related API usage on the sidebar.

You may also want to check out all available functions/classes of the module django.db.migrations , or try the search function .

Example 1
Project: django-sqlserver   Author: denisenkom   File: test_multidb.py    License: MIT License 6 votes vote down vote up
def _test_run_sql(self, app_label, should_run, hints=None):
        with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
            project_state = self.set_up_test_model(app_label)

        sql = """
        INSERT INTO {0}_pony (pink, weight) VALUES (1, 3.55);
        INSERT INTO {0}_pony (pink, weight) VALUES (3, 5.0);
        """.format(app_label)

        operation = migrations.RunSQL(sql, hints=hints or {})
        # Test the state alteration does nothing
        new_state = project_state.clone()
        operation.state_forwards(app_label, new_state)
        self.assertEqual(new_state, project_state)
        # Test the database alteration
        self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
        with connection.schema_editor() as editor:
            operation.database_forwards(app_label, editor, project_state, new_state)
        Pony = project_state.apps.get_model(app_label, "Pony")
        if should_run:
            self.assertEqual(Pony.objects.count(), 2)
        else:
            self.assertEqual(Pony.objects.count(), 0) 
Example 2
Project: django-sqlserver   Author: denisenkom   File: test_operations.py    License: MIT License 6 votes vote down vote up
def test_run_sql_params_invalid(self):
        """
        #23426 - RunSQL should fail when a list of statements with an incorrect
        number of tuples is given.
        """
        project_state = self.set_up_test_model("test_runsql")
        new_state = project_state.clone()
        operation = migrations.RunSQL(
            # forwards
            [
                ["INSERT INTO foo (bar) VALUES ('buz');"]
            ],
            # backwards
            (
                ("DELETE FROM foo WHERE bar = 'buz';", 'invalid', 'parameter count'),
            ),
        )

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 1"):
                operation.database_forwards("test_runsql", editor, project_state, new_state)

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 3"):
                operation.database_backwards("test_runsql", editor, new_state, project_state) 
Example 3
Project: djongo   Author: nesdis   File: test_multidb.py    License: GNU Affero General Public License v3.0 6 votes vote down vote up
def _test_run_sql(self, app_label, should_run, hints=None):
        with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
            project_state = self.set_up_test_model(app_label)

        sql = """
        INSERT INTO {0}_pony (pink, weight) VALUES (1, 3.55);
        INSERT INTO {0}_pony (pink, weight) VALUES (3, 5.0);
        """.format(app_label)

        operation = migrations.RunSQL(sql, hints=hints or {})
        # Test the state alteration does nothing
        new_state = project_state.clone()
        operation.state_forwards(app_label, new_state)
        self.assertEqual(new_state, project_state)
        # Test the database alteration
        self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
        with connection.schema_editor() as editor:
            operation.database_forwards(app_label, editor, project_state, new_state)
        Pony = project_state.apps.get_model(app_label, "Pony")
        if should_run:
            self.assertEqual(Pony.objects.count(), 2)
        else:
            self.assertEqual(Pony.objects.count(), 0) 
Example 4
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 6 votes vote down vote up
def test_run_sql_params_invalid(self):
        """
        #23426 - RunSQL should fail when a list of statements with an incorrect
        number of tuples is given.
        """
        project_state = self.set_up_test_model("test_runsql")
        new_state = project_state.clone()
        operation = migrations.RunSQL(
            # forwards
            [
                ["INSERT INTO foo (bar) VALUES ('buz');"]
            ],
            # backwards
            (
                ("DELETE FROM foo WHERE bar = 'buz';", 'invalid', 'parameter count'),
            ),
        )

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 1"):
                operation.database_forwards("test_runsql", editor, project_state, new_state)

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 3"):
                operation.database_backwards("test_runsql", editor, new_state, project_state) 
Example 5
Project: djongo   Author: nesdis   File: test_multidb.py    License: GNU Affero General Public License v3.0 6 votes vote down vote up
def _test_run_sql(self, app_label, should_run, hints=None):
        with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
            project_state = self.set_up_test_model(app_label)

        sql = """
        INSERT INTO {0}_pony (pink, weight) VALUES (1, 3.55);
        INSERT INTO {0}_pony (pink, weight) VALUES (3, 5.0);
        """.format(app_label)

        operation = migrations.RunSQL(sql, hints=hints or {})
        # Test the state alteration does nothing
        new_state = project_state.clone()
        operation.state_forwards(app_label, new_state)
        self.assertEqual(new_state, project_state)
        # Test the database alteration
        self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
        with connection.schema_editor() as editor:
            operation.database_forwards(app_label, editor, project_state, new_state)
        Pony = project_state.apps.get_model(app_label, "Pony")
        if should_run:
            self.assertEqual(Pony.objects.count(), 2)
        else:
            self.assertEqual(Pony.objects.count(), 0) 
Example 6
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 6 votes vote down vote up
def test_run_sql_params_invalid(self):
        """
        #23426 - RunSQL should fail when a list of statements with an incorrect
        number of tuples is given.
        """
        project_state = self.set_up_test_model("test_runsql")
        new_state = project_state.clone()
        operation = migrations.RunSQL(
            # forwards
            [
                ["INSERT INTO foo (bar) VALUES ('buz');"]
            ],
            # backwards
            (
                ("DELETE FROM foo WHERE bar = 'buz';", 'invalid', 'parameter count'),
            ),
        )

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 1"):
                operation.database_forwards("test_runsql", editor, project_state, new_state)

        with connection.schema_editor() as editor:
            with self.assertRaisesMessage(ValueError, "Expected a 2-tuple but got 3"):
                operation.database_backwards("test_runsql", editor, new_state, project_state) 
Example 7
Project: django-sqlserver   Author: denisenkom   File: test_operations.py    License: MIT License 5 votes vote down vote up
def test_run_sql_noop(self):
        """
        #24098 - Tests no-op RunSQL operations.
        """
        operation = migrations.RunSQL(migrations.RunSQL.noop, migrations.RunSQL.noop)
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, None, None)
            operation.database_backwards("test_runsql", editor, None, None) 
Example 8
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 5 votes vote down vote up
def test_run_sql_noop(self):
        """
        #24098 - Tests no-op RunSQL operations.
        """
        operation = migrations.RunSQL(migrations.RunSQL.noop, migrations.RunSQL.noop)
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, None, None)
            operation.database_backwards("test_runsql", editor, None, None) 
Example 9
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 5 votes vote down vote up
def test_run_sql_noop(self):
        """
        #24098 - Tests no-op RunSQL operations.
        """
        operation = migrations.RunSQL(migrations.RunSQL.noop, migrations.RunSQL.noop)
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, None, None)
            operation.database_backwards("test_runsql", editor, None, None) 
Example 10
Project: django-sqlserver   Author: denisenkom   File: test_operations.py    License: MIT License 4 votes vote down vote up
def test_run_sql(self):
        """
        Tests the RunSQL operation.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            # 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 varchar(15));\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, '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",

            state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
        )
        self.assertEqual(operation.describe(), "Raw SQL operation")
        # Test the state alteration
        new_state = project_state.clone()
        operation.state_forwards("test_runsql", new_state)
        self.assertEqual(len(new_state.models["test_runsql", "somethingelse"].fields), 1)
        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        # Test SQL collection
        with connection.schema_editor(collect_sql=True) as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%ponies';", "\n".join(editor.collected_sql))
            operation.database_backwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%Ponies%%';", "\n".join(editor.collected_sql))
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
        self.assertTableExists("i_love_ponies")
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            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
        self.assertTrue(operation.reversible)
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies")
        # And deconstruction
        definition = operation.deconstruct()
        self.assertEqual(definition[0], "RunSQL")
        self.assertEqual(definition[1], [])
        self.assertEqual(sorted(definition[2]), ["reverse_sql", "sql", "state_operations"])
        # And elidable reduction
        self.assertIs(False, operation.reduce(operation, []))
        elidable_operation = migrations.RunSQL('SELECT 1 FROM void;', elidable=True)
        self.assertEqual(elidable_operation.reduce(operation, []), [operation]) 
Example 11
Project: django-sqlserver   Author: denisenkom   File: test_operations.py    License: MIT License 4 votes vote down vote up
def test_run_sql_params(self):
        """
        #23426 - RunSQL should accept parameters.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            ["CREATE TABLE i_love_ponies (id int, special_thing varchar(15));"],
            ["DROP TABLE i_love_ponies"],
        )
        param_operation = migrations.RunSQL(
            # forwards
            (
                "INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 'Django');",
                ["INSERT INTO i_love_ponies (id, special_thing) VALUES (2, %s);", ['Ponies']],
                ("INSERT INTO i_love_ponies (id, special_thing) VALUES (%s, %s);", (3, 'Python',)),
            ),
            # backwards
            [
                "DELETE FROM i_love_ponies WHERE special_thing = 'Django';",
                ["DELETE FROM i_love_ponies WHERE special_thing = 'Ponies';", None],
                ("DELETE FROM i_love_ponies WHERE id = %s OR special_thing = %s;", [3, 'Python']),
            ]
        )

        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        new_state = project_state.clone()
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)

        # Test parameter passing
        with connection.schema_editor() as editor:
            param_operation.database_forwards("test_runsql", editor, project_state, new_state)
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 3)

        with connection.schema_editor() as editor:
            param_operation.database_backwards("test_runsql", editor, new_state, project_state)
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 0)

        # And test reversal
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies") 
Example 12
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 4 votes vote down vote up
def test_run_sql(self):
        """
        Tests the RunSQL operation.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            # 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 varchar(15));\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, '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",

            state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
        )
        self.assertEqual(operation.describe(), "Raw SQL operation")
        # Test the state alteration
        new_state = project_state.clone()
        operation.state_forwards("test_runsql", new_state)
        self.assertEqual(len(new_state.models["test_runsql", "somethingelse"].fields), 1)
        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        # Test SQL collection
        with connection.schema_editor(collect_sql=True) as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%ponies';", "\n".join(editor.collected_sql))
            operation.database_backwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%Ponies%%';", "\n".join(editor.collected_sql))
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
        self.assertTableExists("i_love_ponies")
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            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
        self.assertTrue(operation.reversible)
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies")
        # And deconstruction
        definition = operation.deconstruct()
        self.assertEqual(definition[0], "RunSQL")
        self.assertEqual(definition[1], [])
        self.assertEqual(sorted(definition[2]), ["reverse_sql", "sql", "state_operations"])
        # And elidable reduction
        self.assertIs(False, operation.reduce(operation, []))
        elidable_operation = migrations.RunSQL('SELECT 1 FROM void;', elidable=True)
        self.assertEqual(elidable_operation.reduce(operation, []), [operation]) 
Example 13
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 4 votes vote down vote up
def test_run_sql_params(self):
        """
        #23426 - RunSQL should accept parameters.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            ["CREATE TABLE i_love_ponies (id int, special_thing varchar(15));"],
            ["DROP TABLE i_love_ponies"],
        )
        param_operation = migrations.RunSQL(
            # forwards
            (
                "INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 'Django');",
                ["INSERT INTO i_love_ponies (id, special_thing) VALUES (2, %s);", ['Ponies']],
                ("INSERT INTO i_love_ponies (id, special_thing) VALUES (%s, %s);", (3, 'Python',)),
            ),
            # backwards
            [
                "DELETE FROM i_love_ponies WHERE special_thing = 'Django';",
                ["DELETE FROM i_love_ponies WHERE special_thing = 'Ponies';", None],
                ("DELETE FROM i_love_ponies WHERE id = %s OR special_thing = %s;", [3, 'Python']),
            ]
        )

        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        new_state = project_state.clone()
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)

        # Test parameter passing
        with connection.schema_editor() as editor:
            param_operation.database_forwards("test_runsql", editor, project_state, new_state)
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 3)

        with connection.schema_editor() as editor:
            param_operation.database_backwards("test_runsql", editor, new_state, project_state)
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 0)

        # And test reversal
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies") 
Example 14
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 4 votes vote down vote up
def test_run_sql(self):
        """
        Tests the RunSQL operation.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            # 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 varchar(15));\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, '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",

            state_operations=[migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))])],
        )
        self.assertEqual(operation.describe(), "Raw SQL operation")
        # Test the state alteration
        new_state = project_state.clone()
        operation.state_forwards("test_runsql", new_state)
        self.assertEqual(len(new_state.models["test_runsql", "somethingelse"].fields), 1)
        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        # Test SQL collection
        with connection.schema_editor(collect_sql=True) as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%ponies';", "\n".join(editor.collected_sql))
            operation.database_backwards("test_runsql", editor, project_state, new_state)
            self.assertIn("LIKE '%%Ponies%%';", "\n".join(editor.collected_sql))
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)
        self.assertTableExists("i_love_ponies")
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            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
        self.assertTrue(operation.reversible)
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies")
        # And deconstruction
        definition = operation.deconstruct()
        self.assertEqual(definition[0], "RunSQL")
        self.assertEqual(definition[1], [])
        self.assertEqual(sorted(definition[2]), ["reverse_sql", "sql", "state_operations"])
        # And elidable reduction
        self.assertIs(False, operation.reduce(operation, []))
        elidable_operation = migrations.RunSQL('SELECT 1 FROM void;', elidable=True)
        self.assertEqual(elidable_operation.reduce(operation, []), [operation]) 
Example 15
Project: djongo   Author: nesdis   File: test_operations.py    License: GNU Affero General Public License v3.0 4 votes vote down vote up
def test_run_sql_params(self):
        """
        #23426 - RunSQL should accept parameters.
        """
        project_state = self.set_up_test_model("test_runsql")
        # Create the operation
        operation = migrations.RunSQL(
            ["CREATE TABLE i_love_ponies (id int, special_thing varchar(15));"],
            ["DROP TABLE i_love_ponies"],
        )
        param_operation = migrations.RunSQL(
            # forwards
            (
                "INSERT INTO i_love_ponies (id, special_thing) VALUES (1, 'Django');",
                ["INSERT INTO i_love_ponies (id, special_thing) VALUES (2, %s);", ['Ponies']],
                ("INSERT INTO i_love_ponies (id, special_thing) VALUES (%s, %s);", (3, 'Python',)),
            ),
            # backwards
            [
                "DELETE FROM i_love_ponies WHERE special_thing = 'Django';",
                ["DELETE FROM i_love_ponies WHERE special_thing = 'Ponies';", None],
                ("DELETE FROM i_love_ponies WHERE id = %s OR special_thing = %s;", [3, 'Python']),
            ]
        )

        # Make sure there's no table
        self.assertTableNotExists("i_love_ponies")
        new_state = project_state.clone()
        # Test the database alteration
        with connection.schema_editor() as editor:
            operation.database_forwards("test_runsql", editor, project_state, new_state)

        # Test parameter passing
        with connection.schema_editor() as editor:
            param_operation.database_forwards("test_runsql", editor, project_state, new_state)
        # Make sure all the SQL was processed
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 3)

        with connection.schema_editor() as editor:
            param_operation.database_backwards("test_runsql", editor, new_state, project_state)
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM i_love_ponies")
            self.assertEqual(cursor.fetchall()[0][0], 0)

        # And test reversal
        with connection.schema_editor() as editor:
            operation.database_backwards("test_runsql", editor, new_state, project_state)
        self.assertTableNotExists("i_love_ponies")