@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.
Files changed (271) hide show
  1. package/dist/core/catalog.diff.js +4 -3
  2. package/dist/core/catalog.model.d.ts +8 -1
  3. package/dist/core/catalog.model.js +10 -8
  4. package/dist/core/expand-replace-dependencies.js +23 -0
  5. package/dist/core/integrations/filter/flatten.js +13 -0
  6. package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
  7. package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
  8. package/dist/core/objects/aggregate/aggregate.model.js +19 -1
  9. package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
  10. package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
  11. package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
  12. package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
  13. package/dist/core/objects/base.model.d.ts +8 -0
  14. package/dist/core/objects/base.model.js +2 -0
  15. package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
  16. package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
  17. package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
  18. package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
  19. package/dist/core/objects/domain/domain.diff.js +16 -0
  20. package/dist/core/objects/domain/domain.model.d.ts +10 -0
  21. package/dist/core/objects/domain/domain.model.js +19 -1
  22. package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
  23. package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
  24. package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
  25. package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
  26. package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
  27. package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
  28. package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
  29. package/dist/core/objects/extract-with-retry.d.ts +36 -0
  30. package/dist/core/objects/extract-with-retry.js +51 -0
  31. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
  32. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
  33. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
  34. package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
  35. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
  36. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
  37. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
  38. package/dist/core/objects/index/index.diff.js +0 -1
  39. package/dist/core/objects/index/index.model.d.ts +2 -3
  40. package/dist/core/objects/index/index.model.js +17 -6
  41. package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
  42. package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
  43. package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
  44. package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
  45. package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
  46. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +24 -1
  47. package/dist/core/objects/materialized-view/materialized-view.model.js +40 -5
  48. package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
  49. package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
  50. package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
  51. package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
  52. package/dist/core/objects/procedure/procedure.diff.js +16 -0
  53. package/dist/core/objects/procedure/procedure.model.d.ts +12 -1
  54. package/dist/core/objects/procedure/procedure.model.js +39 -5
  55. package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
  56. package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
  57. package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
  58. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
  59. package/dist/core/objects/publication/publication.diff.js +16 -0
  60. package/dist/core/objects/publication/publication.model.d.ts +14 -0
  61. package/dist/core/objects/publication/publication.model.js +20 -1
  62. package/dist/core/objects/rls-policy/rls-policy.diff.js +13 -1
  63. package/dist/core/objects/role/changes/role.base.d.ts +1 -1
  64. package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
  65. package/dist/core/objects/role/changes/role.security-label.js +61 -0
  66. package/dist/core/objects/role/changes/role.types.d.ts +2 -1
  67. package/dist/core/objects/role/role.diff.js +16 -0
  68. package/dist/core/objects/role/role.model.d.ts +10 -0
  69. package/dist/core/objects/role/role.model.js +29 -0
  70. package/dist/core/objects/rule/rule.model.d.ts +2 -1
  71. package/dist/core/objects/rule/rule.model.js +20 -3
  72. package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
  73. package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
  74. package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
  75. package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
  76. package/dist/core/objects/schema/schema.diff.js +24 -1
  77. package/dist/core/objects/schema/schema.model.d.ts +10 -0
  78. package/dist/core/objects/schema/schema.model.js +18 -1
  79. package/dist/core/objects/security-label.types.d.ts +20 -0
  80. package/dist/core/objects/security-label.types.js +46 -0
  81. package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
  82. package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
  83. package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
  84. package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
  85. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -1
  86. package/dist/core/objects/sequence/sequence.diff.js +44 -4
  87. package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
  88. package/dist/core/objects/sequence/sequence.model.js +19 -1
  89. package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
  90. package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
  91. package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
  92. package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
  93. package/dist/core/objects/subscription/subscription.diff.js +16 -0
  94. package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
  95. package/dist/core/objects/subscription/subscription.model.js +19 -1
  96. package/dist/core/objects/table/changes/table.alter.d.ts +12 -1
  97. package/dist/core/objects/table/changes/table.alter.js +20 -2
  98. package/dist/core/objects/table/changes/table.base.d.ts +1 -1
  99. package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
  100. package/dist/core/objects/table/changes/table.security-label.js +134 -0
  101. package/dist/core/objects/table/changes/table.types.d.ts +2 -1
  102. package/dist/core/objects/table/table.diff.js +68 -15
  103. package/dist/core/objects/table/table.model.d.ts +36 -1
  104. package/dist/core/objects/table/table.model.js +74 -7
  105. package/dist/core/objects/trigger/trigger.model.d.ts +2 -1
  106. package/dist/core/objects/trigger/trigger.model.js +20 -4
  107. package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
  108. package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
  109. package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
  110. package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
  111. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
  112. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
  113. package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
  114. package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
  115. package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
  116. package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
  117. package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
  118. package/dist/core/objects/type/enum/enum.diff.js +16 -0
  119. package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
  120. package/dist/core/objects/type/enum/enum.model.js +20 -1
  121. package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
  122. package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
  123. package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
  124. package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
  125. package/dist/core/objects/type/range/range.diff.js +16 -0
  126. package/dist/core/objects/type/range/range.model.d.ts +10 -0
  127. package/dist/core/objects/type/range/range.model.js +19 -1
  128. package/dist/core/objects/utils.d.ts +2 -0
  129. package/dist/core/objects/utils.js +6 -0
  130. package/dist/core/objects/view/changes/view.base.d.ts +1 -1
  131. package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
  132. package/dist/core/objects/view/changes/view.security-label.js +61 -0
  133. package/dist/core/objects/view/changes/view.types.d.ts +2 -1
  134. package/dist/core/objects/view/view.diff.js +13 -0
  135. package/dist/core/objects/view/view.model.d.ts +28 -1
  136. package/dist/core/objects/view/view.model.js +40 -5
  137. package/dist/core/plan/create.js +3 -1
  138. package/dist/core/plan/sql-format/fixtures.js +1 -0
  139. package/dist/core/plan/types.d.ts +8 -0
  140. package/dist/core/{post-diff-cycle-breaking.d.ts → post-diff-normalization.d.ts} +8 -1
  141. package/dist/core/post-diff-normalization.js +202 -0
  142. package/dist/core/sort/cycle-breakers.js +1 -1
  143. package/dist/core/sort/utils.d.ts +10 -0
  144. package/dist/core/sort/utils.js +28 -0
  145. package/package.json +1 -1
  146. package/src/core/catalog.diff.ts +4 -2
  147. package/src/core/catalog.model.ts +21 -8
  148. package/src/core/expand-replace-dependencies.test.ts +131 -0
  149. package/src/core/expand-replace-dependencies.ts +24 -0
  150. package/src/core/integrations/filter/dsl.test.ts +27 -0
  151. package/src/core/integrations/filter/flatten.ts +16 -0
  152. package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
  153. package/src/core/objects/aggregate/aggregate.model.ts +22 -1
  154. package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
  155. package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
  156. package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
  157. package/src/core/objects/base.model.ts +2 -0
  158. package/src/core/objects/domain/changes/domain.base.ts +5 -1
  159. package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
  160. package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
  161. package/src/core/objects/domain/changes/domain.types.ts +3 -1
  162. package/src/core/objects/domain/domain.diff.ts +33 -0
  163. package/src/core/objects/domain/domain.model.ts +22 -1
  164. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
  165. package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
  166. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
  167. package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
  168. package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
  169. package/src/core/objects/extract-with-retry.test.ts +143 -0
  170. package/src/core/objects/extract-with-retry.ts +87 -0
  171. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
  172. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
  173. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
  174. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
  175. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
  176. package/src/core/objects/index/index.diff.ts +0 -1
  177. package/src/core/objects/index/index.model.test.ts +37 -1
  178. package/src/core/objects/index/index.model.ts +25 -6
  179. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
  180. package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
  181. package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
  182. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
  183. package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
  184. package/src/core/objects/materialized-view/materialized-view.model.test.ts +93 -0
  185. package/src/core/objects/materialized-view/materialized-view.model.ts +52 -8
  186. package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
  187. package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
  188. package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
  189. package/src/core/objects/procedure/procedure.diff.ts +33 -0
  190. package/src/core/objects/procedure/procedure.model.test.ts +117 -0
  191. package/src/core/objects/procedure/procedure.model.ts +51 -7
  192. package/src/core/objects/publication/changes/publication.base.ts +1 -1
  193. package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
  194. package/src/core/objects/publication/changes/publication.types.ts +3 -1
  195. package/src/core/objects/publication/publication.diff.ts +33 -0
  196. package/src/core/objects/publication/publication.model.ts +24 -1
  197. package/src/core/objects/rls-policy/rls-policy.diff.ts +19 -1
  198. package/src/core/objects/role/changes/role.base.ts +2 -1
  199. package/src/core/objects/role/changes/role.security-label.ts +77 -0
  200. package/src/core/objects/role/changes/role.types.ts +3 -1
  201. package/src/core/objects/role/role.diff.ts +33 -0
  202. package/src/core/objects/role/role.model.ts +32 -0
  203. package/src/core/objects/rule/rule.model.test.ts +99 -0
  204. package/src/core/objects/rule/rule.model.ts +28 -4
  205. package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
  206. package/src/core/objects/schema/changes/schema.base.ts +5 -1
  207. package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
  208. package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
  209. package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
  210. package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
  211. package/src/core/objects/schema/changes/schema.types.ts +3 -1
  212. package/src/core/objects/schema/schema.diff.test.ts +1 -0
  213. package/src/core/objects/schema/schema.diff.ts +43 -1
  214. package/src/core/objects/schema/schema.model.ts +21 -1
  215. package/src/core/objects/security-label.types.test.ts +106 -0
  216. package/src/core/objects/security-label.types.ts +61 -0
  217. package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
  218. package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
  219. package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
  220. package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
  221. package/src/core/objects/sequence/sequence.diff.test.ts +87 -0
  222. package/src/core/objects/sequence/sequence.diff.ts +64 -6
  223. package/src/core/objects/sequence/sequence.model.ts +22 -1
  224. package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
  225. package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
  226. package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
  227. package/src/core/objects/subscription/subscription.diff.ts +33 -0
  228. package/src/core/objects/subscription/subscription.model.ts +22 -1
  229. package/src/core/objects/table/changes/table.alter.test.ts +13 -21
  230. package/src/core/objects/table/changes/table.alter.ts +30 -3
  231. package/src/core/objects/table/changes/table.base.ts +5 -1
  232. package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
  233. package/src/core/objects/table/changes/table.security-label.ts +183 -0
  234. package/src/core/objects/table/changes/table.types.ts +3 -1
  235. package/src/core/objects/table/table.diff.ts +111 -19
  236. package/src/core/objects/table/table.model.test.ts +209 -0
  237. package/src/core/objects/table/table.model.ts +94 -9
  238. package/src/core/objects/trigger/trigger.model.test.ts +113 -0
  239. package/src/core/objects/trigger/trigger.model.ts +28 -5
  240. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
  241. package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
  242. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
  243. package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
  244. package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
  245. package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
  246. package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
  247. package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
  248. package/src/core/objects/type/enum/enum.diff.ts +33 -0
  249. package/src/core/objects/type/enum/enum.model.ts +25 -1
  250. package/src/core/objects/type/range/changes/range.base.ts +5 -1
  251. package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
  252. package/src/core/objects/type/range/changes/range.types.ts +3 -1
  253. package/src/core/objects/type/range/range.diff.ts +33 -0
  254. package/src/core/objects/type/range/range.model.ts +22 -1
  255. package/src/core/objects/utils.ts +6 -0
  256. package/src/core/objects/view/changes/view.base.ts +5 -1
  257. package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
  258. package/src/core/objects/view/changes/view.security-label.ts +77 -0
  259. package/src/core/objects/view/changes/view.types.ts +3 -1
  260. package/src/core/objects/view/view.diff.ts +31 -0
  261. package/src/core/objects/view/view.model.test.ts +90 -0
  262. package/src/core/objects/view/view.model.ts +53 -7
  263. package/src/core/plan/create.ts +3 -1
  264. package/src/core/plan/sql-format/fixtures.ts +1 -0
  265. package/src/core/plan/types.ts +8 -0
  266. package/src/core/{post-diff-cycle-breaking.test.ts → post-diff-normalization.test.ts} +168 -4
  267. package/src/core/post-diff-normalization.ts +260 -0
  268. package/src/core/sort/cycle-breakers.ts +1 -1
  269. package/src/core/sort/utils.ts +38 -0
  270. package/dist/core/post-diff-cycle-breaking.js +0 -100
  271. package/src/core/post-diff-cycle-breaking.ts +0 -138
@@ -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
@@ -343,7 +343,7 @@ describe.concurrent("table", () => {
343
343
  ).toBe("ALTER TABLE public.test_table REPLICA IDENTITY FULL");
344
344
  });
345
345
 
346
- test("replica identity DEFAULT and INDEX fallback", async () => {
346
+ test("replica identity DEFAULT and USING INDEX", async () => {
347
347
  const baseProps: Omit<
348
348
  TableProps,
349
349
  "owner" | "options" | "replica_identity"
@@ -372,31 +372,23 @@ describe.concurrent("table", () => {
372
372
  options: null,
373
373
  replica_identity: "n",
374
374
  });
375
- const toDefault = new Table({
376
- ...baseProps,
377
- owner: "o1",
378
- options: null,
379
- replica_identity: "d",
380
- });
381
- const toIndex = new Table({
382
- ...baseProps,
383
- owner: "o1",
384
- options: null,
385
- replica_identity: "i",
386
- });
387
375
  expect(
388
376
  new AlterTableSetReplicaIdentity({
389
377
  table,
390
- mode: toDefault.replica_identity,
391
- }).serialize(),
392
- ).toBe("ALTER TABLE public.test_table REPLICA IDENTITY DEFAULT");
393
- // AlterTableSetReplicaIdentity of type "i" will not be emitted in diff, it is handled by index changes, we fallback to DEFAULT here
394
- expect(
395
- new AlterTableSetReplicaIdentity({
396
- table,
397
- mode: toIndex.replica_identity,
378
+ mode: "d",
398
379
  }).serialize(),
399
380
  ).toBe("ALTER TABLE public.test_table REPLICA IDENTITY DEFAULT");
381
+ const usingIndex = new AlterTableSetReplicaIdentity({
382
+ table,
383
+ mode: "i",
384
+ indexName: "test_table_pkey",
385
+ });
386
+ expect(usingIndex.serialize()).toBe(
387
+ "ALTER TABLE public.test_table REPLICA IDENTITY USING INDEX test_table_pkey",
388
+ );
389
+ expect(usingIndex.requires).toContain(
390
+ "index:public.test_table.test_table_pkey",
391
+ );
400
392
  });
401
393
 
402
394
  test("columns add/drop/alter", async () => {
@@ -462,20 +462,46 @@ export class AlterTableValidateConstraint extends AlterTableChange {
462
462
 
463
463
  /**
464
464
  * ALTER TABLE ... REPLICA IDENTITY ...
465
+ *
466
+ * When `mode === "i"` (USING INDEX), `indexName` is the name of the index to
467
+ * use. The extractor populates `Table.replica_identity_index` from
468
+ * `pg_index.indisreplident` whenever `Table.replica_identity` is `'i'`, so
469
+ * callers that source their props from a `Table` instance can rely on the
470
+ * pair being consistent. The non-null assertions in `requires` / `serialize`
471
+ * below are justified by that data invariant — the same pattern the FK
472
+ * branch of `AlterTableAddConstraint` uses for `foreign_key_columns!` /
473
+ * `foreign_key_table!` / `foreign_key_schema!`.
465
474
  */
466
475
  export class AlterTableSetReplicaIdentity extends AlterTableChange {
467
476
  public readonly table: Table;
468
477
  public readonly mode: "d" | "n" | "f" | "i";
478
+ public readonly indexName: string | null;
469
479
  public readonly scope = "object" as const;
470
480
 
471
- constructor(props: { table: Table; mode: "d" | "n" | "f" | "i" }) {
481
+ constructor(props: {
482
+ table: Table;
483
+ mode: "d" | "n" | "f" | "i";
484
+ indexName?: string | null;
485
+ }) {
472
486
  super();
473
487
  this.table = props.table;
474
488
  this.mode = props.mode;
489
+ this.indexName = props.indexName ?? null;
475
490
  }
476
491
 
477
492
  get requires() {
478
- return [this.table.stableId];
493
+ const reqs: string[] = [this.table.stableId];
494
+ if (this.mode === "i") {
495
+ reqs.push(
496
+ stableId.index(
497
+ this.table.schema,
498
+ this.table.name,
499
+ // biome-ignore lint/style/noNonNullAssertion: mode 'i' implies the extractor populated replica_identity_index
500
+ this.indexName!,
501
+ ),
502
+ );
503
+ }
504
+ return reqs;
479
505
  }
480
506
 
481
507
  serialize(_options?: SerializeOptions): string {
@@ -486,7 +512,8 @@ export class AlterTableSetReplicaIdentity extends AlterTableChange {
486
512
  ? "NOTHING"
487
513
  : this.mode === "f"
488
514
  ? "FULL"
489
- : "DEFAULT"; // 'i' (USING INDEX) is handled via index changes; fallback to DEFAULT
515
+ : // biome-ignore lint/style/noNonNullAssertion: mode 'i' implies the extractor populated replica_identity_index
516
+ `USING INDEX ${this.indexName!}`;
490
517
  return [
491
518
  "ALTER TABLE",
492
519
  `${this.table.schema}.${this.table.name}`,
@@ -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;