@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
@@ -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
@@ -74,7 +74,6 @@ export function diffIndexes(main, branch, branchIndexableObjects) {
74
74
  "nulls_not_distinct",
75
75
  "immediate",
76
76
  "is_clustered",
77
- "is_replica_identity",
78
77
  "column_collations",
79
78
  "operator_classes",
80
79
  "column_options",
@@ -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: this.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 { rows: indexRows } = await pool.query(sql `
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
- const validatedRows = indexRows
345
- .map((row) => indexRowSchema.parse(row))
346
- .filter((row) => row.definition !== null);
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 { rows: mvRows } = await pool.query(sql `
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
- // Validate and parse each row using the Zod schema
224
- const validatedRows = mvRows.map((row) => materializedViewPropsSchema.parse(row));
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({