Repository navigation
A changed generated column keeps the indexes and constraints on it (#184) - #190
Merged
Merged
Conversation
PostgreSQL cannot change a generation expression in place, so Npgsql renders an ALTER COLUMN that changes a generated column's expression, its storage or a tsvector column's configuration as DROP COLUMN plus ADD COLUMN, and re-creates only EF Core's own indexes. DROP COLUMN took every complex index, exclusion constraint, temporal constraint and temporal foreign key on the column with it. Their declarations were unchanged, so the differs emitted nothing: the migration ran without an error, the snapshot still listed them, and the database had none. The Npgsql differ now treats such an operation as in the way, with the same condition Npgsql uses (RecreatesColumn, which also compares the tsvector annotations Npgsql turns into the expression). Complex indexes go through RequiresIndexRecreation; exclusion and temporal constraints get the same check, a rename pair included, and a temporal foreign key goes with a rebuilt principal constraint. All are dropped before the base operations and added after them. Closes #184 Co-Authored-By: Claude Opus 5.5 <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.
Closes #184
Into
release/5.x: SchemaKit's differ is new code.Closesacts only onmain, so #184 is closed by hand after the merge.Problem
On PostgreSQL, changing a generated column's expression, its storage or a
tsvectorcolumn's configuration silently dropped every complex index, exclusion constraint, temporal constraint and temporal foreign key on the column. PostgreSQL cannot change a generation expression in place, so Npgsql renders theAlterColumnOperationasDROP COLUMNplusADD COLUMN. It then re-creates only EF Core's own indexes (NpgsqlMigrationsSqlGenerator.Generate(AlterColumnOperation, …), Npgsql 10). The declarations were unchanged, so the differs emitted nothing. The migration ran without an error, the snapshot still listed everything, and the nextmigrations addwas empty.Change
NpgsqlComplexIndexMigrationsModelDiffer:RecreatesColumnapplies Npgsql's own condition:ComputedColumnSqlorIsStoredchanged, plus theNpgsql:TsVectorConfig/TsVectorPropertiesannotations, which Npgsql turns into the expression before it compares.RequiresIndexRecreationtreats such an operation on a column the index reads as in the way. That's the same path SQL Server: ALTER COLUMN on a column under a complex index fails at apply (Msg 5074) #84/SQL Server: a renamed complex index stays in the way of ALTER COLUMN, and the migration fails at apply (Msg 5074) #141 use on SQL Server: drop before the base operations, create after them.RecreatedColumns,ReadsRecreatedColumn), covering columns and the columns named in expressions and filters.rebuiltlist. Without that, the principal'sDROP COLUMNfails (2BP01).NpgsqlAnnotationsmirrors the twotsvectorkeys, since Npgsql'sNpgsqlAnnotationNamesis internal API.CustomMigrationsModelDiffer.ColumnsNamedIntakes a table rather than an index descriptor and is internal, so the constraints read columns the same way indexes do.### Changed answersrow (PostgreSQL: changing a generated column's expression silently drops every complex index and constraint on it #184 issilent), anddocs/upgrading.mdA changed generated column keeps what reads it, which says how to find and re-add what an earlier migration dropped. CLAUDE.md is updated too.Tests
GeneratedColumnRecreationTests, five tests, each asserting what is dropped before theAlterColumnOperationand created after it:tsvectorconfiguration rebuilds its GIN indexPostgresIntegrationTests.Changed_generation_expression_keeps_indexes_and_constraintsapplies the change on PostgreSQL 18 with the target model, asdatabase updatedoes. It checks that EF Core's own index, the complex index, the exclusion constraint, the temporal constraint and the temporal FK all exist afterwards, and that the exclusion constraint still enforces (23P01).ApplyInTransactiongains an optionalmodel, because Npgsql re-creates EF's own indexes only when it is given one.🤖 Generated with Claude Code