-
-
Notifications
You must be signed in to change notification settings - Fork 253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
detect Postgresql SERIAL sequences from reflected nextval('table_id_seq'::regclass) #73
Comments
Michael Bayer (@zzzeek) wrote: unfortunately Bitbucket's idiotic new UX just blew away all my comments here. So let's try again. This is a well known limitation of the Postgres dialect. The "nextval()" expression here ideally wouldn't be generated, and we'd know this is the default SERIAL case. But we don't get that info from PG. Sorry you went through all that for the repro case, this is easy to reproduce just by sticking a table on the "metadata", running the upgrade, then removing the table and creating another autogen, producing this code:
The only solution here would be a hardcoded rule/regex in Alembic to have it completely guess that this exact pattern of default means the whole expression should be removed. Usually, any function-based default with PG needs the text() expression surrounding it in any case, so this kind of issue always requires that the user review and edit the migration file. But here, even if you put the text() around the expression so that it is no longer quoted, you still are missing the presence of the sequence itself. I've never been comfortable with SQLAlchemy making this guess. For Alembic, it's slightly less unacceptable, though I'd still consider placing a prominent warning or even an exception (to ensure the user reviews the file) so that these can be manually reviewed/corrected. Autogenerated revisions should always be reviewed and they make no guarantee that they can produce accurate CREATE statements based on reflection, since this cannot be done without guessing which is something SQLA/Alembic aren't too enthused about doing. |
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Michael Armida (@marmida) wrote: No worries about the test case. It actually does exactly what you described - it adds a table, runs the upgrade, and then removes it. I'm confused about one thing (and this is more for curiosity than a solution): why is it that creating a table on an upgrade works fine, but not on a downgrade? Is it that on upgrade, the sequence is created implicitly, but on downgrade, alembic is trying to reference the sequence explicitly, in order to be faithful to the original sequence name? Even if the quoting issue is fixed and an independent sequence is created, the sequence is slightly different from the original in that it doesn't get dropped along with the table. But maybe that can be solved with some constraint (I am not very good with postgres, if you can't tell). Would a potentially hacky but pragmatic solution be to detect this scenario and emit the same creation statement in upgrades as downgrades? That is, to assume that postgres will do the right thing with implicit sequence creation? |
Michael Bayer (@zzzeek) wrote: when autogenerate generates the "upgrade" instruction, that's based on what you've given it as your in-application Table metadata. The Column/Integer/primary_key you've defined is there, and the PG dialect knows that should be generated as SERIAL. The "downgrade" instruction is completely different. autogenerate, via SQLAlchemy, reads the pg_catalog tables to infer information about existing tables, and for all those table names that aren't in your model, needs to reverse-engineer a Table structure out of it. This is an error prone process, and in this case PG doesn't tell us the column was created as SERIAL - it gives us integer along with the server default you see, and no information that there is also a SEQUENCE that needs to go along with it. the best solution here would be to just guess, in an educated way, that this "nextval(tablename_colname_seq)::regclass" default we're getting means, hey this is just SERIAL, we don't need to render this in our Python Table instruction. |
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Michael Bayer (@zzzeek) wrote: another case, |
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Changes by Michael Bayer (@zzzeek):
|
Michael Bayer (@zzzeek) wrote: per #197 we now generate valid SQL:
however, this will fail unless you also add the CREATE SEQUENCE manually, or manually convert the server_default here to a SERIAL for Postgresql. So the generalized solution is here. but the one that folds the SEQUENCE into SERIAL, is not, and that is still this issue. |
Changes by Michael Bayer (@zzzeek):
|
Michael Bayer (@zzzeek) wrote:
→ ff74edf |
Changes by Michael Bayer (@zzzeek):
|
<!-- Provide a general summary of your proposed changes in the Title field above --> Fixes: #1479 ### Description <!-- Describe your changes in detail --> In #73, it tries to detact postgresql serial in autogenerate, so it won't take `nextval('seq'::regclass)` as server default for that column. But it takes not effect for tables not in search path. This PR fixed it. ### Checklist <!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once) --> This pull request is: - [ ] A documentation / typographical error fix - Good to go, no issue or tests are needed - [x] A short code fix - please include the issue number, and create an issue if none exists, which must include a complete example of the issue. one line code fixes without an issue and demonstration will not be accepted. - Please include: `Fixes: #<issue number>` in the commit message - please include tests. one line code fixes without tests will not be accepted. - [ ] A new feature implementation - please include the issue number, and create an issue if none exists, which must include a complete example of how the feature would look. - Please include: `Fixes: #<issue number>` in the commit message - please include tests. **Have a nice day!** Closes: #1486 Pull-request: #1486 Pull-request-sha: 24df8f9 Change-Id: I50276875bfb1d4f920f0fcd20136337ae09b5384
Migrated issue, originally created by Michael Armida (@marmida)
alembic revision --autogenerate
creates SQLAlchemy code that, on postgres, generates SQL syntax errors. I've pasted the stack trace below, and written a fixture to reproduce the problem.In general, table creation upgrades and downgrades aren't symmetric; the generated code for a new table in an upgrade isn't the same as that in a downgrade. This may be by design.
On sqlite, this doesn't cause a problem. Unfortunately, it hits a snag on postgres trying to handle the default value for the PK - it doesn't reference the sequence properly.
I've written a test fixture that (hopefully) isolates and reproduces the problem. Because it's many files and crosses shell commands, I've stored it as a git repo: https://github.com/marmida/alembic-downgrade-fixture
==Environment==
== Stack trace ==
The text was updated successfully, but these errors were encountered: