Repository navigation
Schema change: an existing integer column can become an identity column - #9
Merged
Merged
Conversation
alter_column with autoIncrement on a column that is not one yet adds GENERATED BY DEFAULT AS IDENTITY and starts its sequence after the largest value the column holds, in one transaction (inside the lock retry), so a new row cannot be given a number that is already used. The largest value is read through an index; a table that is not small needs one first. The column has to be an integer type and NOT NULL, and a serial default has to be removed in the same change. The identity's own sequence is the one that is started, because pg_get_serial_sequence is ambiguous for a column that still owns an old serial sequence. On servers older than PostgreSQL 13, which cannot have both on one column, the old sequence is detached first.
… does not depend on the machine Two scenarios: an integer primary key becomes an identity column, and a serial column becomes one (the default is dropped first). Each inserts a row afterwards and checks that it is numbered after the largest value. The check that a lock-retry that gives up stops now only requires that it stops, not how fast, which depended on the load of the machine running it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
alter_columnwithautoIncrement: trueon a column that is not an identity column used to be refused ("not compiled: its sequence has to start after the largest existing value"). It now compiles:ALTER TABLE … ADD GENERATED BY DEFAULT AS IDENTITY, then the sequence is started at the largest value the column holds plus one, so a new row cannot be given a number that is already used.BY DEFAULT, so an insert that supplies its own value still works.defaultValue: null); the step list then drops the default first.pg_get_serial_sequenceis ambiguous for a column that still owns the sequence of an old serial default and started the wrong sequence (found by the serial-to-identity scenario below), so the step looks up the sequence the column depends on internally.nextvalon it by name), and the step says so.How it was checked
scripts/schema-change-pg.ts: an integer primary key becomes an identity column, and a serial column becomes one. Each inserts a row afterwards and checks it is numbered after the largest value (and that an explicit id still works). Lock levels and the predicted end state are checked like every scenario.npm run test:schema-pg:versionspasses on PostgreSQL 12, 13, 14, 15, 16, 17 and 18; the first run caught both the wrong-sequence bug and the PostgreSQL 12 failure above.Reviewer notes