@supabase/pg-delta 1.0.0-alpha.4 → 1.0.0-alpha.6

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 (359) hide show
  1. package/README.md +40 -23
  2. package/dist/cli/app.js +26 -3
  3. package/dist/cli/bin/cli.js +5 -0
  4. package/dist/cli/commands/catalog-export.d.ts +5 -0
  5. package/dist/cli/commands/catalog-export.js +64 -0
  6. package/dist/cli/commands/declarative-apply.d.ts +6 -0
  7. package/dist/cli/commands/declarative-apply.js +288 -0
  8. package/dist/cli/commands/declarative-export.d.ts +5 -0
  9. package/dist/cli/commands/declarative-export.js +245 -0
  10. package/dist/cli/commands/plan.js +19 -6
  11. package/dist/cli/exit-code.d.ts +2 -0
  12. package/dist/cli/exit-code.js +7 -0
  13. package/dist/cli/formatters/tree/tree.js +3 -2
  14. package/dist/cli/utils/apply-display.d.ts +52 -0
  15. package/dist/cli/utils/apply-display.js +183 -0
  16. package/dist/cli/utils/export-display.d.ts +43 -0
  17. package/dist/cli/utils/export-display.js +202 -0
  18. package/dist/cli/utils/resolve-input.d.ts +7 -0
  19. package/dist/cli/utils/resolve-input.js +13 -0
  20. package/dist/core/catalog-export/index.d.ts +11 -0
  21. package/dist/core/catalog-export/index.js +10 -0
  22. package/dist/core/catalog.diff.d.ts +1 -0
  23. package/dist/core/catalog.diff.js +64 -48
  24. package/dist/core/catalog.model.d.ts +14 -1
  25. package/dist/core/catalog.model.js +103 -1
  26. package/dist/core/catalog.snapshot.d.ts +66 -0
  27. package/dist/core/catalog.snapshot.js +206 -0
  28. package/dist/core/declarative-apply/discover-sql.d.ts +18 -0
  29. package/dist/core/declarative-apply/discover-sql.js +86 -0
  30. package/dist/core/declarative-apply/extract-catalog-providers.d.ts +23 -0
  31. package/dist/core/declarative-apply/extract-catalog-providers.js +159 -0
  32. package/dist/core/declarative-apply/index.d.ts +49 -0
  33. package/dist/core/declarative-apply/index.js +134 -0
  34. package/dist/core/declarative-apply/round-apply.d.ts +100 -0
  35. package/dist/core/declarative-apply/round-apply.js +378 -0
  36. package/dist/core/export/file-mapper.d.ts +71 -0
  37. package/dist/core/export/file-mapper.js +474 -0
  38. package/dist/core/export/grouper.d.ts +13 -0
  39. package/dist/core/export/grouper.js +76 -0
  40. package/dist/core/export/index.d.ts +45 -0
  41. package/dist/core/export/index.js +63 -0
  42. package/dist/core/export/types.d.ts +84 -0
  43. package/dist/core/export/types.js +25 -0
  44. package/dist/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  45. package/dist/core/integrations/filter/dsl.d.ts +38 -1
  46. package/dist/core/integrations/filter/dsl.js +20 -2
  47. package/dist/core/integrations/filter/extractors.js +42 -0
  48. package/dist/core/integrations/integration-dsl.d.ts +10 -0
  49. package/dist/core/integrations/supabase.d.ts +8 -0
  50. package/dist/core/integrations/supabase.js +9 -0
  51. package/dist/core/objects/aggregate/aggregate.diff.d.ts +2 -8
  52. package/dist/core/objects/aggregate/aggregate.diff.js +16 -70
  53. package/dist/core/objects/aggregate/aggregate.model.d.ts +8 -8
  54. package/dist/core/objects/aggregate/aggregate.model.js +1 -1
  55. package/dist/core/objects/aggregate/changes/aggregate.create.js +1 -1
  56. package/dist/core/objects/aggregate/changes/aggregate.drop.js +1 -1
  57. package/dist/core/objects/base.privilege-diff.d.ts +38 -13
  58. package/dist/core/objects/base.privilege-diff.js +104 -22
  59. package/dist/core/objects/base.privilege.d.ts +1 -0
  60. package/dist/core/objects/base.privilege.js +9 -2
  61. package/dist/core/objects/collation/collation.diff.d.ts +2 -3
  62. package/dist/core/objects/diff-context.d.ts +15 -0
  63. package/dist/core/objects/diff-context.js +1 -0
  64. package/dist/core/objects/domain/changes/domain.create.js +4 -2
  65. package/dist/core/objects/domain/domain.diff.d.ts +2 -8
  66. package/dist/core/objects/domain/domain.diff.js +16 -77
  67. package/dist/core/objects/domain/domain.model.js +1 -1
  68. package/dist/core/objects/event-trigger/event-trigger.diff.d.ts +2 -3
  69. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.d.ts +2 -8
  70. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.js +13 -77
  71. package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +2 -2
  72. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.d.ts +2 -8
  73. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -77
  74. package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +1 -1
  75. package/dist/core/objects/foreign-data-wrapper/server/server.diff.d.ts +2 -8
  76. package/dist/core/objects/foreign-data-wrapper/server/server.diff.js +13 -77
  77. package/dist/core/objects/language/language.diff.d.ts +2 -5
  78. package/dist/core/objects/language/language.diff.js +7 -39
  79. package/dist/core/objects/materialized-view/materialized-view.diff.d.ts +2 -8
  80. package/dist/core/objects/materialized-view/materialized-view.diff.js +16 -158
  81. package/dist/core/objects/materialized-view/materialized-view.model.d.ts +3 -3
  82. package/dist/core/objects/materialized-view/materialized-view.model.js +1 -1
  83. package/dist/core/objects/procedure/changes/procedure.alter.js +12 -12
  84. package/dist/core/objects/procedure/procedure.diff.d.ts +2 -8
  85. package/dist/core/objects/procedure/procedure.diff.js +16 -77
  86. package/dist/core/objects/procedure/procedure.model.d.ts +9 -9
  87. package/dist/core/objects/procedure/procedure.model.js +1 -1
  88. package/dist/core/objects/publication/changes/publication.alter.d.ts +0 -9
  89. package/dist/core/objects/publication/changes/publication.alter.js +0 -14
  90. package/dist/core/objects/publication/changes/publication.types.d.ts +2 -2
  91. package/dist/core/objects/publication/publication.diff.d.ts +2 -3
  92. package/dist/core/objects/publication/publication.diff.js +8 -13
  93. package/dist/core/objects/rls-policy/changes/rls-policy.alter.js +3 -3
  94. package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
  95. package/dist/core/objects/role/role.diff.js +22 -1
  96. package/dist/core/objects/role/role.model.d.ts +4 -3
  97. package/dist/core/objects/role/role.model.js +118 -12
  98. package/dist/core/objects/rule/rule.model.d.ts +1 -1
  99. package/dist/core/objects/schema/schema.diff.d.ts +2 -8
  100. package/dist/core/objects/schema/schema.diff.js +16 -77
  101. package/dist/core/objects/schema/schema.model.js +1 -1
  102. package/dist/core/objects/sequence/sequence.diff.d.ts +2 -8
  103. package/dist/core/objects/sequence/sequence.diff.js +16 -79
  104. package/dist/core/objects/sequence/sequence.model.js +1 -1
  105. package/dist/core/objects/subscription/subscription.diff.d.ts +2 -3
  106. package/dist/core/objects/table/changes/table.create.js +3 -0
  107. package/dist/core/objects/table/table.diff.d.ts +2 -8
  108. package/dist/core/objects/table/table.diff.js +26 -157
  109. package/dist/core/objects/table/table.model.d.ts +23 -22
  110. package/dist/core/objects/table/table.model.js +1 -1
  111. package/dist/core/objects/trigger/changes/trigger.create.js +2 -4
  112. package/dist/core/objects/trigger/trigger.model.d.ts +8 -0
  113. package/dist/core/objects/trigger/trigger.model.js +11 -0
  114. package/dist/core/objects/type/composite-type/composite-type.diff.d.ts +2 -8
  115. package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -77
  116. package/dist/core/objects/type/composite-type/composite-type.model.d.ts +3 -3
  117. package/dist/core/objects/type/composite-type/composite-type.model.js +2 -1
  118. package/dist/core/objects/type/enum/enum.diff.d.ts +2 -8
  119. package/dist/core/objects/type/enum/enum.diff.js +25 -112
  120. package/dist/core/objects/type/enum/enum.model.js +1 -1
  121. package/dist/core/objects/type/range/changes/range.create.js +6 -3
  122. package/dist/core/objects/type/range/range.diff.d.ts +2 -8
  123. package/dist/core/objects/type/range/range.diff.js +16 -77
  124. package/dist/core/objects/type/range/range.model.js +1 -1
  125. package/dist/core/objects/view/view.diff.d.ts +2 -8
  126. package/dist/core/objects/view/view.diff.js +16 -158
  127. package/dist/core/objects/view/view.model.d.ts +18 -4
  128. package/dist/core/objects/view/view.model.js +3 -13
  129. package/dist/core/plan/apply.js +9 -26
  130. package/dist/core/plan/create.d.ts +19 -6
  131. package/dist/core/plan/create.js +134 -174
  132. package/dist/core/plan/serialize.js +16 -4
  133. package/dist/core/plan/sql-format/fixtures.js +3 -5
  134. package/dist/core/plan/sql-format/keyword-case.js +26 -1
  135. package/dist/core/plan/ssl-config.d.ts +32 -0
  136. package/dist/core/plan/ssl-config.js +115 -0
  137. package/dist/core/plan/types.d.ts +6 -0
  138. package/dist/core/postgres-config.d.ts +14 -0
  139. package/dist/core/postgres-config.js +53 -2
  140. package/dist/core/sort/graph-builder.js +10 -0
  141. package/dist/core/sort/logical-sort.js +31 -23
  142. package/dist/core/test-utils/assert-valid-sql.d.ts +10 -0
  143. package/dist/core/test-utils/assert-valid-sql.js +19 -0
  144. package/dist/index.d.ts +6 -0
  145. package/dist/index.js +6 -1
  146. package/package.json +21 -4
  147. package/src/cli/app.ts +27 -3
  148. package/src/cli/bin/cli.ts +6 -0
  149. package/src/cli/commands/catalog-export.ts +78 -0
  150. package/src/cli/commands/declarative-apply.diagnostics.test.ts +77 -0
  151. package/src/cli/commands/declarative-apply.ts +380 -0
  152. package/src/cli/commands/declarative-export.ts +330 -0
  153. package/src/cli/commands/plan.ts +28 -7
  154. package/src/cli/exit-code.test.ts +19 -0
  155. package/src/cli/exit-code.ts +7 -0
  156. package/src/cli/formatters/tree/tree.ts +3 -2
  157. package/src/cli/utils/apply-display.test.ts +348 -0
  158. package/src/cli/utils/apply-display.ts +238 -0
  159. package/src/cli/utils/export-display.test.ts +103 -0
  160. package/src/cli/utils/export-display.ts +275 -0
  161. package/src/cli/utils/integrations.test.ts +44 -0
  162. package/src/cli/utils/resolve-input.test.ts +38 -0
  163. package/src/cli/utils/resolve-input.ts +17 -0
  164. package/src/core/catalog-export/index.ts +20 -0
  165. package/src/core/catalog.diff.ts +79 -78
  166. package/src/core/catalog.model.test.ts +122 -0
  167. package/src/core/catalog.model.ts +127 -1
  168. package/src/core/catalog.snapshot.test.ts +464 -0
  169. package/src/core/catalog.snapshot.ts +289 -0
  170. package/src/core/declarative-apply/discover-sql.test.ts +103 -0
  171. package/src/core/declarative-apply/discover-sql.ts +107 -0
  172. package/src/core/declarative-apply/extract-catalog-providers.ts +220 -0
  173. package/src/core/declarative-apply/index.test.ts +67 -0
  174. package/src/core/declarative-apply/index.ts +205 -0
  175. package/src/core/declarative-apply/round-apply.test.ts +504 -0
  176. package/src/core/declarative-apply/round-apply.ts +562 -0
  177. package/src/core/expand-replace-dependencies.test.ts +70 -0
  178. package/src/core/export/file-mapper.test.ts +816 -0
  179. package/src/core/export/file-mapper.ts +574 -0
  180. package/src/core/export/grouper.ts +108 -0
  181. package/src/core/export/index.ts +129 -0
  182. package/src/core/export/types.ts +104 -0
  183. package/src/core/fixtures/empty-catalogs/postgres-15-16-baseline.json +287 -0
  184. package/src/core/integrations/filter/dsl.test.ts +211 -0
  185. package/src/core/integrations/filter/dsl.ts +65 -3
  186. package/src/core/integrations/filter/extractors.test.ts +244 -0
  187. package/src/core/integrations/filter/extractors.ts +42 -0
  188. package/src/core/integrations/integration-dsl.ts +10 -0
  189. package/src/core/integrations/serialize/dsl.test.ts +91 -0
  190. package/src/core/integrations/supabase.ts +9 -0
  191. package/src/core/objects/aggregate/aggregate.diff.ts +39 -95
  192. package/src/core/objects/aggregate/aggregate.model.ts +1 -1
  193. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +3 -1
  194. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +5 -2
  195. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +6 -3
  196. package/src/core/objects/aggregate/changes/aggregate.create.ts +1 -1
  197. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +7 -3
  198. package/src/core/objects/aggregate/changes/aggregate.drop.ts +1 -1
  199. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +9 -3
  200. package/src/core/objects/base.privilege-diff.ts +178 -30
  201. package/src/core/objects/base.privilege.ts +9 -2
  202. package/src/core/objects/collation/changes/collation.alter.test.ts +7 -2
  203. package/src/core/objects/collation/changes/collation.create.test.ts +7 -2
  204. package/src/core/objects/collation/changes/collation.drop.test.ts +4 -1
  205. package/src/core/objects/collation/collation.diff.test.ts +9 -12
  206. package/src/core/objects/collation/collation.diff.ts +2 -1
  207. package/src/core/objects/diff-context.ts +16 -0
  208. package/src/core/objects/domain/changes/domain.alter.test.ts +28 -9
  209. package/src/core/objects/domain/changes/domain.create.test.ts +32 -2
  210. package/src/core/objects/domain/changes/domain.create.ts +7 -1
  211. package/src/core/objects/domain/changes/domain.drop.test.ts +4 -1
  212. package/src/core/objects/domain/domain.diff.ts +39 -102
  213. package/src/core/objects/domain/domain.model.ts +1 -1
  214. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +10 -3
  215. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +4 -1
  216. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +4 -1
  217. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +12 -7
  218. package/src/core/objects/event-trigger/event-trigger.diff.ts +2 -1
  219. package/src/core/objects/extension/changes/extension.alter.test.ts +7 -2
  220. package/src/core/objects/extension/changes/extension.create.test.ts +4 -1
  221. package/src/core/objects/extension/changes/extension.drop.test.ts +4 -1
  222. package/src/core/objects/extension/extension.model.test.ts +98 -0
  223. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +16 -5
  224. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +51 -16
  225. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +4 -1
  226. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +111 -4
  227. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +31 -101
  228. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +2 -2
  229. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +46 -15
  230. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +13 -4
  231. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +4 -1
  232. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +39 -102
  233. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +1 -1
  234. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +22 -7
  235. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +19 -6
  236. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +4 -1
  237. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +95 -0
  238. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +31 -101
  239. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +13 -4
  240. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +16 -5
  241. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +10 -3
  242. package/src/core/objects/index/changes/index.alter.test.ts +13 -4
  243. package/src/core/objects/index/changes/index.create.test.ts +4 -1
  244. package/src/core/objects/index/changes/index.drop.test.ts +4 -1
  245. package/src/core/objects/language/changes/language.alter.test.ts +4 -1
  246. package/src/core/objects/language/changes/language.create.test.ts +4 -1
  247. package/src/core/objects/language/changes/language.drop.test.ts +4 -1
  248. package/src/core/objects/language/language.diff.test.ts +86 -4
  249. package/src/core/objects/language/language.diff.ts +17 -49
  250. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +10 -3
  251. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +7 -2
  252. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +4 -1
  253. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +162 -0
  254. package/src/core/objects/materialized-view/materialized-view.diff.ts +41 -191
  255. package/src/core/objects/materialized-view/materialized-view.model.ts +1 -1
  256. package/src/core/objects/procedure/changes/procedure.alter.test.ts +121 -49
  257. package/src/core/objects/procedure/changes/procedure.alter.ts +15 -12
  258. package/src/core/objects/procedure/changes/procedure.create.test.ts +4 -1
  259. package/src/core/objects/procedure/changes/procedure.drop.test.ts +7 -2
  260. package/src/core/objects/procedure/procedure.diff.ts +39 -102
  261. package/src/core/objects/procedure/procedure.model.ts +1 -1
  262. package/src/core/objects/publication/changes/publication.alter.test.ts +15 -21
  263. package/src/core/objects/publication/changes/publication.alter.ts +0 -18
  264. package/src/core/objects/publication/changes/publication.comment.test.ts +5 -2
  265. package/src/core/objects/publication/changes/publication.create.test.ts +5 -2
  266. package/src/core/objects/publication/changes/publication.drop.test.ts +3 -1
  267. package/src/core/objects/publication/changes/publication.types.ts +0 -2
  268. package/src/core/objects/publication/publication.diff.test.ts +24 -19
  269. package/src/core/objects/publication/publication.diff.ts +9 -15
  270. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +31 -14
  271. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +3 -3
  272. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +10 -3
  273. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +4 -1
  274. package/src/core/objects/role/changes/role.alter.test.ts +31 -15
  275. package/src/core/objects/role/changes/role.create.test.ts +6 -2
  276. package/src/core/objects/role/changes/role.drop.test.ts +4 -1
  277. package/src/core/objects/role/role.diff.test.ts +235 -0
  278. package/src/core/objects/role/role.diff.ts +21 -1
  279. package/src/core/objects/role/role.model.ts +122 -14
  280. package/src/core/objects/rule/changes/rule.alter.test.ts +7 -3
  281. package/src/core/objects/rule/changes/rule.comment.test.ts +5 -2
  282. package/src/core/objects/rule/changes/rule.create.test.ts +6 -2
  283. package/src/core/objects/rule/changes/rule.drop.test.ts +3 -1
  284. package/src/core/objects/schema/changes/schema.alter.test.ts +4 -1
  285. package/src/core/objects/schema/changes/schema.create.test.ts +4 -1
  286. package/src/core/objects/schema/changes/schema.drop.test.ts +4 -1
  287. package/src/core/objects/schema/schema.diff.ts +39 -102
  288. package/src/core/objects/schema/schema.model.ts +1 -1
  289. package/src/core/objects/sequence/changes/sequence.alter.test.ts +11 -5
  290. package/src/core/objects/sequence/changes/sequence.create.test.ts +8 -3
  291. package/src/core/objects/sequence/changes/sequence.drop.test.ts +4 -1
  292. package/src/core/objects/sequence/sequence.diff.test.ts +114 -0
  293. package/src/core/objects/sequence/sequence.diff.ts +39 -104
  294. package/src/core/objects/sequence/sequence.model.ts +1 -1
  295. package/src/core/objects/subscription/changes/subscription.alter.test.ts +15 -5
  296. package/src/core/objects/subscription/changes/subscription.comment.test.ts +5 -2
  297. package/src/core/objects/subscription/changes/subscription.create.test.ts +5 -2
  298. package/src/core/objects/subscription/changes/subscription.drop.test.ts +3 -1
  299. package/src/core/objects/subscription/subscription.diff.test.ts +16 -11
  300. package/src/core/objects/subscription/subscription.diff.ts +2 -1
  301. package/src/core/objects/table/changes/table.alter.test.ts +38 -15
  302. package/src/core/objects/table/changes/table.create.test.ts +41 -3
  303. package/src/core/objects/table/changes/table.create.ts +4 -0
  304. package/src/core/objects/table/changes/table.drop.test.ts +3 -1
  305. package/src/core/objects/table/table.diff.test.ts +157 -0
  306. package/src/core/objects/table/table.diff.ts +54 -190
  307. package/src/core/objects/table/table.model.ts +1 -1
  308. package/src/core/objects/trigger/changes/trigger.alter.test.ts +8 -4
  309. package/src/core/objects/trigger/changes/trigger.create.test.ts +5 -1
  310. package/src/core/objects/trigger/changes/trigger.create.ts +7 -4
  311. package/src/core/objects/trigger/changes/trigger.drop.test.ts +5 -1
  312. package/src/core/objects/trigger/trigger.diff.test.ts +1 -0
  313. package/src/core/objects/trigger/trigger.model.ts +12 -0
  314. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +10 -4
  315. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +7 -2
  316. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +4 -1
  317. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +78 -0
  318. package/src/core/objects/type/composite-type/composite-type.diff.ts +39 -101
  319. package/src/core/objects/type/composite-type/composite-type.model.ts +2 -1
  320. package/src/core/objects/type/enum/changes/enum.alter.test.ts +14 -5
  321. package/src/core/objects/type/enum/changes/enum.create.test.ts +4 -1
  322. package/src/core/objects/type/enum/changes/enum.drop.test.ts +4 -1
  323. package/src/core/objects/type/enum/enum.diff.test.ts +181 -0
  324. package/src/core/objects/type/enum/enum.diff.ts +58 -146
  325. package/src/core/objects/type/enum/enum.model.ts +1 -1
  326. package/src/core/objects/type/range/changes/range.alter.test.ts +3 -1
  327. package/src/core/objects/type/range/changes/range.create.test.ts +5 -2
  328. package/src/core/objects/type/range/changes/range.create.ts +6 -2
  329. package/src/core/objects/type/range/changes/range.drop.test.ts +3 -1
  330. package/src/core/objects/type/range/range.diff.test.ts +77 -0
  331. package/src/core/objects/type/range/range.diff.ts +39 -101
  332. package/src/core/objects/type/range/range.model.ts +1 -1
  333. package/src/core/objects/view/changes/view.alter.test.ts +8 -3
  334. package/src/core/objects/view/changes/view.create.test.ts +7 -2
  335. package/src/core/objects/view/changes/view.drop.test.ts +4 -1
  336. package/src/core/objects/view/view.diff.test.ts +82 -0
  337. package/src/core/objects/view/view.diff.ts +41 -191
  338. package/src/core/objects/view/view.model.ts +3 -17
  339. package/src/core/plan/apply.ts +9 -27
  340. package/src/core/plan/create.ts +173 -237
  341. package/src/core/plan/serialize.test.ts +317 -0
  342. package/src/core/plan/serialize.ts +18 -4
  343. package/src/core/plan/sql-format/fixtures.ts +2 -5
  344. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +52 -0
  345. package/src/core/plan/sql-format/format-off.test.ts +14 -17
  346. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +27 -22
  347. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +17 -21
  348. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +25 -20
  349. package/src/core/plan/sql-format/format-pretty-upper.test.ts +23 -20
  350. package/src/core/plan/sql-format/keyword-case.ts +36 -1
  351. package/src/core/plan/ssl-config.ts +172 -0
  352. package/src/core/plan/types.ts +6 -0
  353. package/src/core/postgres-config.ts +71 -2
  354. package/src/core/sort/graph-builder.ts +12 -0
  355. package/src/core/sort/logical-sort.test.ts +371 -0
  356. package/src/core/sort/logical-sort.ts +32 -25
  357. package/src/core/sort/topological-sort.test.ts +275 -0
  358. package/src/core/test-utils/assert-valid-sql.ts +20 -0
  359. package/src/index.ts +26 -2
@@ -148,7 +148,7 @@ select
148
148
  )
149
149
  order by x.grantee, x.privilege_type
150
150
  )
151
- from lateral aclexplode(c.relacl) as x(grantor, grantee, privilege_type, is_grantable)
151
+ from lateral aclexplode(COALESCE(c.relacl, acldefault('S', c.relowner))) as x(grantor, grantee, privilege_type, is_grantable)
152
152
  ), '[]'
153
153
  ) as privileges,
154
154
  c.relowner::regrole::text as owner
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { stableId } from "../../utils.ts";
3
4
  import { Subscription } from "../subscription.model.ts";
4
5
  import {
@@ -44,18 +45,20 @@ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
44
45
  });
45
46
 
46
47
  describe("subscription.alter", () => {
47
- test("set connection serializes conninfo literal", () => {
48
+ test("set connection serializes conninfo literal", async () => {
48
49
  const subscription = makeSubscription({
49
50
  conninfo: "dbname=postgres host=replica",
50
51
  });
51
52
  const change = new AlterSubscriptionSetConnection({ subscription });
52
53
 
54
+ await assertValidSql(change.serialize());
55
+
53
56
  expect(change.serialize()).toBe(
54
57
  "ALTER SUBSCRIPTION sub_base CONNECTION 'dbname=postgres host=replica'",
55
58
  );
56
59
  });
57
60
 
58
- test("set publication preserves ordering and refresh hint when disabled", () => {
61
+ test("set publication preserves ordering and refresh hint when disabled", async () => {
59
62
  const enabledSubscription = makeSubscription({
60
63
  publications: ["pub_a", "pub_b"],
61
64
  enabled: true,
@@ -64,6 +67,8 @@ describe("subscription.alter", () => {
64
67
  subscription: enabledSubscription,
65
68
  });
66
69
 
70
+ await assertValidSql(enabledChange.serialize());
71
+
67
72
  expect(enabledChange.serialize()).toBe(
68
73
  "ALTER SUBSCRIPTION sub_base SET PUBLICATION pub_a, pub_b",
69
74
  );
@@ -76,12 +81,14 @@ describe("subscription.alter", () => {
76
81
  subscription: disabledSubscription,
77
82
  });
78
83
 
84
+ await assertValidSql(disabledChange.serialize());
85
+
79
86
  expect(disabledChange.serialize()).toBe(
80
87
  "ALTER SUBSCRIPTION sub_base SET PUBLICATION pub_a, pub_b WITH (refresh = false)",
81
88
  );
82
89
  });
83
90
 
84
- test("toggle enablement serializes ENABLE and DISABLE statements", () => {
91
+ test("toggle enablement serializes ENABLE and DISABLE statements", async () => {
85
92
  const subscription = makeSubscription();
86
93
 
87
94
  expect(new AlterSubscriptionEnable({ subscription }).serialize()).toBe(
@@ -92,7 +99,7 @@ describe("subscription.alter", () => {
92
99
  );
93
100
  });
94
101
 
95
- test("set options delegates to option formatter", () => {
102
+ test("set options delegates to option formatter", async () => {
96
103
  const subscription = makeSubscription({
97
104
  slot_name: "custom_slot",
98
105
  slot_is_none: false,
@@ -104,12 +111,14 @@ describe("subscription.alter", () => {
104
111
  options: ["slot_name", "disable_on_error", "origin"],
105
112
  });
106
113
 
114
+ await assertValidSql(change.serialize());
115
+
107
116
  expect(change.serialize()).toBe(
108
117
  "ALTER SUBSCRIPTION sub_base SET (slot_name = 'custom_slot', disable_on_error = true, origin = 'none')",
109
118
  );
110
119
  });
111
120
 
112
- test("set owner tracks role dependency", () => {
121
+ test("set owner tracks role dependency", async () => {
113
122
  const subscription = makeSubscription();
114
123
  const change = new AlterSubscriptionSetOwner({
115
124
  subscription,
@@ -117,6 +126,7 @@ describe("subscription.alter", () => {
117
126
  });
118
127
 
119
128
  expect(change.requires).toEqual([stableId.role("new_owner")]);
129
+ await assertValidSql(change.serialize());
120
130
  expect(change.serialize()).toBe(
121
131
  "ALTER SUBSCRIPTION sub_base OWNER TO new_owner",
122
132
  );
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { stableId } from "../../utils.ts";
3
4
  import { Subscription } from "../subscription.model.ts";
4
5
  import {
@@ -40,7 +41,7 @@ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
40
41
  });
41
42
 
42
43
  describe("subscription.comment", () => {
43
- test("create comment serializes and declares dependencies", () => {
44
+ test("create comment serializes and declares dependencies", async () => {
44
45
  const subscription = makeSubscription({
45
46
  comment: "subscription's metadata",
46
47
  });
@@ -48,12 +49,13 @@ describe("subscription.comment", () => {
48
49
 
49
50
  expect(change.creates).toEqual([stableId.comment(subscription.stableId)]);
50
51
  expect(change.requires).toEqual([subscription.stableId]);
52
+ await assertValidSql(change.serialize());
51
53
  expect(change.serialize()).toBe(
52
54
  "COMMENT ON SUBSCRIPTION sub_base IS 'subscription''s metadata'",
53
55
  );
54
56
  });
55
57
 
56
- test("drop comment serializes and tracks drops", () => {
58
+ test("drop comment serializes and tracks drops", async () => {
57
59
  const subscription = makeSubscription({ comment: "not used" });
58
60
  const change = new DropCommentOnSubscription({ subscription });
59
61
 
@@ -62,6 +64,7 @@ describe("subscription.comment", () => {
62
64
  stableId.comment(subscription.stableId),
63
65
  subscription.stableId,
64
66
  ]);
67
+ await assertValidSql(change.serialize());
65
68
  expect(change.serialize()).toBe("COMMENT ON SUBSCRIPTION sub_base IS NULL");
66
69
  });
67
70
  });
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { stableId } from "../../utils.ts";
3
4
  import { Subscription } from "../subscription.model.ts";
4
5
  import { CreateSubscription } from "./subscription.create.ts";
@@ -37,18 +38,19 @@ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
37
38
  });
38
39
 
39
40
  describe("subscription.create", () => {
40
- test("serialize minimal subscription", () => {
41
+ test("serialize minimal subscription", async () => {
41
42
  const subscription = makeSubscription();
42
43
  const change = new CreateSubscription({ subscription });
43
44
 
44
45
  expect(change.creates).toEqual([subscription.stableId]);
45
46
  expect(change.requires).toEqual([stableId.role(subscription.owner)]);
47
+ await assertValidSql(change.serialize());
46
48
  expect(change.serialize()).toBe(
47
49
  "CREATE SUBSCRIPTION sub_base CONNECTION 'host=example dbname=postgres' PUBLICATION pub_base",
48
50
  );
49
51
  });
50
52
 
51
- test("serialize subscription with extended options", () => {
53
+ test("serialize subscription with extended options", async () => {
52
54
  const subscription = makeSubscription({
53
55
  enabled: false,
54
56
  binary: true,
@@ -70,6 +72,7 @@ describe("subscription.create", () => {
70
72
  const change = new CreateSubscription({ subscription });
71
73
 
72
74
  expect(change.requires).toEqual([stableId.role(subscription.owner)]);
75
+ await assertValidSql(change.serialize());
73
76
  expect(change.serialize()).toBe(
74
77
  "CREATE SUBSCRIPTION sub_base CONNECTION 'dbname=postgres application_name=sub_base' PUBLICATION pub_a, pub_b WITH (enabled = false, slot_name = 'custom_slot', binary = true, streaming = 'parallel', synchronous_commit = 'local', two_phase = true, disable_on_error = true, password_required = false, run_as_owner = true, origin = 'none', failover = true, create_slot = false, connect = false)",
75
78
  );
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Subscription } from "../subscription.model.ts";
3
4
  import { DropSubscription } from "./subscription.drop.ts";
4
5
 
@@ -36,11 +37,12 @@ const makeSubscription = (override: Partial<SubscriptionProps> = {}) =>
36
37
  });
37
38
 
38
39
  describe("subscription.drop", () => {
39
- test("serialize drop subscription", () => {
40
+ test("serialize drop subscription", async () => {
40
41
  const subscription = makeSubscription();
41
42
  const change = new DropSubscription({ subscription });
42
43
 
43
44
  expect(change.drops).toEqual([subscription.stableId]);
45
+ await assertValidSql(change.serialize());
44
46
  expect(change.serialize()).toBe("DROP SUBSCRIPTION sub_base");
45
47
  });
46
48
  });
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
2
3
  import {
3
4
  AlterSubscriptionDisable,
4
5
  AlterSubscriptionEnable,
@@ -16,6 +17,10 @@ import { DropSubscription } from "./changes/subscription.drop.ts";
16
17
  import { diffSubscriptions } from "./subscription.diff.ts";
17
18
  import { Subscription, type SubscriptionProps } from "./subscription.model.ts";
18
19
 
20
+ const ctx: Pick<ObjectDiffContext, "currentUser"> = {
21
+ currentUser: "postgres",
22
+ };
23
+
19
24
  const baseProps: SubscriptionProps = {
20
25
  name: "mysub",
21
26
  raw_name: "mysub",
@@ -42,7 +47,7 @@ describe.concurrent("subscription.diff", () => {
42
47
  test("create and drop subscription", () => {
43
48
  const subscription = new Subscription(baseProps);
44
49
  const created = diffSubscriptions(
45
- { currentUser: "postgres" },
50
+ ctx,
46
51
  {},
47
52
  { [subscription.stableId]: subscription },
48
53
  );
@@ -51,7 +56,7 @@ describe.concurrent("subscription.diff", () => {
51
56
  );
52
57
 
53
58
  const dropped = diffSubscriptions(
54
- { currentUser: "postgres" },
59
+ ctx,
55
60
  { [subscription.stableId]: subscription },
56
61
  {},
57
62
  );
@@ -68,7 +73,7 @@ describe.concurrent("subscription.diff", () => {
68
73
  conninfo: "host=replica port=5433 dbname=postgres",
69
74
  });
70
75
  const changes = diffSubscriptions(
71
- { currentUser: "postgres" },
76
+ ctx,
72
77
  { [mainSubscription.stableId]: mainSubscription },
73
78
  { [branchSubscription.stableId]: branchSubscription },
74
79
  );
@@ -87,7 +92,7 @@ describe.concurrent("subscription.diff", () => {
87
92
  publications: ["pub_a", "pub_b"],
88
93
  });
89
94
  const changes = diffSubscriptions(
90
- { currentUser: "postgres" },
95
+ ctx,
91
96
  { [mainSubscription.stableId]: mainSubscription },
92
97
  { [branchSubscription.stableId]: branchSubscription },
93
98
  );
@@ -105,7 +110,7 @@ describe.concurrent("subscription.diff", () => {
105
110
  enabled: false,
106
111
  });
107
112
  const disableChanges = diffSubscriptions(
108
- { currentUser: "postgres" },
113
+ ctx,
109
114
  { [mainSubscription.stableId]: mainSubscription },
110
115
  { [branchDisabled.stableId]: branchDisabled },
111
116
  );
@@ -116,7 +121,7 @@ describe.concurrent("subscription.diff", () => {
116
121
  ).toBe(true);
117
122
 
118
123
  const enableChanges = diffSubscriptions(
119
- { currentUser: "postgres" },
124
+ ctx,
120
125
  { [branchDisabled.stableId]: branchDisabled },
121
126
  { [mainSubscription.stableId]: mainSubscription },
122
127
  );
@@ -141,7 +146,7 @@ describe.concurrent("subscription.diff", () => {
141
146
  slot_is_none: false,
142
147
  });
143
148
  const changes = diffSubscriptions(
144
- { currentUser: "postgres" },
149
+ ctx,
145
150
  { [mainSubscription.stableId]: mainSubscription },
146
151
  { [branchSubscription.stableId]: branchSubscription },
147
152
  );
@@ -163,7 +168,7 @@ describe.concurrent("subscription.diff", () => {
163
168
  replication_slot_created: false,
164
169
  });
165
170
  const changes = diffSubscriptions(
166
- { currentUser: "postgres" },
171
+ ctx,
167
172
  { [mainSubscription.stableId]: mainSubscription },
168
173
  { [branchSubscription.stableId]: branchSubscription },
169
174
  );
@@ -184,7 +189,7 @@ describe.concurrent("subscription.diff", () => {
184
189
  comment: "replication subscription",
185
190
  });
186
191
  const changes = diffSubscriptions(
187
- { currentUser: "postgres" },
192
+ ctx,
188
193
  { [mainSubscription.stableId]: mainSubscription },
189
194
  { [branchSubscription.stableId]: branchSubscription },
190
195
  );
@@ -200,7 +205,7 @@ describe.concurrent("subscription.diff", () => {
200
205
  comment: null,
201
206
  });
202
207
  const dropCommentChanges = diffSubscriptions(
203
- { currentUser: "postgres" },
208
+ ctx,
204
209
  { [branchSubscription.stableId]: branchSubscription },
205
210
  { [removeCommentSubscription.stableId]: removeCommentSubscription },
206
211
  );
@@ -218,7 +223,7 @@ describe.concurrent("subscription.diff", () => {
218
223
  two_phase: true,
219
224
  });
220
225
  const changes = diffSubscriptions(
221
- { currentUser: "postgres" },
226
+ ctx,
222
227
  { [mainSubscription.stableId]: mainSubscription },
223
228
  { [branchSubscription.stableId]: branchSubscription },
224
229
  );
@@ -1,4 +1,5 @@
1
1
  import { diffObjects } from "../base.diff.ts";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
2
3
  import { hasNonAlterableChanges } from "../utils.ts";
3
4
  import {
4
5
  AlterSubscriptionDisable,
@@ -35,7 +36,7 @@ const SETTABLE_OPTIONS: SubscriptionSettableOption[] = [
35
36
  ];
36
37
 
37
38
  export function diffSubscriptions(
38
- ctx: { currentUser: string },
39
+ ctx: Pick<ObjectDiffContext, "currentUser">,
39
40
  main: Record<string, Subscription>,
40
41
  branch: Record<string, Subscription>,
41
42
  ): SubscriptionChange[] {
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import type { ColumnProps } from "../../base.model.ts";
3
4
  import { Table, type TableProps } from "../table.model.ts";
4
5
  import {
@@ -28,7 +29,7 @@ import {
28
29
 
29
30
  describe.concurrent("table", () => {
30
31
  describe("alter", () => {
31
- test("change owner", () => {
32
+ test("change owner", async () => {
32
33
  const props: Omit<TableProps, "owner"> = {
33
34
  schema: "public",
34
35
  name: "test_table",
@@ -57,12 +58,14 @@ describe.concurrent("table", () => {
57
58
 
58
59
  const change = new AlterTableChangeOwner({ table, owner: "new_owner" });
59
60
 
61
+ await assertValidSql(change.serialize());
62
+
60
63
  expect(change.serialize()).toBe(
61
64
  "ALTER TABLE public.test_table OWNER TO new_owner",
62
65
  );
63
66
  });
64
67
 
65
- test("set unlogged", () => {
68
+ test("set unlogged", async () => {
66
69
  const props: Omit<TableProps, "owner" | "options"> = {
67
70
  schema: "public",
68
71
  name: "test_table",
@@ -86,12 +89,13 @@ describe.concurrent("table", () => {
86
89
  const table = new Table({ ...props, owner: "o1", options: null });
87
90
 
88
91
  const change = new AlterTableSetUnlogged({ table });
92
+ await assertValidSql(change.serialize());
89
93
  expect(change.serialize()).toBe(
90
94
  "ALTER TABLE public.test_table SET UNLOGGED",
91
95
  );
92
96
  });
93
97
 
94
- test("set logged", () => {
98
+ test("set logged", async () => {
95
99
  const props: Omit<TableProps, "owner" | "options"> = {
96
100
  schema: "public",
97
101
  name: "test_table",
@@ -115,12 +119,13 @@ describe.concurrent("table", () => {
115
119
  const table = new Table({ ...props, owner: "o1", options: null });
116
120
 
117
121
  const change = new AlterTableSetLogged({ table });
122
+ await assertValidSql(change.serialize());
118
123
  expect(change.serialize()).toBe(
119
124
  "ALTER TABLE public.test_table SET LOGGED",
120
125
  );
121
126
  });
122
127
 
123
- test("enable/disable row level security", () => {
128
+ test("enable/disable row level security", async () => {
124
129
  const base: Omit<TableProps, "owner" | "options" | "row_security"> = {
125
130
  schema: "public",
126
131
  name: "test_table",
@@ -148,6 +153,7 @@ describe.concurrent("table", () => {
148
153
  row_security: false,
149
154
  }),
150
155
  });
156
+ await assertValidSql(enable.serialize());
151
157
  expect(enable.serialize()).toBe(
152
158
  "ALTER TABLE public.test_table ENABLE ROW LEVEL SECURITY",
153
159
  );
@@ -159,12 +165,13 @@ describe.concurrent("table", () => {
159
165
  row_security: true,
160
166
  }),
161
167
  });
168
+ await assertValidSql(disable.serialize());
162
169
  expect(disable.serialize()).toBe(
163
170
  "ALTER TABLE public.test_table DISABLE ROW LEVEL SECURITY",
164
171
  );
165
172
  });
166
173
 
167
- test("force/no force row level security", () => {
174
+ test("force/no force row level security", async () => {
168
175
  const base: Omit<TableProps, "owner" | "options" | "force_row_security"> =
169
176
  {
170
177
  schema: "public",
@@ -193,6 +200,7 @@ describe.concurrent("table", () => {
193
200
  force_row_security: false,
194
201
  }),
195
202
  });
203
+ await assertValidSql(force.serialize());
196
204
  expect(force.serialize()).toBe(
197
205
  "ALTER TABLE public.test_table FORCE ROW LEVEL SECURITY",
198
206
  );
@@ -204,12 +212,13 @@ describe.concurrent("table", () => {
204
212
  force_row_security: true,
205
213
  }),
206
214
  });
215
+ await assertValidSql(noforce.serialize());
207
216
  expect(noforce.serialize()).toBe(
208
217
  "ALTER TABLE public.test_table NO FORCE ROW LEVEL SECURITY",
209
218
  );
210
219
  });
211
220
 
212
- test("set storage params", () => {
221
+ test("set storage params", async () => {
213
222
  const base: Omit<TableProps, "owner" | "options"> = {
214
223
  schema: "public",
215
224
  name: "test_table",
@@ -234,12 +243,13 @@ describe.concurrent("table", () => {
234
243
  table: new Table({ ...base, owner: "o1", options: null }),
235
244
  options: ["fillfactor=90"],
236
245
  });
246
+ await assertValidSql(change.serialize());
237
247
  expect(change.serialize()).toBe(
238
248
  "ALTER TABLE public.test_table SET (fillfactor=90)",
239
249
  );
240
250
  });
241
251
 
242
- test("reset storage params", () => {
252
+ test("reset storage params", async () => {
243
253
  const base: Omit<TableProps, "owner" | "options"> = {
244
254
  schema: "public",
245
255
  name: "test_table",
@@ -269,12 +279,13 @@ describe.concurrent("table", () => {
269
279
  table,
270
280
  params: ["fillfactor", "autovacuum_enabled"],
271
281
  });
282
+ await assertValidSql(change.serialize());
272
283
  expect(change.serialize()).toBe(
273
284
  "ALTER TABLE public.test_table RESET (fillfactor, autovacuum_enabled)",
274
285
  );
275
286
  });
276
287
 
277
- test("replica identity default/nothing/full", () => {
288
+ test("replica identity default/nothing/full", async () => {
278
289
  const baseProps: Omit<
279
290
  TableProps,
280
291
  "owner" | "options" | "replica_identity"
@@ -329,7 +340,7 @@ describe.concurrent("table", () => {
329
340
  ).toBe("ALTER TABLE public.test_table REPLICA IDENTITY FULL");
330
341
  });
331
342
 
332
- test("replica identity DEFAULT and INDEX fallback", () => {
343
+ test("replica identity DEFAULT and INDEX fallback", async () => {
333
344
  const baseProps: Omit<
334
345
  TableProps,
335
346
  "owner" | "options" | "replica_identity"
@@ -385,7 +396,7 @@ describe.concurrent("table", () => {
385
396
  ).toBe("ALTER TABLE public.test_table REPLICA IDENTITY DEFAULT");
386
397
  });
387
398
 
388
- test("columns add/drop/alter", () => {
399
+ test("columns add/drop/alter", async () => {
389
400
  const tableProps: Omit<TableProps, "owner" | "options"> = {
390
401
  schema: "public",
391
402
  name: "test_table",
@@ -440,6 +451,7 @@ describe.concurrent("table", () => {
440
451
  table: withCols,
441
452
  column: colInt,
442
453
  });
454
+ await assertValidSql(changeAdd.serialize());
443
455
  expect(changeAdd.serialize()).toBe(
444
456
  "ALTER TABLE public.test_table ADD COLUMN a integer",
445
457
  );
@@ -454,6 +466,7 @@ describe.concurrent("table", () => {
454
466
  table: dropFrom,
455
467
  column: colText,
456
468
  });
469
+ await assertValidSql(changeDrop.serialize());
457
470
  expect(changeDrop.serialize()).toBe(
458
471
  "ALTER TABLE public.test_table DROP COLUMN b",
459
472
  );
@@ -462,6 +475,7 @@ describe.concurrent("table", () => {
462
475
  table: withCols,
463
476
  column: colText,
464
477
  });
478
+ await assertValidSql(changeType.serialize());
465
479
  expect(changeType.serialize()).toBe(
466
480
  "ALTER TABLE public.test_table ALTER COLUMN b TYPE text",
467
481
  );
@@ -470,6 +484,7 @@ describe.concurrent("table", () => {
470
484
  table: withCols,
471
485
  column: { ...colInt, default: "0" },
472
486
  });
487
+ await assertValidSql(changeSetDefault.serialize());
473
488
  expect(changeSetDefault.serialize()).toBe(
474
489
  "ALTER TABLE public.test_table ALTER COLUMN a SET DEFAULT 0",
475
490
  );
@@ -478,6 +493,7 @@ describe.concurrent("table", () => {
478
493
  table: withCols,
479
494
  column: { ...colInt, default: null },
480
495
  });
496
+ await assertValidSql(changeDropDefault.serialize());
481
497
  expect(changeDropDefault.serialize()).toBe(
482
498
  "ALTER TABLE public.test_table ALTER COLUMN a DROP DEFAULT",
483
499
  );
@@ -486,6 +502,7 @@ describe.concurrent("table", () => {
486
502
  table: withCols,
487
503
  column: { ...colInt, not_null: true },
488
504
  });
505
+ await assertValidSql(changeSetNotNull.serialize());
489
506
  expect(changeSetNotNull.serialize()).toBe(
490
507
  "ALTER TABLE public.test_table ALTER COLUMN a SET NOT NULL",
491
508
  );
@@ -494,12 +511,13 @@ describe.concurrent("table", () => {
494
511
  table: withCols,
495
512
  column: { ...colInt, not_null: false },
496
513
  });
514
+ await assertValidSql(changeDropNotNull.serialize());
497
515
  expect(changeDropNotNull.serialize()).toBe(
498
516
  "ALTER TABLE public.test_table ALTER COLUMN a DROP NOT NULL",
499
517
  );
500
518
  });
501
519
 
502
- test("add column with collation, default and not null", () => {
520
+ test("add column with collation, default and not null", async () => {
503
521
  const tableProps: Omit<TableProps, "owner" | "options"> = {
504
522
  schema: "public",
505
523
  name: "test_table",
@@ -540,12 +558,13 @@ describe.concurrent("table", () => {
540
558
  comment: null,
541
559
  };
542
560
  const change = new AlterTableAddColumn({ table: withCols, column: col });
561
+ await assertValidSql(change.serialize());
543
562
  expect(change.serialize()).toBe(
544
563
  "ALTER TABLE public.test_table ADD COLUMN a integer COLLATE mycoll DEFAULT 0 NOT NULL",
545
564
  );
546
565
  });
547
566
 
548
- test("alter column type with collation", () => {
567
+ test("alter column type with collation", async () => {
549
568
  const tableProps: Omit<TableProps, "owner" | "options"> = {
550
569
  schema: "public",
551
570
  name: "test_table",
@@ -589,12 +608,13 @@ describe.concurrent("table", () => {
589
608
  table: withCols,
590
609
  column: col,
591
610
  });
611
+ await assertValidSql(change.serialize());
592
612
  expect(change.serialize()).toBe(
593
613
  "ALTER TABLE public.test_table ALTER COLUMN b TYPE text COLLATE mycoll",
594
614
  );
595
615
  });
596
616
 
597
- test("set default NULL fallback", () => {
617
+ test("set default NULL fallback", async () => {
598
618
  const tableProps: Omit<TableProps, "owner" | "options"> = {
599
619
  schema: "public",
600
620
  name: "test_table",
@@ -638,12 +658,13 @@ describe.concurrent("table", () => {
638
658
  table: withCols,
639
659
  column: col,
640
660
  });
661
+ await assertValidSql(change.serialize());
641
662
  expect(change.serialize()).toBe(
642
663
  "ALTER TABLE public.test_table ALTER COLUMN a SET DEFAULT NULL",
643
664
  );
644
665
  });
645
666
 
646
- test("constraints add/drop/validate and flavors", () => {
667
+ test("constraints add/drop/validate and flavors", async () => {
647
668
  const t = new Table({
648
669
  schema: "public",
649
670
  name: "test_table",
@@ -736,7 +757,7 @@ describe.concurrent("table", () => {
736
757
  ).toBe("ALTER TABLE public.test_table VALIDATE CONSTRAINT pk_t");
737
758
  });
738
759
 
739
- test("attach/detach partition", () => {
760
+ test("attach/detach partition", async () => {
740
761
  const table = new Table({
741
762
  schema: "public",
742
763
  name: "events",
@@ -807,6 +828,7 @@ describe.concurrent("table", () => {
807
828
  table,
808
829
  partition: part2025,
809
830
  });
831
+ await assertValidSql(attach.serialize());
810
832
  expect(attach.serialize()).toBe(
811
833
  "ALTER TABLE public.events ATTACH PARTITION public.events_2025 FOR VALUES FROM ('2025-01-01 00:00:00') TO ('2026-01-01 00:00:00')",
812
834
  );
@@ -815,6 +837,7 @@ describe.concurrent("table", () => {
815
837
  table,
816
838
  partition: part2025,
817
839
  });
840
+ await assertValidSql(detach.serialize());
818
841
  expect(detach.serialize()).toBe(
819
842
  "ALTER TABLE public.events DETACH PARTITION public.events_2025",
820
843
  );
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Table, type TableProps } from "../table.model.ts";
3
4
  import { CreateTable } from "./table.create.ts";
4
5
 
@@ -26,13 +27,14 @@ const base: TableProps = {
26
27
  };
27
28
 
28
29
  describe.concurrent("table.create", () => {
29
- test("minimal create with no columns", () => {
30
+ test("minimal create with no columns", async () => {
30
31
  const t = new Table(base);
31
32
  const change = new CreateTable({ table: t });
33
+ await assertValidSql(change.serialize());
32
34
  expect(change.serialize()).toBe("CREATE TABLE public.t ()");
33
35
  });
34
36
 
35
- test("TEMPORARY with columns, inherits and options", () => {
37
+ test("TEMPORARY with columns, inherits and options", async () => {
36
38
  const t = new Table({
37
39
  ...base,
38
40
  persistence: "t",
@@ -134,17 +136,53 @@ describe.concurrent("table.create", () => {
134
136
  });
135
137
 
136
138
  const change = new CreateTable({ table: t });
139
+ await assertValidSql(change.serialize());
137
140
  expect(change.serialize()).toBe(
138
141
  'CREATE TEMPORARY TABLE public.t (c1 integer DEFAULT 0 NOT NULL, c2 text COLLATE "en_US", c3 integer GENERATED ALWAYS AS IDENTITY, c4 text GENERATED ALWAYS AS (lower((name))) STORED, c5 integer GENERATED BY DEFAULT AS IDENTITY) INHERITS (public.parent) WITH (fillfactor=90, autovacuum_enabled=true)',
139
142
  );
140
143
  });
141
144
 
142
- test("UNLOGGED minimal create (no columns)", () => {
145
+ test("UNLOGGED minimal create (no columns)", async () => {
143
146
  const t = new Table({
144
147
  ...base,
145
148
  persistence: "u",
146
149
  });
147
150
  const change = new CreateTable({ table: t });
151
+ await assertValidSql(change.serialize());
148
152
  expect(change.serialize()).toBe("CREATE UNLOGGED TABLE public.t ()");
149
153
  });
154
+
155
+ test("requires does NOT include procedure stableIds from DEFAULT expressions (handled by pg_depend catalog constraints)", async () => {
156
+ // Function dependencies in DEFAULT expressions are resolved through pg_depend
157
+ // in the sort pipeline, which provides exact argument types and covers all
158
+ // expression contexts. The CreateTable change itself does not need to list them.
159
+ const t = new Table({
160
+ ...base,
161
+ columns: [
162
+ {
163
+ name: "auth_role",
164
+ position: 1,
165
+ data_type: "text",
166
+ data_type_str: "text",
167
+ is_custom_type: false,
168
+ custom_type_type: null,
169
+ custom_type_category: null,
170
+ custom_type_schema: null,
171
+ custom_type_name: null,
172
+ not_null: false,
173
+ is_identity: false,
174
+ is_identity_always: false,
175
+ is_generated: false,
176
+ collation: null,
177
+ default: "auth.role()",
178
+ comment: null,
179
+ },
180
+ ],
181
+ });
182
+ const change = new CreateTable({ table: t });
183
+ const procedureRequires = change.requires.filter((r) =>
184
+ r.startsWith("procedure:"),
185
+ );
186
+ expect(procedureRequires).toEqual([]);
187
+ });
150
188
  });