@supabase/pg-delta 1.0.0-alpha.2 → 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/integrations/supabase.js +2 -0
- 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,175 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatObjectPrivilegeList,
|
|
3
|
+
getObjectKindPrefix,
|
|
4
|
+
} from "../../../base.privilege.ts";
|
|
5
|
+
import { stableId } from "../../../utils.ts";
|
|
6
|
+
import type { Range } from "../range.model.ts";
|
|
7
|
+
import { AlterRangeChange } from "./range.base.ts";
|
|
8
|
+
|
|
9
|
+
export type RangePrivilege =
|
|
10
|
+
| GrantRangePrivileges
|
|
11
|
+
| RevokeRangePrivileges
|
|
12
|
+
| RevokeGrantOptionRangePrivileges;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Grant privileges on a range type.
|
|
16
|
+
*
|
|
17
|
+
* @see https://www.postgresql.org/docs/17/sql-grant.html
|
|
18
|
+
*
|
|
19
|
+
* Synopsis
|
|
20
|
+
* ```sql
|
|
21
|
+
* GRANT { USAGE | ALL [ PRIVILEGES ] }
|
|
22
|
+
* ON TYPE type_name [, ...]
|
|
23
|
+
* TO role_specification [, ...] [ WITH GRANT OPTION ]
|
|
24
|
+
* [ GRANTED BY role_specification ]
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class GrantRangePrivileges extends AlterRangeChange {
|
|
28
|
+
public readonly range: Range;
|
|
29
|
+
public readonly grantee: string;
|
|
30
|
+
public readonly privileges: { privilege: string; grantable: boolean }[];
|
|
31
|
+
public readonly version: number | undefined;
|
|
32
|
+
public readonly scope = "privilege" as const;
|
|
33
|
+
|
|
34
|
+
constructor(props: {
|
|
35
|
+
range: Range;
|
|
36
|
+
grantee: string;
|
|
37
|
+
privileges: { privilege: string; grantable: boolean }[];
|
|
38
|
+
version?: number;
|
|
39
|
+
}) {
|
|
40
|
+
super();
|
|
41
|
+
this.range = props.range;
|
|
42
|
+
this.grantee = props.grantee;
|
|
43
|
+
this.privileges = props.privileges;
|
|
44
|
+
this.version = props.version;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get creates() {
|
|
48
|
+
return [stableId.acl(this.range.stableId, this.grantee)];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get requires() {
|
|
52
|
+
return [this.range.stableId, stableId.role(this.grantee)];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
serialize(): string {
|
|
56
|
+
const hasGrantable = this.privileges.some((p) => p.grantable);
|
|
57
|
+
const hasBase = this.privileges.some((p) => !p.grantable);
|
|
58
|
+
if (hasGrantable && hasBase) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"GrantRangePrivileges expects privileges with uniform grantable flag",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const withGrant = hasGrantable ? " WITH GRANT OPTION" : "";
|
|
64
|
+
const kindPrefix = getObjectKindPrefix("TYPE");
|
|
65
|
+
const list = this.privileges.map((p) => p.privilege);
|
|
66
|
+
const privSql = formatObjectPrivilegeList("TYPE", list, this.version);
|
|
67
|
+
const typeName = `${this.range.schema}.${this.range.name}`;
|
|
68
|
+
return `GRANT ${privSql} ${kindPrefix} ${typeName} TO ${this.grantee}${withGrant}`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Revoke privileges on a range type.
|
|
74
|
+
*
|
|
75
|
+
* @see https://www.postgresql.org/docs/17/sql-revoke.html
|
|
76
|
+
*
|
|
77
|
+
* Synopsis
|
|
78
|
+
* ```sql
|
|
79
|
+
* REVOKE [ GRANT OPTION FOR ]
|
|
80
|
+
* { USAGE | ALL [ PRIVILEGES ] }
|
|
81
|
+
* ON TYPE type_name [, ...]
|
|
82
|
+
* FROM role_specification [, ...]
|
|
83
|
+
* [ GRANTED BY role_specification ]
|
|
84
|
+
* [ CASCADE | RESTRICT ]
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export class RevokeRangePrivileges extends AlterRangeChange {
|
|
88
|
+
public readonly range: Range;
|
|
89
|
+
public readonly grantee: string;
|
|
90
|
+
public readonly privileges: { privilege: string; grantable: boolean }[];
|
|
91
|
+
public readonly version: number | undefined;
|
|
92
|
+
public readonly scope = "privilege" as const;
|
|
93
|
+
|
|
94
|
+
constructor(props: {
|
|
95
|
+
range: Range;
|
|
96
|
+
grantee: string;
|
|
97
|
+
privileges: { privilege: string; grantable: boolean }[];
|
|
98
|
+
version?: number;
|
|
99
|
+
}) {
|
|
100
|
+
super();
|
|
101
|
+
this.range = props.range;
|
|
102
|
+
this.grantee = props.grantee;
|
|
103
|
+
this.privileges = props.privileges;
|
|
104
|
+
this.version = props.version;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get drops() {
|
|
108
|
+
// Return ACL ID for dependency tracking, even though this is an ALTER operation
|
|
109
|
+
// Phase assignment now uses operation type, so this won't affect phase placement
|
|
110
|
+
return [stableId.acl(this.range.stableId, this.grantee)];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get requires() {
|
|
114
|
+
return [
|
|
115
|
+
stableId.acl(this.range.stableId, this.grantee),
|
|
116
|
+
this.range.stableId,
|
|
117
|
+
stableId.role(this.grantee),
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
serialize(): string {
|
|
122
|
+
const kindPrefix = getObjectKindPrefix("TYPE");
|
|
123
|
+
const list = this.privileges.map((p) => p.privilege);
|
|
124
|
+
const privSql = formatObjectPrivilegeList("TYPE", list, this.version);
|
|
125
|
+
const typeName = `${this.range.schema}.${this.range.name}`;
|
|
126
|
+
return `REVOKE ${privSql} ${kindPrefix} ${typeName} FROM ${this.grantee}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Revoke grant option for privileges on a range type.
|
|
132
|
+
*
|
|
133
|
+
* This removes the ability to grant the privilege to others, but keeps the privilege itself.
|
|
134
|
+
*
|
|
135
|
+
* @see https://www.postgresql.org/docs/17/sql-revoke.html
|
|
136
|
+
*/
|
|
137
|
+
export class RevokeGrantOptionRangePrivileges extends AlterRangeChange {
|
|
138
|
+
public readonly range: Range;
|
|
139
|
+
public readonly grantee: string;
|
|
140
|
+
public readonly privilegeNames: string[];
|
|
141
|
+
public readonly version: number | undefined;
|
|
142
|
+
public readonly scope = "privilege" as const;
|
|
143
|
+
|
|
144
|
+
constructor(props: {
|
|
145
|
+
range: Range;
|
|
146
|
+
grantee: string;
|
|
147
|
+
privilegeNames: string[];
|
|
148
|
+
version?: number;
|
|
149
|
+
}) {
|
|
150
|
+
super();
|
|
151
|
+
this.range = props.range;
|
|
152
|
+
this.grantee = props.grantee;
|
|
153
|
+
this.privilegeNames = [...new Set(props.privilegeNames)].sort();
|
|
154
|
+
this.version = props.version;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
get requires() {
|
|
158
|
+
return [
|
|
159
|
+
stableId.acl(this.range.stableId, this.grantee),
|
|
160
|
+
this.range.stableId,
|
|
161
|
+
stableId.role(this.grantee),
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
serialize(): string {
|
|
166
|
+
const kindPrefix = getObjectKindPrefix("TYPE");
|
|
167
|
+
const privSql = formatObjectPrivilegeList(
|
|
168
|
+
"TYPE",
|
|
169
|
+
this.privilegeNames,
|
|
170
|
+
this.version,
|
|
171
|
+
);
|
|
172
|
+
const typeName = `${this.range.schema}.${this.range.name}`;
|
|
173
|
+
return `REVOKE GRANT OPTION FOR ${privSql} ${kindPrefix} ${typeName} FROM ${this.grantee}`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AlterRange } from "./range.alter.ts";
|
|
2
|
+
import type { CommentRange } from "./range.comment.ts";
|
|
3
|
+
import type { CreateRange } from "./range.create.ts";
|
|
4
|
+
import type { DropRange } from "./range.drop.ts";
|
|
5
|
+
import type { RangePrivilege } from "./range.privilege.ts";
|
|
6
|
+
|
|
7
|
+
export type RangeChange =
|
|
8
|
+
| AlterRange
|
|
9
|
+
| CommentRange
|
|
10
|
+
| CreateRange
|
|
11
|
+
| DropRange
|
|
12
|
+
| RangePrivilege;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { DefaultPrivilegeState } from "../../base.default-privileges.ts";
|
|
3
|
+
import { AlterRangeChangeOwner } from "./changes/range.alter.ts";
|
|
4
|
+
import { CreateRange } from "./changes/range.create.ts";
|
|
5
|
+
import { DropRange } from "./changes/range.drop.ts";
|
|
6
|
+
import { diffRanges } from "./range.diff.ts";
|
|
7
|
+
import { Range, type RangeProps } from "./range.model.ts";
|
|
8
|
+
|
|
9
|
+
const base: RangeProps = {
|
|
10
|
+
schema: "public",
|
|
11
|
+
name: "ts_custom",
|
|
12
|
+
owner: "o1",
|
|
13
|
+
subtype_schema: "pg_catalog",
|
|
14
|
+
subtype_str: "int4",
|
|
15
|
+
collation: null,
|
|
16
|
+
canonical_function_schema: null,
|
|
17
|
+
canonical_function_name: null,
|
|
18
|
+
subtype_diff_schema: null,
|
|
19
|
+
subtype_diff_name: null,
|
|
20
|
+
subtype_opclass_schema: null,
|
|
21
|
+
subtype_opclass_name: null,
|
|
22
|
+
comment: null,
|
|
23
|
+
privileges: [],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const testContext = {
|
|
27
|
+
version: 170000,
|
|
28
|
+
currentUser: "postgres",
|
|
29
|
+
defaultPrivilegeState: new DefaultPrivilegeState({}),
|
|
30
|
+
mainRoles: {},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe.concurrent("range.diff", () => {
|
|
34
|
+
test("create and drop", () => {
|
|
35
|
+
const r = new Range(base);
|
|
36
|
+
const created = diffRanges(testContext, {}, { [r.stableId]: r });
|
|
37
|
+
expect(created[0]).toBeInstanceOf(CreateRange);
|
|
38
|
+
const dropped = diffRanges(testContext, { [r.stableId]: r }, {});
|
|
39
|
+
expect(dropped[0]).toBeInstanceOf(DropRange);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("alter owner", () => {
|
|
43
|
+
const main = new Range(base);
|
|
44
|
+
const branch = new Range({ ...base, owner: "o2" });
|
|
45
|
+
const changes = diffRanges(
|
|
46
|
+
testContext,
|
|
47
|
+
{ [main.stableId]: main },
|
|
48
|
+
{ [branch.stableId]: branch },
|
|
49
|
+
);
|
|
50
|
+
expect(changes[0]).toBeInstanceOf(AlterRangeChangeOwner);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("drop and create when non-alterable property changes", () => {
|
|
54
|
+
const main = new Range(base);
|
|
55
|
+
const branch = new Range({
|
|
56
|
+
...base,
|
|
57
|
+
subtype_schema: "pg_catalog",
|
|
58
|
+
subtype_str: "text",
|
|
59
|
+
collation: "en_US",
|
|
60
|
+
});
|
|
61
|
+
const changes = diffRanges(
|
|
62
|
+
testContext,
|
|
63
|
+
{ [main.stableId]: main },
|
|
64
|
+
{ [branch.stableId]: branch },
|
|
65
|
+
);
|
|
66
|
+
expect(changes).toHaveLength(2);
|
|
67
|
+
expect(changes[0]).toBeInstanceOf(DropRange);
|
|
68
|
+
expect(changes[1]).toBeInstanceOf(CreateRange);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import type { DefaultPrivilegeState } from "../../base.default-privileges.ts";
|
|
2
|
+
import { diffObjects } from "../../base.diff.ts";
|
|
3
|
+
import {
|
|
4
|
+
diffPrivileges,
|
|
5
|
+
filterPublicBuiltInDefaults,
|
|
6
|
+
groupPrivilegesByGrantable,
|
|
7
|
+
} from "../../base.privilege-diff.ts";
|
|
8
|
+
import type { Role } from "../../role/role.model.ts";
|
|
9
|
+
import { hasNonAlterableChanges } from "../../utils.ts";
|
|
10
|
+
import { AlterRangeChangeOwner } from "./changes/range.alter.ts";
|
|
11
|
+
import {
|
|
12
|
+
CreateCommentOnRange,
|
|
13
|
+
DropCommentOnRange,
|
|
14
|
+
} from "./changes/range.comment.ts";
|
|
15
|
+
import { CreateRange } from "./changes/range.create.ts";
|
|
16
|
+
import { DropRange } from "./changes/range.drop.ts";
|
|
17
|
+
import {
|
|
18
|
+
GrantRangePrivileges,
|
|
19
|
+
RevokeGrantOptionRangePrivileges,
|
|
20
|
+
RevokeRangePrivileges,
|
|
21
|
+
} from "./changes/range.privilege.ts";
|
|
22
|
+
import type { RangeChange } from "./changes/range.types.ts";
|
|
23
|
+
import type { Range } from "./range.model.ts";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Diff two sets of range types from main and branch catalogs.
|
|
27
|
+
*
|
|
28
|
+
* @param ctx - Context containing version, currentUser, and defaultPrivilegeState
|
|
29
|
+
* @param main - The ranges in the main catalog.
|
|
30
|
+
* @param branch - The ranges in the branch catalog.
|
|
31
|
+
* @returns A list of changes to apply to main to make it match branch.
|
|
32
|
+
*/
|
|
33
|
+
export function diffRanges(
|
|
34
|
+
ctx: {
|
|
35
|
+
version: number;
|
|
36
|
+
currentUser: string;
|
|
37
|
+
defaultPrivilegeState: DefaultPrivilegeState;
|
|
38
|
+
mainRoles: Record<string, Role>;
|
|
39
|
+
},
|
|
40
|
+
main: Record<string, Range>,
|
|
41
|
+
branch: Record<string, Range>,
|
|
42
|
+
): RangeChange[] {
|
|
43
|
+
const { created, dropped, altered } = diffObjects(main, branch);
|
|
44
|
+
|
|
45
|
+
const changes: RangeChange[] = [];
|
|
46
|
+
|
|
47
|
+
for (const id of created) {
|
|
48
|
+
const createdRange = branch[id];
|
|
49
|
+
changes.push(new CreateRange({ range: createdRange }));
|
|
50
|
+
|
|
51
|
+
// OWNER: If the range type should be owned by someone other than the current user,
|
|
52
|
+
// emit ALTER TYPE ... OWNER TO after creation
|
|
53
|
+
if (createdRange.owner !== ctx.currentUser) {
|
|
54
|
+
changes.push(
|
|
55
|
+
new AlterRangeChangeOwner({
|
|
56
|
+
range: createdRange,
|
|
57
|
+
owner: createdRange.owner,
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (createdRange.comment !== null) {
|
|
63
|
+
changes.push(new CreateCommentOnRange({ range: createdRange }));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// PRIVILEGES: For created objects, compare against default privileges state
|
|
67
|
+
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
68
|
+
// so objects are created with the default privileges state in effect.
|
|
69
|
+
// We compare default privileges against desired privileges to generate REVOKE/GRANT statements
|
|
70
|
+
// needed to reach the final desired state.
|
|
71
|
+
const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(
|
|
72
|
+
ctx.currentUser,
|
|
73
|
+
"range",
|
|
74
|
+
createdRange.schema ?? "",
|
|
75
|
+
);
|
|
76
|
+
// Filter out PUBLIC's built-in default USAGE privilege (PostgreSQL grants it automatically)
|
|
77
|
+
// Reference: https://www.postgresql.org/docs/17/ddl-priv.html Table 5.2
|
|
78
|
+
// This prevents generating unnecessary "GRANT USAGE TO PUBLIC" statements
|
|
79
|
+
const desiredPrivileges = filterPublicBuiltInDefaults(
|
|
80
|
+
"range",
|
|
81
|
+
createdRange.privileges,
|
|
82
|
+
);
|
|
83
|
+
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
84
|
+
// and shouldn't be compared. Use the range owner as the reference.
|
|
85
|
+
const privilegeResults = diffPrivileges(
|
|
86
|
+
effectiveDefaults,
|
|
87
|
+
desiredPrivileges,
|
|
88
|
+
createdRange.owner,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Generate grant changes
|
|
92
|
+
for (const [grantee, result] of privilegeResults) {
|
|
93
|
+
if (result.grants.length > 0) {
|
|
94
|
+
const grantGroups = groupPrivilegesByGrantable(result.grants);
|
|
95
|
+
for (const [grantable, list] of grantGroups) {
|
|
96
|
+
void grantable;
|
|
97
|
+
changes.push(
|
|
98
|
+
new GrantRangePrivileges({
|
|
99
|
+
range: createdRange,
|
|
100
|
+
grantee,
|
|
101
|
+
privileges: list,
|
|
102
|
+
version: ctx.version,
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Generate revoke changes
|
|
109
|
+
if (result.revokes.length > 0) {
|
|
110
|
+
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
111
|
+
for (const [grantable, list] of revokeGroups) {
|
|
112
|
+
void grantable;
|
|
113
|
+
changes.push(
|
|
114
|
+
new RevokeRangePrivileges({
|
|
115
|
+
range: createdRange,
|
|
116
|
+
grantee,
|
|
117
|
+
privileges: list,
|
|
118
|
+
version: ctx.version,
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Generate revoke grant option changes
|
|
125
|
+
if (result.revokeGrantOption.length > 0) {
|
|
126
|
+
changes.push(
|
|
127
|
+
new RevokeGrantOptionRangePrivileges({
|
|
128
|
+
range: createdRange,
|
|
129
|
+
grantee,
|
|
130
|
+
privilegeNames: result.revokeGrantOption,
|
|
131
|
+
version: ctx.version,
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const id of dropped) {
|
|
139
|
+
changes.push(new DropRange({ range: main[id] }));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const id of altered) {
|
|
143
|
+
const mainRange = main[id];
|
|
144
|
+
const branchRange = branch[id];
|
|
145
|
+
|
|
146
|
+
const NON_ALTERABLE_FIELDS: Array<keyof Range> = [
|
|
147
|
+
// Changes to these require DROP + CREATE
|
|
148
|
+
"subtype_schema",
|
|
149
|
+
"subtype_str",
|
|
150
|
+
"collation",
|
|
151
|
+
"canonical_function_schema",
|
|
152
|
+
"canonical_function_name",
|
|
153
|
+
"subtype_diff_schema",
|
|
154
|
+
"subtype_diff_name",
|
|
155
|
+
"subtype_opclass_schema",
|
|
156
|
+
"subtype_opclass_name",
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
const nonAlterablePropsChanged = hasNonAlterableChanges(
|
|
160
|
+
mainRange,
|
|
161
|
+
branchRange,
|
|
162
|
+
NON_ALTERABLE_FIELDS,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
if (nonAlterablePropsChanged) {
|
|
166
|
+
changes.push(
|
|
167
|
+
new DropRange({ range: mainRange }),
|
|
168
|
+
new CreateRange({ range: branchRange }),
|
|
169
|
+
);
|
|
170
|
+
} else {
|
|
171
|
+
if (mainRange.owner !== branchRange.owner) {
|
|
172
|
+
changes.push(
|
|
173
|
+
new AlterRangeChangeOwner({
|
|
174
|
+
range: mainRange,
|
|
175
|
+
owner: branchRange.owner,
|
|
176
|
+
}),
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// COMMENT
|
|
181
|
+
if (mainRange.comment !== branchRange.comment) {
|
|
182
|
+
if (branchRange.comment === null) {
|
|
183
|
+
changes.push(new DropCommentOnRange({ range: mainRange }));
|
|
184
|
+
} else {
|
|
185
|
+
changes.push(new CreateCommentOnRange({ range: branchRange }));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// PRIVILEGES
|
|
190
|
+
// Filter out PUBLIC's built-in default USAGE privilege from main catalog
|
|
191
|
+
// (PostgreSQL grants it automatically, so we shouldn't compare it)
|
|
192
|
+
const mainPrivilegesFiltered = filterPublicBuiltInDefaults(
|
|
193
|
+
"range",
|
|
194
|
+
mainRange.privileges,
|
|
195
|
+
);
|
|
196
|
+
// Filter out PUBLIC's built-in default USAGE privilege from branch catalog
|
|
197
|
+
const branchPrivilegesFiltered = filterPublicBuiltInDefaults(
|
|
198
|
+
"range",
|
|
199
|
+
branchRange.privileges,
|
|
200
|
+
);
|
|
201
|
+
// Filter out owner privileges - owner always has ALL privileges implicitly
|
|
202
|
+
// and shouldn't be compared. Use branch owner as the reference.
|
|
203
|
+
const privilegeResults = diffPrivileges(
|
|
204
|
+
mainPrivilegesFiltered,
|
|
205
|
+
branchPrivilegesFiltered,
|
|
206
|
+
branchRange.owner,
|
|
207
|
+
ctx.mainRoles,
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
for (const [grantee, result] of privilegeResults) {
|
|
211
|
+
// Generate grant changes
|
|
212
|
+
if (result.grants.length > 0) {
|
|
213
|
+
const grantGroups = groupPrivilegesByGrantable(result.grants);
|
|
214
|
+
for (const [grantable, list] of grantGroups) {
|
|
215
|
+
void grantable;
|
|
216
|
+
changes.push(
|
|
217
|
+
new GrantRangePrivileges({
|
|
218
|
+
range: branchRange,
|
|
219
|
+
grantee,
|
|
220
|
+
privileges: list,
|
|
221
|
+
version: ctx.version,
|
|
222
|
+
}),
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Generate revoke changes
|
|
228
|
+
if (result.revokes.length > 0) {
|
|
229
|
+
const revokeGroups = groupPrivilegesByGrantable(result.revokes);
|
|
230
|
+
for (const [grantable, list] of revokeGroups) {
|
|
231
|
+
void grantable;
|
|
232
|
+
changes.push(
|
|
233
|
+
new RevokeRangePrivileges({
|
|
234
|
+
range: mainRange,
|
|
235
|
+
grantee,
|
|
236
|
+
privileges: list,
|
|
237
|
+
version: ctx.version,
|
|
238
|
+
}),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Generate revoke grant option changes
|
|
244
|
+
if (result.revokeGrantOption.length > 0) {
|
|
245
|
+
changes.push(
|
|
246
|
+
new RevokeGrantOptionRangePrivileges({
|
|
247
|
+
range: mainRange,
|
|
248
|
+
grantee,
|
|
249
|
+
privilegeNames: result.revokeGrantOption,
|
|
250
|
+
version: ctx.version,
|
|
251
|
+
}),
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return changes;
|
|
259
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { sql } from "@ts-safeql/sql-tag";
|
|
2
|
+
import type { Pool } from "pg";
|
|
3
|
+
import z from "zod";
|
|
4
|
+
import { BasePgModel } from "../../base.model.ts";
|
|
5
|
+
import {
|
|
6
|
+
type PrivilegeProps,
|
|
7
|
+
privilegePropsSchema,
|
|
8
|
+
} from "../../base.privilege-diff.ts";
|
|
9
|
+
|
|
10
|
+
const rangePropsSchema = z.object({
|
|
11
|
+
schema: z.string(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
owner: z.string(),
|
|
14
|
+
comment: z.string().nullable(),
|
|
15
|
+
|
|
16
|
+
// Subtype information
|
|
17
|
+
subtype_schema: z.string(),
|
|
18
|
+
subtype_str: z.string(),
|
|
19
|
+
|
|
20
|
+
// Optional, only present when non-default relative to subtype
|
|
21
|
+
collation: z.string().nullable(),
|
|
22
|
+
|
|
23
|
+
// Canonical and diff functions when present (non-default)
|
|
24
|
+
canonical_function_schema: z.string().nullable(),
|
|
25
|
+
canonical_function_name: z.string().nullable(),
|
|
26
|
+
subtype_diff_schema: z.string().nullable(),
|
|
27
|
+
subtype_diff_name: z.string().nullable(),
|
|
28
|
+
|
|
29
|
+
// Optional: print only when non-default (see extractor logic)
|
|
30
|
+
subtype_opclass_schema: z.string().nullable(),
|
|
31
|
+
subtype_opclass_name: z.string().nullable(),
|
|
32
|
+
privileges: z.array(privilegePropsSchema),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
type RangePrivilegeProps = PrivilegeProps;
|
|
36
|
+
export type RangeProps = z.infer<typeof rangePropsSchema>;
|
|
37
|
+
|
|
38
|
+
export class Range extends BasePgModel {
|
|
39
|
+
public readonly schema: RangeProps["schema"];
|
|
40
|
+
public readonly name: RangeProps["name"];
|
|
41
|
+
public readonly owner: RangeProps["owner"];
|
|
42
|
+
public readonly comment: RangeProps["comment"];
|
|
43
|
+
|
|
44
|
+
public readonly subtype_schema: RangeProps["subtype_schema"];
|
|
45
|
+
public readonly subtype_str: RangeProps["subtype_str"];
|
|
46
|
+
|
|
47
|
+
public readonly collation: RangeProps["collation"];
|
|
48
|
+
|
|
49
|
+
public readonly canonical_function_schema: RangeProps["canonical_function_schema"];
|
|
50
|
+
public readonly canonical_function_name: RangeProps["canonical_function_name"];
|
|
51
|
+
public readonly subtype_diff_schema: RangeProps["subtype_diff_schema"];
|
|
52
|
+
public readonly subtype_diff_name: RangeProps["subtype_diff_name"];
|
|
53
|
+
|
|
54
|
+
public readonly subtype_opclass_schema: RangeProps["subtype_opclass_schema"];
|
|
55
|
+
public readonly subtype_opclass_name: RangeProps["subtype_opclass_name"];
|
|
56
|
+
public readonly privileges: RangePrivilegeProps[];
|
|
57
|
+
|
|
58
|
+
constructor(props: RangeProps) {
|
|
59
|
+
super();
|
|
60
|
+
|
|
61
|
+
// Identity fields
|
|
62
|
+
this.schema = props.schema;
|
|
63
|
+
this.name = props.name;
|
|
64
|
+
|
|
65
|
+
// Data fields
|
|
66
|
+
this.owner = props.owner;
|
|
67
|
+
this.comment = props.comment;
|
|
68
|
+
this.subtype_schema = props.subtype_schema;
|
|
69
|
+
this.subtype_str = props.subtype_str;
|
|
70
|
+
this.collation = props.collation;
|
|
71
|
+
this.canonical_function_schema = props.canonical_function_schema;
|
|
72
|
+
this.canonical_function_name = props.canonical_function_name;
|
|
73
|
+
this.subtype_diff_schema = props.subtype_diff_schema;
|
|
74
|
+
this.subtype_diff_name = props.subtype_diff_name;
|
|
75
|
+
this.subtype_opclass_schema = props.subtype_opclass_schema;
|
|
76
|
+
this.subtype_opclass_name = props.subtype_opclass_name;
|
|
77
|
+
this.privileges = props.privileges;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get stableId(): `type:${string}` {
|
|
81
|
+
return `type:${this.schema}.${this.name}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get identityFields() {
|
|
85
|
+
return {
|
|
86
|
+
schema: this.schema,
|
|
87
|
+
name: this.name,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get dataFields() {
|
|
92
|
+
return {
|
|
93
|
+
owner: this.owner,
|
|
94
|
+
subtype_schema: this.subtype_schema,
|
|
95
|
+
subtype_str: this.subtype_str,
|
|
96
|
+
collation: this.collation,
|
|
97
|
+
canonical_function_schema: this.canonical_function_schema,
|
|
98
|
+
canonical_function_name: this.canonical_function_name,
|
|
99
|
+
subtype_diff_schema: this.subtype_diff_schema,
|
|
100
|
+
subtype_diff_name: this.subtype_diff_name,
|
|
101
|
+
subtype_opclass_schema: this.subtype_opclass_schema,
|
|
102
|
+
subtype_opclass_name: this.subtype_opclass_name,
|
|
103
|
+
comment: this.comment,
|
|
104
|
+
privileges: this.privileges,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Extract all range types from the database.
|
|
111
|
+
*
|
|
112
|
+
* We intentionally capture only non-default options for CREATE TYPE AS RANGE:
|
|
113
|
+
* - SUBTYPE is required and always present
|
|
114
|
+
* - SUBTYPE_OPCLASS is included only when it differs from the default btree opclass
|
|
115
|
+
* - COLLATION is included only when it differs from the subtype's typcollation
|
|
116
|
+
* - CANONICAL and SUBTYPE_DIFF are included only when set
|
|
117
|
+
* - MULTIRANGE_TYPE_NAME is not included (we currently do not attempt to infer
|
|
118
|
+
* whether it differs from the default auto-generated name)
|
|
119
|
+
*/
|
|
120
|
+
export async function extractRanges(pool: Pool): Promise<Range[]> {
|
|
121
|
+
const { rows } = await pool.query<RangeProps>(sql`
|
|
122
|
+
with extension_oids as (
|
|
123
|
+
select objid from pg_depend d
|
|
124
|
+
where d.refclassid = 'pg_extension'::regclass and d.classid = 'pg_type'::regclass
|
|
125
|
+
), default_btree_opclass as (
|
|
126
|
+
-- For each input type, find its default btree operator class
|
|
127
|
+
select oc2.opcintype as type_oid, oc2.oid as opclass_oid
|
|
128
|
+
from pg_opclass oc2
|
|
129
|
+
join pg_am am on am.oid = oc2.opcmethod and am.amname = 'btree'
|
|
130
|
+
where oc2.opcdefault
|
|
131
|
+
)
|
|
132
|
+
select
|
|
133
|
+
-- range type identity
|
|
134
|
+
t.typnamespace::regnamespace::text as schema,
|
|
135
|
+
quote_ident(t.typname) as name,
|
|
136
|
+
t.typowner::regrole::text as owner,
|
|
137
|
+
obj_description(t.oid, 'pg_type') as comment,
|
|
138
|
+
|
|
139
|
+
-- subtype info
|
|
140
|
+
subt.typnamespace::regnamespace::text as subtype_schema,
|
|
141
|
+
format_type(r.rngsubtype, 0) as subtype_str,
|
|
142
|
+
|
|
143
|
+
-- include collation only if not default
|
|
144
|
+
case when r.rngcollation is not null and r.rngcollation <> 0 and r.rngcollation <> subt.typcollation then quote_ident(c.collname) else null end as collation,
|
|
145
|
+
|
|
146
|
+
-- include canonical/subtype_diff when set
|
|
147
|
+
case when r.rngcanonical <> 0 then pn_subcanon.nspname::regnamespace::text else null end as canonical_function_schema,
|
|
148
|
+
case when r.rngcanonical <> 0 then quote_ident(p_subcanon.proname) else null end as canonical_function_name,
|
|
149
|
+
case when r.rngsubdiff <> 0 then pn_subdiff.nspname::regnamespace::text else null end as subtype_diff_schema,
|
|
150
|
+
case when r.rngsubdiff <> 0 then quote_ident(p_subdiff.proname) else null end as subtype_diff_name,
|
|
151
|
+
|
|
152
|
+
-- include opclass only when not default for btree
|
|
153
|
+
case when r.rngsubopc is not null and r.rngsubopc <> 0 and r.rngsubopc <> dbo.opclass_oid then opc.opcnamespace::regnamespace::text else null end as subtype_opclass_schema,
|
|
154
|
+
case when r.rngsubopc is not null and r.rngsubopc <> 0 and r.rngsubopc <> dbo.opclass_oid then quote_ident(opc.opcname) else null end as subtype_opclass_name,
|
|
155
|
+
|
|
156
|
+
-- privileges
|
|
157
|
+
coalesce(
|
|
158
|
+
(
|
|
159
|
+
select json_agg(
|
|
160
|
+
json_build_object(
|
|
161
|
+
'grantee', case when x.grantee = 0 then 'PUBLIC' else x.grantee::regrole::text end,
|
|
162
|
+
'privilege', x.privilege_type,
|
|
163
|
+
'grantable', x.is_grantable
|
|
164
|
+
)
|
|
165
|
+
order by x.grantee, x.privilege_type
|
|
166
|
+
)
|
|
167
|
+
from lateral aclexplode(t.typacl) as x(grantor, grantee, privilege_type, is_grantable)
|
|
168
|
+
), '[]'
|
|
169
|
+
) as privileges
|
|
170
|
+
from pg_catalog.pg_range r
|
|
171
|
+
join pg_catalog.pg_type t on t.oid = r.rngtypid
|
|
172
|
+
join pg_catalog.pg_type subt on subt.oid = r.rngsubtype
|
|
173
|
+
left join default_btree_opclass dbo on dbo.type_oid = r.rngsubtype
|
|
174
|
+
left join pg_catalog.pg_opclass opc on opc.oid = r.rngsubopc
|
|
175
|
+
left join pg_catalog.pg_collation c on c.oid = r.rngcollation
|
|
176
|
+
left join pg_catalog.pg_proc p_subcanon on p_subcanon.oid = r.rngcanonical
|
|
177
|
+
left join pg_catalog.pg_namespace pn_subcanon on pn_subcanon.oid = p_subcanon.pronamespace
|
|
178
|
+
left join pg_catalog.pg_proc p_subdiff on p_subdiff.oid = r.rngsubdiff
|
|
179
|
+
left join pg_catalog.pg_namespace pn_subdiff on pn_subdiff.oid = p_subdiff.pronamespace
|
|
180
|
+
left outer join extension_oids e on t.oid = e.objid
|
|
181
|
+
where not t.typnamespace::regnamespace::text like any(array['pg\_%', 'information\_schema'])
|
|
182
|
+
and e.objid is null
|
|
183
|
+
order by 1, 2
|
|
184
|
+
`);
|
|
185
|
+
const validated = rows.map((row: unknown) => rangePropsSchema.parse(row));
|
|
186
|
+
return validated.map((row: RangeProps) => new Range(row));
|
|
187
|
+
}
|