agdsn/pycroft

Autogenerate migrations for views

Opened this issue · 0 comments

We should extend alembic so that it understands views, triggers, and functions in its autogenerate and check commands.

Here is a rough WIP dump from the alembic_wrapper snippet regarding a starting point:

def diff(obj: ContextObject):
    # https://alembic.sqlalchemy.org/en/latest/api/autogenerate.html#getting-diffs
    config = obj.alembic_cfg
    migration_context = MigrationContext.configure(obj.conn)

    from rich import print
    from pycroft.model._all import User

    metadata = User.metadata
    from alembic.autogenerate.compare import comparators
    from alembic.autogenerate.api import AutogenContext
    from alembic.operations.ops import UpgradeOps

    @comparators.dispatch_for("schema")
    def _autogen_for_views(
        autogen_context: AutogenContext,
        upgrade_ops: UpgradeOps,
        schemas: set[None] | set[str | None],
    ) -> None:
        # the context.metadata is the VCS "source of truth".
        # the `MigrationContext` is what's actually in the DB.
        metadata = autogen_context.metadata
        migration_ctx = autogen_context.migration_context

        # TODO reflect `View`s from metadata and migration_ctx:
        # first, gather views
        # then, dispatch views as the alembic functions do, to call sth registered as `dispatch_for("view")`
        # select *, pg_catalog.pg_get_function_sqlbody(oid)
        # from pg_catalog.pg_proc
        # where proname='user_ensure_tombstone' \gx

        # print(f"[bold red]{schemas=!r}[/]")
        # print(f"[bold red]{autogen_context=!r}[/]")
        # print(f"[bold red]{upgrade_ops=!r}[/]")

    print(render_diffset(autogen.compare_metadata(migration_context, metadata)))

The comparators object is a registry of diffing functions which alembic uses internally (alembic.autogenerate.compare)