@supabase/pg-delta 1.0.0-alpha.22 → 1.0.0-alpha.24

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.
Files changed (228) hide show
  1. package/dist/core/catalog.model.js +1 -0
  2. package/dist/core/integrations/filter/flatten.js +13 -0
  3. package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
  4. package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
  5. package/dist/core/objects/aggregate/aggregate.model.js +19 -1
  6. package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
  7. package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
  8. package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
  9. package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
  10. package/dist/core/objects/base.model.d.ts +8 -0
  11. package/dist/core/objects/base.model.js +2 -0
  12. package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
  13. package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
  14. package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
  15. package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
  16. package/dist/core/objects/domain/domain.diff.js +16 -0
  17. package/dist/core/objects/domain/domain.model.d.ts +10 -0
  18. package/dist/core/objects/domain/domain.model.js +19 -1
  19. package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
  20. package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
  21. package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
  22. package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
  23. package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
  24. package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
  25. package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
  26. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
  27. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
  28. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
  29. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
  30. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
  31. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
  32. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
  33. package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
  34. package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
  35. package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
  36. package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
  37. package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
  38. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +22 -0
  39. package/dist/core/objects/materialized-view/materialized-view.model.js +20 -1
  40. package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
  41. package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
  42. package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
  43. package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
  44. package/dist/core/objects/procedure/procedure.diff.js +16 -0
  45. package/dist/core/objects/procedure/procedure.model.d.ts +10 -0
  46. package/dist/core/objects/procedure/procedure.model.js +19 -1
  47. package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
  48. package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
  49. package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
  50. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
  51. package/dist/core/objects/publication/publication.diff.js +16 -0
  52. package/dist/core/objects/publication/publication.model.d.ts +14 -0
  53. package/dist/core/objects/publication/publication.model.js +20 -1
  54. package/dist/core/objects/role/changes/role.base.d.ts +1 -1
  55. package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
  56. package/dist/core/objects/role/changes/role.security-label.js +61 -0
  57. package/dist/core/objects/role/changes/role.types.d.ts +2 -1
  58. package/dist/core/objects/role/role.diff.js +16 -0
  59. package/dist/core/objects/role/role.model.d.ts +10 -0
  60. package/dist/core/objects/role/role.model.js +29 -0
  61. package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
  62. package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
  63. package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
  64. package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
  65. package/dist/core/objects/schema/schema.diff.js +24 -1
  66. package/dist/core/objects/schema/schema.model.d.ts +10 -0
  67. package/dist/core/objects/schema/schema.model.js +18 -1
  68. package/dist/core/objects/security-label.types.d.ts +20 -0
  69. package/dist/core/objects/security-label.types.js +46 -0
  70. package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
  71. package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
  72. package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
  73. package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
  74. package/dist/core/objects/sequence/sequence.diff.js +16 -0
  75. package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
  76. package/dist/core/objects/sequence/sequence.model.js +19 -1
  77. package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
  78. package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
  79. package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
  80. package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
  81. package/dist/core/objects/subscription/subscription.diff.js +16 -0
  82. package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
  83. package/dist/core/objects/subscription/subscription.model.js +19 -1
  84. package/dist/core/objects/table/changes/table.base.d.ts +1 -1
  85. package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
  86. package/dist/core/objects/table/changes/table.security-label.js +134 -0
  87. package/dist/core/objects/table/changes/table.types.d.ts +2 -1
  88. package/dist/core/objects/table/table.diff.js +49 -0
  89. package/dist/core/objects/table/table.model.d.ts +30 -0
  90. package/dist/core/objects/table/table.model.js +34 -2
  91. package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
  92. package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
  93. package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
  94. package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
  95. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
  96. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
  97. package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
  98. package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
  99. package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
  100. package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
  101. package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
  102. package/dist/core/objects/type/enum/enum.diff.js +16 -0
  103. package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
  104. package/dist/core/objects/type/enum/enum.model.js +20 -1
  105. package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
  106. package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
  107. package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
  108. package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
  109. package/dist/core/objects/type/range/range.diff.js +16 -0
  110. package/dist/core/objects/type/range/range.model.d.ts +10 -0
  111. package/dist/core/objects/type/range/range.model.js +19 -1
  112. package/dist/core/objects/utils.d.ts +1 -0
  113. package/dist/core/objects/utils.js +3 -0
  114. package/dist/core/objects/view/changes/view.base.d.ts +1 -1
  115. package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
  116. package/dist/core/objects/view/changes/view.security-label.js +61 -0
  117. package/dist/core/objects/view/changes/view.types.d.ts +2 -1
  118. package/dist/core/objects/view/view.diff.js +13 -0
  119. package/dist/core/objects/view/view.model.d.ts +26 -0
  120. package/dist/core/objects/view/view.model.js +20 -1
  121. package/dist/core/plan/sql-format/fixtures.js +1 -0
  122. package/dist/core/post-diff-normalization.d.ts +7 -0
  123. package/dist/core/post-diff-normalization.js +33 -4
  124. package/dist/core/sort/cycle-breakers.js +139 -17
  125. package/package.json +1 -1
  126. package/src/core/catalog.model.ts +1 -0
  127. package/src/core/integrations/filter/dsl.test.ts +27 -0
  128. package/src/core/integrations/filter/flatten.ts +16 -0
  129. package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
  130. package/src/core/objects/aggregate/aggregate.model.ts +22 -1
  131. package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
  132. package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
  133. package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
  134. package/src/core/objects/base.model.ts +2 -0
  135. package/src/core/objects/domain/changes/domain.base.ts +5 -1
  136. package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
  137. package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
  138. package/src/core/objects/domain/changes/domain.types.ts +3 -1
  139. package/src/core/objects/domain/domain.diff.ts +33 -0
  140. package/src/core/objects/domain/domain.model.ts +22 -1
  141. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
  142. package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
  143. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
  144. package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
  145. package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
  146. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
  147. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
  149. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
  151. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
  152. package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
  153. package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
  154. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
  155. package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
  156. package/src/core/objects/materialized-view/materialized-view.model.ts +25 -4
  157. package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
  158. package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
  159. package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
  160. package/src/core/objects/procedure/procedure.diff.ts +33 -0
  161. package/src/core/objects/procedure/procedure.model.ts +23 -2
  162. package/src/core/objects/publication/changes/publication.base.ts +1 -1
  163. package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
  164. package/src/core/objects/publication/changes/publication.types.ts +3 -1
  165. package/src/core/objects/publication/publication.diff.ts +33 -0
  166. package/src/core/objects/publication/publication.model.ts +24 -1
  167. package/src/core/objects/role/changes/role.base.ts +2 -1
  168. package/src/core/objects/role/changes/role.security-label.ts +77 -0
  169. package/src/core/objects/role/changes/role.types.ts +3 -1
  170. package/src/core/objects/role/role.diff.ts +33 -0
  171. package/src/core/objects/role/role.model.ts +32 -0
  172. package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
  173. package/src/core/objects/schema/changes/schema.base.ts +5 -1
  174. package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
  175. package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
  176. package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
  177. package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
  178. package/src/core/objects/schema/changes/schema.types.ts +3 -1
  179. package/src/core/objects/schema/schema.diff.test.ts +1 -0
  180. package/src/core/objects/schema/schema.diff.ts +43 -1
  181. package/src/core/objects/schema/schema.model.ts +21 -1
  182. package/src/core/objects/security-label.types.test.ts +106 -0
  183. package/src/core/objects/security-label.types.ts +61 -0
  184. package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
  185. package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
  186. package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
  187. package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
  188. package/src/core/objects/sequence/sequence.diff.ts +33 -0
  189. package/src/core/objects/sequence/sequence.model.ts +22 -1
  190. package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
  191. package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
  192. package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
  193. package/src/core/objects/subscription/subscription.diff.ts +33 -0
  194. package/src/core/objects/subscription/subscription.model.ts +22 -1
  195. package/src/core/objects/table/changes/table.base.ts +5 -1
  196. package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
  197. package/src/core/objects/table/changes/table.security-label.ts +183 -0
  198. package/src/core/objects/table/changes/table.types.ts +3 -1
  199. package/src/core/objects/table/table.diff.ts +87 -0
  200. package/src/core/objects/table/table.model.ts +42 -2
  201. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
  202. package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
  203. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
  204. package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
  205. package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
  206. package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
  207. package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
  208. package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
  209. package/src/core/objects/type/enum/enum.diff.ts +33 -0
  210. package/src/core/objects/type/enum/enum.model.ts +25 -1
  211. package/src/core/objects/type/range/changes/range.base.ts +5 -1
  212. package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
  213. package/src/core/objects/type/range/changes/range.types.ts +3 -1
  214. package/src/core/objects/type/range/range.diff.ts +33 -0
  215. package/src/core/objects/type/range/range.model.ts +22 -1
  216. package/src/core/objects/utils.ts +3 -0
  217. package/src/core/objects/view/changes/view.base.ts +5 -1
  218. package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
  219. package/src/core/objects/view/changes/view.security-label.ts +77 -0
  220. package/src/core/objects/view/changes/view.types.ts +3 -1
  221. package/src/core/objects/view/view.diff.ts +31 -0
  222. package/src/core/objects/view/view.model.ts +25 -2
  223. package/src/core/plan/sql-format/fixtures.ts +1 -0
  224. package/src/core/post-diff-normalization.test.ts +123 -0
  225. package/src/core/post-diff-normalization.ts +40 -4
  226. package/src/core/sort/cycle-breakers.test.ts +236 -2
  227. package/src/core/sort/cycle-breakers.ts +184 -24
  228. package/src/core/sort/sort-changes.test.ts +317 -0
@@ -6,6 +6,10 @@ import {
6
6
  type PrivilegeProps,
7
7
  privilegePropsSchema,
8
8
  } from "../base.privilege-diff.ts";
9
+ import {
10
+ type SecurityLabelProps,
11
+ securityLabelPropsSchema,
12
+ } from "../security-label.types.ts";
9
13
 
10
14
  const sequencePropsSchema = z.object({
11
15
  schema: z.string(),
@@ -24,6 +28,7 @@ const sequencePropsSchema = z.object({
24
28
  comment: z.string().nullable(),
25
29
  privileges: z.array(privilegePropsSchema),
26
30
  owner: z.string(),
31
+ security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
27
32
  });
28
33
 
29
34
  type SequencePrivilegeProps = PrivilegeProps;
@@ -46,6 +51,7 @@ export class Sequence extends BasePgModel {
46
51
  public readonly comment: SequenceProps["comment"];
47
52
  public readonly privileges: SequencePrivilegeProps[];
48
53
  public readonly owner: SequenceProps["owner"];
54
+ public readonly security_labels: SecurityLabelProps[];
49
55
 
50
56
  constructor(props: SequenceProps) {
51
57
  super();
@@ -69,6 +75,7 @@ export class Sequence extends BasePgModel {
69
75
  this.comment = props.comment;
70
76
  this.privileges = props.privileges;
71
77
  this.owner = props.owner;
78
+ this.security_labels = props.security_labels ?? [];
72
79
  }
73
80
 
74
81
  get stableId(): `sequence:${string}` {
@@ -98,6 +105,7 @@ export class Sequence extends BasePgModel {
98
105
  comment: this.comment,
99
106
  privileges: this.privileges,
100
107
  owner: this.owner,
108
+ security_labels: this.security_labels,
101
109
  };
102
110
  }
103
111
  }
@@ -151,7 +159,20 @@ select
151
159
  from lateral aclexplode(COALESCE(c.relacl, acldefault('S', c.relowner))) as x(grantor, grantee, privilege_type, is_grantable)
152
160
  ), '[]'
153
161
  ) as privileges,
154
- c.relowner::regrole::text as owner
162
+ c.relowner::regrole::text as owner,
163
+ coalesce(
164
+ (
165
+ select json_agg(
166
+ json_build_object('provider', sl.provider, 'label', sl.label)
167
+ order by sl.provider
168
+ )
169
+ from pg_catalog.pg_seclabel sl
170
+ where sl.objoid = c.oid
171
+ and sl.classoid = 'pg_class'::regclass
172
+ and sl.objsubid = 0
173
+ ),
174
+ '[]'::json
175
+ ) as security_labels
155
176
  from
156
177
  pg_catalog.pg_class c
157
178
  inner join pg_catalog.pg_sequence s on s.seqrelid = c.oid
@@ -3,7 +3,7 @@ import type { Subscription } from "../subscription.model.ts";
3
3
 
4
4
  abstract class BaseSubscriptionChange extends BaseChange {
5
5
  abstract readonly subscription: Subscription;
6
- abstract readonly scope: "object" | "comment";
6
+ abstract readonly scope: "object" | "comment" | "security_label";
7
7
  readonly objectType = "subscription" as const;
8
8
  }
9
9
 
@@ -0,0 +1,95 @@
1
+ import { quoteLiteral } from "../../base.change.ts";
2
+ import type { SecurityLabelProps } from "../../security-label.types.ts";
3
+ import { stableId } from "../../utils.ts";
4
+ import type { Subscription } from "../subscription.model.ts";
5
+ import {
6
+ CreateSubscriptionChange,
7
+ DropSubscriptionChange,
8
+ } from "./subscription.base.ts";
9
+
10
+ export type SecurityLabelSubscription =
11
+ | CreateSecurityLabelOnSubscription
12
+ | DropSecurityLabelOnSubscription;
13
+
14
+ export class CreateSecurityLabelOnSubscription extends CreateSubscriptionChange {
15
+ public readonly subscription: Subscription;
16
+ public readonly securityLabel: SecurityLabelProps;
17
+ public readonly scope = "security_label" as const;
18
+
19
+ constructor(props: {
20
+ subscription: Subscription;
21
+ securityLabel: SecurityLabelProps;
22
+ }) {
23
+ super();
24
+ this.subscription = props.subscription;
25
+ this.securityLabel = props.securityLabel;
26
+ }
27
+
28
+ get creates() {
29
+ return [
30
+ stableId.securityLabel(
31
+ this.subscription.stableId,
32
+ this.securityLabel.provider,
33
+ ),
34
+ ];
35
+ }
36
+
37
+ get requires() {
38
+ return [this.subscription.stableId];
39
+ }
40
+
41
+ serialize(): string {
42
+ return [
43
+ "SECURITY LABEL FOR",
44
+ this.securityLabel.provider,
45
+ "ON SUBSCRIPTION",
46
+ this.subscription.name,
47
+ "IS",
48
+ quoteLiteral(this.securityLabel.label),
49
+ ].join(" ");
50
+ }
51
+ }
52
+
53
+ export class DropSecurityLabelOnSubscription extends DropSubscriptionChange {
54
+ public readonly subscription: Subscription;
55
+ public readonly securityLabel: SecurityLabelProps;
56
+ public readonly scope = "security_label" as const;
57
+
58
+ constructor(props: {
59
+ subscription: Subscription;
60
+ securityLabel: SecurityLabelProps;
61
+ }) {
62
+ super();
63
+ this.subscription = props.subscription;
64
+ this.securityLabel = props.securityLabel;
65
+ }
66
+
67
+ get drops() {
68
+ return [
69
+ stableId.securityLabel(
70
+ this.subscription.stableId,
71
+ this.securityLabel.provider,
72
+ ),
73
+ ];
74
+ }
75
+
76
+ get requires() {
77
+ return [
78
+ stableId.securityLabel(
79
+ this.subscription.stableId,
80
+ this.securityLabel.provider,
81
+ ),
82
+ this.subscription.stableId,
83
+ ];
84
+ }
85
+
86
+ serialize(): string {
87
+ return [
88
+ "SECURITY LABEL FOR",
89
+ this.securityLabel.provider,
90
+ "ON SUBSCRIPTION",
91
+ this.subscription.name,
92
+ "IS NULL",
93
+ ].join(" ");
94
+ }
95
+ }
@@ -9,6 +9,7 @@ import type {
9
9
  import type { CommentSubscription } from "./subscription.comment.ts";
10
10
  import type { CreateSubscription } from "./subscription.create.ts";
11
11
  import type { DropSubscription } from "./subscription.drop.ts";
12
+ import type { SecurityLabelSubscription } from "./subscription.security-label.ts";
12
13
 
13
14
  /** Union of all subscription-related change variants (`objectType: "subscription"`). @category Change Types */
14
15
  export type SubscriptionChange =
@@ -20,4 +21,5 @@ export type SubscriptionChange =
20
21
  | AlterSubscriptionDisable
21
22
  | AlterSubscriptionSetOptions
22
23
  | AlterSubscriptionSetOwner
23
- | CommentSubscription;
24
+ | CommentSubscription
25
+ | SecurityLabelSubscription;
@@ -1,5 +1,6 @@
1
1
  import { diffObjects } from "../base.diff.ts";
2
2
  import type { ObjectDiffContext } from "../diff-context.ts";
3
+ import { diffSecurityLabels } from "../security-label.types.ts";
3
4
  import { hasNonAlterableChanges } from "../utils.ts";
4
5
  import {
5
6
  AlterSubscriptionDisable,
@@ -15,6 +16,10 @@ import {
15
16
  } from "./changes/subscription.comment.ts";
16
17
  import { CreateSubscription } from "./changes/subscription.create.ts";
17
18
  import { DropSubscription } from "./changes/subscription.drop.ts";
19
+ import {
20
+ CreateSecurityLabelOnSubscription,
21
+ DropSecurityLabelOnSubscription,
22
+ } from "./changes/subscription.security-label.ts";
18
23
  import type { SubscriptionChange } from "./changes/subscription.types.ts";
19
24
  import type { Subscription } from "./subscription.model.ts";
20
25
  import type { SubscriptionSettableOption } from "./utils.ts";
@@ -61,6 +66,14 @@ export function diffSubscriptions(
61
66
  if (subscription.comment !== null) {
62
67
  changes.push(new CreateCommentOnSubscription({ subscription }));
63
68
  }
69
+ for (const label of subscription.security_labels) {
70
+ changes.push(
71
+ new CreateSecurityLabelOnSubscription({
72
+ subscription,
73
+ securityLabel: label,
74
+ }),
75
+ );
76
+ }
64
77
  }
65
78
 
66
79
  for (const id of dropped) {
@@ -236,6 +249,26 @@ export function diffSubscriptions(
236
249
  );
237
250
  }
238
251
  }
252
+
253
+ // SECURITY LABELS
254
+ changes.push(
255
+ ...diffSecurityLabels<
256
+ CreateSecurityLabelOnSubscription | DropSecurityLabelOnSubscription
257
+ >(
258
+ mainSubscription.security_labels,
259
+ branchSubscription.security_labels,
260
+ (securityLabel) =>
261
+ new CreateSecurityLabelOnSubscription({
262
+ subscription: branchSubscription,
263
+ securityLabel,
264
+ }),
265
+ (securityLabel) =>
266
+ new DropSecurityLabelOnSubscription({
267
+ subscription: mainSubscription,
268
+ securityLabel,
269
+ }),
270
+ ),
271
+ );
239
272
  }
240
273
 
241
274
  return changes;
@@ -2,6 +2,10 @@ import type { Pool } from "pg";
2
2
  import z from "zod";
3
3
  import { extractVersion } from "../../context.ts";
4
4
  import { BasePgModel } from "../base.model.ts";
5
+ import {
6
+ type SecurityLabelProps,
7
+ securityLabelPropsSchema,
8
+ } from "../security-label.types.ts";
5
9
 
6
10
  const subscriptionPropsSchema = z.object({
7
11
  name: z.string(),
@@ -23,6 +27,7 @@ const subscriptionPropsSchema = z.object({
23
27
  synchronous_commit: z.string(),
24
28
  publications: z.array(z.string()),
25
29
  origin: z.enum(["any", "none"]),
30
+ security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
26
31
  });
27
32
 
28
33
  export type SubscriptionProps = z.infer<typeof subscriptionPropsSchema>;
@@ -47,6 +52,7 @@ export class Subscription extends BasePgModel {
47
52
  public readonly synchronous_commit: SubscriptionProps["synchronous_commit"];
48
53
  public readonly publications: SubscriptionProps["publications"];
49
54
  public readonly origin: SubscriptionProps["origin"];
55
+ public readonly security_labels: SecurityLabelProps[];
50
56
 
51
57
  constructor(props: SubscriptionProps) {
52
58
  super();
@@ -72,6 +78,7 @@ export class Subscription extends BasePgModel {
72
78
  a.localeCompare(b),
73
79
  );
74
80
  this.origin = props.origin;
81
+ this.security_labels = props.security_labels ?? [];
75
82
  }
76
83
 
77
84
  get stableId(): `subscription:${string}` {
@@ -104,6 +111,7 @@ export class Subscription extends BasePgModel {
104
111
  synchronous_commit: this.synchronous_commit,
105
112
  publications: this.publications,
106
113
  origin: this.origin,
114
+ security_labels: this.security_labels,
107
115
  };
108
116
  }
109
117
  }
@@ -173,7 +181,20 @@ export async function extractSubscriptions(
173
181
  ),
174
182
  '[]'::json
175
183
  ) as publications,
176
- ${originExpr} as origin
184
+ ${originExpr} as origin,
185
+ coalesce(
186
+ (
187
+ select json_agg(
188
+ json_build_object('provider', sl.provider, 'label', sl.label)
189
+ order by sl.provider
190
+ )
191
+ from pg_catalog.pg_seclabel sl
192
+ where sl.objoid = s.oid
193
+ and sl.classoid = 'pg_subscription'::regclass
194
+ and sl.objsubid = 0
195
+ ),
196
+ '[]'::json
197
+ ) as security_labels
177
198
  from scoped_subscriptions s
178
199
  left join pg_replication_slots r
179
200
  on r.slot_name = s.subslotname
@@ -3,7 +3,11 @@ import type { Table } from "../table.model.ts";
3
3
 
4
4
  abstract class BaseTableChange extends BaseChange {
5
5
  abstract readonly table: Table;
6
- abstract readonly scope: "object" | "comment" | "privilege";
6
+ abstract readonly scope:
7
+ | "object"
8
+ | "comment"
9
+ | "privilege"
10
+ | "security_label";
7
11
  readonly objectType: "table" = "table";
8
12
  }
9
13
 
@@ -0,0 +1,140 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
3
+ import type { ColumnProps } from "../../base.model.ts";
4
+ import { stableId } from "../../utils.ts";
5
+ import { Table, type TableProps } from "../table.model.ts";
6
+ import {
7
+ CreateSecurityLabelOnColumn,
8
+ CreateSecurityLabelOnTable,
9
+ DropSecurityLabelOnColumn,
10
+ DropSecurityLabelOnTable,
11
+ } from "./table.security-label.ts";
12
+
13
+ const makeColumn = (overrides: Partial<ColumnProps> = {}): ColumnProps => ({
14
+ name: "id",
15
+ position: 1,
16
+ data_type: "integer",
17
+ data_type_str: "integer",
18
+ is_custom_type: false,
19
+ custom_type_type: null,
20
+ custom_type_category: null,
21
+ custom_type_schema: null,
22
+ custom_type_name: null,
23
+ not_null: false,
24
+ is_identity: false,
25
+ is_identity_always: false,
26
+ is_generated: false,
27
+ collation: null,
28
+ default: null,
29
+ comment: null,
30
+ ...overrides,
31
+ });
32
+
33
+ const makeTable = (): Table =>
34
+ new Table({
35
+ schema: "public",
36
+ name: "users",
37
+ persistence: "p",
38
+ row_security: false,
39
+ force_row_security: false,
40
+ has_indexes: false,
41
+ has_rules: false,
42
+ has_triggers: false,
43
+ has_subclasses: false,
44
+ is_populated: true,
45
+ replica_identity: "d",
46
+ is_partition: false,
47
+ options: null,
48
+ partition_bound: null,
49
+ partition_by: null,
50
+ owner: "postgres",
51
+ comment: null,
52
+ parent_schema: null,
53
+ parent_name: null,
54
+ columns: [makeColumn({ name: "email" })],
55
+ privileges: [],
56
+ security_labels: [],
57
+ } as TableProps);
58
+
59
+ describe("table.security-label", () => {
60
+ test("table create serializes and tracks dependencies", async () => {
61
+ const table = makeTable();
62
+ const change = new CreateSecurityLabelOnTable({
63
+ table,
64
+ securityLabel: { provider: "dummy", label: "classified" },
65
+ });
66
+
67
+ expect(change.scope).toBe("security_label");
68
+ expect(change.objectType).toBe("table");
69
+ expect(change.operation).toBe("create");
70
+ expect(change.creates).toEqual([
71
+ stableId.securityLabel(table.stableId, "dummy"),
72
+ ]);
73
+ expect(change.requires).toEqual([table.stableId]);
74
+ await assertValidSql(change.serialize());
75
+ expect(change.serialize()).toBe(
76
+ "SECURITY LABEL FOR dummy ON TABLE public.users IS 'classified'",
77
+ );
78
+ });
79
+
80
+ test("table drop serializes to IS NULL", async () => {
81
+ const table = makeTable();
82
+ const change = new DropSecurityLabelOnTable({
83
+ table,
84
+ securityLabel: { provider: "dummy", label: "classified" },
85
+ });
86
+ expect(change.drops).toEqual([
87
+ stableId.securityLabel(table.stableId, "dummy"),
88
+ ]);
89
+ expect(change.requires).toEqual([
90
+ stableId.securityLabel(table.stableId, "dummy"),
91
+ table.stableId,
92
+ ]);
93
+ await assertValidSql(change.serialize());
94
+ expect(change.serialize()).toBe(
95
+ "SECURITY LABEL FOR dummy ON TABLE public.users IS NULL",
96
+ );
97
+ });
98
+
99
+ test("column create serializes and tracks dependencies", async () => {
100
+ const table = makeTable();
101
+ const column = makeColumn({ name: "email" });
102
+ const change = new CreateSecurityLabelOnColumn({
103
+ table,
104
+ column,
105
+ securityLabel: { provider: "dummy", label: "classified" },
106
+ });
107
+
108
+ const colStableId = stableId.column(table.schema, table.name, column.name);
109
+ expect(change.creates).toEqual([
110
+ stableId.securityLabel(colStableId, "dummy"),
111
+ ]);
112
+ expect(change.requires).toEqual([colStableId]);
113
+ await assertValidSql(change.serialize());
114
+ expect(change.serialize()).toBe(
115
+ "SECURITY LABEL FOR dummy ON COLUMN public.users.email IS 'classified'",
116
+ );
117
+ });
118
+
119
+ test("column drop serializes to IS NULL", async () => {
120
+ const table = makeTable();
121
+ const column = makeColumn({ name: "email" });
122
+ const change = new DropSecurityLabelOnColumn({
123
+ table,
124
+ column,
125
+ securityLabel: { provider: "dummy", label: "x" },
126
+ });
127
+ const colStableId = stableId.column(table.schema, table.name, column.name);
128
+ expect(change.drops).toEqual([
129
+ stableId.securityLabel(colStableId, "dummy"),
130
+ ]);
131
+ expect(change.requires).toEqual([
132
+ stableId.securityLabel(colStableId, "dummy"),
133
+ colStableId,
134
+ ]);
135
+ await assertValidSql(change.serialize());
136
+ expect(change.serialize()).toBe(
137
+ "SECURITY LABEL FOR dummy ON COLUMN public.users.email IS NULL",
138
+ );
139
+ });
140
+ });
@@ -0,0 +1,183 @@
1
+ import { quoteLiteral } from "../../base.change.ts";
2
+ import type { ColumnProps } from "../../base.model.ts";
3
+ import type { SecurityLabelProps } from "../../security-label.types.ts";
4
+ import { stableId } from "../../utils.ts";
5
+ import type { Table } from "../table.model.ts";
6
+ import { CreateTableChange, DropTableChange } from "./table.base.ts";
7
+
8
+ export type SecurityLabelTable =
9
+ | CreateSecurityLabelOnTable
10
+ | DropSecurityLabelOnTable
11
+ | CreateSecurityLabelOnColumn
12
+ | DropSecurityLabelOnColumn;
13
+
14
+ /**
15
+ * SECURITY LABEL FOR <provider> ON TABLE <schema>.<table> IS <literal>
16
+ */
17
+ export class CreateSecurityLabelOnTable extends CreateTableChange {
18
+ public readonly table: Table;
19
+ public readonly securityLabel: SecurityLabelProps;
20
+ public readonly scope = "security_label" as const;
21
+
22
+ constructor(props: { table: Table; securityLabel: SecurityLabelProps }) {
23
+ super();
24
+ this.table = props.table;
25
+ this.securityLabel = props.securityLabel;
26
+ }
27
+
28
+ get creates() {
29
+ return [
30
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
31
+ ];
32
+ }
33
+
34
+ get requires() {
35
+ return [this.table.stableId];
36
+ }
37
+
38
+ serialize(): string {
39
+ return [
40
+ "SECURITY LABEL FOR",
41
+ this.securityLabel.provider,
42
+ "ON TABLE",
43
+ `${this.table.schema}.${this.table.name}`,
44
+ "IS",
45
+ quoteLiteral(this.securityLabel.label),
46
+ ].join(" ");
47
+ }
48
+ }
49
+
50
+ export class DropSecurityLabelOnTable extends DropTableChange {
51
+ public readonly table: Table;
52
+ public readonly securityLabel: SecurityLabelProps;
53
+ public readonly scope = "security_label" as const;
54
+
55
+ constructor(props: { table: Table; securityLabel: SecurityLabelProps }) {
56
+ super();
57
+ this.table = props.table;
58
+ this.securityLabel = props.securityLabel;
59
+ }
60
+
61
+ get drops() {
62
+ return [
63
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
64
+ ];
65
+ }
66
+
67
+ get requires() {
68
+ return [
69
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
70
+ this.table.stableId,
71
+ ];
72
+ }
73
+
74
+ serialize(): string {
75
+ return [
76
+ "SECURITY LABEL FOR",
77
+ this.securityLabel.provider,
78
+ "ON TABLE",
79
+ `${this.table.schema}.${this.table.name}`,
80
+ "IS NULL",
81
+ ].join(" ");
82
+ }
83
+ }
84
+
85
+ /**
86
+ * SECURITY LABEL FOR <provider> ON COLUMN <schema>.<table>.<column> IS <literal>
87
+ */
88
+ export class CreateSecurityLabelOnColumn extends CreateTableChange {
89
+ public readonly table: Table;
90
+ public readonly column: ColumnProps;
91
+ public readonly securityLabel: SecurityLabelProps;
92
+ public readonly scope = "security_label" as const;
93
+
94
+ constructor(props: {
95
+ table: Table;
96
+ column: ColumnProps;
97
+ securityLabel: SecurityLabelProps;
98
+ }) {
99
+ super();
100
+ this.table = props.table;
101
+ this.column = props.column;
102
+ this.securityLabel = props.securityLabel;
103
+ }
104
+
105
+ get creates() {
106
+ const columnStableId = stableId.column(
107
+ this.table.schema,
108
+ this.table.name,
109
+ this.column.name,
110
+ );
111
+ return [
112
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
113
+ ];
114
+ }
115
+
116
+ get requires() {
117
+ return [
118
+ stableId.column(this.table.schema, this.table.name, this.column.name),
119
+ ];
120
+ }
121
+
122
+ serialize(): string {
123
+ return [
124
+ "SECURITY LABEL FOR",
125
+ this.securityLabel.provider,
126
+ "ON COLUMN",
127
+ `${this.table.schema}.${this.table.name}.${this.column.name}`,
128
+ "IS",
129
+ quoteLiteral(this.securityLabel.label),
130
+ ].join(" ");
131
+ }
132
+ }
133
+
134
+ export class DropSecurityLabelOnColumn extends DropTableChange {
135
+ public readonly table: Table;
136
+ public readonly column: ColumnProps;
137
+ public readonly securityLabel: SecurityLabelProps;
138
+ public readonly scope = "security_label" as const;
139
+
140
+ constructor(props: {
141
+ table: Table;
142
+ column: ColumnProps;
143
+ securityLabel: SecurityLabelProps;
144
+ }) {
145
+ super();
146
+ this.table = props.table;
147
+ this.column = props.column;
148
+ this.securityLabel = props.securityLabel;
149
+ }
150
+
151
+ get drops() {
152
+ const columnStableId = stableId.column(
153
+ this.table.schema,
154
+ this.table.name,
155
+ this.column.name,
156
+ );
157
+ return [
158
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
159
+ ];
160
+ }
161
+
162
+ get requires() {
163
+ const columnStableId = stableId.column(
164
+ this.table.schema,
165
+ this.table.name,
166
+ this.column.name,
167
+ );
168
+ return [
169
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
170
+ columnStableId,
171
+ ];
172
+ }
173
+
174
+ serialize(): string {
175
+ return [
176
+ "SECURITY LABEL FOR",
177
+ this.securityLabel.provider,
178
+ "ON COLUMN",
179
+ `${this.table.schema}.${this.table.name}.${this.column.name}`,
180
+ "IS NULL",
181
+ ].join(" ");
182
+ }
183
+ }
@@ -3,6 +3,7 @@ import type { CommentTable } from "./table.comment.ts";
3
3
  import type { CreateTable } from "./table.create.ts";
4
4
  import type { DropTable } from "./table.drop.ts";
5
5
  import type { TablePrivilege } from "./table.privilege.ts";
6
+ import type { SecurityLabelTable } from "./table.security-label.ts";
6
7
 
7
8
  /** Union of all table-related change variants (`objectType: "table"`). @category Change Types */
8
9
  export type TableChange =
@@ -10,4 +11,5 @@ export type TableChange =
10
11
  | CommentTable
11
12
  | CreateTable
12
13
  | DropTable
13
- | TablePrivilege;
14
+ | TablePrivilege
15
+ | SecurityLabelTable;