@supabase/pg-delta 1.0.0-alpha.21 → 1.0.0-alpha.23
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/dist/core/catalog.diff.js +4 -3
- package/dist/core/catalog.model.d.ts +8 -1
- package/dist/core/catalog.model.js +10 -8
- package/dist/core/expand-replace-dependencies.js +23 -0
- package/dist/core/integrations/filter/flatten.js +13 -0
- package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
- package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
- package/dist/core/objects/aggregate/aggregate.model.js +19 -1
- package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
- package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
- package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
- package/dist/core/objects/base.model.d.ts +8 -0
- package/dist/core/objects/base.model.js +2 -0
- package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
- package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
- package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
- package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
- package/dist/core/objects/domain/domain.diff.js +16 -0
- package/dist/core/objects/domain/domain.model.d.ts +10 -0
- package/dist/core/objects/domain/domain.model.js +19 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
- package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
- package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
- package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
- package/dist/core/objects/extract-with-retry.d.ts +36 -0
- package/dist/core/objects/extract-with-retry.js +51 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
- package/dist/core/objects/index/index.diff.js +0 -1
- package/dist/core/objects/index/index.model.d.ts +2 -3
- package/dist/core/objects/index/index.model.js +17 -6
- package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
- package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
- package/dist/core/objects/materialized-view/materialized-view.model.d.ts +24 -1
- package/dist/core/objects/materialized-view/materialized-view.model.js +40 -5
- package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
- package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
- package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
- package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
- package/dist/core/objects/procedure/procedure.diff.js +16 -0
- package/dist/core/objects/procedure/procedure.model.d.ts +12 -1
- package/dist/core/objects/procedure/procedure.model.js +39 -5
- package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
- package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
- package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
- package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
- package/dist/core/objects/publication/publication.diff.js +16 -0
- package/dist/core/objects/publication/publication.model.d.ts +14 -0
- package/dist/core/objects/publication/publication.model.js +20 -1
- package/dist/core/objects/rls-policy/rls-policy.diff.js +13 -1
- package/dist/core/objects/role/changes/role.base.d.ts +1 -1
- package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
- package/dist/core/objects/role/changes/role.security-label.js +61 -0
- package/dist/core/objects/role/changes/role.types.d.ts +2 -1
- package/dist/core/objects/role/role.diff.js +16 -0
- package/dist/core/objects/role/role.model.d.ts +10 -0
- package/dist/core/objects/role/role.model.js +29 -0
- package/dist/core/objects/rule/rule.model.d.ts +2 -1
- package/dist/core/objects/rule/rule.model.js +20 -3
- package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
- package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
- package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
- package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
- package/dist/core/objects/schema/schema.diff.js +24 -1
- package/dist/core/objects/schema/schema.model.d.ts +10 -0
- package/dist/core/objects/schema/schema.model.js +18 -1
- package/dist/core/objects/security-label.types.d.ts +20 -0
- package/dist/core/objects/security-label.types.js +46 -0
- package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
- package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
- package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
- package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
- package/dist/core/objects/sequence/sequence.diff.d.ts +2 -1
- package/dist/core/objects/sequence/sequence.diff.js +44 -4
- package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
- package/dist/core/objects/sequence/sequence.model.js +19 -1
- package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
- package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
- package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
- package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
- package/dist/core/objects/subscription/subscription.diff.js +16 -0
- package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
- package/dist/core/objects/subscription/subscription.model.js +19 -1
- package/dist/core/objects/table/changes/table.alter.d.ts +12 -1
- package/dist/core/objects/table/changes/table.alter.js +20 -2
- package/dist/core/objects/table/changes/table.base.d.ts +1 -1
- package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
- package/dist/core/objects/table/changes/table.security-label.js +134 -0
- package/dist/core/objects/table/changes/table.types.d.ts +2 -1
- package/dist/core/objects/table/table.diff.js +68 -15
- package/dist/core/objects/table/table.model.d.ts +36 -1
- package/dist/core/objects/table/table.model.js +74 -7
- package/dist/core/objects/trigger/trigger.model.d.ts +2 -1
- package/dist/core/objects/trigger/trigger.model.js +20 -4
- package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
- package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
- package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
- package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
- package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
- package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
- package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
- package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
- package/dist/core/objects/type/enum/enum.diff.js +16 -0
- package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
- package/dist/core/objects/type/enum/enum.model.js +20 -1
- package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
- package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
- package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
- package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
- package/dist/core/objects/type/range/range.diff.js +16 -0
- package/dist/core/objects/type/range/range.model.d.ts +10 -0
- package/dist/core/objects/type/range/range.model.js +19 -1
- package/dist/core/objects/utils.d.ts +2 -0
- package/dist/core/objects/utils.js +6 -0
- package/dist/core/objects/view/changes/view.base.d.ts +1 -1
- package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
- package/dist/core/objects/view/changes/view.security-label.js +61 -0
- package/dist/core/objects/view/changes/view.types.d.ts +2 -1
- package/dist/core/objects/view/view.diff.js +13 -0
- package/dist/core/objects/view/view.model.d.ts +28 -1
- package/dist/core/objects/view/view.model.js +40 -5
- package/dist/core/plan/create.js +3 -1
- package/dist/core/plan/sql-format/fixtures.js +1 -0
- package/dist/core/plan/types.d.ts +8 -0
- package/dist/core/{post-diff-cycle-breaking.d.ts → post-diff-normalization.d.ts} +8 -1
- package/dist/core/post-diff-normalization.js +202 -0
- package/dist/core/sort/cycle-breakers.js +1 -1
- package/dist/core/sort/utils.d.ts +10 -0
- package/dist/core/sort/utils.js +28 -0
- package/package.json +1 -1
- package/src/core/catalog.diff.ts +4 -2
- package/src/core/catalog.model.ts +21 -8
- package/src/core/expand-replace-dependencies.test.ts +131 -0
- package/src/core/expand-replace-dependencies.ts +24 -0
- package/src/core/integrations/filter/dsl.test.ts +27 -0
- package/src/core/integrations/filter/flatten.ts +16 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
- package/src/core/objects/aggregate/aggregate.model.ts +22 -1
- package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
- package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
- package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
- package/src/core/objects/base.model.ts +2 -0
- package/src/core/objects/domain/changes/domain.base.ts +5 -1
- package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
- package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
- package/src/core/objects/domain/changes/domain.types.ts +3 -1
- package/src/core/objects/domain/domain.diff.ts +33 -0
- package/src/core/objects/domain/domain.model.ts +22 -1
- package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
- package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
- package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
- package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
- package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
- package/src/core/objects/extract-with-retry.test.ts +143 -0
- package/src/core/objects/extract-with-retry.ts +87 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
- package/src/core/objects/index/index.diff.ts +0 -1
- package/src/core/objects/index/index.model.test.ts +37 -1
- package/src/core/objects/index/index.model.ts +25 -6
- package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
- package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
- package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
- package/src/core/objects/materialized-view/materialized-view.model.test.ts +93 -0
- package/src/core/objects/materialized-view/materialized-view.model.ts +52 -8
- package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
- package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
- package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
- package/src/core/objects/procedure/procedure.diff.ts +33 -0
- package/src/core/objects/procedure/procedure.model.test.ts +117 -0
- package/src/core/objects/procedure/procedure.model.ts +51 -7
- package/src/core/objects/publication/changes/publication.base.ts +1 -1
- package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
- package/src/core/objects/publication/changes/publication.types.ts +3 -1
- package/src/core/objects/publication/publication.diff.ts +33 -0
- package/src/core/objects/publication/publication.model.ts +24 -1
- package/src/core/objects/rls-policy/rls-policy.diff.ts +19 -1
- package/src/core/objects/role/changes/role.base.ts +2 -1
- package/src/core/objects/role/changes/role.security-label.ts +77 -0
- package/src/core/objects/role/changes/role.types.ts +3 -1
- package/src/core/objects/role/role.diff.ts +33 -0
- package/src/core/objects/role/role.model.ts +32 -0
- package/src/core/objects/rule/rule.model.test.ts +99 -0
- package/src/core/objects/rule/rule.model.ts +28 -4
- package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.base.ts +5 -1
- package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
- package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
- package/src/core/objects/schema/changes/schema.types.ts +3 -1
- package/src/core/objects/schema/schema.diff.test.ts +1 -0
- package/src/core/objects/schema/schema.diff.ts +43 -1
- package/src/core/objects/schema/schema.model.ts +21 -1
- package/src/core/objects/security-label.types.test.ts +106 -0
- package/src/core/objects/security-label.types.ts +61 -0
- package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
- package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
- package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
- package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
- package/src/core/objects/sequence/sequence.diff.test.ts +87 -0
- package/src/core/objects/sequence/sequence.diff.ts +64 -6
- package/src/core/objects/sequence/sequence.model.ts +22 -1
- package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
- package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
- package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
- package/src/core/objects/subscription/subscription.diff.ts +33 -0
- package/src/core/objects/subscription/subscription.model.ts +22 -1
- package/src/core/objects/table/changes/table.alter.test.ts +13 -21
- package/src/core/objects/table/changes/table.alter.ts +30 -3
- package/src/core/objects/table/changes/table.base.ts +5 -1
- package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
- package/src/core/objects/table/changes/table.security-label.ts +183 -0
- package/src/core/objects/table/changes/table.types.ts +3 -1
- package/src/core/objects/table/table.diff.ts +111 -19
- package/src/core/objects/table/table.model.test.ts +209 -0
- package/src/core/objects/table/table.model.ts +94 -9
- package/src/core/objects/trigger/trigger.model.test.ts +113 -0
- package/src/core/objects/trigger/trigger.model.ts +28 -5
- package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
- package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
- package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
- package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
- package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
- package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
- package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
- package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
- package/src/core/objects/type/enum/enum.diff.ts +33 -0
- package/src/core/objects/type/enum/enum.model.ts +25 -1
- package/src/core/objects/type/range/changes/range.base.ts +5 -1
- package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
- package/src/core/objects/type/range/changes/range.types.ts +3 -1
- package/src/core/objects/type/range/range.diff.ts +33 -0
- package/src/core/objects/type/range/range.model.ts +22 -1
- package/src/core/objects/utils.ts +6 -0
- package/src/core/objects/view/changes/view.base.ts +5 -1
- package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
- package/src/core/objects/view/changes/view.security-label.ts +77 -0
- package/src/core/objects/view/changes/view.types.ts +3 -1
- package/src/core/objects/view/view.diff.ts +31 -0
- package/src/core/objects/view/view.model.test.ts +90 -0
- package/src/core/objects/view/view.model.ts +53 -7
- package/src/core/plan/create.ts +3 -1
- package/src/core/plan/sql-format/fixtures.ts +1 -0
- package/src/core/plan/types.ts +8 -0
- package/src/core/{post-diff-cycle-breaking.test.ts → post-diff-normalization.test.ts} +168 -4
- package/src/core/post-diff-normalization.ts +260 -0
- package/src/core/sort/cycle-breakers.ts +1 -1
- package/src/core/sort/utils.ts +38 -0
- package/dist/core/post-diff-cycle-breaking.js +0 -100
- package/src/core/post-diff-cycle-breaking.ts +0 -138
|
@@ -2,6 +2,7 @@ import { sql } from "@ts-safeql/sql-tag";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel, columnPropsSchema, } from "../../base.model.js";
|
|
4
4
|
import { privilegePropsSchema, } from "../../base.privilege-diff.js";
|
|
5
|
+
import { normalizeSecurityLabels, securityLabelPropsSchema, } from "../../security-label.types.js";
|
|
5
6
|
/**
|
|
6
7
|
* All properties exposed by CREATE FOREIGN TABLE statement are included in diff output.
|
|
7
8
|
* https://www.postgresql.org/docs/17/sql-createforeigntable.html
|
|
@@ -21,6 +22,7 @@ const foreignTablePropsSchema = z.object({
|
|
|
21
22
|
comment: z.string().nullable(),
|
|
22
23
|
columns: z.array(columnPropsSchema),
|
|
23
24
|
privileges: z.array(privilegePropsSchema),
|
|
25
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
24
26
|
});
|
|
25
27
|
export class ForeignTable extends BasePgModel {
|
|
26
28
|
schema;
|
|
@@ -31,6 +33,7 @@ export class ForeignTable extends BasePgModel {
|
|
|
31
33
|
comment;
|
|
32
34
|
columns;
|
|
33
35
|
privileges;
|
|
36
|
+
security_labels;
|
|
34
37
|
constructor(props) {
|
|
35
38
|
super();
|
|
36
39
|
// Identity fields
|
|
@@ -43,6 +46,7 @@ export class ForeignTable extends BasePgModel {
|
|
|
43
46
|
this.comment = props.comment;
|
|
44
47
|
this.columns = props.columns;
|
|
45
48
|
this.privileges = props.privileges;
|
|
49
|
+
this.security_labels = props.security_labels ?? [];
|
|
46
50
|
}
|
|
47
51
|
get stableId() {
|
|
48
52
|
return `foreignTable:${this.schema}.${this.name}`;
|
|
@@ -61,6 +65,7 @@ export class ForeignTable extends BasePgModel {
|
|
|
61
65
|
comment: this.comment,
|
|
62
66
|
columns: this.columns,
|
|
63
67
|
privileges: this.privileges,
|
|
68
|
+
security_labels: this.security_labels,
|
|
64
69
|
};
|
|
65
70
|
}
|
|
66
71
|
stableSnapshot() {
|
|
@@ -79,6 +84,7 @@ export class ForeignTable extends BasePgModel {
|
|
|
79
84
|
data: {
|
|
80
85
|
...this.dataFields,
|
|
81
86
|
columns: normalizeColumns(),
|
|
87
|
+
security_labels: normalizeSecurityLabels(this.security_labels),
|
|
82
88
|
},
|
|
83
89
|
};
|
|
84
90
|
}
|
|
@@ -181,7 +187,20 @@ export async function extractForeignTables(pool) {
|
|
|
181
187
|
join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
|
|
182
188
|
group by x.grantee, x.privilege_type
|
|
183
189
|
) as grp
|
|
184
|
-
), '[]') as privileges
|
|
190
|
+
), '[]') as privileges,
|
|
191
|
+
coalesce(
|
|
192
|
+
(
|
|
193
|
+
select json_agg(
|
|
194
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
195
|
+
order by sl.provider
|
|
196
|
+
)
|
|
197
|
+
from pg_catalog.pg_seclabel sl
|
|
198
|
+
where sl.objoid = ft.oid
|
|
199
|
+
and sl.classoid = 'pg_class'::regclass
|
|
200
|
+
and sl.objsubid = 0
|
|
201
|
+
),
|
|
202
|
+
'[]'::json
|
|
203
|
+
) as security_labels
|
|
185
204
|
from
|
|
186
205
|
foreign_tables ft
|
|
187
206
|
left join pg_attribute a on a.attrelid = ft.oid and a.attnum > 0 and not a.attisdropped
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Pool } from "pg";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.ts";
|
|
4
|
+
import { type ExtractRetryOptions } from "../extract-with-retry.ts";
|
|
4
5
|
declare const indexPropsSchema: z.ZodObject<{
|
|
5
6
|
schema: z.ZodString;
|
|
6
7
|
table_name: z.ZodString;
|
|
@@ -97,7 +98,6 @@ export declare class Index extends BasePgModel {
|
|
|
97
98
|
nulls_not_distinct: boolean;
|
|
98
99
|
immediate: boolean;
|
|
99
100
|
is_clustered: boolean;
|
|
100
|
-
is_replica_identity: boolean;
|
|
101
101
|
column_collations: (string | null)[];
|
|
102
102
|
operator_classes: string[];
|
|
103
103
|
column_options: number[];
|
|
@@ -132,7 +132,6 @@ export declare class Index extends BasePgModel {
|
|
|
132
132
|
nulls_not_distinct: boolean;
|
|
133
133
|
immediate: boolean;
|
|
134
134
|
is_clustered: boolean;
|
|
135
|
-
is_replica_identity: boolean;
|
|
136
135
|
index_expressions: string | null;
|
|
137
136
|
partial_predicate: string | null;
|
|
138
137
|
table_relkind: "r" | "m" | "p";
|
|
@@ -146,5 +145,5 @@ export declare class Index extends BasePgModel {
|
|
|
146
145
|
};
|
|
147
146
|
};
|
|
148
147
|
}
|
|
149
|
-
export declare function extractIndexes(pool: Pool): Promise<Index[]>;
|
|
148
|
+
export declare function extractIndexes(pool: Pool, options?: ExtractRetryOptions): Promise<Index[]>;
|
|
150
149
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sql } from "@ts-safeql/sql-tag";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel } from "../base.model.js";
|
|
4
|
+
import { extractWithDefinitionRetry, } from "../extract-with-retry.js";
|
|
4
5
|
const TableRelkindSchema = z.enum([
|
|
5
6
|
"r", // table (regular relation)
|
|
6
7
|
"m", // materialized view
|
|
@@ -136,7 +137,11 @@ export class Index extends BasePgModel {
|
|
|
136
137
|
nulls_not_distinct: this.nulls_not_distinct,
|
|
137
138
|
immediate: this.immediate,
|
|
138
139
|
is_clustered: this.is_clustered,
|
|
139
|
-
is_replica_identity:
|
|
140
|
+
// is_replica_identity excluded: the table's `replica_identity` /
|
|
141
|
+
// `replica_identity_index` is the source of truth, set via
|
|
142
|
+
// ALTER TABLE ... REPLICA IDENTITY USING INDEX. Including this flag here
|
|
143
|
+
// would trigger spurious DROP+CREATE of the index whenever the table's
|
|
144
|
+
// replica identity changes.
|
|
140
145
|
// key_columns excluded: contains attribute numbers that can differ between databases
|
|
141
146
|
// even when indexes are logically identical. The definition field already captures
|
|
142
147
|
// the logical structure using column names, so we compare by definition instead.
|
|
@@ -184,8 +189,13 @@ export class Index extends BasePgModel {
|
|
|
184
189
|
};
|
|
185
190
|
}
|
|
186
191
|
}
|
|
187
|
-
export async function extractIndexes(pool) {
|
|
188
|
-
const
|
|
192
|
+
export async function extractIndexes(pool, options) {
|
|
193
|
+
const indexRows = await extractWithDefinitionRetry({
|
|
194
|
+
label: "indexes",
|
|
195
|
+
options,
|
|
196
|
+
hasNullDefinition: (row) => row.definition === null,
|
|
197
|
+
query: async () => {
|
|
198
|
+
const result = await pool.query(sql `
|
|
189
199
|
with extension_oids as (
|
|
190
200
|
select objid
|
|
191
201
|
from pg_depend d
|
|
@@ -341,8 +351,9 @@ export async function extractIndexes(pool) {
|
|
|
341
351
|
|
|
342
352
|
order by 1, 2
|
|
343
353
|
`);
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
354
|
+
return result.rows.map((row) => indexRowSchema.parse(row));
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
const validatedRows = indexRows.filter((row) => row.definition !== null);
|
|
347
358
|
return validatedRows.map((row) => new Index(row));
|
|
348
359
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseChange } from "../../base.change.ts";
|
|
|
2
2
|
import type { MaterializedView } from "../materialized-view.model.ts";
|
|
3
3
|
declare abstract class BaseMaterializedViewChange extends BaseChange {
|
|
4
4
|
abstract readonly materializedView: MaterializedView;
|
|
5
|
-
abstract readonly scope: "object" | "comment" | "privilege";
|
|
5
|
+
abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
|
|
6
6
|
readonly objectType: "materialized_view";
|
|
7
7
|
}
|
|
8
8
|
export declare abstract class CreateMaterializedViewChange extends BaseMaterializedViewChange {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
2
|
+
import type { MaterializedView } from "../materialized-view.model.ts";
|
|
3
|
+
import { CreateMaterializedViewChange, DropMaterializedViewChange } from "./materialized-view.base.ts";
|
|
4
|
+
export type SecurityLabelMaterializedView = CreateSecurityLabelOnMaterializedView | DropSecurityLabelOnMaterializedView;
|
|
5
|
+
export declare class CreateSecurityLabelOnMaterializedView extends CreateMaterializedViewChange {
|
|
6
|
+
readonly materializedView: MaterializedView;
|
|
7
|
+
readonly securityLabel: SecurityLabelProps;
|
|
8
|
+
readonly scope: "security_label";
|
|
9
|
+
constructor(props: {
|
|
10
|
+
materializedView: MaterializedView;
|
|
11
|
+
securityLabel: SecurityLabelProps;
|
|
12
|
+
});
|
|
13
|
+
get creates(): `securityLabel:${string}::provider:${string}`[];
|
|
14
|
+
get requires(): `materializedView:${string}`[];
|
|
15
|
+
serialize(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare class DropSecurityLabelOnMaterializedView extends DropMaterializedViewChange {
|
|
18
|
+
readonly materializedView: MaterializedView;
|
|
19
|
+
readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
readonly scope: "security_label";
|
|
21
|
+
constructor(props: {
|
|
22
|
+
materializedView: MaterializedView;
|
|
23
|
+
securityLabel: SecurityLabelProps;
|
|
24
|
+
});
|
|
25
|
+
get drops(): `securityLabel:${string}::provider:${string}`[];
|
|
26
|
+
get requires(): (`securityLabel:${string}::provider:${string}` | `materializedView:${string}`)[];
|
|
27
|
+
serialize(): string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.js";
|
|
2
|
+
import { stableId } from "../../utils.js";
|
|
3
|
+
import { CreateMaterializedViewChange, DropMaterializedViewChange, } from "./materialized-view.base.js";
|
|
4
|
+
export class CreateSecurityLabelOnMaterializedView extends CreateMaterializedViewChange {
|
|
5
|
+
materializedView;
|
|
6
|
+
securityLabel;
|
|
7
|
+
scope = "security_label";
|
|
8
|
+
constructor(props) {
|
|
9
|
+
super();
|
|
10
|
+
this.materializedView = props.materializedView;
|
|
11
|
+
this.securityLabel = props.securityLabel;
|
|
12
|
+
}
|
|
13
|
+
get creates() {
|
|
14
|
+
return [
|
|
15
|
+
stableId.securityLabel(this.materializedView.stableId, this.securityLabel.provider),
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
get requires() {
|
|
19
|
+
return [this.materializedView.stableId];
|
|
20
|
+
}
|
|
21
|
+
serialize() {
|
|
22
|
+
return [
|
|
23
|
+
"SECURITY LABEL FOR",
|
|
24
|
+
this.securityLabel.provider,
|
|
25
|
+
"ON MATERIALIZED VIEW",
|
|
26
|
+
`${this.materializedView.schema}.${this.materializedView.name}`,
|
|
27
|
+
"IS",
|
|
28
|
+
quoteLiteral(this.securityLabel.label),
|
|
29
|
+
].join(" ");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class DropSecurityLabelOnMaterializedView extends DropMaterializedViewChange {
|
|
33
|
+
materializedView;
|
|
34
|
+
securityLabel;
|
|
35
|
+
scope = "security_label";
|
|
36
|
+
constructor(props) {
|
|
37
|
+
super();
|
|
38
|
+
this.materializedView = props.materializedView;
|
|
39
|
+
this.securityLabel = props.securityLabel;
|
|
40
|
+
}
|
|
41
|
+
get drops() {
|
|
42
|
+
return [
|
|
43
|
+
stableId.securityLabel(this.materializedView.stableId, this.securityLabel.provider),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
get requires() {
|
|
47
|
+
return [
|
|
48
|
+
stableId.securityLabel(this.materializedView.stableId, this.securityLabel.provider),
|
|
49
|
+
this.materializedView.stableId,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
serialize() {
|
|
53
|
+
return [
|
|
54
|
+
"SECURITY LABEL FOR",
|
|
55
|
+
this.securityLabel.provider,
|
|
56
|
+
"ON MATERIALIZED VIEW",
|
|
57
|
+
`${this.materializedView.schema}.${this.materializedView.name}`,
|
|
58
|
+
"IS NULL",
|
|
59
|
+
].join(" ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -3,5 +3,6 @@ import type { CommentMaterializedView } from "./materialized-view.comment.ts";
|
|
|
3
3
|
import type { CreateMaterializedView } from "./materialized-view.create.ts";
|
|
4
4
|
import type { DropMaterializedView } from "./materialized-view.drop.ts";
|
|
5
5
|
import type { MaterializedViewPrivilege } from "./materialized-view.privilege.ts";
|
|
6
|
+
import type { SecurityLabelMaterializedView } from "./materialized-view.security-label.ts";
|
|
6
7
|
/** Union of all materialized-view-related change variants (`objectType: "materialized_view"`). @category Change Types */
|
|
7
|
-
export type MaterializedViewChange = AlterMaterializedView | CommentMaterializedView | CreateMaterializedView | DropMaterializedView | MaterializedViewPrivilege;
|
|
8
|
+
export type MaterializedViewChange = AlterMaterializedView | CommentMaterializedView | CreateMaterializedView | DropMaterializedView | MaterializedViewPrivilege | SecurityLabelMaterializedView;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
2
|
import { diffPrivileges, emitColumnPrivilegeChanges, } from "../base.privilege-diff.js";
|
|
3
|
+
import { diffSecurityLabels } from "../security-label.types.js";
|
|
3
4
|
import { deepEqual, hasNonAlterableChanges } from "../utils.js";
|
|
4
5
|
import { AlterMaterializedViewChangeOwner, AlterMaterializedViewSetStorageParams, } from "./changes/materialized-view.alter.js";
|
|
5
6
|
import { CreateCommentOnMaterializedView, CreateCommentOnMaterializedViewColumn, DropCommentOnMaterializedView, DropCommentOnMaterializedViewColumn, } from "./changes/materialized-view.comment.js";
|
|
6
7
|
import { CreateMaterializedView } from "./changes/materialized-view.create.js";
|
|
7
8
|
import { DropMaterializedView } from "./changes/materialized-view.drop.js";
|
|
8
9
|
import { GrantMaterializedViewPrivileges, RevokeGrantOptionMaterializedViewPrivileges, RevokeMaterializedViewPrivileges, } from "./changes/materialized-view.privilege.js";
|
|
10
|
+
import { CreateSecurityLabelOnMaterializedView, DropSecurityLabelOnMaterializedView, } from "./changes/materialized-view.security-label.js";
|
|
9
11
|
/**
|
|
10
12
|
* Diff two sets of materialized views from main and branch catalogs.
|
|
11
13
|
*
|
|
@@ -48,6 +50,14 @@ export function diffMaterializedViews(ctx, main, branch) {
|
|
|
48
50
|
}));
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
// Security labels on the matview itself (columns of matviews are not
|
|
54
|
+
// supported targets of SECURITY LABEL, so we only label the relation).
|
|
55
|
+
for (const label of mv.security_labels) {
|
|
56
|
+
changes.push(new CreateSecurityLabelOnMaterializedView({
|
|
57
|
+
materializedView: mv,
|
|
58
|
+
securityLabel: label,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
51
61
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
52
62
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
53
63
|
// so objects are created with the default privileges state in effect.
|
|
@@ -156,6 +166,14 @@ export function diffMaterializedViews(ctx, main, branch) {
|
|
|
156
166
|
}));
|
|
157
167
|
}
|
|
158
168
|
}
|
|
169
|
+
// SECURITY LABELS
|
|
170
|
+
changes.push(...diffSecurityLabels(mainMaterializedView.security_labels, branchMaterializedView.security_labels, (securityLabel) => new CreateSecurityLabelOnMaterializedView({
|
|
171
|
+
materializedView: branchMaterializedView,
|
|
172
|
+
securityLabel,
|
|
173
|
+
}), (securityLabel) => new DropSecurityLabelOnMaterializedView({
|
|
174
|
+
materializedView: mainMaterializedView,
|
|
175
|
+
securityLabel,
|
|
176
|
+
})));
|
|
159
177
|
// COMMENT changes on columns
|
|
160
178
|
const mainCols = new Map(mainMaterializedView.columns.map((c) => [c.name, c]));
|
|
161
179
|
const branchCols = new Map(branchMaterializedView.columns.map((c) => [c.name, c]));
|
|
@@ -2,6 +2,8 @@ import type { Pool } from "pg";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel, type TableLikeObject } from "../base.model.ts";
|
|
4
4
|
import { type PrivilegeProps } from "../base.privilege-diff.ts";
|
|
5
|
+
import { type ExtractRetryOptions } from "../extract-with-retry.ts";
|
|
6
|
+
import { type SecurityLabelProps } from "../security-label.types.ts";
|
|
5
7
|
declare const materializedViewPropsSchema: z.ZodObject<{
|
|
6
8
|
schema: z.ZodString;
|
|
7
9
|
name: z.ZodString;
|
|
@@ -41,6 +43,10 @@ declare const materializedViewPropsSchema: z.ZodObject<{
|
|
|
41
43
|
collation: z.ZodNullable<z.ZodString>;
|
|
42
44
|
default: z.ZodNullable<z.ZodString>;
|
|
43
45
|
comment: z.ZodNullable<z.ZodString>;
|
|
46
|
+
security_labels: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
47
|
+
provider: z.ZodString;
|
|
48
|
+
label: z.ZodString;
|
|
49
|
+
}, z.z.core.$strip>>>;
|
|
44
50
|
}, z.z.core.$strip>>;
|
|
45
51
|
privileges: z.ZodArray<z.ZodObject<{
|
|
46
52
|
grantee: z.ZodString;
|
|
@@ -48,6 +54,10 @@ declare const materializedViewPropsSchema: z.ZodObject<{
|
|
|
48
54
|
grantable: z.ZodBoolean;
|
|
49
55
|
columns: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
50
56
|
}, z.z.core.$strip>>;
|
|
57
|
+
security_labels: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
58
|
+
provider: z.ZodString;
|
|
59
|
+
label: z.ZodString;
|
|
60
|
+
}, z.z.core.$strip>>>>;
|
|
51
61
|
}, z.z.core.$strip>;
|
|
52
62
|
type MaterializedViewPrivilegeProps = PrivilegeProps;
|
|
53
63
|
export type MaterializedViewProps = z.infer<typeof materializedViewPropsSchema>;
|
|
@@ -70,6 +80,7 @@ export declare class MaterializedView extends BasePgModel implements TableLikeOb
|
|
|
70
80
|
readonly comment: MaterializedViewProps["comment"];
|
|
71
81
|
readonly columns: MaterializedViewProps["columns"];
|
|
72
82
|
readonly privileges: MaterializedViewPrivilegeProps[];
|
|
83
|
+
readonly security_labels: SecurityLabelProps[];
|
|
73
84
|
constructor(props: MaterializedViewProps);
|
|
74
85
|
get stableId(): `materializedView:${string}`;
|
|
75
86
|
get identityFields(): {
|
|
@@ -108,6 +119,10 @@ export declare class MaterializedView extends BasePgModel implements TableLikeOb
|
|
|
108
119
|
collation: string | null;
|
|
109
120
|
default: string | null;
|
|
110
121
|
comment: string | null;
|
|
122
|
+
security_labels?: {
|
|
123
|
+
provider: string;
|
|
124
|
+
label: string;
|
|
125
|
+
}[] | undefined;
|
|
111
126
|
}[];
|
|
112
127
|
privileges: {
|
|
113
128
|
grantee: string;
|
|
@@ -115,6 +130,10 @@ export declare class MaterializedView extends BasePgModel implements TableLikeOb
|
|
|
115
130
|
grantable: boolean;
|
|
116
131
|
columns?: string[] | null | undefined;
|
|
117
132
|
}[];
|
|
133
|
+
security_labels: {
|
|
134
|
+
provider: string;
|
|
135
|
+
label: string;
|
|
136
|
+
}[];
|
|
118
137
|
};
|
|
119
138
|
stableSnapshot(): {
|
|
120
139
|
identity: {
|
|
@@ -125,6 +144,10 @@ export declare class MaterializedView extends BasePgModel implements TableLikeOb
|
|
|
125
144
|
columns: {
|
|
126
145
|
[x: string]: unknown;
|
|
127
146
|
}[];
|
|
147
|
+
security_labels: {
|
|
148
|
+
provider: string;
|
|
149
|
+
label: string;
|
|
150
|
+
}[];
|
|
128
151
|
definition: string;
|
|
129
152
|
row_security: boolean;
|
|
130
153
|
force_row_security: boolean;
|
|
@@ -148,5 +171,5 @@ export declare class MaterializedView extends BasePgModel implements TableLikeOb
|
|
|
148
171
|
};
|
|
149
172
|
};
|
|
150
173
|
}
|
|
151
|
-
export declare function extractMaterializedViews(pool: Pool): Promise<MaterializedView[]>;
|
|
174
|
+
export declare function extractMaterializedViews(pool: Pool, options?: ExtractRetryOptions): Promise<MaterializedView[]>;
|
|
152
175
|
export {};
|
|
@@ -2,6 +2,8 @@ import { sql } from "@ts-safeql/sql-tag";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { BasePgModel, columnPropsSchema, } from "../base.model.js";
|
|
4
4
|
import { privilegePropsSchema, } from "../base.privilege-diff.js";
|
|
5
|
+
import { extractWithDefinitionRetry, } from "../extract-with-retry.js";
|
|
6
|
+
import { normalizeSecurityLabels, securityLabelPropsSchema, } from "../security-label.types.js";
|
|
5
7
|
import { ReplicaIdentitySchema } from "../table/table.model.js";
|
|
6
8
|
const materializedViewPropsSchema = z.object({
|
|
7
9
|
schema: z.string(),
|
|
@@ -22,6 +24,15 @@ const materializedViewPropsSchema = z.object({
|
|
|
22
24
|
comment: z.string().nullable(),
|
|
23
25
|
columns: z.array(columnPropsSchema),
|
|
24
26
|
privileges: z.array(privilegePropsSchema),
|
|
27
|
+
security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
|
|
28
|
+
});
|
|
29
|
+
// pg_get_viewdef(oid) can return NULL when the underlying matview (or its
|
|
30
|
+
// pg_rewrite row) is dropped between catalog scan and resolution, or under
|
|
31
|
+
// transient catalog state during recovery. An unreadable matview cannot be
|
|
32
|
+
// diffed, so we accept NULL here and filter the row out at extraction time
|
|
33
|
+
// rather than crashing the whole catalog parse with a ZodError.
|
|
34
|
+
const materializedViewRowSchema = materializedViewPropsSchema.extend({
|
|
35
|
+
definition: z.string().nullable(),
|
|
25
36
|
});
|
|
26
37
|
export class MaterializedView extends BasePgModel {
|
|
27
38
|
schema;
|
|
@@ -42,6 +53,7 @@ export class MaterializedView extends BasePgModel {
|
|
|
42
53
|
comment;
|
|
43
54
|
columns;
|
|
44
55
|
privileges;
|
|
56
|
+
security_labels;
|
|
45
57
|
constructor(props) {
|
|
46
58
|
super();
|
|
47
59
|
// Identity fields
|
|
@@ -64,6 +76,7 @@ export class MaterializedView extends BasePgModel {
|
|
|
64
76
|
this.comment = props.comment;
|
|
65
77
|
this.columns = props.columns;
|
|
66
78
|
this.privileges = props.privileges;
|
|
79
|
+
this.security_labels = props.security_labels ?? [];
|
|
67
80
|
}
|
|
68
81
|
get stableId() {
|
|
69
82
|
return `materializedView:${this.schema}.${this.name}`;
|
|
@@ -92,6 +105,7 @@ export class MaterializedView extends BasePgModel {
|
|
|
92
105
|
comment: this.comment,
|
|
93
106
|
columns: this.columns,
|
|
94
107
|
privileges: this.privileges,
|
|
108
|
+
security_labels: this.security_labels,
|
|
95
109
|
};
|
|
96
110
|
}
|
|
97
111
|
stableSnapshot() {
|
|
@@ -110,12 +124,18 @@ export class MaterializedView extends BasePgModel {
|
|
|
110
124
|
data: {
|
|
111
125
|
...this.dataFields,
|
|
112
126
|
columns: normalizeColumns(),
|
|
127
|
+
security_labels: normalizeSecurityLabels(this.security_labels),
|
|
113
128
|
},
|
|
114
129
|
};
|
|
115
130
|
}
|
|
116
131
|
}
|
|
117
|
-
export async function extractMaterializedViews(pool) {
|
|
118
|
-
const
|
|
132
|
+
export async function extractMaterializedViews(pool, options) {
|
|
133
|
+
const mvRows = await extractWithDefinitionRetry({
|
|
134
|
+
label: "materialized views",
|
|
135
|
+
options,
|
|
136
|
+
hasNullDefinition: (row) => row.definition === null,
|
|
137
|
+
query: async () => {
|
|
138
|
+
const result = await pool.query(sql `
|
|
119
139
|
with extension_oids as (
|
|
120
140
|
select
|
|
121
141
|
objid
|
|
@@ -205,7 +225,20 @@ select
|
|
|
205
225
|
join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
|
|
206
226
|
group by x.grantee, x.privilege_type
|
|
207
227
|
) as grp
|
|
208
|
-
), '[]') as privileges
|
|
228
|
+
), '[]') as privileges,
|
|
229
|
+
coalesce(
|
|
230
|
+
(
|
|
231
|
+
select json_agg(
|
|
232
|
+
json_build_object('provider', sl.provider, 'label', sl.label)
|
|
233
|
+
order by sl.provider
|
|
234
|
+
)
|
|
235
|
+
from pg_catalog.pg_seclabel sl
|
|
236
|
+
where sl.objoid = c.oid
|
|
237
|
+
and sl.classoid = 'pg_class'::regclass
|
|
238
|
+
and sl.objsubid = 0
|
|
239
|
+
),
|
|
240
|
+
'[]'::json
|
|
241
|
+
) as security_labels
|
|
209
242
|
from
|
|
210
243
|
pg_catalog.pg_class c
|
|
211
244
|
left outer join extension_oids e on c.oid = e.objid
|
|
@@ -220,7 +253,9 @@ group by
|
|
|
220
253
|
order by
|
|
221
254
|
c.relnamespace::regnamespace, c.relname
|
|
222
255
|
`);
|
|
223
|
-
|
|
224
|
-
|
|
256
|
+
return result.rows.map((row) => materializedViewRowSchema.parse(row));
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
const validatedRows = mvRows.filter((row) => row.definition !== null);
|
|
225
260
|
return validatedRows.map((row) => new MaterializedView(row));
|
|
226
261
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseChange } from "../../base.change.ts";
|
|
|
2
2
|
import type { Procedure } from "../procedure.model.ts";
|
|
3
3
|
declare abstract class BaseProcedureChange extends BaseChange {
|
|
4
4
|
abstract readonly procedure: Procedure;
|
|
5
|
-
abstract readonly scope: "object" | "comment" | "privilege";
|
|
5
|
+
abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
|
|
6
6
|
readonly objectType: "procedure";
|
|
7
7
|
}
|
|
8
8
|
export declare abstract class CreateProcedureChange extends BaseProcedureChange {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SecurityLabelProps } from "../../security-label.types.ts";
|
|
2
|
+
import type { Procedure } from "../procedure.model.ts";
|
|
3
|
+
import { CreateProcedureChange, DropProcedureChange } from "./procedure.base.ts";
|
|
4
|
+
export type SecurityLabelProcedure = CreateSecurityLabelOnProcedure | DropSecurityLabelOnProcedure;
|
|
5
|
+
export declare class CreateSecurityLabelOnProcedure extends CreateProcedureChange {
|
|
6
|
+
readonly procedure: Procedure;
|
|
7
|
+
readonly securityLabel: SecurityLabelProps;
|
|
8
|
+
readonly scope: "security_label";
|
|
9
|
+
constructor(props: {
|
|
10
|
+
procedure: Procedure;
|
|
11
|
+
securityLabel: SecurityLabelProps;
|
|
12
|
+
});
|
|
13
|
+
get creates(): `securityLabel:${string}::provider:${string}`[];
|
|
14
|
+
get requires(): `procedure:${string}`[];
|
|
15
|
+
serialize(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare class DropSecurityLabelOnProcedure extends DropProcedureChange {
|
|
18
|
+
readonly procedure: Procedure;
|
|
19
|
+
readonly securityLabel: SecurityLabelProps;
|
|
20
|
+
readonly scope: "security_label";
|
|
21
|
+
constructor(props: {
|
|
22
|
+
procedure: Procedure;
|
|
23
|
+
securityLabel: SecurityLabelProps;
|
|
24
|
+
});
|
|
25
|
+
get drops(): `securityLabel:${string}::provider:${string}`[];
|
|
26
|
+
get requires(): (`securityLabel:${string}::provider:${string}` | `procedure:${string}`)[];
|
|
27
|
+
serialize(): string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { quoteLiteral } from "../../base.change.js";
|
|
2
|
+
import { stableId } from "../../utils.js";
|
|
3
|
+
import { CreateProcedureChange, DropProcedureChange, } from "./procedure.base.js";
|
|
4
|
+
function targetKeyword(p) {
|
|
5
|
+
return p.kind === "p" ? "PROCEDURE" : "FUNCTION";
|
|
6
|
+
}
|
|
7
|
+
function procedureIdentity(p) {
|
|
8
|
+
return `${p.schema}.${p.name}(${(p.argument_types ?? []).join(",")})`;
|
|
9
|
+
}
|
|
10
|
+
export class CreateSecurityLabelOnProcedure extends CreateProcedureChange {
|
|
11
|
+
procedure;
|
|
12
|
+
securityLabel;
|
|
13
|
+
scope = "security_label";
|
|
14
|
+
constructor(props) {
|
|
15
|
+
super();
|
|
16
|
+
this.procedure = props.procedure;
|
|
17
|
+
this.securityLabel = props.securityLabel;
|
|
18
|
+
}
|
|
19
|
+
get creates() {
|
|
20
|
+
return [
|
|
21
|
+
stableId.securityLabel(this.procedure.stableId, this.securityLabel.provider),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
get requires() {
|
|
25
|
+
return [this.procedure.stableId];
|
|
26
|
+
}
|
|
27
|
+
serialize() {
|
|
28
|
+
return [
|
|
29
|
+
"SECURITY LABEL FOR",
|
|
30
|
+
this.securityLabel.provider,
|
|
31
|
+
"ON",
|
|
32
|
+
targetKeyword(this.procedure),
|
|
33
|
+
procedureIdentity(this.procedure),
|
|
34
|
+
"IS",
|
|
35
|
+
quoteLiteral(this.securityLabel.label),
|
|
36
|
+
].join(" ");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class DropSecurityLabelOnProcedure extends DropProcedureChange {
|
|
40
|
+
procedure;
|
|
41
|
+
securityLabel;
|
|
42
|
+
scope = "security_label";
|
|
43
|
+
constructor(props) {
|
|
44
|
+
super();
|
|
45
|
+
this.procedure = props.procedure;
|
|
46
|
+
this.securityLabel = props.securityLabel;
|
|
47
|
+
}
|
|
48
|
+
get drops() {
|
|
49
|
+
return [
|
|
50
|
+
stableId.securityLabel(this.procedure.stableId, this.securityLabel.provider),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
get requires() {
|
|
54
|
+
return [
|
|
55
|
+
stableId.securityLabel(this.procedure.stableId, this.securityLabel.provider),
|
|
56
|
+
this.procedure.stableId,
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
serialize() {
|
|
60
|
+
return [
|
|
61
|
+
"SECURITY LABEL FOR",
|
|
62
|
+
this.securityLabel.provider,
|
|
63
|
+
"ON",
|
|
64
|
+
targetKeyword(this.procedure),
|
|
65
|
+
procedureIdentity(this.procedure),
|
|
66
|
+
"IS NULL",
|
|
67
|
+
].join(" ");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -3,5 +3,6 @@ import type { CommentProcedure } from "./procedure.comment.ts";
|
|
|
3
3
|
import type { CreateProcedure } from "./procedure.create.ts";
|
|
4
4
|
import type { DropProcedure } from "./procedure.drop.ts";
|
|
5
5
|
import type { ProcedurePrivilege } from "./procedure.privilege.ts";
|
|
6
|
+
import type { SecurityLabelProcedure } from "./procedure.security-label.ts";
|
|
6
7
|
/** Union of all procedure-related change variants (`objectType: "procedure"`). @category Change Types */
|
|
7
|
-
export type ProcedureChange = AlterProcedure | CommentProcedure | CreateProcedure | DropProcedure | ProcedurePrivilege;
|
|
8
|
+
export type ProcedureChange = AlterProcedure | CommentProcedure | CreateProcedure | DropProcedure | ProcedurePrivilege | SecurityLabelProcedure;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { diffObjects } from "../base.diff.js";
|
|
2
2
|
import { diffPrivileges, emitObjectPrivilegeChanges, filterPublicBuiltInDefaults, } from "../base.privilege-diff.js";
|
|
3
|
+
import { diffSecurityLabels } from "../security-label.types.js";
|
|
3
4
|
import { deepEqual, hasNonAlterableChanges } from "../utils.js";
|
|
4
5
|
import { AlterProcedureChangeOwner, AlterProcedureSetConfig, AlterProcedureSetLeakproof, AlterProcedureSetParallel, AlterProcedureSetSecurity, AlterProcedureSetStrictness, AlterProcedureSetVolatility, } from "./changes/procedure.alter.js";
|
|
5
6
|
import { CreateCommentOnProcedure, DropCommentOnProcedure, } from "./changes/procedure.comment.js";
|
|
6
7
|
import { CreateProcedure } from "./changes/procedure.create.js";
|
|
7
8
|
import { DropProcedure } from "./changes/procedure.drop.js";
|
|
8
9
|
import { GrantProcedurePrivileges, RevokeGrantOptionProcedurePrivileges, RevokeProcedurePrivileges, } from "./changes/procedure.privilege.js";
|
|
10
|
+
import { CreateSecurityLabelOnProcedure, DropSecurityLabelOnProcedure, } from "./changes/procedure.security-label.js";
|
|
9
11
|
/**
|
|
10
12
|
* Diff two sets of procedures from main and branch catalogs.
|
|
11
13
|
*
|
|
@@ -30,6 +32,12 @@ export function diffProcedures(ctx, main, branch) {
|
|
|
30
32
|
if (proc.comment !== null) {
|
|
31
33
|
changes.push(new CreateCommentOnProcedure({ procedure: proc }));
|
|
32
34
|
}
|
|
35
|
+
for (const label of proc.security_labels) {
|
|
36
|
+
changes.push(new CreateSecurityLabelOnProcedure({
|
|
37
|
+
procedure: proc,
|
|
38
|
+
securityLabel: label,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
33
41
|
// PRIVILEGES: For created objects, compare against default privileges state
|
|
34
42
|
// The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
|
|
35
43
|
// so objects are created with the default privileges state in effect.
|
|
@@ -139,6 +147,14 @@ export function diffProcedures(ctx, main, branch) {
|
|
|
139
147
|
changes.push(new CreateCommentOnProcedure({ procedure: branchProcedure }));
|
|
140
148
|
}
|
|
141
149
|
}
|
|
150
|
+
// SECURITY LABELS
|
|
151
|
+
changes.push(...diffSecurityLabels(mainProcedure.security_labels, branchProcedure.security_labels, (securityLabel) => new CreateSecurityLabelOnProcedure({
|
|
152
|
+
procedure: branchProcedure,
|
|
153
|
+
securityLabel,
|
|
154
|
+
}), (securityLabel) => new DropSecurityLabelOnProcedure({
|
|
155
|
+
procedure: mainProcedure,
|
|
156
|
+
securityLabel,
|
|
157
|
+
})));
|
|
142
158
|
// SECURITY DEFINER/INVOKER
|
|
143
159
|
if (mainProcedure.security_definer !== branchProcedure.security_definer) {
|
|
144
160
|
changes.push(new AlterProcedureSetSecurity({
|