Repository navigation
fix: a rename in place whose name is held when it runs is a rebuild - #137
Closed
CaffeinatedCoder wants to merge 1 commit into
Closed
CaffeinatedCoder wants to merge 1 commit into
CaffeinatedCoder wants to merge 1 commit into
Conversation
A contributor's change in place runs after EF Core's operations. An index EF Core created under the name a constraint gave up ran while the constraint still held it, and the migration failed with 42P07; two constraints on two tables of one schema swapping names failed the same way. The planner now compares the name a rename gives up and the name it takes, through NameClaims, with what holds a name at that moment: EF Core's objects as the target has them, the declared objects as EF Core's operations leave them but for those dropped before or lost, and the earlier changes in place under their new names. A change that collides is rebuilt: dropped before EF Core's operations and created after them, with its extension ensured. The contributor's statements for it never reach the migration. A name EF Core gives up is free by then, as the server confirms. Closes #99 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
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 #99
This PR is stacked on #133 (#100). Its base is that PR's branch. It compares names with the same
NameClaims.Collide, which needs #133'sISchemaDialect.DefaultSchema. Once #133 merges, retarget this PR tomain.Problem
A contributor's in-place statements are written after EF Core's operations. When an exclusion constraint is renamed and the same migration has EF Core create an index under the name the constraint gives up,
CREATE INDEXruns while the constraint's index still holds that name. The migration scaffolds and fails at apply with 42P07.NameClaims.Requirereads the end state only, where every name is taken once.I measured this on PostgreSQL 18 against
main@ 010ff31, before the fix. Four cases fail with 42P07:Change
SchemaOperationPlanner.KeepInPlace.InPlaceanswer is written into aSchemaSqlof its own. Its statements reach the migration only if the change stays in place.AfterOperations: tables and columns renamed, tables moved), except those dropped before EF Core's operations or lost with them. ABeforeTablesobject is dropped last, so it still holds its name.BeforeTablescontributor's rename that collides is refused (SchemaKitStrings.RenameBeforeTablesCollides), because such an object cannot be rebuilt around tables.NameClaims.Taken,Of,CollideandOfTheModelare the helpers thatRequireand the planner now share. There is one comparison, with one set of namespace rules.SchemaSql.Append(internal).CLAUDE.md: one bullet under "The planner".The mirror case, on the server
A constraint renamed into a name that an EF Core index gives up in the same migration (dropped or renamed away) applies today, and keeps its oid. EF Core's operation runs before the rename. The planner therefore does not treat a name EF Core gives up as a collision, and the rename stays one
RENAME CONSTRAINT. Tests:A_renamed_constraint_takes_the_name_of_an_index_that_is_dropped(live)A_renamed_constraint_takes_the_name_of_an_index_that_is_renamed(live)A_rename_into_a_name_an_index_gives_up_stays_a_rename(statements)Unchanged
Constraints_on_one_table_that_swap_names_or_pass_one_on_are_rebuilt_as_beforeandConstraints_on_one_table_swap_names_and_pass_one_on.RENAME CONSTRAINT.Tests
PgExclusionMigrationTests, the statements of each case:btree_gistensured for the rebuilt constraintIntegration/PgExclusionLiveTests. Each case is applied throughAssertMigratesToagainst the catalog ofEnsureCreated(), Up and Down, on PostgreSQL 16 and 18. The schema-move cases run Up only: a move back to a table without a schema fails on Npgsql today, which is A table moved back to the default schema stays where it was on Npgsql, and a statement written after the move fails with 42P01 #105.Migrations/RenameInPlaceTests, with the sample contributors on Npgsql, SQL Server and SQLite. One case is not on SQLite: a lost holder needs an altered column, and SQLite rebuilds the table for that. The cases:BeforeTablesrename that collides is refused; without a collision it stays a renameI broke each part of the rule in a scratch copy (rsync without
.git,bin,obj) and ran both suites against PostgreSQL 18:Before) instead of after EF Core's operationsA_move_to_another_schema_is_compared_where_the_table_is_by_then,A_move_to_another_schema_neither_invents_a_collision_nor_hides_oneConstraints_on_two_tables_that_swap_names_are_renamed_once_and_rebuilt_once,A_rename_chain_over_two_tables_is_renamed_where_the_order_allowsA_rename_into_a_name_a_dropped_declaration_gives_up_stays_in_place(3 providers)A_rename_into_a_name_a_lost_declaration_gives_up_stays_in_place(Npgsql, SQL Server)BeforeTablesWhat_tables_are_made_of_is_not_rebuilt_around_a_collision(3 providers)Every suite passes:
SchemaKit.ApiProbes: 125 testsdotnet build CodoMetis.EFCore.SchemaKit.slnxhas no warning.What the point fix leaves to #115
It reasons about one moment, the changes in place, and treats every other phase as a whole. It does not look at:
NameClaims.Requirecovers the end state of the consumer's own model only, so a snapshot-to-snapshot diff is not checked.BeforeTablescreate against anEnsureSchemaof the same migration. This is the lead in Change planning and impact: SchemaChange, BaseChange, ImpactOf, dependencies #24's comment.The ledger over ordered actions is the general answer.
Decisions in this PR that are not confirmed
BeforeTablesrename that collides is refused, with a message, instead of being rebuilt. No shipped contributor isBeforeTables.TestDomainContributorgainsClaimsOverridein the test harness. Domains claim nothing by default, as before.🤖 Generated with Claude Code