@supabase/pg-delta 1.0.0-alpha.3 → 1.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cli/bin/cli.js +0 -0
- package/dist/cli/commands/plan.js +21 -0
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.js +1 -1
- package/dist/core/objects/table/table.model.d.ts +4 -2
- package/dist/core/objects/table/table.model.js +3 -0
- package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
- package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
- package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
- package/dist/core/objects/trigger/trigger.model.js +3 -0
- package/dist/core/plan/apply.js +3 -3
- package/dist/core/plan/create.js +34 -15
- package/dist/core/plan/sql-format/constants.d.ts +2 -0
- package/dist/core/plan/sql-format/constants.js +11 -0
- package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
- package/dist/core/plan/sql-format/fixtures.js +2449 -0
- package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
- package/dist/core/plan/sql-format/format-utils.js +274 -0
- package/dist/core/plan/sql-format/formatters.d.ts +20 -0
- package/dist/core/plan/sql-format/formatters.js +737 -0
- package/dist/core/plan/sql-format/index.d.ts +2 -0
- package/dist/core/plan/sql-format/index.js +98 -0
- package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
- package/dist/core/plan/sql-format/keyword-case.js +868 -0
- package/dist/core/plan/sql-format/protect.d.ts +3 -0
- package/dist/core/plan/sql-format/protect.js +269 -0
- package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
- package/dist/core/plan/sql-format/sql-scanner.js +202 -0
- package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
- package/dist/core/plan/sql-format/tokenizer.js +118 -0
- package/dist/core/plan/sql-format/types.d.ts +28 -0
- package/dist/core/plan/sql-format/types.js +1 -0
- package/dist/core/plan/sql-format/wrap.d.ts +2 -0
- package/dist/core/plan/sql-format/wrap.js +165 -0
- package/dist/core/plan/sql-format.d.ts +2 -0
- package/dist/core/plan/sql-format.js +1 -0
- package/dist/core/plan/statements.d.ts +2 -1
- package/dist/core/plan/statements.js +6 -2
- package/dist/core/postgres-config.d.ts +15 -0
- package/dist/core/postgres-config.js +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/package.json +37 -22
- package/src/cli/app.ts +28 -0
- package/src/cli/bin/cli.ts +9 -0
- package/src/cli/commands/apply.ts +101 -0
- package/src/cli/commands/plan.ts +195 -0
- package/src/cli/commands/sync.ts +185 -0
- package/src/cli/formatters/index.ts +5 -0
- package/src/cli/formatters/tree/tree-builder.ts +380 -0
- package/src/cli/formatters/tree/tree-renderer.ts +372 -0
- package/src/cli/formatters/tree/tree.ts +237 -0
- package/src/cli/utils/integrations.ts +42 -0
- package/src/cli/utils.ts +231 -0
- package/src/core/catalog.diff.ts +246 -0
- package/src/core/catalog.model.ts +384 -0
- package/src/core/change.types.ts +44 -0
- package/src/core/context.ts +26 -0
- package/src/core/depend.ts +1870 -0
- package/src/core/expand-replace-dependencies.ts +380 -0
- package/src/core/fingerprint.ts +204 -0
- package/src/core/integrations/filter/dsl.ts +204 -0
- package/src/core/integrations/filter/extractors.ts +145 -0
- package/src/core/integrations/filter/filter.types.ts +3 -0
- package/src/core/integrations/integration-dsl.ts +24 -0
- package/src/core/integrations/integration.types.ts +7 -0
- package/src/core/integrations/serialize/dsl.ts +77 -0
- package/src/core/integrations/serialize/serialize.types.ts +3 -0
- package/src/core/integrations/supabase.ts +121 -0
- package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
- package/src/core/objects/aggregate/aggregate.model.ts +317 -0
- package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
- package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
- package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
- package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
- package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
- package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
- package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
- package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
- package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
- package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
- package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
- package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
- package/src/core/objects/base.change.ts +62 -0
- package/src/core/objects/base.default-privileges.ts +204 -0
- package/src/core/objects/base.diff.ts +20 -0
- package/src/core/objects/base.model.ts +82 -0
- package/src/core/objects/base.privilege-diff.ts +299 -0
- package/src/core/objects/base.privilege.ts +184 -0
- package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
- package/src/core/objects/collation/changes/collation.alter.ts +79 -0
- package/src/core/objects/collation/changes/collation.base.ts +20 -0
- package/src/core/objects/collation/changes/collation.comment.ts +68 -0
- package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
- package/src/core/objects/collation/changes/collation.create.ts +106 -0
- package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
- package/src/core/objects/collation/changes/collation.drop.ts +37 -0
- package/src/core/objects/collation/changes/collation.types.ts +10 -0
- package/src/core/objects/collation/collation.diff.test.ts +100 -0
- package/src/core/objects/collation/collation.diff.ts +126 -0
- package/src/core/objects/collation/collation.model.ts +224 -0
- package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
- package/src/core/objects/domain/changes/domain.alter.ts +286 -0
- package/src/core/objects/domain/changes/domain.base.ts +20 -0
- package/src/core/objects/domain/changes/domain.comment.ts +59 -0
- package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
- package/src/core/objects/domain/changes/domain.create.ts +118 -0
- package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
- package/src/core/objects/domain/changes/domain.drop.ts +34 -0
- package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
- package/src/core/objects/domain/changes/domain.types.ts +12 -0
- package/src/core/objects/domain/domain.diff.test.ts +284 -0
- package/src/core/objects/domain/domain.diff.ts +358 -0
- package/src/core/objects/domain/domain.model.ts +190 -0
- package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
- package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
- package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
- package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
- package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
- package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
- package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
- package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
- package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
- package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
- package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
- package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
- package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
- package/src/core/objects/extension/changes/extension.alter.ts +78 -0
- package/src/core/objects/extension/changes/extension.base.ts +20 -0
- package/src/core/objects/extension/changes/extension.comment.ts +64 -0
- package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
- package/src/core/objects/extension/changes/extension.create.ts +63 -0
- package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
- package/src/core/objects/extension/changes/extension.drop.ts +34 -0
- package/src/core/objects/extension/changes/extension.types.ts +10 -0
- package/src/core/objects/extension/extension.diff.test.ts +42 -0
- package/src/core/objects/extension/extension.diff.ts +90 -0
- package/src/core/objects/extension/extension.model.ts +280 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
- package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
- package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
- package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
- package/src/core/objects/index/changes/index.alter.test.ts +200 -0
- package/src/core/objects/index/changes/index.alter.ts +144 -0
- package/src/core/objects/index/changes/index.base.ts +20 -0
- package/src/core/objects/index/changes/index.comment.ts +63 -0
- package/src/core/objects/index/changes/index.create.test.ts +66 -0
- package/src/core/objects/index/changes/index.create.ts +68 -0
- package/src/core/objects/index/changes/index.drop.test.ts +44 -0
- package/src/core/objects/index/changes/index.drop.ts +34 -0
- package/src/core/objects/index/changes/index.types.ts +6 -0
- package/src/core/objects/index/changes/utils.ts +16 -0
- package/src/core/objects/index/index.diff.test.ts +153 -0
- package/src/core/objects/index/index.diff.ts +243 -0
- package/src/core/objects/index/index.model.ts +370 -0
- package/src/core/objects/language/changes/language.alter.test.ts +33 -0
- package/src/core/objects/language/changes/language.alter.ts +53 -0
- package/src/core/objects/language/changes/language.base.ts +20 -0
- package/src/core/objects/language/changes/language.comment.ts +58 -0
- package/src/core/objects/language/changes/language.create.test.ts +27 -0
- package/src/core/objects/language/changes/language.create.ts +104 -0
- package/src/core/objects/language/changes/language.drop.test.ts +25 -0
- package/src/core/objects/language/changes/language.drop.ts +39 -0
- package/src/core/objects/language/changes/language.privilege.ts +172 -0
- package/src/core/objects/language/changes/language.types.ts +12 -0
- package/src/core/objects/language/language.diff.test.ts +53 -0
- package/src/core/objects/language/language.diff.ts +176 -0
- package/src/core/objects/language/language.model.ts +150 -0
- package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
- package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
- package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
- package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
- package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
- package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
- package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
- package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
- package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
- package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
- package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
- package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
- package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
- package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
- package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
- package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
- package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
- package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
- package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
- package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
- package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
- package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
- package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
- package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
- package/src/core/objects/procedure/procedure.diff.ts +404 -0
- package/src/core/objects/procedure/procedure.model.ts +264 -0
- package/src/core/objects/procedure/utils.ts +58 -0
- package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
- package/src/core/objects/publication/changes/publication.alter.ts +243 -0
- package/src/core/objects/publication/changes/publication.base.ts +20 -0
- package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
- package/src/core/objects/publication/changes/publication.comment.ts +64 -0
- package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
- package/src/core/objects/publication/changes/publication.create.ts +82 -0
- package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
- package/src/core/objects/publication/changes/publication.drop.ts +29 -0
- package/src/core/objects/publication/changes/publication.types.ts +26 -0
- package/src/core/objects/publication/publication.diff.test.ts +292 -0
- package/src/core/objects/publication/publication.diff.ts +253 -0
- package/src/core/objects/publication/publication.model.ts +206 -0
- package/src/core/objects/publication/utils.ts +55 -0
- package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
- package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
- package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
- package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
- package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
- package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
- package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
- package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
- package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
- package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
- package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
- package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
- package/src/core/objects/role/changes/role.alter.test.ts +346 -0
- package/src/core/objects/role/changes/role.alter.ts +110 -0
- package/src/core/objects/role/changes/role.base.ts +24 -0
- package/src/core/objects/role/changes/role.comment.ts +55 -0
- package/src/core/objects/role/changes/role.create.test.ts +52 -0
- package/src/core/objects/role/changes/role.create.ts +102 -0
- package/src/core/objects/role/changes/role.drop.test.ts +29 -0
- package/src/core/objects/role/changes/role.drop.ts +34 -0
- package/src/core/objects/role/changes/role.privilege.ts +376 -0
- package/src/core/objects/role/changes/role.types.ts +12 -0
- package/src/core/objects/role/role.diff.test.ts +44 -0
- package/src/core/objects/role/role.diff.ts +479 -0
- package/src/core/objects/role/role.model.ts +344 -0
- package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
- package/src/core/objects/rule/changes/rule.alter.ts +72 -0
- package/src/core/objects/rule/changes/rule.base.ts +20 -0
- package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
- package/src/core/objects/rule/changes/rule.comment.ts +62 -0
- package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
- package/src/core/objects/rule/changes/rule.create.ts +42 -0
- package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
- package/src/core/objects/rule/changes/rule.drop.ts +29 -0
- package/src/core/objects/rule/changes/rule.types.ts +12 -0
- package/src/core/objects/rule/rule.diff.test.ts +132 -0
- package/src/core/objects/rule/rule.diff.ts +79 -0
- package/src/core/objects/rule/rule.model.ts +173 -0
- package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
- package/src/core/objects/schema/changes/schema.alter.ts +45 -0
- package/src/core/objects/schema/changes/schema.base.ts +20 -0
- package/src/core/objects/schema/changes/schema.comment.ts +56 -0
- package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
- package/src/core/objects/schema/changes/schema.create.ts +47 -0
- package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
- package/src/core/objects/schema/changes/schema.drop.ts +34 -0
- package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
- package/src/core/objects/schema/changes/schema.types.ts +12 -0
- package/src/core/objects/schema/schema.diff.test.ts +42 -0
- package/src/core/objects/schema/schema.diff.ts +209 -0
- package/src/core/objects/schema/schema.model.ts +107 -0
- package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
- package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
- package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
- package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
- package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
- package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
- package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
- package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
- package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
- package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
- package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
- package/src/core/objects/sequence/sequence.diff.ts +359 -0
- package/src/core/objects/sequence/sequence.model.ts +185 -0
- package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
- package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
- package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
- package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
- package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
- package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
- package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
- package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
- package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
- package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
- package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
- package/src/core/objects/subscription/subscription.diff.ts +241 -0
- package/src/core/objects/subscription/subscription.model.ts +190 -0
- package/src/core/objects/subscription/utils.ts +156 -0
- package/src/core/objects/table/changes/table.alter.test.ts +823 -0
- package/src/core/objects/table/changes/table.alter.ts +806 -0
- package/src/core/objects/table/changes/table.base.ts +20 -0
- package/src/core/objects/table/changes/table.comment.ts +266 -0
- package/src/core/objects/table/changes/table.create.test.ts +150 -0
- package/src/core/objects/table/changes/table.create.ts +188 -0
- package/src/core/objects/table/changes/table.drop.test.ts +34 -0
- package/src/core/objects/table/changes/table.drop.ts +45 -0
- package/src/core/objects/table/changes/table.privilege.ts +200 -0
- package/src/core/objects/table/changes/table.types.ts +12 -0
- package/src/core/objects/table/table.diff.test.ts +711 -0
- package/src/core/objects/table/table.diff.ts +953 -0
- package/src/core/objects/table/table.model.ts +460 -0
- package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
- package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
- package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
- package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
- package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
- package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
- package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
- package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
- package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
- package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
- package/src/core/objects/trigger/trigger.diff.ts +116 -0
- package/src/core/objects/trigger/trigger.model.ts +252 -0
- package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
- package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
- package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
- package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
- package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
- package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
- package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
- package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
- package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
- package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
- package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
- package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
- package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
- package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
- package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
- package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
- package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
- package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
- package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
- package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
- package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
- package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
- package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
- package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
- package/src/core/objects/type/enum/enum.diff.ts +396 -0
- package/src/core/objects/type/enum/enum.model.ts +194 -0
- package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
- package/src/core/objects/type/range/changes/range.alter.ts +51 -0
- package/src/core/objects/type/range/changes/range.base.ts +20 -0
- package/src/core/objects/type/range/changes/range.comment.ts +64 -0
- package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
- package/src/core/objects/type/range/changes/range.create.ts +151 -0
- package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
- package/src/core/objects/type/range/changes/range.drop.ts +34 -0
- package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
- package/src/core/objects/type/range/changes/range.types.ts +12 -0
- package/src/core/objects/type/range/range.diff.test.ts +70 -0
- package/src/core/objects/type/range/range.diff.ts +259 -0
- package/src/core/objects/type/range/range.model.ts +187 -0
- package/src/core/objects/type/type.types.ts +5 -0
- package/src/core/objects/utils.ts +171 -0
- package/src/core/objects/view/changes/view.alter.test.ts +110 -0
- package/src/core/objects/view/changes/view.alter.ts +112 -0
- package/src/core/objects/view/changes/view.base.ts +20 -0
- package/src/core/objects/view/changes/view.comment.ts +59 -0
- package/src/core/objects/view/changes/view.create.test.ts +65 -0
- package/src/core/objects/view/changes/view.create.ts +73 -0
- package/src/core/objects/view/changes/view.drop.test.ts +34 -0
- package/src/core/objects/view/changes/view.drop.ts +40 -0
- package/src/core/objects/view/changes/view.privilege.ts +200 -0
- package/src/core/objects/view/changes/view.types.ts +12 -0
- package/src/core/objects/view/view.diff.test.ts +91 -0
- package/src/core/objects/view/view.diff.ts +365 -0
- package/src/core/objects/view/view.model.ts +276 -0
- package/src/core/plan/apply.ts +190 -0
- package/src/core/plan/create.ts +432 -0
- package/src/core/plan/hierarchy.ts +574 -0
- package/src/core/plan/index.ts +29 -0
- package/src/core/plan/io.ts +20 -0
- package/src/core/plan/risk.ts +48 -0
- package/src/core/plan/serialize.ts +195 -0
- package/src/core/plan/sql-format/constants.ts +13 -0
- package/src/core/plan/sql-format/fixtures.ts +2806 -0
- package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
- package/src/core/plan/sql-format/format-functions.test.ts +127 -0
- package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
- package/src/core/plan/sql-format/format-off.test.ts +809 -0
- package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
- package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
- package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
- package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
- package/src/core/plan/sql-format/format-stress.test.ts +616 -0
- package/src/core/plan/sql-format/format-utils.test.ts +91 -0
- package/src/core/plan/sql-format/format-utils.ts +391 -0
- package/src/core/plan/sql-format/formatters.ts +921 -0
- package/src/core/plan/sql-format/index.ts +149 -0
- package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
- package/src/core/plan/sql-format/keyword-case.ts +1085 -0
- package/src/core/plan/sql-format/protect.test.ts +127 -0
- package/src/core/plan/sql-format/protect.ts +337 -0
- package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
- package/src/core/plan/sql-format/sql-scanner.ts +252 -0
- package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
- package/src/core/plan/sql-format/tokenizer.ts +152 -0
- package/src/core/plan/sql-format/types.ts +31 -0
- package/src/core/plan/sql-format/wrap.test.ts +119 -0
- package/src/core/plan/sql-format/wrap.ts +196 -0
- package/src/core/plan/sql-format.ts +2 -0
- package/src/core/plan/statements.ts +22 -0
- package/src/core/plan/types.ts +165 -0
- package/src/core/postgres-config.ts +169 -0
- package/src/core/sort/custom-constraints.ts +161 -0
- package/src/core/sort/debug-visualization.ts +239 -0
- package/src/core/sort/dependency-filter.ts +224 -0
- package/src/core/sort/graph-builder.ts +223 -0
- package/src/core/sort/graph-utils.ts +51 -0
- package/src/core/sort/logical-sort.ts +590 -0
- package/src/core/sort/sort-changes.ts +234 -0
- package/src/core/sort/topological-sort.ts +184 -0
- package/src/core/sort/types.ts +112 -0
- package/src/core/sort/utils.ts +69 -0
- package/src/index.ts +14 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
import { sql } from "@ts-safeql/sql-tag";
|
|
2
|
+
import type { Pool } from "pg";
|
|
3
|
+
import z from "zod";
|
|
4
|
+
import {
|
|
5
|
+
BasePgModel,
|
|
6
|
+
columnPropsSchema,
|
|
7
|
+
normalizeColumns,
|
|
8
|
+
type TableLikeObject,
|
|
9
|
+
} from "../base.model.ts";
|
|
10
|
+
import { normalizePrivileges } from "../base.privilege.ts";
|
|
11
|
+
import {
|
|
12
|
+
type PrivilegeProps,
|
|
13
|
+
privilegePropsSchema,
|
|
14
|
+
} from "../base.privilege-diff.ts";
|
|
15
|
+
|
|
16
|
+
const RelationPersistenceSchema = z.enum([
|
|
17
|
+
"p", // permanent
|
|
18
|
+
"u", // unlogged
|
|
19
|
+
"t", // temporary
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
export const ReplicaIdentitySchema = z.enum([
|
|
23
|
+
"d", // DEFAULT (use default key)
|
|
24
|
+
"n", // NOTHING (no replica identity)
|
|
25
|
+
"f", // FULL (all columns)
|
|
26
|
+
"i", // INDEX (specific index)
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const ForeignKeyActionSchema = z.enum([
|
|
30
|
+
"a", // NO ACTION
|
|
31
|
+
"r", // RESTRICT
|
|
32
|
+
"c", // CASCADE
|
|
33
|
+
"n", // SET NULL
|
|
34
|
+
"d", // SET DEFAULT
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const ForeignKeyMatchTypeSchema = z.enum([
|
|
38
|
+
"f", // FULL
|
|
39
|
+
"p", // PARTIAL
|
|
40
|
+
"s", // SIMPLE
|
|
41
|
+
"u", // UNSPECIFIED (default)
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
const tableConstraintPropsSchema = z.object({
|
|
45
|
+
name: z.string(),
|
|
46
|
+
constraint_type: z.enum([
|
|
47
|
+
"c", // CHECK constraint
|
|
48
|
+
"f", // FOREIGN KEY constraint
|
|
49
|
+
"p", // PRIMARY KEY constraint
|
|
50
|
+
"t", // TRIGGER constraint
|
|
51
|
+
"u", // UNIQUE constraint
|
|
52
|
+
"x", // EXCLUDE constraint
|
|
53
|
+
]),
|
|
54
|
+
deferrable: z.boolean(),
|
|
55
|
+
initially_deferred: z.boolean(),
|
|
56
|
+
validated: z.boolean(),
|
|
57
|
+
is_local: z.boolean(),
|
|
58
|
+
no_inherit: z.boolean(),
|
|
59
|
+
is_partition_clone: z.boolean(),
|
|
60
|
+
parent_constraint_schema: z.string().nullable(),
|
|
61
|
+
parent_constraint_name: z.string().nullable(),
|
|
62
|
+
parent_table_schema: z.string().nullable(),
|
|
63
|
+
parent_table_name: z.string().nullable(),
|
|
64
|
+
key_columns: z.array(z.string()),
|
|
65
|
+
foreign_key_columns: z.array(z.string()).nullable(),
|
|
66
|
+
foreign_key_table: z.string().nullable(),
|
|
67
|
+
foreign_key_schema: z.string().nullable(),
|
|
68
|
+
foreign_key_table_is_partition: z.boolean().nullable(),
|
|
69
|
+
foreign_key_parent_schema: z.string().nullable(),
|
|
70
|
+
foreign_key_parent_table: z.string().nullable(),
|
|
71
|
+
foreign_key_effective_schema: z.string().nullable(),
|
|
72
|
+
foreign_key_effective_table: z.string().nullable(),
|
|
73
|
+
on_update: ForeignKeyActionSchema.nullable(),
|
|
74
|
+
on_delete: ForeignKeyActionSchema.nullable(),
|
|
75
|
+
match_type: ForeignKeyMatchTypeSchema.nullable(),
|
|
76
|
+
check_expression: z.string().nullable(),
|
|
77
|
+
owner: z.string(),
|
|
78
|
+
definition: z.string(),
|
|
79
|
+
comment: z.string().nullable().optional(),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export type TableConstraintProps = z.infer<typeof tableConstraintPropsSchema>;
|
|
83
|
+
|
|
84
|
+
const tablePropsSchema = z.object({
|
|
85
|
+
schema: z.string(),
|
|
86
|
+
name: z.string(),
|
|
87
|
+
persistence: RelationPersistenceSchema,
|
|
88
|
+
row_security: z.boolean(),
|
|
89
|
+
force_row_security: z.boolean(),
|
|
90
|
+
has_indexes: z.boolean(),
|
|
91
|
+
has_rules: z.boolean(),
|
|
92
|
+
has_triggers: z.boolean(),
|
|
93
|
+
has_subclasses: z.boolean(),
|
|
94
|
+
is_populated: z.boolean(),
|
|
95
|
+
replica_identity: ReplicaIdentitySchema,
|
|
96
|
+
is_partition: z.boolean(),
|
|
97
|
+
options: z.array(z.string()).nullable(),
|
|
98
|
+
partition_bound: z.string().nullable(),
|
|
99
|
+
partition_by: z.string().nullable(),
|
|
100
|
+
owner: z.string(),
|
|
101
|
+
comment: z.string().nullable().optional(),
|
|
102
|
+
parent_schema: z.string().nullable(),
|
|
103
|
+
parent_name: z.string().nullable(),
|
|
104
|
+
columns: z.array(columnPropsSchema),
|
|
105
|
+
constraints: z.array(tableConstraintPropsSchema).optional(),
|
|
106
|
+
privileges: z.array(privilegePropsSchema),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
type TablePrivilegeProps = PrivilegeProps;
|
|
110
|
+
export type TableProps = z.infer<typeof tablePropsSchema>;
|
|
111
|
+
|
|
112
|
+
export class Table extends BasePgModel implements TableLikeObject {
|
|
113
|
+
public readonly schema: TableProps["schema"];
|
|
114
|
+
public readonly name: TableProps["name"];
|
|
115
|
+
public readonly persistence: TableProps["persistence"];
|
|
116
|
+
public readonly row_security: TableProps["row_security"];
|
|
117
|
+
public readonly force_row_security: TableProps["force_row_security"];
|
|
118
|
+
public readonly has_indexes: TableProps["has_indexes"];
|
|
119
|
+
public readonly has_rules: TableProps["has_rules"];
|
|
120
|
+
public readonly has_triggers: TableProps["has_triggers"];
|
|
121
|
+
public readonly has_subclasses: TableProps["has_subclasses"];
|
|
122
|
+
public readonly is_populated: TableProps["is_populated"];
|
|
123
|
+
public readonly replica_identity: TableProps["replica_identity"];
|
|
124
|
+
public readonly is_partition: TableProps["is_partition"];
|
|
125
|
+
public readonly options: TableProps["options"];
|
|
126
|
+
public readonly partition_bound: TableProps["partition_bound"];
|
|
127
|
+
public readonly partition_by: TableProps["partition_by"];
|
|
128
|
+
public readonly owner: TableProps["owner"];
|
|
129
|
+
public readonly comment: TableProps["comment"];
|
|
130
|
+
public readonly parent_schema: TableProps["parent_schema"];
|
|
131
|
+
public readonly parent_name: TableProps["parent_name"];
|
|
132
|
+
public readonly columns: TableProps["columns"];
|
|
133
|
+
public readonly constraints: TableConstraintProps[];
|
|
134
|
+
public readonly privileges: TablePrivilegeProps[];
|
|
135
|
+
|
|
136
|
+
constructor(props: TableProps) {
|
|
137
|
+
super();
|
|
138
|
+
|
|
139
|
+
// Identity fields
|
|
140
|
+
this.schema = props.schema;
|
|
141
|
+
this.name = props.name;
|
|
142
|
+
|
|
143
|
+
// Data fields
|
|
144
|
+
this.persistence = props.persistence;
|
|
145
|
+
this.row_security = props.row_security;
|
|
146
|
+
this.force_row_security = props.force_row_security;
|
|
147
|
+
this.has_indexes = props.has_indexes;
|
|
148
|
+
this.has_rules = props.has_rules;
|
|
149
|
+
this.has_triggers = props.has_triggers;
|
|
150
|
+
this.has_subclasses = props.has_subclasses;
|
|
151
|
+
this.is_populated = props.is_populated;
|
|
152
|
+
this.replica_identity = props.replica_identity;
|
|
153
|
+
this.is_partition = props.is_partition;
|
|
154
|
+
this.options = props.options;
|
|
155
|
+
this.partition_bound = props.partition_bound;
|
|
156
|
+
this.partition_by = props.partition_by;
|
|
157
|
+
this.owner = props.owner;
|
|
158
|
+
this.comment = props.comment;
|
|
159
|
+
this.parent_schema = props.parent_schema;
|
|
160
|
+
this.parent_name = props.parent_name;
|
|
161
|
+
this.columns = props.columns;
|
|
162
|
+
this.constraints = props.constraints ?? [];
|
|
163
|
+
this.privileges = props.privileges;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
get stableId(): `table:${string}` {
|
|
167
|
+
return `table:${this.schema}.${this.name}`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
get identityFields() {
|
|
171
|
+
return {
|
|
172
|
+
schema: this.schema,
|
|
173
|
+
name: this.name,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get dataFields() {
|
|
178
|
+
return {
|
|
179
|
+
// Only include fields that can be managed via ALTER safely
|
|
180
|
+
persistence: this.persistence,
|
|
181
|
+
row_security: this.row_security,
|
|
182
|
+
force_row_security: this.force_row_security,
|
|
183
|
+
replica_identity: this.replica_identity,
|
|
184
|
+
options: this.options,
|
|
185
|
+
// Partition membership can be altered via ATTACH/DETACH
|
|
186
|
+
parent_schema: this.parent_schema,
|
|
187
|
+
parent_name: this.parent_name,
|
|
188
|
+
partition_bound: this.partition_bound,
|
|
189
|
+
owner: this.owner,
|
|
190
|
+
comment: this.comment,
|
|
191
|
+
columns: this.columns,
|
|
192
|
+
constraints: this.constraints,
|
|
193
|
+
privileges: this.privileges,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
override stableSnapshot() {
|
|
198
|
+
const normalizeConstraints = () =>
|
|
199
|
+
[...this.constraints].sort((a, b) => {
|
|
200
|
+
const nameA = (a.name as string | undefined) ?? "";
|
|
201
|
+
const nameB = (b.name as string | undefined) ?? "";
|
|
202
|
+
return nameA.localeCompare(nameB);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
identity: this.identityFields,
|
|
207
|
+
data: {
|
|
208
|
+
...this.dataFields,
|
|
209
|
+
columns: normalizeColumns(this.columns),
|
|
210
|
+
options: this.options ? [...this.options].sort() : this.options,
|
|
211
|
+
constraints: normalizeConstraints(),
|
|
212
|
+
privileges: normalizePrivileges(this.privileges),
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export async function extractTables(pool: Pool): Promise<Table[]> {
|
|
219
|
+
const { rows: tableRows } = await pool.query<TableProps>(sql`
|
|
220
|
+
with extension_oids as (
|
|
221
|
+
select objid
|
|
222
|
+
from pg_depend d
|
|
223
|
+
where d.refclassid = 'pg_extension'::regclass
|
|
224
|
+
and d.classid = 'pg_class'::regclass
|
|
225
|
+
), tables as (
|
|
226
|
+
select
|
|
227
|
+
c.relnamespace::regnamespace::text as schema,
|
|
228
|
+
quote_ident(c.relname) as name,
|
|
229
|
+
c.relpersistence as persistence,
|
|
230
|
+
c.relrowsecurity as row_security,
|
|
231
|
+
c.relforcerowsecurity as force_row_security,
|
|
232
|
+
c.relhasindex as has_indexes,
|
|
233
|
+
c.relhasrules as has_rules,
|
|
234
|
+
c.relhastriggers as has_triggers,
|
|
235
|
+
c.relhassubclass as has_subclasses,
|
|
236
|
+
c.relispopulated as is_populated,
|
|
237
|
+
c.relreplident as replica_identity,
|
|
238
|
+
c.relispartition as is_partition,
|
|
239
|
+
c.reloptions as options,
|
|
240
|
+
pg_get_expr(c.relpartbound, c.oid) as partition_bound,
|
|
241
|
+
pg_get_partkeydef(c.oid) as partition_by,
|
|
242
|
+
c.relowner::regrole::text as owner,
|
|
243
|
+
c_parent.relnamespace::regnamespace as parent_schema,
|
|
244
|
+
quote_ident(c_parent.relname) as parent_name,
|
|
245
|
+
c.oid as oid
|
|
246
|
+
from
|
|
247
|
+
pg_class c
|
|
248
|
+
left join extension_oids e1 on c.oid = e1.objid
|
|
249
|
+
left join pg_inherits i on i.inhrelid = c.oid
|
|
250
|
+
left join pg_class c_parent on i.inhparent = c_parent.oid
|
|
251
|
+
where
|
|
252
|
+
c.relkind in ('r', 'p')
|
|
253
|
+
and not c.relnamespace::regnamespace::text like any(array['pg\\_%', 'information\\_schema'])
|
|
254
|
+
and e1.objid is null
|
|
255
|
+
)
|
|
256
|
+
select
|
|
257
|
+
t.schema,
|
|
258
|
+
t.name,
|
|
259
|
+
t.persistence,
|
|
260
|
+
t.row_security,
|
|
261
|
+
t.force_row_security,
|
|
262
|
+
t.has_indexes,
|
|
263
|
+
t.has_rules,
|
|
264
|
+
t.has_triggers,
|
|
265
|
+
t.has_subclasses,
|
|
266
|
+
t.is_populated,
|
|
267
|
+
t.replica_identity,
|
|
268
|
+
t.is_partition,
|
|
269
|
+
t.options,
|
|
270
|
+
t.partition_bound,
|
|
271
|
+
t.partition_by,
|
|
272
|
+
t.owner,
|
|
273
|
+
obj_description(t.oid, 'pg_class') as comment,
|
|
274
|
+
t.parent_schema,
|
|
275
|
+
t.parent_name,
|
|
276
|
+
coalesce(
|
|
277
|
+
(
|
|
278
|
+
select json_agg(
|
|
279
|
+
json_build_object(
|
|
280
|
+
'name', quote_ident(c.conname),
|
|
281
|
+
'constraint_type', c.contype,
|
|
282
|
+
'deferrable', c.condeferrable,
|
|
283
|
+
'initially_deferred', c.condeferred,
|
|
284
|
+
'validated', c.convalidated,
|
|
285
|
+
'is_local', c.conislocal,
|
|
286
|
+
'no_inherit', c.connoinherit,
|
|
287
|
+
|
|
288
|
+
-- NEW: propagated-to-partition tagging (PG15+)
|
|
289
|
+
'is_partition_clone', (c.conparentid <> 0::oid),
|
|
290
|
+
'parent_constraint_schema', case when c.conparentid <> 0::oid then pc.connamespace::regnamespace::text end,
|
|
291
|
+
'parent_constraint_name', case when c.conparentid <> 0::oid then quote_ident(pc.conname) end,
|
|
292
|
+
'parent_table_schema', case when c.conparentid <> 0::oid then pc_rel.relnamespace::regnamespace::text end,
|
|
293
|
+
'parent_table_name', case when c.conparentid <> 0::oid then quote_ident(pc_rel.relname) end,
|
|
294
|
+
|
|
295
|
+
'key_columns',
|
|
296
|
+
case
|
|
297
|
+
when c.conkey is not null then (
|
|
298
|
+
select json_agg(quote_ident(att.attname) order by pk.ordinality)
|
|
299
|
+
from unnest(c.conkey) with ordinality as pk(attnum, ordinality)
|
|
300
|
+
join pg_attribute att
|
|
301
|
+
on att.attrelid = c.conrelid
|
|
302
|
+
and att.attnum = pk.attnum
|
|
303
|
+
and att.attisdropped = false
|
|
304
|
+
)
|
|
305
|
+
else '[]'::json
|
|
306
|
+
end,
|
|
307
|
+
|
|
308
|
+
'foreign_key_columns',
|
|
309
|
+
case
|
|
310
|
+
when c.contype = 'f' then (
|
|
311
|
+
select json_agg(quote_ident(att.attname) order by fk.ordinality)
|
|
312
|
+
from unnest(c.confkey) with ordinality as fk(attnum, ordinality)
|
|
313
|
+
join pg_attribute att
|
|
314
|
+
on att.attrelid = c.confrelid
|
|
315
|
+
and att.attnum = fk.attnum
|
|
316
|
+
and att.attisdropped = false
|
|
317
|
+
)
|
|
318
|
+
else null
|
|
319
|
+
end,
|
|
320
|
+
|
|
321
|
+
-- existing FK target
|
|
322
|
+
'foreign_key_table', quote_ident(ftc.relname),
|
|
323
|
+
'foreign_key_schema', ftc.relnamespace::regnamespace::text,
|
|
324
|
+
|
|
325
|
+
-- NEW: if FK points at a *partition*, expose its parent + an "effective" target
|
|
326
|
+
'foreign_key_table_is_partition',
|
|
327
|
+
case when c.contype = 'f' then coalesce(ftc.relispartition, false) else null end,
|
|
328
|
+
'foreign_key_parent_schema',
|
|
329
|
+
case when c.contype = 'f' and ftc.relispartition then ftc_parent.relnamespace::regnamespace::text else null end,
|
|
330
|
+
'foreign_key_parent_table',
|
|
331
|
+
case when c.contype = 'f' and ftc.relispartition then quote_ident(ftc_parent.relname) else null end,
|
|
332
|
+
'foreign_key_effective_schema',
|
|
333
|
+
case
|
|
334
|
+
when c.contype <> 'f' then null
|
|
335
|
+
when ftc.relispartition then ftc_parent.relnamespace::regnamespace::text
|
|
336
|
+
else ftc.relnamespace::regnamespace::text
|
|
337
|
+
end,
|
|
338
|
+
'foreign_key_effective_table',
|
|
339
|
+
case
|
|
340
|
+
when c.contype <> 'f' then null
|
|
341
|
+
when ftc.relispartition then quote_ident(ftc_parent.relname)
|
|
342
|
+
else quote_ident(ftc.relname)
|
|
343
|
+
end,
|
|
344
|
+
|
|
345
|
+
'on_update', case when c.contype = 'f' then c.confupdtype else null end,
|
|
346
|
+
'on_delete', case when c.contype = 'f' then c.confdeltype else null end,
|
|
347
|
+
'match_type', case when c.contype = 'f' then c.confmatchtype else null end,
|
|
348
|
+
|
|
349
|
+
'check_expression', pg_get_expr(c.conbin, c.conrelid),
|
|
350
|
+
'owner', t.owner,
|
|
351
|
+
'definition', pg_get_constraintdef(c.oid, true),
|
|
352
|
+
'comment', obj_description(c.oid, 'pg_constraint')
|
|
353
|
+
)
|
|
354
|
+
order by c.conname
|
|
355
|
+
)
|
|
356
|
+
from pg_catalog.pg_constraint c
|
|
357
|
+
|
|
358
|
+
-- NEW: parent constraint/table lookup (for propagated constraints)
|
|
359
|
+
left join pg_catalog.pg_constraint pc on pc.oid = c.conparentid
|
|
360
|
+
left join pg_catalog.pg_class pc_rel on pc_rel.oid = pc.conrelid
|
|
361
|
+
|
|
362
|
+
-- FK referenced table + parent table if it’s a partition
|
|
363
|
+
left join pg_catalog.pg_class ftc on ftc.oid = c.confrelid
|
|
364
|
+
left join pg_catalog.pg_inherits fi on fi.inhrelid = ftc.oid
|
|
365
|
+
left join pg_catalog.pg_class ftc_parent on ftc_parent.oid = fi.inhparent
|
|
366
|
+
|
|
367
|
+
left join pg_depend de
|
|
368
|
+
on de.classid = 'pg_constraint'::regclass
|
|
369
|
+
and de.objid = c.oid
|
|
370
|
+
and de.refclassid = 'pg_extension'::regclass
|
|
371
|
+
|
|
372
|
+
where c.conrelid = t.oid
|
|
373
|
+
-- Skip constraint triggers; they are modeled as triggers, not table constraints
|
|
374
|
+
and c.contype <> 't'
|
|
375
|
+
and not c.connamespace::regnamespace::text like any(array['pg\\_%', 'information\\_schema'])
|
|
376
|
+
and de.objid is null
|
|
377
|
+
),
|
|
378
|
+
'[]'
|
|
379
|
+
) as constraints,
|
|
380
|
+
coalesce(json_agg(
|
|
381
|
+
case when a.attname is not null then
|
|
382
|
+
json_build_object(
|
|
383
|
+
'name', quote_ident(a.attname),
|
|
384
|
+
'position', a.attnum,
|
|
385
|
+
'data_type', a.atttypid::regtype::text,
|
|
386
|
+
'data_type_str', format_type(a.atttypid, a.atttypmod),
|
|
387
|
+
'is_custom_type', ty.typnamespace::regnamespace::text not in ('pg_catalog', 'information_schema'),
|
|
388
|
+
'custom_type_type', case when ty.typnamespace::regnamespace::text not in ('pg_catalog', 'information_schema') then ty.typtype else null end,
|
|
389
|
+
'custom_type_category', case when ty.typnamespace::regnamespace::text not in ('pg_catalog', 'information_schema') then ty.typcategory else null end,
|
|
390
|
+
'custom_type_schema', case when ty.typnamespace::regnamespace::text not in ('pg_catalog', 'information_schema') then ty.typnamespace::regnamespace else null end,
|
|
391
|
+
'custom_type_name', case when ty.typnamespace::regnamespace::text not in ('pg_catalog', 'information_schema') then quote_ident(ty.typname) else null end,
|
|
392
|
+
'not_null', a.attnotnull,
|
|
393
|
+
'is_identity', a.attidentity != '',
|
|
394
|
+
'is_identity_always', a.attidentity = 'a',
|
|
395
|
+
'is_generated', a.attgenerated != '',
|
|
396
|
+
'collation', (
|
|
397
|
+
select quote_ident(c2.collname)
|
|
398
|
+
from pg_collation c2, pg_type t2
|
|
399
|
+
where c2.oid = a.attcollation
|
|
400
|
+
and t2.oid = a.atttypid
|
|
401
|
+
and a.attcollation <> t2.typcollation
|
|
402
|
+
),
|
|
403
|
+
'default', pg_get_expr(ad.adbin, ad.adrelid),
|
|
404
|
+
'comment', col_description(a.attrelid, a.attnum)
|
|
405
|
+
)
|
|
406
|
+
end
|
|
407
|
+
order by a.attnum
|
|
408
|
+
) filter (where a.attname is not null), '[]') as columns,
|
|
409
|
+
coalesce((
|
|
410
|
+
select json_agg(
|
|
411
|
+
json_build_object(
|
|
412
|
+
'grantee', case when grp.grantee = 0 then 'PUBLIC' else grp.grantee::regrole::text end,
|
|
413
|
+
'privilege', grp.privilege_type,
|
|
414
|
+
'grantable', grp.is_grantable,
|
|
415
|
+
'columns', case when grp.cols is not null and array_length(grp.cols,1) > 0
|
|
416
|
+
then grp.cols
|
|
417
|
+
else null end
|
|
418
|
+
)
|
|
419
|
+
order by grp.grantee, grp.privilege_type
|
|
420
|
+
)
|
|
421
|
+
from (
|
|
422
|
+
select
|
|
423
|
+
x.grantee,
|
|
424
|
+
x.privilege_type,
|
|
425
|
+
bool_or(x.is_grantable) as is_grantable,
|
|
426
|
+
array_agg(quote_ident(src.attname) order by src.attname)
|
|
427
|
+
filter (where src.attname is not null) as cols
|
|
428
|
+
from (
|
|
429
|
+
-- one row for object ACL + one row per column ACL
|
|
430
|
+
select null::name as attname, t.oid as relacl_oid, (
|
|
431
|
+
select c_rel.relacl from pg_class c_rel where c_rel.oid = t.oid
|
|
432
|
+
) as acl
|
|
433
|
+
union all
|
|
434
|
+
select a2.attname, t.oid as relacl_oid, a2.attacl
|
|
435
|
+
from pg_attribute a2
|
|
436
|
+
where a2.attrelid = t.oid
|
|
437
|
+
and a2.attnum > 0
|
|
438
|
+
and not a2.attisdropped
|
|
439
|
+
and a2.attacl is not null
|
|
440
|
+
) as src
|
|
441
|
+
join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
|
|
442
|
+
group by x.grantee, x.privilege_type
|
|
443
|
+
) as grp
|
|
444
|
+
), '[]') as privileges
|
|
445
|
+
from
|
|
446
|
+
tables t
|
|
447
|
+
left join pg_attribute a on a.attrelid = t.oid and a.attnum > 0 and not a.attisdropped
|
|
448
|
+
left join pg_attrdef ad on a.attrelid = ad.adrelid and a.attnum = ad.adnum
|
|
449
|
+
left join pg_type ty on ty.oid = a.atttypid
|
|
450
|
+
group by
|
|
451
|
+
t.oid, t.schema, t.name, t.persistence, t.row_security, t.force_row_security, t.has_indexes, t.has_rules, t.has_triggers, t.has_subclasses, t.is_populated, t.replica_identity, t.is_partition, t.options, t.partition_bound, t.partition_by, t.owner, t.parent_schema, t.parent_name
|
|
452
|
+
order by
|
|
453
|
+
t.schema, t.name
|
|
454
|
+
`);
|
|
455
|
+
// Validate and parse each row using the Zod schema
|
|
456
|
+
const validatedRows = tableRows.map((row: unknown) =>
|
|
457
|
+
tablePropsSchema.parse(row),
|
|
458
|
+
);
|
|
459
|
+
return validatedRows.map((row: TableProps) => new Table(row));
|
|
460
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { Trigger, type TriggerProps } from "../trigger.model.ts";
|
|
3
|
+
import { ReplaceTrigger } from "./trigger.alter.ts";
|
|
4
|
+
|
|
5
|
+
describe.concurrent("trigger", () => {
|
|
6
|
+
describe("alter", () => {
|
|
7
|
+
test("replace trigger", () => {
|
|
8
|
+
const props: Omit<TriggerProps, "enabled"> = {
|
|
9
|
+
schema: "public",
|
|
10
|
+
name: "test_trigger",
|
|
11
|
+
table_name: "test_table",
|
|
12
|
+
function_schema: "public",
|
|
13
|
+
function_name: "test_function",
|
|
14
|
+
trigger_type: 1 << 4, // UPDATE (1<<4) = 16, AFTER is default (0), STATEMENT is default (0)
|
|
15
|
+
is_internal: false,
|
|
16
|
+
deferrable: true,
|
|
17
|
+
initially_deferred: false,
|
|
18
|
+
argument_count: 0,
|
|
19
|
+
column_numbers: null,
|
|
20
|
+
arguments: [],
|
|
21
|
+
when_condition: null,
|
|
22
|
+
old_table: null,
|
|
23
|
+
new_table: null,
|
|
24
|
+
is_partition_clone: false,
|
|
25
|
+
parent_trigger_name: null,
|
|
26
|
+
parent_table_schema: null,
|
|
27
|
+
parent_table_name: null,
|
|
28
|
+
is_on_partitioned_table: false,
|
|
29
|
+
owner: "test",
|
|
30
|
+
definition:
|
|
31
|
+
"CREATE TRIGGER test_trigger AFTER UPDATE ON public.test_table DEFERRABLE EXECUTE FUNCTION public.test_function()",
|
|
32
|
+
comment: null,
|
|
33
|
+
};
|
|
34
|
+
const branch = new Trigger({
|
|
35
|
+
...props,
|
|
36
|
+
enabled: "D",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const change = new ReplaceTrigger({ trigger: branch });
|
|
40
|
+
|
|
41
|
+
expect(change.serialize()).toBe(
|
|
42
|
+
"CREATE OR REPLACE TRIGGER test_trigger AFTER UPDATE ON public.test_table DEFERRABLE EXECUTE FUNCTION public.test_function()",
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.ts";
|
|
2
|
+
import type { TableLikeObject } from "../../base.model.ts";
|
|
3
|
+
import type { Trigger } from "../trigger.model.ts";
|
|
4
|
+
import { AlterTriggerChange } from "./trigger.base.ts";
|
|
5
|
+
import { CreateTrigger } from "./trigger.create.ts";
|
|
6
|
+
import { DropTrigger } from "./trigger.drop.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Alter a trigger.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.postgresql.org/docs/17/sql-altertrigger.html
|
|
12
|
+
*
|
|
13
|
+
* Synopsis
|
|
14
|
+
* ```sql
|
|
15
|
+
* ALTER TRIGGER name ON table_name RENAME TO new_name
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type AlterTrigger = ReplaceTrigger;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Replace a trigger by dropping and recreating it.
|
|
23
|
+
* This is used when properties that cannot be altered via ALTER TRIGGER change.
|
|
24
|
+
*/
|
|
25
|
+
export class ReplaceTrigger extends AlterTriggerChange {
|
|
26
|
+
public readonly trigger: Trigger;
|
|
27
|
+
public readonly indexableObject?: TableLikeObject;
|
|
28
|
+
public readonly scope = "object" as const;
|
|
29
|
+
|
|
30
|
+
constructor(props: {
|
|
31
|
+
trigger: Trigger;
|
|
32
|
+
indexableObject?: TableLikeObject;
|
|
33
|
+
}) {
|
|
34
|
+
super();
|
|
35
|
+
this.trigger = props.trigger;
|
|
36
|
+
this.indexableObject = props.indexableObject;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get requires() {
|
|
40
|
+
return [this.trigger.stableId];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
serialize(): string {
|
|
44
|
+
if (this.trigger.isConstraintTrigger) {
|
|
45
|
+
const dropChange = new DropTrigger({ trigger: this.trigger });
|
|
46
|
+
const createChange = new CreateTrigger({
|
|
47
|
+
trigger: this.trigger,
|
|
48
|
+
indexableObject: this.indexableObject,
|
|
49
|
+
orReplace: false,
|
|
50
|
+
});
|
|
51
|
+
const commentSql =
|
|
52
|
+
this.trigger.comment !== null
|
|
53
|
+
? [
|
|
54
|
+
"COMMENT ON TRIGGER",
|
|
55
|
+
this.trigger.name,
|
|
56
|
+
"ON",
|
|
57
|
+
`${this.trigger.schema}.${this.trigger.table_name}`,
|
|
58
|
+
"IS",
|
|
59
|
+
quoteLiteral(this.trigger.comment),
|
|
60
|
+
].join(" ")
|
|
61
|
+
: null;
|
|
62
|
+
|
|
63
|
+
return [dropChange.serialize(), createChange.serialize(), commentSql]
|
|
64
|
+
.filter(Boolean)
|
|
65
|
+
.join(";\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const createChange = new CreateTrigger({
|
|
69
|
+
trigger: this.trigger,
|
|
70
|
+
indexableObject: this.indexableObject,
|
|
71
|
+
orReplace: true,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return createChange.serialize();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseChange } from "../../base.change.ts";
|
|
2
|
+
import type { Trigger } from "../trigger.model.ts";
|
|
3
|
+
|
|
4
|
+
abstract class BaseTriggerChange extends BaseChange {
|
|
5
|
+
abstract readonly trigger: Trigger;
|
|
6
|
+
abstract readonly scope: "object" | "comment";
|
|
7
|
+
readonly objectType: "trigger" = "trigger";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export abstract class CreateTriggerChange extends BaseTriggerChange {
|
|
11
|
+
readonly operation = "create" as const;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export abstract class AlterTriggerChange extends BaseTriggerChange {
|
|
15
|
+
readonly operation = "alter" as const;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export abstract class DropTriggerChange extends BaseTriggerChange {
|
|
19
|
+
readonly operation = "drop" as const;
|
|
20
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.ts";
|
|
2
|
+
import { stableId } from "../../utils.ts";
|
|
3
|
+
import type { Trigger } from "../trigger.model.ts";
|
|
4
|
+
import { CreateTriggerChange, DropTriggerChange } from "./trigger.base.ts";
|
|
5
|
+
|
|
6
|
+
export type CommentTrigger = CreateCommentOnTrigger | DropCommentOnTrigger;
|
|
7
|
+
|
|
8
|
+
export class CreateCommentOnTrigger extends CreateTriggerChange {
|
|
9
|
+
public readonly trigger: Trigger;
|
|
10
|
+
public readonly scope = "comment" as const;
|
|
11
|
+
|
|
12
|
+
constructor(props: { trigger: Trigger }) {
|
|
13
|
+
super();
|
|
14
|
+
this.trigger = props.trigger;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get creates() {
|
|
18
|
+
return [stableId.comment(this.trigger.stableId)];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get requires() {
|
|
22
|
+
return [this.trigger.stableId];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
serialize(): string {
|
|
26
|
+
return [
|
|
27
|
+
"COMMENT ON TRIGGER",
|
|
28
|
+
this.trigger.name,
|
|
29
|
+
"ON",
|
|
30
|
+
`${this.trigger.schema}.${this.trigger.table_name}`,
|
|
31
|
+
"IS",
|
|
32
|
+
// biome-ignore lint/style/noNonNullAssertion: trigger comment is not nullable in this case
|
|
33
|
+
quoteLiteral(this.trigger.comment!),
|
|
34
|
+
].join(" ");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class DropCommentOnTrigger extends DropTriggerChange {
|
|
39
|
+
public readonly trigger: Trigger;
|
|
40
|
+
public readonly scope = "comment" as const;
|
|
41
|
+
|
|
42
|
+
constructor(props: { trigger: Trigger }) {
|
|
43
|
+
super();
|
|
44
|
+
this.trigger = props.trigger;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get drops() {
|
|
48
|
+
return [stableId.comment(this.trigger.stableId)];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get requires() {
|
|
52
|
+
return [stableId.comment(this.trigger.stableId), this.trigger.stableId];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
serialize(): string {
|
|
56
|
+
return [
|
|
57
|
+
"COMMENT ON TRIGGER",
|
|
58
|
+
this.trigger.name,
|
|
59
|
+
"ON",
|
|
60
|
+
`${this.trigger.schema}.${this.trigger.table_name}`,
|
|
61
|
+
"IS NULL",
|
|
62
|
+
].join(" ");
|
|
63
|
+
}
|
|
64
|
+
}
|