Offline mode: how to make Alembic use a single (project_name, version_num) table instead of alembic_version? #1747
Replies: 3 comments 3 replies
-
no there's not (although it is python so maybe with patching), but since you are using a static SQL script you can edit the SQL script to do whatever you want
you can use version_table_impl to provide for a Table that has other columns that you want. But the INSERT statement that's generated by migration.py is hardcoded in an object called HeadMaintainer, and there's not a hook to override how HeadMaintainer works. You can maybe use execution event hooks to intercept the INSERT and rewrite it but im not sure that would work with
the API for operations is open, so it's in theory possible sure but it would be a lot of work to achieve since you'd need to make your own migration runner that steps through the migration files and runs the commands in the way that you want.
maybe, but the way information is stored in alembic_version is pretty idiosyncratic. it currently stores a list of heads (having just one head revision is the most common, but just a specific case). there are commands for insert version, delete version, update version. but if I made an extension point out of this, it would be like "you tell us the name of the table, and how to write insert/update/delete", it would be much more abstracted than that, where you could store and manipulate these heads in a file or whatever you want.
right if I'm adding API for "custom version store" it would not assume it's even using SQL, so sure, it's a thing we can add but it's the kind of API taht has to be designed carefully, and would need to be integration tested for at least two cases: 1. using an alternative version table format with custom DML 2. using a plain file. both scenarios would have to assert that there is no alembic_version table created at all as well as that version_table-specific elements like
the usual way to do this is to have multiple alembic_version tables, one for each project.
Sure but what is the technical reason for that. |
Beta Was this translation helpful? Give feedback.
-
|
I'd like to propose this as a major change instead to the default alembic_versions table. In almost all other migration tools, there is a table that follows this structure, so we should have a table like this as well, as it is clearly better for multiple reasons:
Currently, there is a date alongside the migration hash, which 1: is horrible for performance in long term projects that may have multiple migrations, and 2: does not cover the need for knowing when the migration was applied vs when it was created. For multiple compliance reasons this is bad, specially when working with fragmented teams: If there is a production issue because someone applied the wrong migration at a given time, currently alembic makes troubleshooting this very hard. |
Beta Was this translation helpful? Give feedback.
-
|
In short:
What could be accepted:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
I run Alembic in offline mode (
as_sql=True) and execute the generated SQL with a custom adapter (targets PostgreSQL and DuckDB). I need Alembic to store and read the current revision from a single table that tracks multiple projects:I want Alembic to use this table instead of the default
alembic_version, so that each run specifies aproject_nameand Alembic performsDELETE … WHERE project_name = :p+ optionalINSERT … (project_name, version_num)for that project, and also reads the current revision for that project in offline mode.What I tried (and why it isn’t enough)
on_version_applymirrorI used
on_version_applyto create/updateproject_versions. This mirrors the step, but Alembic still writes toalembic_version(e.g.,INSERT INTO alembic_version (...)). That means the authoritative store remainsalembic_version, which doesn’t support multiple projects and causes collisions.version_table=Passing a custom name to
env.configure(version_table=...)changes the table name, but it still expects Alembic’s default single-column schema (version_num PK). I need a different schema and DML (keyed byproject_name), not just a different table name.version_table_implIt looks oriented to dialect authors for DDL differences, not for changing the semantics of how Alembic stores/reads the current revision (e.g., custom
SELECT/DELETE/INSERTkeyed byproject_name). I couldn’t find a documented way to implement “get/set current revision for a given project” here—especially in offline mode.Post-run stamping
As a workaround, after generating and executing the migration SQL, I run my own SQL to upsert
project_versions. This works operationally but does not make Alembic itself useproject_versions; Alembic still touchesalembic_versionduring the run.Desired behavior
In offline mode, for a given
project_name(passed viaenv.configure(...)), I’d like Alembic to:Read the current revision for that project from
project_versions(or accept a providedstarting_revsafely).Emit only SQL against
project_versionsfor version bookkeeping, e.g.:DELETE FROM project_versions WHERE project_name = :p;INSERT INTO project_versions(project_name, version_num) VALUES (:p, :v);Never emit DDL/DML for
alembic_versionduring that run.In other words, I need a single shared table with
(project_name, version_num)that is the authoritative version store across multiple projects.Questions
project_versions)—including both read (current revision) and write (stamp) paths—in offline mode?version_table_implbe used for this purpose, or is it strictly for DDL shape and not for altering the CRUD semantics of the version store?alembic_versionentirely for a run, and route all version bookkeeping to a custom implementation?get_current_revision()/stamp_revision()callbacks that works in offline and online modes)?Minimal (redacted) sketch
Why this matters
alembic_versiontable can’t represent multiple project histories.alembic_version_*tables is a different design (multiple tables). Our requirement is one table with an explicitproject_namekey.Thanks for any guidance on the correct, supported way to accomplish this, or on whether a new extension point would be acceptable.
Beta Was this translation helpful? Give feedback.
All reactions