@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,134 @@
1
+ import { quoteLiteral } from "../../base.change.js";
2
+ import { stableId } from "../../utils.js";
3
+ import { CreateTableChange, DropTableChange } from "./table.base.js";
4
+ /**
5
+ * SECURITY LABEL FOR <provider> ON TABLE <schema>.<table> IS <literal>
6
+ */
7
+ export class CreateSecurityLabelOnTable extends CreateTableChange {
8
+ table;
9
+ securityLabel;
10
+ scope = "security_label";
11
+ constructor(props) {
12
+ super();
13
+ this.table = props.table;
14
+ this.securityLabel = props.securityLabel;
15
+ }
16
+ get creates() {
17
+ return [
18
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
19
+ ];
20
+ }
21
+ get requires() {
22
+ return [this.table.stableId];
23
+ }
24
+ serialize() {
25
+ return [
26
+ "SECURITY LABEL FOR",
27
+ this.securityLabel.provider,
28
+ "ON TABLE",
29
+ `${this.table.schema}.${this.table.name}`,
30
+ "IS",
31
+ quoteLiteral(this.securityLabel.label),
32
+ ].join(" ");
33
+ }
34
+ }
35
+ export class DropSecurityLabelOnTable extends DropTableChange {
36
+ table;
37
+ securityLabel;
38
+ scope = "security_label";
39
+ constructor(props) {
40
+ super();
41
+ this.table = props.table;
42
+ this.securityLabel = props.securityLabel;
43
+ }
44
+ get drops() {
45
+ return [
46
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
47
+ ];
48
+ }
49
+ get requires() {
50
+ return [
51
+ stableId.securityLabel(this.table.stableId, this.securityLabel.provider),
52
+ this.table.stableId,
53
+ ];
54
+ }
55
+ serialize() {
56
+ return [
57
+ "SECURITY LABEL FOR",
58
+ this.securityLabel.provider,
59
+ "ON TABLE",
60
+ `${this.table.schema}.${this.table.name}`,
61
+ "IS NULL",
62
+ ].join(" ");
63
+ }
64
+ }
65
+ /**
66
+ * SECURITY LABEL FOR <provider> ON COLUMN <schema>.<table>.<column> IS <literal>
67
+ */
68
+ export class CreateSecurityLabelOnColumn extends CreateTableChange {
69
+ table;
70
+ column;
71
+ securityLabel;
72
+ scope = "security_label";
73
+ constructor(props) {
74
+ super();
75
+ this.table = props.table;
76
+ this.column = props.column;
77
+ this.securityLabel = props.securityLabel;
78
+ }
79
+ get creates() {
80
+ const columnStableId = stableId.column(this.table.schema, this.table.name, this.column.name);
81
+ return [
82
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
83
+ ];
84
+ }
85
+ get requires() {
86
+ return [
87
+ stableId.column(this.table.schema, this.table.name, this.column.name),
88
+ ];
89
+ }
90
+ serialize() {
91
+ return [
92
+ "SECURITY LABEL FOR",
93
+ this.securityLabel.provider,
94
+ "ON COLUMN",
95
+ `${this.table.schema}.${this.table.name}.${this.column.name}`,
96
+ "IS",
97
+ quoteLiteral(this.securityLabel.label),
98
+ ].join(" ");
99
+ }
100
+ }
101
+ export class DropSecurityLabelOnColumn extends DropTableChange {
102
+ table;
103
+ column;
104
+ securityLabel;
105
+ scope = "security_label";
106
+ constructor(props) {
107
+ super();
108
+ this.table = props.table;
109
+ this.column = props.column;
110
+ this.securityLabel = props.securityLabel;
111
+ }
112
+ get drops() {
113
+ const columnStableId = stableId.column(this.table.schema, this.table.name, this.column.name);
114
+ return [
115
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
116
+ ];
117
+ }
118
+ get requires() {
119
+ const columnStableId = stableId.column(this.table.schema, this.table.name, this.column.name);
120
+ return [
121
+ stableId.securityLabel(columnStableId, this.securityLabel.provider),
122
+ columnStableId,
123
+ ];
124
+ }
125
+ serialize() {
126
+ return [
127
+ "SECURITY LABEL FOR",
128
+ this.securityLabel.provider,
129
+ "ON COLUMN",
130
+ `${this.table.schema}.${this.table.name}.${this.column.name}`,
131
+ "IS NULL",
132
+ ].join(" ");
133
+ }
134
+ }
@@ -3,5 +3,6 @@ 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
  /** Union of all table-related change variants (`objectType: "table"`). @category Change Types */
7
- export type TableChange = AlterTable | CommentTable | CreateTable | DropTable | TablePrivilege;
8
+ export type TableChange = AlterTable | CommentTable | CreateTable | DropTable | TablePrivilege | SecurityLabelTable;
@@ -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 } from "../utils.js";
4
5
  import { AlterTableAddColumn, AlterTableAddConstraint, AlterTableAlterColumnAddIdentity, AlterTableAlterColumnDropDefault, AlterTableAlterColumnDropIdentity, AlterTableAlterColumnDropNotNull, AlterTableAlterColumnSetDefault, AlterTableAlterColumnSetGenerated, AlterTableAlterColumnSetNotNull, AlterTableAlterColumnType, AlterTableAttachPartition, AlterTableChangeOwner, AlterTableDetachPartition, AlterTableDisableRowLevelSecurity, AlterTableDropColumn, AlterTableDropConstraint, AlterTableEnableRowLevelSecurity, AlterTableForceRowLevelSecurity, AlterTableNoForceRowLevelSecurity, AlterTableResetStorageParams, AlterTableSetLogged, AlterTableSetReplicaIdentity, AlterTableSetStorageParams, AlterTableSetUnlogged, AlterTableValidateConstraint, } from "./changes/table.alter.js";
5
6
  import { CreateCommentOnColumn, CreateCommentOnConstraint, CreateCommentOnTable, DropCommentOnColumn, DropCommentOnConstraint, DropCommentOnTable, } from "./changes/table.comment.js";
6
7
  import { CreateTable } from "./changes/table.create.js";
7
8
  import { DropTable } from "./changes/table.drop.js";
8
9
  import { GrantTablePrivileges, RevokeGrantOptionTablePrivileges, RevokeTablePrivileges, } from "./changes/table.privilege.js";
10
+ import { CreateSecurityLabelOnColumn, CreateSecurityLabelOnTable, DropSecurityLabelOnColumn, DropSecurityLabelOnTable, } from "./changes/table.security-label.js";
9
11
  import { Table } from "./table.model.js";
10
12
  function createAlterConstraintChange(mainTable, branchTable) {
11
13
  const changes = [];
@@ -152,13 +154,11 @@ export function diffTables(ctx, main, branch) {
152
154
  }
153
155
  // REPLICA IDENTITY: If non-default, emit ALTER TABLE ... REPLICA IDENTITY
154
156
  if (branchTable.replica_identity !== "d") {
155
- // Skip 'i' (USING INDEX) — handled by index changes
156
- if (branchTable.replica_identity !== "i") {
157
- changes.push(new AlterTableSetReplicaIdentity({
158
- table: branchTable,
159
- mode: branchTable.replica_identity,
160
- }));
161
- }
157
+ changes.push(new AlterTableSetReplicaIdentity({
158
+ table: branchTable,
159
+ mode: branchTable.replica_identity,
160
+ indexName: branchTable.replica_identity_index,
161
+ }));
162
162
  }
163
163
  changes.push(...createAlterConstraintChange(
164
164
  // Create a dummy table with no constraints do diff constraints against
@@ -176,6 +176,23 @@ export function diffTables(ctx, main, branch) {
176
176
  changes.push(new CreateCommentOnColumn({ table: branchTable, column: col }));
177
177
  }
178
178
  }
179
+ // Table security labels on creation
180
+ for (const label of branchTable.security_labels) {
181
+ changes.push(new CreateSecurityLabelOnTable({
182
+ table: branchTable,
183
+ securityLabel: label,
184
+ }));
185
+ }
186
+ // Column security labels on creation
187
+ for (const col of branchTable.columns) {
188
+ for (const label of col.security_labels ?? []) {
189
+ changes.push(new CreateSecurityLabelOnColumn({
190
+ table: branchTable,
191
+ column: col,
192
+ securityLabel: label,
193
+ }));
194
+ }
195
+ }
179
196
  // PRIVILEGES: For created objects, compare against default privileges state
180
197
  // The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
181
198
  // so objects are created with the default privileges state in effect.
@@ -261,14 +278,20 @@ export function diffTables(ctx, main, branch) {
261
278
  }
262
279
  }
263
280
  // REPLICA IDENTITY
264
- if (mainTable.replica_identity !== branchTable.replica_identity) {
265
- // Skip when target is 'i' (USING INDEX) handled by index changes
266
- if (branchTable.replica_identity !== "i") {
267
- changes.push(new AlterTableSetReplicaIdentity({
268
- table: mainTable,
269
- mode: branchTable.replica_identity,
270
- }));
271
- }
281
+ // Re-emit when the mode changes, or when staying in 'i' mode but pointing
282
+ // at a different index. The index named on the branch must already exist
283
+ // before this ALTER runs; AlterTableSetReplicaIdentity declares that
284
+ // dependency in its `requires`.
285
+ const replicaIdentityChanged = mainTable.replica_identity !== branchTable.replica_identity ||
286
+ (branchTable.replica_identity === "i" &&
287
+ mainTable.replica_identity_index !==
288
+ branchTable.replica_identity_index);
289
+ if (replicaIdentityChanged) {
290
+ changes.push(new AlterTableSetReplicaIdentity({
291
+ table: mainTable,
292
+ mode: branchTable.replica_identity,
293
+ indexName: branchTable.replica_identity_index,
294
+ }));
272
295
  }
273
296
  // OWNER
274
297
  if (mainTable.owner !== branchTable.owner) {
@@ -286,6 +309,14 @@ export function diffTables(ctx, main, branch) {
286
309
  changes.push(new CreateCommentOnTable({ table: branchTable }));
287
310
  }
288
311
  }
312
+ // TABLE SECURITY LABELS
313
+ changes.push(...diffSecurityLabels(mainTable.security_labels, branchTable.security_labels, (securityLabel) => new CreateSecurityLabelOnTable({
314
+ table: branchTable,
315
+ securityLabel,
316
+ }), (securityLabel) => new DropSecurityLabelOnTable({
317
+ table: mainTable,
318
+ securityLabel,
319
+ })));
289
320
  // PARTITION ATTACH/DETACH
290
321
  const mainIsPartition = Boolean(mainTable.parent_schema && mainTable.parent_name);
291
322
  const branchIsPartition = Boolean(branchTable.parent_schema && branchTable.parent_name);
@@ -592,6 +623,28 @@ export function diffTables(ctx, main, branch) {
592
623
  }));
593
624
  }
594
625
  }
626
+ // SECURITY LABELS on column
627
+ changes.push(...diffSecurityLabels(mainCol.security_labels ?? [], branchCol.security_labels ?? [], (securityLabel) => new CreateSecurityLabelOnColumn({
628
+ table: branchTable,
629
+ column: branchCol,
630
+ securityLabel,
631
+ }), (securityLabel) => new DropSecurityLabelOnColumn({
632
+ table: mainTable,
633
+ column: mainCol,
634
+ securityLabel,
635
+ })));
636
+ }
637
+ // Added columns with security labels (for created columns on existing tables)
638
+ for (const [name, col] of branchCols) {
639
+ if (!mainCols.has(name)) {
640
+ for (const label of col.security_labels ?? []) {
641
+ changes.push(new CreateSecurityLabelOnColumn({
642
+ table: branchTable,
643
+ column: col,
644
+ securityLabel: label,
645
+ }));
646
+ }
647
+ }
595
648
  }
596
649
  // PRIVILEGES (unified object and column privileges)
597
650
  // Filter out owner privileges - owner always has ALL privileges implicitly
@@ -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
  export declare const ReplicaIdentitySchema: z.ZodEnum<{
6
8
  n: "n";
7
9
  i: "i";
@@ -85,6 +87,7 @@ declare const tablePropsSchema: z.ZodObject<{
85
87
  d: "d";
86
88
  f: "f";
87
89
  }>;
90
+ replica_identity_index: z.ZodOptional<z.ZodNullable<z.ZodString>>;
88
91
  is_partition: z.ZodBoolean;
89
92
  options: z.ZodNullable<z.ZodArray<z.ZodString>>;
90
93
  partition_bound: z.ZodNullable<z.ZodString>;
@@ -110,6 +113,10 @@ declare const tablePropsSchema: z.ZodObject<{
110
113
  collation: z.ZodNullable<z.ZodString>;
111
114
  default: z.ZodNullable<z.ZodString>;
112
115
  comment: z.ZodNullable<z.ZodString>;
116
+ security_labels: z.ZodOptional<z.ZodArray<z.ZodObject<{
117
+ provider: z.ZodString;
118
+ label: z.ZodString;
119
+ }, z.z.core.$strip>>>;
113
120
  }, z.z.core.$strip>>;
114
121
  constraints: z.ZodOptional<z.ZodArray<z.ZodObject<{
115
122
  name: z.ZodString;
@@ -172,8 +179,16 @@ declare const tablePropsSchema: z.ZodObject<{
172
179
  grantable: z.ZodBoolean;
173
180
  columns: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
174
181
  }, z.z.core.$strip>>;
182
+ security_labels: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
183
+ provider: z.ZodString;
184
+ label: z.ZodString;
185
+ }, z.z.core.$strip>>>>;
175
186
  }, z.z.core.$strip>;
176
187
  type TablePrivilegeProps = PrivilegeProps;
188
+ /**
189
+ * Table input props. `security_labels` is optional on direct construction
190
+ * (defaults to `[]`); extraction always produces it via the Zod default.
191
+ */
177
192
  export type TableProps = z.infer<typeof tablePropsSchema>;
178
193
  export declare class Table extends BasePgModel implements TableLikeObject {
179
194
  readonly schema: TableProps["schema"];
@@ -187,6 +202,7 @@ export declare class Table extends BasePgModel implements TableLikeObject {
187
202
  readonly has_subclasses: TableProps["has_subclasses"];
188
203
  readonly is_populated: TableProps["is_populated"];
189
204
  readonly replica_identity: TableProps["replica_identity"];
205
+ readonly replica_identity_index: TableProps["replica_identity_index"];
190
206
  readonly is_partition: TableProps["is_partition"];
191
207
  readonly options: TableProps["options"];
192
208
  readonly partition_bound: TableProps["partition_bound"];
@@ -198,6 +214,7 @@ export declare class Table extends BasePgModel implements TableLikeObject {
198
214
  readonly columns: TableProps["columns"];
199
215
  readonly constraints: TableConstraintProps[];
200
216
  readonly privileges: TablePrivilegeProps[];
217
+ readonly security_labels: SecurityLabelProps[];
201
218
  constructor(props: TableProps);
202
219
  get stableId(): `table:${string}`;
203
220
  get identityFields(): {
@@ -209,6 +226,7 @@ export declare class Table extends BasePgModel implements TableLikeObject {
209
226
  row_security: boolean;
210
227
  force_row_security: boolean;
211
228
  replica_identity: "n" | "i" | "d" | "f";
229
+ replica_identity_index: string | null | undefined;
212
230
  options: string[] | null;
213
231
  parent_schema: string | null;
214
232
  parent_name: string | null;
@@ -232,6 +250,10 @@ export declare class Table extends BasePgModel implements TableLikeObject {
232
250
  collation: string | null;
233
251
  default: string | null;
234
252
  comment: string | null;
253
+ security_labels?: {
254
+ provider: string;
255
+ label: string;
256
+ }[] | undefined;
235
257
  }[];
236
258
  constraints: {
237
259
  name: string;
@@ -270,6 +292,10 @@ export declare class Table extends BasePgModel implements TableLikeObject {
270
292
  grantable: boolean;
271
293
  columns?: string[] | null | undefined;
272
294
  }[];
295
+ security_labels: {
296
+ provider: string;
297
+ label: string;
298
+ }[];
273
299
  };
274
300
  stableSnapshot(): {
275
301
  identity: {
@@ -293,6 +319,10 @@ export declare class Table extends BasePgModel implements TableLikeObject {
293
319
  collation: string | null;
294
320
  default: string | null;
295
321
  comment: string | null;
322
+ security_labels?: {
323
+ provider: string;
324
+ label: string;
325
+ }[] | undefined;
296
326
  }[];
297
327
  options: string[] | null;
298
328
  constraints: {
@@ -332,10 +362,15 @@ export declare class Table extends BasePgModel implements TableLikeObject {
332
362
  grantable: boolean;
333
363
  columns: string[] | null | undefined;
334
364
  }[];
365
+ security_labels: {
366
+ provider: string;
367
+ label: string;
368
+ }[];
335
369
  persistence: "u" | "t" | "p";
336
370
  row_security: boolean;
337
371
  force_row_security: boolean;
338
372
  replica_identity: "n" | "i" | "d" | "f";
373
+ replica_identity_index: string | null | undefined;
339
374
  parent_schema: string | null;
340
375
  parent_name: string | null;
341
376
  partition_bound: string | null;
@@ -344,5 +379,5 @@ export declare class Table extends BasePgModel implements TableLikeObject {
344
379
  };
345
380
  };
346
381
  }
347
- export declare function extractTables(pool: Pool): Promise<Table[]>;
382
+ export declare function extractTables(pool: Pool, options?: ExtractRetryOptions): Promise<Table[]>;
348
383
  export {};
@@ -3,6 +3,8 @@ import z from "zod";
3
3
  import { BasePgModel, columnPropsSchema, normalizeColumns, } from "../base.model.js";
4
4
  import { normalizePrivileges } from "../base.privilege.js";
5
5
  import { privilegePropsSchema, } from "../base.privilege-diff.js";
6
+ import { extractWithDefinitionRetry, } from "../extract-with-retry.js";
7
+ import { normalizeSecurityLabels, securityLabelPropsSchema, } from "../security-label.types.js";
6
8
  const RelationPersistenceSchema = z.enum([
7
9
  "p", // permanent
8
10
  "u", // unlogged
@@ -65,6 +67,14 @@ const tableConstraintPropsSchema = z.object({
65
67
  definition: z.string(),
66
68
  comment: z.string().nullable().optional(),
67
69
  });
70
+ // pg_get_constraintdef(oid, pretty) can return NULL under the same conditions
71
+ // as pg_get_indexdef: races with concurrent DDL, transient catalog
72
+ // inconsistencies, recovery edges. An unreadable constraint cannot be diffed,
73
+ // so we accept NULL here and filter the constraint out at extraction time
74
+ // rather than crashing the whole catalog parse with a ZodError.
75
+ const tableConstraintRowSchema = tableConstraintPropsSchema.extend({
76
+ definition: z.string().nullable(),
77
+ });
68
78
  const tablePropsSchema = z.object({
69
79
  schema: z.string(),
70
80
  name: z.string(),
@@ -77,6 +87,7 @@ const tablePropsSchema = z.object({
77
87
  has_subclasses: z.boolean(),
78
88
  is_populated: z.boolean(),
79
89
  replica_identity: ReplicaIdentitySchema,
90
+ replica_identity_index: z.string().nullable().optional(),
80
91
  is_partition: z.boolean(),
81
92
  options: z.array(z.string()).nullable(),
82
93
  partition_bound: z.string().nullable(),
@@ -88,6 +99,10 @@ const tablePropsSchema = z.object({
88
99
  columns: z.array(columnPropsSchema),
89
100
  constraints: z.array(tableConstraintPropsSchema).optional(),
90
101
  privileges: z.array(privilegePropsSchema),
102
+ security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
103
+ });
104
+ const tableRowSchema = tablePropsSchema.extend({
105
+ constraints: z.array(tableConstraintRowSchema).optional(),
91
106
  });
92
107
  export class Table extends BasePgModel {
93
108
  schema;
@@ -101,6 +116,7 @@ export class Table extends BasePgModel {
101
116
  has_subclasses;
102
117
  is_populated;
103
118
  replica_identity;
119
+ replica_identity_index;
104
120
  is_partition;
105
121
  options;
106
122
  partition_bound;
@@ -112,6 +128,7 @@ export class Table extends BasePgModel {
112
128
  columns;
113
129
  constraints;
114
130
  privileges;
131
+ security_labels;
115
132
  constructor(props) {
116
133
  super();
117
134
  // Identity fields
@@ -127,6 +144,7 @@ export class Table extends BasePgModel {
127
144
  this.has_subclasses = props.has_subclasses;
128
145
  this.is_populated = props.is_populated;
129
146
  this.replica_identity = props.replica_identity;
147
+ this.replica_identity_index = props.replica_identity_index ?? null;
130
148
  this.is_partition = props.is_partition;
131
149
  this.options = props.options;
132
150
  this.partition_bound = props.partition_bound;
@@ -138,6 +156,7 @@ export class Table extends BasePgModel {
138
156
  this.columns = props.columns;
139
157
  this.constraints = props.constraints ?? [];
140
158
  this.privileges = props.privileges;
159
+ this.security_labels = props.security_labels ?? [];
141
160
  }
142
161
  get stableId() {
143
162
  return `table:${this.schema}.${this.name}`;
@@ -155,6 +174,7 @@ export class Table extends BasePgModel {
155
174
  row_security: this.row_security,
156
175
  force_row_security: this.force_row_security,
157
176
  replica_identity: this.replica_identity,
177
+ replica_identity_index: this.replica_identity_index,
158
178
  options: this.options,
159
179
  // Partition membership can be altered via ATTACH/DETACH
160
180
  parent_schema: this.parent_schema,
@@ -165,6 +185,7 @@ export class Table extends BasePgModel {
165
185
  columns: this.columns,
166
186
  constraints: this.constraints,
167
187
  privileges: this.privileges,
188
+ security_labels: this.security_labels,
168
189
  };
169
190
  }
170
191
  stableSnapshot() {
@@ -181,12 +202,18 @@ export class Table extends BasePgModel {
181
202
  options: this.options ? [...this.options].sort() : this.options,
182
203
  constraints: normalizeConstraints(),
183
204
  privileges: normalizePrivileges(this.privileges),
205
+ security_labels: normalizeSecurityLabels(this.security_labels),
184
206
  },
185
207
  };
186
208
  }
187
209
  }
188
- export async function extractTables(pool) {
189
- const { rows: tableRows } = await pool.query(sql `
210
+ export async function extractTables(pool, options) {
211
+ const tableRows = await extractWithDefinitionRetry({
212
+ label: "table constraints",
213
+ options,
214
+ hasNullDefinition: (row) => row.constraints?.some((c) => c.definition === null) ?? false,
215
+ query: async () => {
216
+ const result = await pool.query(sql `
190
217
  with extension_oids as (
191
218
  select objid
192
219
  from pg_depend d
@@ -205,6 +232,14 @@ with extension_oids as (
205
232
  c.relhassubclass as has_subclasses,
206
233
  c.relispopulated as is_populated,
207
234
  c.relreplident as replica_identity,
235
+ (
236
+ select quote_ident(ri_class.relname)
237
+ from pg_index ri
238
+ join pg_class ri_class on ri_class.oid = ri.indexrelid
239
+ where ri.indrelid = c.oid
240
+ and ri.indisreplident is true
241
+ limit 1
242
+ ) as replica_identity_index,
208
243
  c.relispartition as is_partition,
209
244
  c.reloptions as options,
210
245
  pg_get_expr(c.relpartbound, c.oid) as partition_bound,
@@ -235,6 +270,7 @@ select
235
270
  t.has_subclasses,
236
271
  t.is_populated,
237
272
  t.replica_identity,
273
+ t.replica_identity_index,
238
274
  t.is_partition,
239
275
  t.options,
240
276
  t.partition_bound,
@@ -375,7 +411,20 @@ select
375
411
  and a.attcollation <> t2.typcollation
376
412
  ),
377
413
  'default', pg_get_expr(ad.adbin, ad.adrelid),
378
- 'comment', col_description(a.attrelid, a.attnum)
414
+ 'comment', col_description(a.attrelid, a.attnum),
415
+ 'security_labels', coalesce(
416
+ (
417
+ select json_agg(
418
+ json_build_object('provider', sl.provider, 'label', sl.label)
419
+ order by sl.provider
420
+ )
421
+ from pg_catalog.pg_seclabel sl
422
+ where sl.objoid = t.oid
423
+ and sl.classoid = 'pg_class'::regclass
424
+ and sl.objsubid = a.attnum
425
+ ),
426
+ '[]'::json
427
+ )
379
428
  )
380
429
  end
381
430
  order by a.attnum
@@ -415,18 +464,36 @@ select
415
464
  join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
416
465
  group by x.grantee, x.privilege_type
417
466
  ) as grp
418
- ), '[]') as privileges
467
+ ), '[]') as privileges,
468
+ coalesce(
469
+ (
470
+ select json_agg(
471
+ json_build_object('provider', sl.provider, 'label', sl.label)
472
+ order by sl.provider
473
+ )
474
+ from pg_catalog.pg_seclabel sl
475
+ where sl.objoid = t.oid
476
+ and sl.classoid = 'pg_class'::regclass
477
+ and sl.objsubid = 0
478
+ ),
479
+ '[]'::json
480
+ ) as security_labels
419
481
  from
420
482
  tables t
421
483
  left join pg_attribute a on a.attrelid = t.oid and a.attnum > 0 and not a.attisdropped
422
484
  left join pg_attrdef ad on a.attrelid = ad.adrelid and a.attnum = ad.adnum
423
485
  left join pg_type ty on ty.oid = a.atttypid
424
486
  group by
425
- t.oid, t.schema, t.name, t.persistence, t.row_security, t.force_row_security, t.has_indexes, t.has_rules, t.has_triggers, t.has_subclasses, t.is_populated, t.replica_identity, t.is_partition, t.options, t.partition_bound, t.partition_by, t.owner, t.parent_schema, t.parent_name
487
+ t.oid, t.schema, t.name, t.persistence, t.row_security, t.force_row_security, t.has_indexes, t.has_rules, t.has_triggers, t.has_subclasses, t.is_populated, t.replica_identity, t.replica_identity_index, t.is_partition, t.options, t.partition_bound, t.partition_by, t.owner, t.parent_schema, t.parent_name
426
488
  order by
427
489
  t.schema, t.name
428
490
  `);
429
- // Validate and parse each row using the Zod schema
430
- const validatedRows = tableRows.map((row) => tablePropsSchema.parse(row));
491
+ return result.rows.map((row) => tableRowSchema.parse(row));
492
+ },
493
+ });
494
+ const validatedRows = tableRows.map((row) => {
495
+ const filteredConstraints = row.constraints?.filter((c) => c.definition !== null);
496
+ return { ...row, constraints: filteredConstraints };
497
+ });
431
498
  return validatedRows.map((row) => new Table(row));
432
499
  }
@@ -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 triggerPropsSchema: z.ZodObject<{
5
6
  schema: z.ZodString;
6
7
  name: z.ZodString;
@@ -97,5 +98,5 @@ export declare class Trigger extends BasePgModel {
97
98
  comment: string | null;
98
99
  };
99
100
  }
100
- export declare function extractTriggers(pool: Pool): Promise<Trigger[]>;
101
+ export declare function extractTriggers(pool: Pool, options?: ExtractRetryOptions): Promise<Trigger[]>;
101
102
  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 TriggerEnabledSchema = z.enum([
5
6
  "O", // ORIGIN - trigger fires in "origin" and "local" replica modes
6
7
  "D", // DISABLED - trigger is disabled
@@ -41,6 +42,14 @@ const triggerPropsSchema = z.object({
41
42
  definition: z.string(),
42
43
  comment: z.string().nullable(),
43
44
  });
45
+ // pg_get_triggerdef(oid, pretty) can return NULL when the trigger (its
46
+ // pg_trigger row) is dropped between catalog scan and resolution, or under
47
+ // transient catalog state. An unreadable trigger cannot be diffed, so we
48
+ // accept NULL here and filter the row out at extraction time rather than
49
+ // crashing the whole catalog parse with a ZodError.
50
+ const triggerRowSchema = triggerPropsSchema.extend({
51
+ definition: z.string().nullable(),
52
+ });
44
53
  export class Trigger extends BasePgModel {
45
54
  schema;
46
55
  name;
@@ -139,8 +148,13 @@ export class Trigger extends BasePgModel {
139
148
  };
140
149
  }
141
150
  }
142
- export async function extractTriggers(pool) {
143
- const { rows: triggerRows } = await pool.query(sql `
151
+ export async function extractTriggers(pool, options) {
152
+ const triggerRows = await extractWithDefinitionRetry({
153
+ label: "triggers",
154
+ options,
155
+ hasNullDefinition: (row) => row.definition === null,
156
+ query: async () => {
157
+ const result = await pool.query(sql `
144
158
  with extension_trigger_oids as (
145
159
  select objid
146
160
  from pg_depend d
@@ -245,7 +259,9 @@ export async function extractTriggers(pool) {
245
259
 
246
260
  order by 1, 2
247
261
  `);
248
- // Validate and parse each row using the Zod schema
249
- const validatedRows = triggerRows.map((row) => triggerPropsSchema.parse(row));
262
+ return result.rows.map((row) => triggerRowSchema.parse(row));
263
+ },
264
+ });
265
+ const validatedRows = triggerRows.filter((row) => row.definition !== null);
250
266
  return validatedRows.map((row) => new Trigger(row));
251
267
  }
@@ -2,7 +2,7 @@ import { BaseChange } from "../../../base.change.ts";
2
2
  import type { CompositeType } from "../composite-type.model.ts";
3
3
  declare abstract class BaseCompositeTypeChange extends BaseChange {
4
4
  abstract readonly compositeType: CompositeType;
5
- abstract readonly scope: "object" | "comment" | "privilege";
5
+ abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
6
6
  readonly objectType: "composite_type";
7
7
  }
8
8
  export declare abstract class CreateCompositeTypeChange extends BaseCompositeTypeChange {