sql/postgres: treat serial as equivalent to integer + nextval default#1
Open
wokalski wants to merge 4 commits into
Open
sql/postgres: treat serial as equivalent to integer + nextval default#1wokalski wants to merge 4 commits into
wokalski wants to merge 4 commits into
Conversation
A column declared as `serial` is semantically equivalent to an integer
column with a `nextval('<table>_<column>_seq')` default. Switching
between the two declarative forms currently produces a (type + default)
change even though no migration is required.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A column declared as `serial` is semantically identical to an integer
column with a `DEFAULT nextval('<table>_<column>_seq')` clause. The
PostgreSQL inspector already normalizes the latter to a SerialType
(see columnDefault in inspect.go) but the HCL parser does not, so a
state-based diff between the two declarative forms reported a spurious
ChangeType + ChangeDefault change.
Mirror the inspect-time normalization at the diff step by implementing
sqlx.Normalizer on the postgres diff driver so that both forms collapse
to the same representation before comparison.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the misleading HCL-level test that compared `type = serial` against `type = integer + nextval default` without a sequence block; the AFTER state was incomplete and looked like a sequence drop. - Add a positive guard for the user-reported case: `serial -> integer` with no default must still report `ChangeType` so the migration plan can emit `DROP SEQUENCE`. Verified end-to-end against a live PostgreSQL: inspected serial column diffed against a programmatic schema with `integer + nextval default + explicit Sequence object` produces 0 changes, while diffing against plain `integer` produces `DROP DEFAULT` + `DROP SEQUENCE`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Collapse Normalize doc comment to match diff.go's one-line style.
- Skip *schema.NamedDefault wrappers so a named DEFAULT constraint is
not silently dropped while normalizing.
- Guard against unrecognized integer T values where SerialType.SetType
leaves T empty (would otherwise hard-error in FormatType).
- Chain crdbDiff.Normalize into the base differ so the equivalence
also applies on CockroachDB.
- Drop the verbose test introduction comment; rewrite the misleading
"drops the sequence" comment to point at the existing plan-level
assertion in TestPlanChanges ("Drop serial sequence").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
A column declared as
serialin PostgreSQL is semantically identical to an integer column with aDEFAULT nextval('<table>_<column>_seq')clause. The PostgreSQL inspector already normalizes the latter to aSerialType(seecolumnDefaultininspect.go), but the HCL parser does not — so a state-based diff between the two declarative forms reports a spuriousChangeType + ChangeDefaultchange.Example that previously produced a diff but no longer does:
Approach
Two commits:
d9d7853d— reproduction: adds three subtest cases toTestDiff_TableDiffcoveringserial ↔ integer + nextval,bigserial ↔ bigint + nextval, and the reversed direction. Without the fix these tests fail withChangeType | ChangeDefault.6404929a— fix: implementssqlx.Normalizeron the postgresdiffdriver. TheNormalizemethod rewrites anyIntegerTypecolumn whoseDefaultis aRawExprmatchingnextval('<table>_<column>_seq'[::regclass])into the equivalentSerialTypewith the default cleared, mirroring the existing inspection-time normalization. Bothfromandtotables are normalized before diffing, so both declarative forms collapse to the same representation. CockroachDB'scrdbDiffstill overridesNormalizewith its own logic, so it is unaffected.Also adds an HCL-level end-to-end test
TestDiff_SerialVsIntegerNextvalexercising the user's exact scenario through the HCL parser.Test plan
go test ./sql/postgres/...— passes including the new testsgo test ./...— passes everywhere exceptatlasexec(pre-existing failure: tests require anatlasCLI binary in$PATH, unrelated)🤖 Generated with Claude Code