diff --git a/alembic/runtime/migration.py b/alembic/runtime/migration.py index 3fccf22a..31e03d0c 100644 --- a/alembic/runtime/migration.py +++ b/alembic/runtime/migration.py @@ -639,9 +639,11 @@ def run_migrations(self, **kw: Any) -> None: run_args=kw, ) - if self.as_sql and not head_maintainer.heads: - assert self.connection is not None - self._version.drop(self.connection) + # NOTE: offline ("--sql") mode intentionally does not emit a DROP + # of the version table when ending at base. Online mode never drops + # the version table (e.g. ``downgrade base`` only deletes its rows), + # so dropping it in offline mode only was an inconsistency present + # since the version table was first introduced. See #1822. def _in_connection_transaction(self) -> bool: try: diff --git a/docs/build/unreleased/1822.rst b/docs/build/unreleased/1822.rst new file mode 100644 index 00000000..f0f598b0 --- /dev/null +++ b/docs/build/unreleased/1822.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, commands + :tickets: 1822 + + Fixed inconsistency where running ``stamp`` or ``downgrade`` to ``base`` + in offline (``--sql``) mode would emit a ``DROP TABLE alembic_version`` + statement, while the same operations in online mode never drop the version + table. Offline mode no longer emits this ``DROP``, matching online + behavior. The version table continues to be created when it does not + exist; only the spurious offline-only drop has been removed. diff --git a/tests/test_command.py b/tests/test_command.py index 391a19d0..96427b5c 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -988,7 +988,7 @@ def test_version_to_none(self): command.downgrade(self.cfg, "%s:base" % self.c, sql=True) assert "CREATE TABLE alembic_version" not in buf.getvalue() assert "INSERT INTO alembic_version" not in buf.getvalue() - assert "DROP TABLE alembic_version" in buf.getvalue() + assert "DROP TABLE alembic_version" not in buf.getvalue() assert "DROP STEP 3" in buf.getvalue() assert "DROP STEP 2" in buf.getvalue() assert "DROP STEP 1" in buf.getvalue() @@ -1047,6 +1047,13 @@ def test_sql_stamp_revision_as_kw(self): in buf.getvalue() ) + def test_sql_stamp_to_base_no_drop(self): + # stamping to "base" in offline mode must not emit a DROP of the + # version table; online mode never drops it. See #1822. + with capture_context_buffer() as buf: + command.stamp(self.cfg, "base", sql=True) + assert "DROP TABLE alembic_version" not in buf.getvalue() + def test_stamp_argparser_single_rev(self): cmd = config.CommandLine() options = cmd.parser.parse_args(["stamp", self.c, "--sql"])