@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
@@ -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 { hasNonAlterableChanges } from "../../utils.js";
4
5
  import { AlterRangeChangeOwner } from "./changes/range.alter.js";
5
6
  import { CreateCommentOnRange, DropCommentOnRange, } from "./changes/range.comment.js";
6
7
  import { CreateRange } from "./changes/range.create.js";
7
8
  import { DropRange } from "./changes/range.drop.js";
8
9
  import { GrantRangePrivileges, RevokeGrantOptionRangePrivileges, RevokeRangePrivileges, } from "./changes/range.privilege.js";
10
+ import { CreateSecurityLabelOnRange, DropSecurityLabelOnRange, } from "./changes/range.security-label.js";
9
11
  /**
10
12
  * Diff two sets of range types from main and branch catalogs.
11
13
  *
@@ -31,6 +33,12 @@ export function diffRanges(ctx, main, branch) {
31
33
  if (createdRange.comment !== null) {
32
34
  changes.push(new CreateCommentOnRange({ range: createdRange }));
33
35
  }
36
+ for (const label of createdRange.security_labels) {
37
+ changes.push(new CreateSecurityLabelOnRange({
38
+ range: createdRange,
39
+ securityLabel: label,
40
+ }));
41
+ }
34
42
  // PRIVILEGES: For created objects, compare against default privileges state
35
43
  // The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
36
44
  // so objects are created with the default privileges state in effect.
@@ -91,6 +99,14 @@ export function diffRanges(ctx, main, branch) {
91
99
  changes.push(new CreateCommentOnRange({ range: branchRange }));
92
100
  }
93
101
  }
102
+ // SECURITY LABELS
103
+ changes.push(...diffSecurityLabels(mainRange.security_labels, branchRange.security_labels, (securityLabel) => new CreateSecurityLabelOnRange({
104
+ range: branchRange,
105
+ securityLabel,
106
+ }), (securityLabel) => new DropSecurityLabelOnRange({
107
+ range: mainRange,
108
+ securityLabel,
109
+ })));
94
110
  // PRIVILEGES
95
111
  // Filter out PUBLIC's built-in default USAGE privilege from main catalog
96
112
  // (PostgreSQL grants it automatically, so we shouldn't compare it)
@@ -2,6 +2,7 @@ import type { Pool } from "pg";
2
2
  import z from "zod";
3
3
  import { BasePgModel } from "../../base.model.ts";
4
4
  import { type PrivilegeProps } from "../../base.privilege-diff.ts";
5
+ import { type SecurityLabelProps } from "../../security-label.types.ts";
5
6
  declare const rangePropsSchema: z.ZodObject<{
6
7
  schema: z.ZodString;
7
8
  name: z.ZodString;
@@ -22,6 +23,10 @@ declare const rangePropsSchema: z.ZodObject<{
22
23
  grantable: z.ZodBoolean;
23
24
  columns: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
24
25
  }, z.z.core.$strip>>;
26
+ security_labels: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
27
+ provider: z.ZodString;
28
+ label: z.ZodString;
29
+ }, z.z.core.$strip>>>>;
25
30
  }, z.z.core.$strip>;
26
31
  type RangePrivilegeProps = PrivilegeProps;
27
32
  export type RangeProps = z.infer<typeof rangePropsSchema>;
@@ -40,6 +45,7 @@ export declare class Range extends BasePgModel {
40
45
  readonly subtype_opclass_schema: RangeProps["subtype_opclass_schema"];
41
46
  readonly subtype_opclass_name: RangeProps["subtype_opclass_name"];
42
47
  readonly privileges: RangePrivilegeProps[];
48
+ readonly security_labels: SecurityLabelProps[];
43
49
  constructor(props: RangeProps);
44
50
  get stableId(): `type:${string}`;
45
51
  get identityFields(): {
@@ -64,6 +70,10 @@ export declare class Range extends BasePgModel {
64
70
  grantable: boolean;
65
71
  columns?: string[] | null | undefined;
66
72
  }[];
73
+ security_labels: {
74
+ provider: string;
75
+ label: string;
76
+ }[];
67
77
  };
68
78
  }
69
79
  /**
@@ -2,6 +2,7 @@ import { sql } from "@ts-safeql/sql-tag";
2
2
  import z from "zod";
3
3
  import { BasePgModel } from "../../base.model.js";
4
4
  import { privilegePropsSchema, } from "../../base.privilege-diff.js";
5
+ import { securityLabelPropsSchema, } from "../../security-label.types.js";
5
6
  const rangePropsSchema = z.object({
6
7
  schema: z.string(),
7
8
  name: z.string(),
@@ -21,6 +22,7 @@ const rangePropsSchema = z.object({
21
22
  subtype_opclass_schema: z.string().nullable(),
22
23
  subtype_opclass_name: z.string().nullable(),
23
24
  privileges: z.array(privilegePropsSchema),
25
+ security_labels: z.array(securityLabelPropsSchema).default([]).optional(),
24
26
  });
25
27
  export class Range extends BasePgModel {
26
28
  schema;
@@ -37,6 +39,7 @@ export class Range extends BasePgModel {
37
39
  subtype_opclass_schema;
38
40
  subtype_opclass_name;
39
41
  privileges;
42
+ security_labels;
40
43
  constructor(props) {
41
44
  super();
42
45
  // Identity fields
@@ -55,6 +58,7 @@ export class Range extends BasePgModel {
55
58
  this.subtype_opclass_schema = props.subtype_opclass_schema;
56
59
  this.subtype_opclass_name = props.subtype_opclass_name;
57
60
  this.privileges = props.privileges;
61
+ this.security_labels = props.security_labels ?? [];
58
62
  }
59
63
  get stableId() {
60
64
  return `type:${this.schema}.${this.name}`;
@@ -79,6 +83,7 @@ export class Range extends BasePgModel {
79
83
  subtype_opclass_name: this.subtype_opclass_name,
80
84
  comment: this.comment,
81
85
  privileges: this.privileges,
86
+ security_labels: this.security_labels,
82
87
  };
83
88
  }
84
89
  }
@@ -142,7 +147,20 @@ select
142
147
  )
143
148
  from lateral aclexplode(COALESCE(t.typacl, acldefault('T', t.typowner))) as x(grantor, grantee, privilege_type, is_grantable)
144
149
  ), '[]'
145
- ) as privileges
150
+ ) as privileges,
151
+ coalesce(
152
+ (
153
+ select json_agg(
154
+ json_build_object('provider', sl.provider, 'label', sl.label)
155
+ order by sl.provider
156
+ )
157
+ from pg_catalog.pg_seclabel sl
158
+ where sl.objoid = t.oid
159
+ and sl.classoid = 'pg_type'::regclass
160
+ and sl.objsubid = 0
161
+ ),
162
+ '[]'::json
163
+ ) as security_labels
146
164
  from pg_catalog.pg_range r
147
165
  join pg_catalog.pg_type t on t.oid = r.rngtypid
148
166
  join pg_catalog.pg_type subt on subt.oid = r.rngsubtype
@@ -20,7 +20,9 @@ export declare const stableId: {
20
20
  defacl(grantor: string, objtype: string, schema: string | null, grantee: string): `defacl:${string}:${string}:${string}:grantee:${string}`;
21
21
  column(schema: string, table: string, column: string): `column:${string}.${string}.${string}`;
22
22
  constraint(schema: string, table: string, constraint: string): `constraint:${string}.${string}.${string}`;
23
+ index(schema: string, table: string, indexName: string): `index:${string}.${string}.${string}`;
23
24
  comment(objectStableId: string): `comment:${string}`;
25
+ securityLabel(objectStableId: string, provider: string): `securityLabel:${string}::provider:${string}`;
24
26
  role(role: string): `role:${string}`;
25
27
  type(schema: string, name: string): `type:${string}.${string}`;
26
28
  collation(schema: string, name: string): `collation:${string}.${string}`;
@@ -49,9 +49,15 @@ export const stableId = {
49
49
  constraint(schema, table, constraint) {
50
50
  return `constraint:${schema}.${table}.${constraint}`;
51
51
  },
52
+ index(schema, table, indexName) {
53
+ return `index:${schema}.${table}.${indexName}`;
54
+ },
52
55
  comment(objectStableId) {
53
56
  return `comment:${objectStableId}`;
54
57
  },
58
+ securityLabel(objectStableId, provider) {
59
+ return `securityLabel:${objectStableId}::provider:${provider}`;
60
+ },
55
61
  role(role) {
56
62
  return `role:${role}`;
57
63
  },
@@ -2,7 +2,7 @@ import { BaseChange } from "../../base.change.ts";
2
2
  import type { View } from "../view.model.ts";
3
3
  declare abstract class BaseViewChange extends BaseChange {
4
4
  abstract readonly view: View;
5
- abstract readonly scope: "object" | "comment" | "privilege";
5
+ abstract readonly scope: "object" | "comment" | "privilege" | "security_label";
6
6
  readonly objectType: "view";
7
7
  }
8
8
  export declare abstract class CreateViewChange extends BaseViewChange {
@@ -0,0 +1,28 @@
1
+ import type { SecurityLabelProps } from "../../security-label.types.ts";
2
+ import type { View } from "../view.model.ts";
3
+ import { CreateViewChange, DropViewChange } from "./view.base.ts";
4
+ export type SecurityLabelView = CreateSecurityLabelOnView | DropSecurityLabelOnView;
5
+ export declare class CreateSecurityLabelOnView extends CreateViewChange {
6
+ readonly view: View;
7
+ readonly securityLabel: SecurityLabelProps;
8
+ readonly scope: "security_label";
9
+ constructor(props: {
10
+ view: View;
11
+ securityLabel: SecurityLabelProps;
12
+ });
13
+ get creates(): `securityLabel:${string}::provider:${string}`[];
14
+ get requires(): `view:${string}`[];
15
+ serialize(): string;
16
+ }
17
+ export declare class DropSecurityLabelOnView extends DropViewChange {
18
+ readonly view: View;
19
+ readonly securityLabel: SecurityLabelProps;
20
+ readonly scope: "security_label";
21
+ constructor(props: {
22
+ view: View;
23
+ securityLabel: SecurityLabelProps;
24
+ });
25
+ get drops(): `securityLabel:${string}::provider:${string}`[];
26
+ get requires(): (`securityLabel:${string}::provider:${string}` | `view:${string}`)[];
27
+ serialize(): string;
28
+ }
@@ -0,0 +1,61 @@
1
+ import { quoteLiteral } from "../../base.change.js";
2
+ import { stableId } from "../../utils.js";
3
+ import { CreateViewChange, DropViewChange } from "./view.base.js";
4
+ export class CreateSecurityLabelOnView extends CreateViewChange {
5
+ view;
6
+ securityLabel;
7
+ scope = "security_label";
8
+ constructor(props) {
9
+ super();
10
+ this.view = props.view;
11
+ this.securityLabel = props.securityLabel;
12
+ }
13
+ get creates() {
14
+ return [
15
+ stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
16
+ ];
17
+ }
18
+ get requires() {
19
+ return [this.view.stableId];
20
+ }
21
+ serialize() {
22
+ return [
23
+ "SECURITY LABEL FOR",
24
+ this.securityLabel.provider,
25
+ "ON VIEW",
26
+ `${this.view.schema}.${this.view.name}`,
27
+ "IS",
28
+ quoteLiteral(this.securityLabel.label),
29
+ ].join(" ");
30
+ }
31
+ }
32
+ export class DropSecurityLabelOnView extends DropViewChange {
33
+ view;
34
+ securityLabel;
35
+ scope = "security_label";
36
+ constructor(props) {
37
+ super();
38
+ this.view = props.view;
39
+ this.securityLabel = props.securityLabel;
40
+ }
41
+ get drops() {
42
+ return [
43
+ stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
44
+ ];
45
+ }
46
+ get requires() {
47
+ return [
48
+ stableId.securityLabel(this.view.stableId, this.securityLabel.provider),
49
+ this.view.stableId,
50
+ ];
51
+ }
52
+ serialize() {
53
+ return [
54
+ "SECURITY LABEL FOR",
55
+ this.securityLabel.provider,
56
+ "ON VIEW",
57
+ `${this.view.schema}.${this.view.name}`,
58
+ "IS NULL",
59
+ ].join(" ");
60
+ }
61
+ }
@@ -3,5 +3,6 @@ import type { CommentView } from "./view.comment.ts";
3
3
  import type { CreateView } from "./view.create.ts";
4
4
  import type { DropView } from "./view.drop.ts";
5
5
  import type { ViewPrivilege } from "./view.privilege.ts";
6
+ import type { SecurityLabelView } from "./view.security-label.ts";
6
7
  /** Union of all view-related change variants (`objectType: "view"`). @category Change Types */
7
- export type ViewChange = AlterView | CommentView | CreateView | DropView | ViewPrivilege;
8
+ export type ViewChange = AlterView | CommentView | CreateView | DropView | ViewPrivilege | SecurityLabelView;
@@ -1,12 +1,14 @@
1
1
  import { diffObjects } from "../base.diff.js";
2
2
  import { normalizeColumns } from "../base.model.js";
3
3
  import { diffPrivileges, emitColumnPrivilegeChanges, } from "../base.privilege-diff.js";
4
+ import { diffSecurityLabels } from "../security-label.types.js";
4
5
  import { deepEqual, hasNonAlterableChanges } from "../utils.js";
5
6
  import { AlterViewChangeOwner, AlterViewResetOptions, AlterViewSetOptions, } from "./changes/view.alter.js";
6
7
  import { CreateCommentOnView, DropCommentOnView, } from "./changes/view.comment.js";
7
8
  import { CreateView } from "./changes/view.create.js";
8
9
  import { DropView } from "./changes/view.drop.js";
9
10
  import { GrantViewPrivileges, RevokeGrantOptionViewPrivileges, RevokeViewPrivileges, } from "./changes/view.privilege.js";
11
+ import { CreateSecurityLabelOnView, DropSecurityLabelOnView, } from "./changes/view.security-label.js";
10
12
  /**
11
13
  * Diff two sets of views from main and branch catalogs.
12
14
  *
@@ -28,6 +30,9 @@ export function diffViews(ctx, main, branch) {
28
30
  if (view.comment !== null) {
29
31
  changes.push(new CreateCommentOnView({ view }));
30
32
  }
33
+ for (const label of view.security_labels) {
34
+ changes.push(new CreateSecurityLabelOnView({ view, securityLabel: label }));
35
+ }
31
36
  // PRIVILEGES: For created objects, compare against default privileges state
32
37
  // The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
33
38
  // so objects are created with the default privileges state in effect.
@@ -121,6 +126,14 @@ export function diffViews(ctx, main, branch) {
121
126
  changes.push(new CreateCommentOnView({ view: branchView }));
122
127
  }
123
128
  }
129
+ // SECURITY LABELS
130
+ changes.push(...diffSecurityLabels(mainView.security_labels, branchView.security_labels, (securityLabel) => new CreateSecurityLabelOnView({
131
+ view: branchView,
132
+ securityLabel,
133
+ }), (securityLabel) => new DropSecurityLabelOnView({
134
+ view: mainView,
135
+ securityLabel,
136
+ })));
124
137
  // Note: View renaming would also use ALTER VIEW ... RENAME TO ...
125
138
  // But since our View model uses 'name' as the identity field,
126
139
  // a name change would be handled as drop + create by diffObjects()
@@ -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 viewPropsSchema: z.ZodObject<{
6
8
  schema: z.ZodString;
7
9
  name: z.ZodString;
@@ -41,6 +43,10 @@ declare const viewPropsSchema: 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 viewPropsSchema: 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 ViewPrivilegeProps = PrivilegeProps;
53
63
  export type ViewProps = z.infer<typeof viewPropsSchema>;
@@ -70,6 +80,7 @@ export declare class View extends BasePgModel implements TableLikeObject {
70
80
  readonly comment: ViewProps["comment"];
71
81
  readonly columns: ViewProps["columns"];
72
82
  readonly privileges: ViewPrivilegeProps[];
83
+ readonly security_labels: SecurityLabelProps[];
73
84
  constructor(props: ViewProps);
74
85
  get stableId(): `view:${string}`;
75
86
  get identityFields(): {
@@ -108,6 +119,10 @@ export declare class View extends BasePgModel implements TableLikeObject {
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 View extends BasePgModel implements TableLikeObject {
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: {
@@ -138,6 +157,14 @@ export declare class View extends BasePgModel implements TableLikeObject {
138
157
  collation: string | null;
139
158
  default: string | null;
140
159
  comment: string | null;
160
+ security_labels?: {
161
+ provider: string;
162
+ label: string;
163
+ }[] | undefined;
164
+ }[];
165
+ security_labels: {
166
+ provider: string;
167
+ label: string;
141
168
  }[];
142
169
  definition: string;
143
170
  row_security: boolean;
@@ -162,5 +189,5 @@ export declare class View extends BasePgModel implements TableLikeObject {
162
189
  };
163
190
  };
164
191
  }
165
- export declare function extractViews(pool: Pool): Promise<View[]>;
192
+ export declare function extractViews(pool: Pool, options?: ExtractRetryOptions): Promise<View[]>;
166
193
  export {};
@@ -2,6 +2,8 @@ import { sql } from "@ts-safeql/sql-tag";
2
2
  import z from "zod";
3
3
  import { BasePgModel, columnPropsSchema, normalizeColumns, } 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 viewPropsSchema = z.object({
7
9
  schema: z.string(),
@@ -22,6 +24,15 @@ const viewPropsSchema = 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 view (or its
30
+ // pg_rewrite row) is dropped between catalog scan and resolution, or under
31
+ // transient catalog state during recovery. An unreadable view 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 viewRowSchema = viewPropsSchema.extend({
35
+ definition: z.string().nullable(),
25
36
  });
26
37
  export class View extends BasePgModel {
27
38
  schema;
@@ -42,6 +53,7 @@ export class View 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 View 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 `view:${this.schema}.${this.name}`;
@@ -92,6 +105,7 @@ export class View 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() {
@@ -100,12 +114,18 @@ export class View extends BasePgModel {
100
114
  data: {
101
115
  ...this.dataFields,
102
116
  columns: normalizeColumns(this.columns),
117
+ security_labels: normalizeSecurityLabels(this.security_labels),
103
118
  },
104
119
  };
105
120
  }
106
121
  }
107
- export async function extractViews(pool) {
108
- const { rows: viewRows } = await pool.query(sql `
122
+ export async function extractViews(pool, options) {
123
+ const viewRows = await extractWithDefinitionRetry({
124
+ label: "views",
125
+ options,
126
+ hasNullDefinition: (row) => row.definition === null,
127
+ query: async () => {
128
+ const result = await pool.query(sql `
109
129
  with extension_oids as (
110
130
  select
111
131
  objid
@@ -221,7 +241,20 @@ select
221
241
  join lateral aclexplode(src.acl) as x(grantor, grantee, privilege_type, is_grantable) on true
222
242
  group by x.grantee, x.privilege_type
223
243
  ) as grp
224
- ), '[]') as privileges
244
+ ), '[]') as privileges,
245
+ coalesce(
246
+ (
247
+ select json_agg(
248
+ json_build_object('provider', sl.provider, 'label', sl.label)
249
+ order by sl.provider
250
+ )
251
+ from pg_catalog.pg_seclabel sl
252
+ where sl.objoid = v.oid
253
+ and sl.classoid = 'pg_class'::regclass
254
+ and sl.objsubid = 0
255
+ ),
256
+ '[]'::json
257
+ ) as security_labels
225
258
  from
226
259
  views v
227
260
  left join pg_attribute a on a.attrelid = v.oid and a.attnum > 0 and not a.attisdropped
@@ -232,7 +265,9 @@ group by
232
265
  order by
233
266
  v.schema, v.name
234
267
  `);
235
- // Validate and parse each row using the Zod schema
236
- const validatedRows = viewRows.map((row) => viewPropsSchema.parse(row));
268
+ return result.rows.map((row) => viewRowSchema.parse(row));
269
+ },
270
+ });
271
+ const validatedRows = viewRows.filter((row) => row.definition !== null);
237
272
  return validatedRows.map((row) => new View(row));
238
273
  }
@@ -62,7 +62,9 @@ export async function createPlan(source, target, options = {}) {
62
62
  }
63
63
  const resolved = await resolvePool(input, label);
64
64
  pools.push(resolved);
65
- return extractCatalog(resolved.pool);
65
+ return extractCatalog(resolved.pool, {
66
+ extractRetries: options.extractRetries,
67
+ });
66
68
  };
67
69
  const pools = [];
68
70
  try {
@@ -806,6 +806,7 @@ const schema = new Schema({
806
806
  owner: "admin",
807
807
  comment: "application schema",
808
808
  privileges: [],
809
+ security_labels: [],
809
810
  });
810
811
  const extension = new Extension({
811
812
  name: "pgcrypto",
@@ -141,5 +141,13 @@ export interface CreatePlanOptions {
141
141
  * the output must be self-contained and not rely on statement execution order.
142
142
  */
143
143
  skipDefaultPrivilegeSubtraction?: boolean;
144
+ /**
145
+ * Number of retry attempts for catalog extractors when `pg_get_*def()`
146
+ * returns NULL for at least one row (a transient race with concurrent DDL).
147
+ * Total attempts is `extractRetries + 1`. When undefined, the value is read
148
+ * from the `PGDELTA_EXTRACT_RETRIES` environment variable, falling back to
149
+ * a default of 1 (i.e. the first attempt plus one retry, 2 attempts total).
150
+ */
151
+ extractRetries?: number;
144
152
  }
145
153
  export {};
@@ -1,4 +1,5 @@
1
1
  import type { Change } from "./change.types.ts";
2
+ import type { Table } from "./objects/table/table.model.ts";
2
3
  /**
3
4
  * Apply structural rewrites to the change list that are only obvious once
4
5
  * every object diff has been collected. This pass does NOT prevent dependency
@@ -19,11 +20,17 @@ import type { Change } from "./change.types.ts";
19
20
  * produced when `diffTables()` and `expandReplaceDependencies()` both
20
21
  * emit the same constraint operation for a replaced table. Last write
21
22
  * wins so the expansion's emission survives.
23
+ * - Re-emits `ALTER TABLE ... REPLICA IDENTITY USING INDEX <idx>` after any
24
+ * `DropIndex(idx) + CreateIndex(idx)` pair where `idx` is the replica
25
+ * identity index of a branch table — Postgres silently clears the marker
26
+ * when the underlying index is dropped, and `CREATE INDEX` cannot restore
27
+ * it.
22
28
  *
23
29
  * Object-local PostgreSQL semantics (for example owned-sequence cascades)
24
30
  * stay in the corresponding `diff*` function instead of this pass.
25
31
  */
26
- export declare function normalizePostDiffCycles({ changes, replacedTableIds, }: {
32
+ export declare function normalizePostDiffChanges({ changes, replacedTableIds, branchTables, }: {
27
33
  changes: Change[];
28
34
  replacedTableIds?: ReadonlySet<string>;
35
+ branchTables?: Record<string, Table>;
29
36
  }): Change[];