@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,299 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import type { Change } from "../change.types.ts";
|
|
3
|
+
import type { Role } from "./role/role.model.ts";
|
|
4
|
+
import { stableId } from "./utils.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Privilege properties that all privilege objects share.
|
|
8
|
+
*/
|
|
9
|
+
export const privilegePropsSchema = z.object({
|
|
10
|
+
grantee: z.string(),
|
|
11
|
+
privilege: z.string(),
|
|
12
|
+
grantable: z.boolean(),
|
|
13
|
+
columns: z.array(z.string()).nullable().optional(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type PrivilegeProps = z.infer<typeof privilegePropsSchema>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Result of privilege diffing for a single grantee
|
|
20
|
+
*/
|
|
21
|
+
interface PrivilegeDiffResult<T extends PrivilegeProps> {
|
|
22
|
+
grants: T[];
|
|
23
|
+
revokes: T[];
|
|
24
|
+
revokeGrantOption: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Groups privileges by grantee for efficient diffing
|
|
29
|
+
*/
|
|
30
|
+
function groupPrivilegesByGrantee<T extends PrivilegeProps>(
|
|
31
|
+
privileges: T[],
|
|
32
|
+
): Map<string, T[]> {
|
|
33
|
+
const byGrantee = new Map<string, T[]>();
|
|
34
|
+
|
|
35
|
+
for (const privilege of privileges) {
|
|
36
|
+
const existing = byGrantee.get(privilege.grantee) || [];
|
|
37
|
+
existing.push(privilege);
|
|
38
|
+
byGrantee.set(privilege.grantee, existing);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return byGrantee;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Diffs privileges for a single grantee between main and branch
|
|
46
|
+
*/
|
|
47
|
+
function diffPrivilegesForGrantee<T extends PrivilegeProps>(
|
|
48
|
+
mainPrivs: T[],
|
|
49
|
+
branchPrivs: T[],
|
|
50
|
+
): PrivilegeDiffResult<T> {
|
|
51
|
+
// Create comparison key - always include columns (null for object-level privileges)
|
|
52
|
+
const toKey = (p: T) => {
|
|
53
|
+
const cols = p.columns || [];
|
|
54
|
+
return `${p.privilege}:${p.grantable}:${cols.sort().join(",")}`;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Create key-to-object mappings to retain original data structures
|
|
58
|
+
const mainKeyToObj = new Map(mainPrivs.map((p) => [toKey(p), p]));
|
|
59
|
+
const branchKeyToObj = new Map(branchPrivs.map((p) => [toKey(p), p]));
|
|
60
|
+
|
|
61
|
+
const aSet = new Set(mainPrivs.map(toKey));
|
|
62
|
+
const bSet = new Set(branchPrivs.map(toKey));
|
|
63
|
+
|
|
64
|
+
const grants: T[] = [];
|
|
65
|
+
const revokes: T[] = [];
|
|
66
|
+
const revokeGrantOption: string[] = [];
|
|
67
|
+
|
|
68
|
+
// Find privileges to grant
|
|
69
|
+
for (const key of bSet) {
|
|
70
|
+
if (!aSet.has(key)) {
|
|
71
|
+
const obj = branchKeyToObj.get(key);
|
|
72
|
+
if (obj) grants.push(obj);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Find privileges to revoke
|
|
77
|
+
for (const key of aSet) {
|
|
78
|
+
if (!bSet.has(key)) {
|
|
79
|
+
const obj = mainKeyToObj.get(key);
|
|
80
|
+
if (!obj) continue;
|
|
81
|
+
|
|
82
|
+
const wasGrantable = obj.grantable;
|
|
83
|
+
|
|
84
|
+
// Upgrade: base -> with grant option (no base revoke)
|
|
85
|
+
const upgradedKey = key.replace(":false", ":true");
|
|
86
|
+
const upgraded = !wasGrantable && bSet.has(upgradedKey);
|
|
87
|
+
if (upgraded) continue;
|
|
88
|
+
|
|
89
|
+
// If only grantable flipped from true to false, emit REVOKE GRANT OPTION FOR
|
|
90
|
+
const stillHasBase = checkStillHasBase(branchPrivs, obj.privilege, key);
|
|
91
|
+
if (wasGrantable && stillHasBase) {
|
|
92
|
+
revokeGrantOption.push(obj.privilege);
|
|
93
|
+
} else {
|
|
94
|
+
revokes.push(obj);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { grants, revokes, revokeGrantOption };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Check if a privilege still exists in the target set
|
|
104
|
+
*/
|
|
105
|
+
function checkStillHasBase<T extends PrivilegeProps>(
|
|
106
|
+
targetPrivs: T[],
|
|
107
|
+
privilege: string,
|
|
108
|
+
key: string,
|
|
109
|
+
): boolean {
|
|
110
|
+
const [, , columnsStr] = key.split(":");
|
|
111
|
+
return targetPrivs.some(
|
|
112
|
+
(p) =>
|
|
113
|
+
p.privilege === privilege &&
|
|
114
|
+
(p.columns || []).sort().join(",") === columnsStr,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Groups privileges by grantable flag for efficient SQL generation
|
|
120
|
+
*/
|
|
121
|
+
export function groupPrivilegesByGrantable<T extends PrivilegeProps>(
|
|
122
|
+
privileges: T[],
|
|
123
|
+
): Map<boolean, T[]> {
|
|
124
|
+
const groups = new Map<boolean, T[]>();
|
|
125
|
+
|
|
126
|
+
for (const privilege of privileges) {
|
|
127
|
+
const arr = groups.get(privilege.grantable) ?? [];
|
|
128
|
+
arr.push(privilege);
|
|
129
|
+
groups.set(privilege.grantable, arr);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return groups;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Groups privileges by columns and grantable flag
|
|
137
|
+
*/
|
|
138
|
+
export function groupPrivilegesByColumns<T extends PrivilegeProps>(
|
|
139
|
+
privileges: T[],
|
|
140
|
+
): Map<string, { columns?: string[]; byGrant: Map<boolean, Set<string>> }> {
|
|
141
|
+
const groups = new Map<
|
|
142
|
+
string,
|
|
143
|
+
{ columns?: string[]; byGrant: Map<boolean, Set<string>> }
|
|
144
|
+
>();
|
|
145
|
+
|
|
146
|
+
for (const privilege of privileges) {
|
|
147
|
+
const key = privilege.columns ? privilege.columns.sort().join(",") : "";
|
|
148
|
+
|
|
149
|
+
if (!groups.has(key)) {
|
|
150
|
+
groups.set(key, {
|
|
151
|
+
columns: privilege.columns ? [...privilege.columns] : undefined,
|
|
152
|
+
byGrant: new Map(),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const group = groups.get(key);
|
|
157
|
+
if (!group) continue;
|
|
158
|
+
|
|
159
|
+
if (!group.byGrant.has(privilege.grantable)) {
|
|
160
|
+
group.byGrant.set(privilege.grantable, new Set());
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const privSet = group.byGrant.get(privilege.grantable);
|
|
164
|
+
if (!privSet) continue;
|
|
165
|
+
|
|
166
|
+
privSet.add(privilege.privilege);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return groups;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Filters out PUBLIC's built-in default privileges that PostgreSQL automatically grants
|
|
174
|
+
* when creating certain object types. This prevents generating unnecessary GRANT statements
|
|
175
|
+
* for privileges that PostgreSQL grants automatically.
|
|
176
|
+
*
|
|
177
|
+
* Reference: PostgreSQL 17 Documentation, Table 5.2 "Summary of Access Privileges"
|
|
178
|
+
* https://www.postgresql.org/docs/17/ddl-priv.html
|
|
179
|
+
*
|
|
180
|
+
* Objects with default PUBLIC privileges:
|
|
181
|
+
* - Functions/Procedures/Aggregates: EXECUTE
|
|
182
|
+
* - Types/Domains/Enums/Ranges/Composite Types: USAGE
|
|
183
|
+
* - Languages: USAGE
|
|
184
|
+
*
|
|
185
|
+
* Objects WITHOUT default PUBLIC privileges (so we should generate GRANT statements):
|
|
186
|
+
* - Tables, Views, Materialized Views, Sequences, Schemas, etc.
|
|
187
|
+
*/
|
|
188
|
+
export function filterPublicBuiltInDefaults<T extends PrivilegeProps>(
|
|
189
|
+
objectType: Change["objectType"],
|
|
190
|
+
privileges: T[],
|
|
191
|
+
): T[] {
|
|
192
|
+
// Only filter PUBLIC privileges
|
|
193
|
+
return privileges.filter((priv) => {
|
|
194
|
+
if (priv.grantee !== "PUBLIC") {
|
|
195
|
+
return true; // Keep all non-PUBLIC privileges
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Check if this is a built-in default privilege for this object type
|
|
199
|
+
switch (objectType) {
|
|
200
|
+
case "procedure":
|
|
201
|
+
case "aggregate":
|
|
202
|
+
// Functions/Procedures/Aggregates: EXECUTE is granted to PUBLIC by default
|
|
203
|
+
// Filter it out so we don't generate unnecessary GRANT EXECUTE TO PUBLIC
|
|
204
|
+
return priv.privilege !== "EXECUTE";
|
|
205
|
+
|
|
206
|
+
case "domain":
|
|
207
|
+
case "enum":
|
|
208
|
+
case "range":
|
|
209
|
+
case "composite_type":
|
|
210
|
+
// Types/Domains/Enums/Ranges/Composite Types: USAGE is granted to PUBLIC by default
|
|
211
|
+
// Filter it out so we don't generate unnecessary GRANT USAGE TO PUBLIC
|
|
212
|
+
return priv.privilege !== "USAGE";
|
|
213
|
+
|
|
214
|
+
case "language":
|
|
215
|
+
// Languages: USAGE is granted to PUBLIC by default
|
|
216
|
+
// Filter it out so we don't generate unnecessary GRANT USAGE TO PUBLIC
|
|
217
|
+
return priv.privilege !== "USAGE";
|
|
218
|
+
|
|
219
|
+
default:
|
|
220
|
+
// For other object types (tables, views, sequences, schemas, etc.),
|
|
221
|
+
// PUBLIC has NO default privileges, so we should keep all PUBLIC privileges
|
|
222
|
+
// and generate GRANT statements for them
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Filter out owner privileges from a privilege list.
|
|
230
|
+
* Owner privileges are implicit (owner always has ALL) and shouldn't be compared.
|
|
231
|
+
*/
|
|
232
|
+
function filterOwnerPrivileges<T extends PrivilegeProps>(
|
|
233
|
+
privileges: T[],
|
|
234
|
+
owner: string,
|
|
235
|
+
): T[] {
|
|
236
|
+
return privileges.filter((p) => p.grantee !== owner);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Filter out privileges for superuser roles, as PostgreSQL doesn't store
|
|
241
|
+
* GRANTs to superusers in relacl (they already have all privileges implicitly).
|
|
242
|
+
* Reference: https://www.postgresql.org/docs/current/role-attributes.html
|
|
243
|
+
*/
|
|
244
|
+
function filterSuperuserPrivileges<T extends PrivilegeProps>(
|
|
245
|
+
privileges: T[],
|
|
246
|
+
mainRoles?: Record<string, Role>,
|
|
247
|
+
): T[] {
|
|
248
|
+
if (!mainRoles) return privileges;
|
|
249
|
+
return privileges.filter((priv) => {
|
|
250
|
+
const role = mainRoles[stableId.role(priv.grantee)];
|
|
251
|
+
return !role?.is_superuser;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Generic privilege diffing function that works for any object type
|
|
257
|
+
*/
|
|
258
|
+
export function diffPrivileges<T extends PrivilegeProps>(
|
|
259
|
+
mainPrivileges: T[],
|
|
260
|
+
branchPrivileges: T[],
|
|
261
|
+
owner?: string,
|
|
262
|
+
mainRoles?: Record<string, Role>,
|
|
263
|
+
): Map<string, PrivilegeDiffResult<T>> {
|
|
264
|
+
// Filter out superuser privileges from branch - PostgreSQL doesn't store GRANTs
|
|
265
|
+
// to superusers in relacl because they already have all privileges implicitly
|
|
266
|
+
const branchPrivilegesFiltered = filterSuperuserPrivileges(
|
|
267
|
+
branchPrivileges,
|
|
268
|
+
mainRoles,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// Filter out owner privileges if owner is provided
|
|
272
|
+
const mainFiltered = owner
|
|
273
|
+
? filterOwnerPrivileges(mainPrivileges, owner)
|
|
274
|
+
: mainPrivileges;
|
|
275
|
+
const branchFiltered = owner
|
|
276
|
+
? filterOwnerPrivileges(branchPrivilegesFiltered, owner)
|
|
277
|
+
: branchPrivilegesFiltered;
|
|
278
|
+
|
|
279
|
+
const mainByGrantee = groupPrivilegesByGrantee(mainFiltered);
|
|
280
|
+
const branchByGrantee = groupPrivilegesByGrantee(branchFiltered);
|
|
281
|
+
|
|
282
|
+
// Get all grantees
|
|
283
|
+
const allGrantees = new Set([
|
|
284
|
+
...mainByGrantee.keys(),
|
|
285
|
+
...branchByGrantee.keys(),
|
|
286
|
+
]);
|
|
287
|
+
|
|
288
|
+
const results = new Map<string, PrivilegeDiffResult<T>>();
|
|
289
|
+
|
|
290
|
+
for (const grantee of allGrantees) {
|
|
291
|
+
const mainPrivs = mainByGrantee.get(grantee) || [];
|
|
292
|
+
const branchPrivs = branchByGrantee.get(grantee) || [];
|
|
293
|
+
|
|
294
|
+
const result = diffPrivilegesForGrantee(mainPrivs, branchPrivs);
|
|
295
|
+
results.set(grantee, result);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base utilities and helpers for object privilege changes.
|
|
3
|
+
* These functions support GRANT/REVOKE operations across different database objects.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PrivilegeProps } from "./base.privilege-diff.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns the complete set of available privileges for a given object kind.
|
|
10
|
+
* This is used to determine whether a privilege list represents "ALL PRIVILEGES".
|
|
11
|
+
*
|
|
12
|
+
* @param kind - The PostgreSQL object kind (TABLE, VIEW, SEQUENCE, etc.)
|
|
13
|
+
* @param version - The PostgreSQL version number (e.g., 170000 for 17.0.0)
|
|
14
|
+
* @returns An array of privilege names available for this object kind
|
|
15
|
+
*/
|
|
16
|
+
function objectPrivilegeUniverse(
|
|
17
|
+
kind: string,
|
|
18
|
+
version: number | undefined,
|
|
19
|
+
): string[] {
|
|
20
|
+
switch (kind) {
|
|
21
|
+
case "TABLE": {
|
|
22
|
+
const includesMaintain = (version ?? 170000) >= 170000;
|
|
23
|
+
return [
|
|
24
|
+
"DELETE",
|
|
25
|
+
"INSERT",
|
|
26
|
+
...(includesMaintain ? (["MAINTAIN"] as const) : []),
|
|
27
|
+
"REFERENCES",
|
|
28
|
+
"SELECT",
|
|
29
|
+
"TRIGGER",
|
|
30
|
+
"TRUNCATE",
|
|
31
|
+
"UPDATE",
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
case "VIEW": {
|
|
35
|
+
// Per PostgreSQL docs, views are table-like and share the table privilege set
|
|
36
|
+
// for GRANT/REVOKE purposes. MAINTAIN exists on PostgreSQL >= 17
|
|
37
|
+
const includesMaintain = (version ?? 170000) >= 170000;
|
|
38
|
+
return [
|
|
39
|
+
"DELETE",
|
|
40
|
+
"INSERT",
|
|
41
|
+
...(includesMaintain ? (["MAINTAIN"] as const) : []),
|
|
42
|
+
"REFERENCES",
|
|
43
|
+
"SELECT",
|
|
44
|
+
"TRIGGER",
|
|
45
|
+
"TRUNCATE",
|
|
46
|
+
"UPDATE",
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
case "MATERIALIZED VIEW": {
|
|
50
|
+
// Materialized views support the same table-like privileges as tables/views
|
|
51
|
+
// Per PostgreSQL docs, materialized views are table-like for GRANT/REVOKE purposes
|
|
52
|
+
const includesMaintain = (version ?? 170000) >= 170000;
|
|
53
|
+
return [
|
|
54
|
+
"DELETE",
|
|
55
|
+
"INSERT",
|
|
56
|
+
...(includesMaintain ? (["MAINTAIN"] as const) : []),
|
|
57
|
+
"REFERENCES",
|
|
58
|
+
"SELECT",
|
|
59
|
+
"TRIGGER",
|
|
60
|
+
"TRUNCATE",
|
|
61
|
+
"UPDATE",
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
case "SEQUENCE":
|
|
65
|
+
return ["SELECT", "UPDATE", "USAGE"].sort();
|
|
66
|
+
case "SCHEMA":
|
|
67
|
+
return ["CREATE", "USAGE"].sort();
|
|
68
|
+
case "LANGUAGE":
|
|
69
|
+
return ["USAGE"];
|
|
70
|
+
case "FUNCTION":
|
|
71
|
+
case "PROCEDURE":
|
|
72
|
+
case "ROUTINE":
|
|
73
|
+
return ["EXECUTE"];
|
|
74
|
+
case "TYPE":
|
|
75
|
+
case "DOMAIN":
|
|
76
|
+
return ["USAGE"];
|
|
77
|
+
case "FOREIGN DATA WRAPPER":
|
|
78
|
+
return ["USAGE"];
|
|
79
|
+
case "SERVER":
|
|
80
|
+
return ["USAGE"];
|
|
81
|
+
case "FOREIGN TABLE": {
|
|
82
|
+
const includesMaintain = (version ?? 170000) >= 170000;
|
|
83
|
+
return [
|
|
84
|
+
"DELETE",
|
|
85
|
+
"INSERT",
|
|
86
|
+
...(includesMaintain ? (["MAINTAIN"] as const) : []),
|
|
87
|
+
"REFERENCES",
|
|
88
|
+
"SELECT",
|
|
89
|
+
"TRIGGER",
|
|
90
|
+
"TRUNCATE",
|
|
91
|
+
"UPDATE",
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Checks if a privilege list represents the full set of privileges for an object kind.
|
|
101
|
+
* This determines whether we can use "ALL PRIVILEGES" shorthand in SQL.
|
|
102
|
+
*
|
|
103
|
+
* @param kind - The PostgreSQL object kind
|
|
104
|
+
* @param list - Array of privilege names to check
|
|
105
|
+
* @param version - The PostgreSQL version number
|
|
106
|
+
* @returns true if the list contains all available privileges for this object kind
|
|
107
|
+
*/
|
|
108
|
+
function isFullObjectPrivilegeSet(
|
|
109
|
+
kind: string,
|
|
110
|
+
list: string[],
|
|
111
|
+
version: number | undefined,
|
|
112
|
+
): boolean {
|
|
113
|
+
const uniqSorted = [...new Set(list)].sort();
|
|
114
|
+
const fullSorted = [...objectPrivilegeUniverse(kind, version)].sort();
|
|
115
|
+
if (uniqSorted.length !== fullSorted.length) return false;
|
|
116
|
+
for (let i = 0; i < uniqSorted.length; i++) {
|
|
117
|
+
if (uniqSorted[i] !== fullSorted[i]) return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Formats a list of privileges for use in GRANT/REVOKE statements.
|
|
124
|
+
* If the list represents all privileges, returns "ALL", otherwise returns a comma-separated list.
|
|
125
|
+
*
|
|
126
|
+
* @param kind - The PostgreSQL object kind
|
|
127
|
+
* @param list - Array of privilege names to format
|
|
128
|
+
* @param version - The PostgreSQL version number
|
|
129
|
+
* @returns A SQL-formatted privilege list (either "ALL" or "PRIV1, PRIV2, ...")
|
|
130
|
+
*/
|
|
131
|
+
export function formatObjectPrivilegeList(
|
|
132
|
+
kind: string,
|
|
133
|
+
list: string[],
|
|
134
|
+
version: number | undefined,
|
|
135
|
+
): string {
|
|
136
|
+
const uniqSorted = [...new Set(list)].sort();
|
|
137
|
+
return isFullObjectPrivilegeSet(kind, uniqSorted, version)
|
|
138
|
+
? "ALL"
|
|
139
|
+
: uniqSorted.join(", ");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Gets the SQL keyword prefix for a given object kind in GRANT/REVOKE statements.
|
|
144
|
+
*
|
|
145
|
+
* @param objectKind - The PostgreSQL object kind
|
|
146
|
+
* @returns The SQL prefix (e.g., "ON SCHEMA", "ON DOMAIN", "ON")
|
|
147
|
+
*/
|
|
148
|
+
export function getObjectKindPrefix(objectKind: string): string {
|
|
149
|
+
switch (objectKind) {
|
|
150
|
+
case "FUNCTION":
|
|
151
|
+
return "ON FUNCTION";
|
|
152
|
+
case "PROCEDURE":
|
|
153
|
+
return "ON PROCEDURE";
|
|
154
|
+
case "ROUTINE":
|
|
155
|
+
return "ON ROUTINE";
|
|
156
|
+
case "LANGUAGE":
|
|
157
|
+
return "ON LANGUAGE";
|
|
158
|
+
case "SCHEMA":
|
|
159
|
+
return "ON SCHEMA";
|
|
160
|
+
case "SEQUENCE":
|
|
161
|
+
return "ON SEQUENCE";
|
|
162
|
+
case "DOMAIN":
|
|
163
|
+
return "ON DOMAIN";
|
|
164
|
+
case "TYPE":
|
|
165
|
+
return "ON TYPE";
|
|
166
|
+
case "FOREIGN TABLE":
|
|
167
|
+
return "ON FOREIGN TABLE";
|
|
168
|
+
default:
|
|
169
|
+
return "ON";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function normalizePrivileges(privileges: PrivilegeProps[]) {
|
|
174
|
+
return privileges
|
|
175
|
+
.map((privilege) => ({
|
|
176
|
+
grantee: privilege.grantee,
|
|
177
|
+
privilege: privilege.privilege,
|
|
178
|
+
grantable: privilege.grantable,
|
|
179
|
+
}))
|
|
180
|
+
.sort((a, b) => {
|
|
181
|
+
if (a.grantee !== b.grantee) return a.grantee.localeCompare(b.grantee);
|
|
182
|
+
return a.privilege.localeCompare(b.privilege);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { Collation } from "../collation.model.ts";
|
|
3
|
+
import {
|
|
4
|
+
AlterCollationChangeOwner,
|
|
5
|
+
AlterCollationRefreshVersion,
|
|
6
|
+
} from "./collation.alter.ts";
|
|
7
|
+
|
|
8
|
+
describe.concurrent("collation", () => {
|
|
9
|
+
describe("alter", () => {
|
|
10
|
+
test("change owner", () => {
|
|
11
|
+
const collation = new Collation({
|
|
12
|
+
schema: "public",
|
|
13
|
+
name: "test",
|
|
14
|
+
provider: "c",
|
|
15
|
+
is_deterministic: true,
|
|
16
|
+
encoding: 1,
|
|
17
|
+
collate: "en_US",
|
|
18
|
+
locale: "en_US",
|
|
19
|
+
version: "1.0",
|
|
20
|
+
ctype: "test",
|
|
21
|
+
icu_rules: "test",
|
|
22
|
+
comment: null,
|
|
23
|
+
owner: "old_owner",
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const change = new AlterCollationChangeOwner({
|
|
27
|
+
collation,
|
|
28
|
+
owner: "new_owner",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(change.serialize()).toBe(
|
|
32
|
+
"ALTER COLLATION public.test OWNER TO new_owner",
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("refresh version", () => {
|
|
37
|
+
const collation = new Collation({
|
|
38
|
+
schema: "public",
|
|
39
|
+
name: "test",
|
|
40
|
+
provider: "c",
|
|
41
|
+
is_deterministic: true,
|
|
42
|
+
encoding: 1,
|
|
43
|
+
collate: "en_US",
|
|
44
|
+
locale: "en_US",
|
|
45
|
+
ctype: "test",
|
|
46
|
+
icu_rules: "test",
|
|
47
|
+
comment: null,
|
|
48
|
+
owner: "test",
|
|
49
|
+
version: "1.0",
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const change = new AlterCollationRefreshVersion({
|
|
53
|
+
collation,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(change.serialize()).toBe(
|
|
57
|
+
"ALTER COLLATION public.test REFRESH VERSION",
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// replace behavior moved into collation.diff.ts as separate Drop + Create
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Collation } from "../collation.model.ts";
|
|
2
|
+
import { AlterCollationChange } from "./collation.base.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Alter a collation.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.postgresql.org/docs/17/sql-altercollation.html
|
|
8
|
+
*
|
|
9
|
+
* Synopsis
|
|
10
|
+
* ```sql
|
|
11
|
+
* ALTER COLLATION name REFRESH VERSION
|
|
12
|
+
* ALTER COLLATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
|
|
13
|
+
* ALTER COLLATION name RENAME TO new_name
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type AlterCollation =
|
|
18
|
+
| AlterCollationChangeOwner
|
|
19
|
+
| AlterCollationRefreshVersion;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* ALTER COLLATION ... OWNER TO ...
|
|
23
|
+
*/
|
|
24
|
+
export class AlterCollationChangeOwner extends AlterCollationChange {
|
|
25
|
+
public readonly collation: Collation;
|
|
26
|
+
public readonly owner: string;
|
|
27
|
+
public readonly scope = "object" as const;
|
|
28
|
+
|
|
29
|
+
constructor(props: { collation: Collation; owner: string }) {
|
|
30
|
+
super();
|
|
31
|
+
this.collation = props.collation;
|
|
32
|
+
this.owner = props.owner;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get requires() {
|
|
36
|
+
return [this.collation.stableId];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
serialize(): string {
|
|
40
|
+
return [
|
|
41
|
+
"ALTER COLLATION",
|
|
42
|
+
`${this.collation.schema}.${this.collation.name}`,
|
|
43
|
+
"OWNER TO",
|
|
44
|
+
this.owner,
|
|
45
|
+
].join(" ");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ALTER COLLATION ... REFRESH VERSION
|
|
51
|
+
*/
|
|
52
|
+
export class AlterCollationRefreshVersion extends AlterCollationChange {
|
|
53
|
+
public readonly collation: Collation;
|
|
54
|
+
public readonly scope = "object" as const;
|
|
55
|
+
|
|
56
|
+
constructor(props: { collation: Collation }) {
|
|
57
|
+
super();
|
|
58
|
+
this.collation = props.collation;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get requires() {
|
|
62
|
+
return [this.collation.stableId];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
serialize(): string {
|
|
66
|
+
return [
|
|
67
|
+
"ALTER COLLATION",
|
|
68
|
+
`${this.collation.schema}.${this.collation.name}`,
|
|
69
|
+
"REFRESH VERSION",
|
|
70
|
+
].join(" ");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Replace a collation by dropping and recreating it.
|
|
76
|
+
* This is used when properties that cannot be altered via ALTER COLLATION change.
|
|
77
|
+
*/
|
|
78
|
+
// NOTE: ReplaceCollation has been removed. Non-alterable property changes
|
|
79
|
+
// are modeled as separate DropCollation + CreateCollation changes in collation.diff.ts.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseChange } from "../../base.change.ts";
|
|
2
|
+
import type { Collation } from "../collation.model.ts";
|
|
3
|
+
|
|
4
|
+
abstract class BaseCollationChange extends BaseChange {
|
|
5
|
+
abstract readonly collation: Collation;
|
|
6
|
+
abstract readonly scope: "object" | "comment";
|
|
7
|
+
readonly objectType: "collation" = "collation";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export abstract class CreateCollationChange extends BaseCollationChange {
|
|
11
|
+
readonly operation = "create" as const;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export abstract class AlterCollationChange extends BaseCollationChange {
|
|
15
|
+
readonly operation = "alter" as const;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export abstract class DropCollationChange extends BaseCollationChange {
|
|
19
|
+
readonly operation = "drop" as const;
|
|
20
|
+
}
|