feat: reactive dependency-conflict primitives for targeted matview drops - #1
Merged
Conversation
Add the framework-agnostic primitives a consumer (the Symfony deploy lane) needs to clear a migration blocked by a managed materialized view by dropping only the conflicting closure instead of every managed view. - DependencyConflictSqlState: gate on 2BP01 / 0A000 via the DBAL driver-exception chain, never the locale-dependent message text. - PostgresDependencyConflict: best-effort, locale-aware parse of the blocked relation and dependents; QualifiedName adds the quote-aware identifier scanner. - CatalogDependencyResolver::resolveConflictClosure(): catalog walk by OID from an arbitrary seed relation (e.g. a plain table, which is not a managed-graph node), classifying managed vs unmanaged dependents and ordering dependents-first. - MaterializedViewManager::dropConflictClosure(): drop the managed closure in order, refusing (UnmanagedDependentFound) on any unmanaged dependent unless DropDependentPolicy::Cascade. The drop set is confirmed against the catalog. - ManagementMarker: isManagedComment() / readHash() read-side helpers. Primitives only; no existing behaviour changes. Covered by unit tests and PG integration tests (2BP01 DROP COLUMN, 0A000 ALTER TYPE, drop ordering, guard refusal on an unmanaged dependent).
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.
Why
When a schema migration tries to
DROP TABLE/DROP COLUMNorALTER COLUMN … TYPEon a relation a managed materialized view reads, PostgreSQL blocks the DDL. The bundle's deploy lane currently clears this by dropping every managed materialized view up-front. This PR adds the framework-agnostic primitives needed to instead drop only the conflicting closure (a futurereactive_retrylane strategy in the bundle, gated onth3mouk/materialized-view ^1.2).Primitives only — no existing behaviour changes.
What
Core\Sql\DependencyConflictSqlState— recognises the two blocking SQLSTATEs by walking the DBAL driver-exception chain, never the (locale-dependent) message text:2BP01dependent_objects_still_exist— blockedDROP TABLE/DROP COLUMN0A000feature_not_supported— blockedALTER COLUMN … TYPECore\Dependency\PostgresDependencyConflict— best-effort, locale-aware parse of the blocked relation + named dependents (theDETAILlist is only a seed; PostgreSQL caps it at 100 entries).Core\Sql\QualifiedNameadds the quote-aware identifier scanner.Core\Dependency\CatalogDependencyResolver::resolveConflictClosure()— resolves the authoritative closure from the catalog: seeds viato_regclass, walkspg_depend/pg_rewriteby OID from an arbitrary relation (a plain table is not a node in the managed graph), classifies each dependent managed/unmanaged, orders dependents-first. ReusesDependencyGraphfor ordering.Core\MaterializedViewManager::dropConflictClosure()— drops the managed closure in order, refusing (UnmanagedDependentFound) when any unmanaged dependent is present unlessDropDependentPolicy::Cascade. The drop set is always confirmed against the catalog, never the error text alone.Core\Sql\ManagementMarker—isManagedComment()/readHash()read-side helpers (top-level marker-key check, not a substring match).Tests
of tablemarker, schema-qualified double-quoted names, 0A000 rule, truncation, non-English → not parsed),QualifiedName::scan/render, marker read helpers, closure VO merge.DROP COLUMNand 0A000ALTER TYPEprovoked against a live server → parsed, surgically cleared, blocked DDL then succeeds; managed drop-ordering from the blocked table; guard refusal when an unmanaged view is in the closure.Gates green locally:
cs:check,stan(level 8, no baseline),test:unit(590),test:pg(11).