feat: support user-defined composite types#279
Open
dilame wants to merge 1 commit intostripe:mainfrom
Open
Conversation
Add introspection and migration planning for user-defined composite types, including nested composite dependencies, array-of-composite dependencies, and drop/recreate cascades for function and procedure consumers when composite attributes change. Reject attribute changes when the affected composite type, or a dependent composite type, is used by a table column.
dd07ba3 to
d86d01a
Compare
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
Plan and apply
CREATE TYPE foo AS (...)andDROP TYPE foofor user-defined composite types (pg_type.typtype = 'c'with a backingpg_class.relkind = 'c').When a composite type's attribute list changes:
ErrNotImplemented(recreating the type would require rewriting the consumer table).pg_dependrecord points at the type is force-recreated in the same migration so PostgreSQL resolves their argument and return types against the new attribute layout.COMMENT ON TYPEis also supported (add / change / remove).This addresses the README's "Types (Only enums are currently supported)" caveat for the composite-type case. Domains and base types are still out of scope.
Why
The current behavior silently drops
CREATE TYPE foo AS (...)from migration plans. For declarative schemas that describe composite types as input/output structs for SQL functions, this means every dev has to applyCREATE TYPEby hand alongside every migration, or wrap definitions inIF NOT EXISTSblocks that won't catch attribute drift.How
internal/queries/queries.sql:GetCompositeTypes— returns one row per(type, attribute), joiningpg_typewith the underlyingpg_class(relkind = 'c') andpg_attribute. Filters out implicit row types of tables/views/sequences.GetDependsOnCompositeTypes— composite types referenced (by argument, return, or body resolution) by a function or procedure viapg_depend.GetCompositeTypeTableConsumers— tables whose columns declare a given composite type. Drives the table-dependency rejection.internal/schema/schema.go:CompositeType+CompositeTypeAttribute,Function.DependsOnCompositeTypes,Procedure.DependsOnCompositeTypes,CompositeType.IsUsedByTable.pkg/diff/composite_type_sql_generator.go: asqlVertexGeneratorwith explicit dependency edges so the type'sCREATEruns before any consumer'sCREATE/ALTER, and the type'sDROPruns after every consumer in the old schema is dropped/altered. ThetypeDelete > consumerAddAlteredge is omitted when the consumer still depends on the type in the new schema, to avoid the cycletypeAdd → consumerAddAlter → typeDelete → typeAddin the recreation case.pkg/diff/sql_generator.go:buildSchemaDiffbuilds acompositeTypesBeingRecreatedset when attribute lists differ, and the function and procedure factories check the new schema'sDependsOnCompositeTypesagainst that set to force their own recreation.internal/migration_acceptance_tests/composite_type_cases_test.go: 16 cases — create, drop, comment add/change/remove, with-collation, nested types, used-by-function, dropped-with-function, attribute-change cascade through dependent function / procedure / multiple functions, and the table-dependency rejection.No new flags. The cascade to functions/procedures is conservative: it only force-recreates when the dependent object actually references a type whose attribute list is changing.