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

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
@@ -1,10 +1,11 @@
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 { Index } from "../index.model.ts";
4
5
  import { CreateIndex } from "./index.create.ts";
5
6
 
6
7
  describe("index", () => {
7
- test("create", () => {
8
+ test("create", async () => {
8
9
  const index = new Index({
9
10
  schema: "public",
10
11
  table_name: "test_table",
@@ -59,6 +60,8 @@ describe("index", () => {
59
60
 
60
61
  const change = new CreateIndex({ index, indexableObject: { columns } });
61
62
 
63
+ await assertValidSql(change.serialize());
64
+
62
65
  expect(change.serialize()).toBe(
63
66
  "CREATE INDEX test_index ON public.test_table (id)",
64
67
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Index } from "../index.model.ts";
3
4
  import { DropIndex } from "./index.drop.ts";
4
5
 
5
6
  describe("index", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const index = new Index({
8
9
  schema: "public",
9
10
  table_name: "test_table",
@@ -39,6 +40,8 @@ describe("index", () => {
39
40
  index,
40
41
  });
41
42
 
43
+ await assertValidSql(change.serialize());
44
+
42
45
  expect(change.serialize()).toBe("DROP INDEX public.test_index");
43
46
  });
44
47
  });
@@ -1,10 +1,11 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Language, type LanguageProps } from "../language.model.ts";
3
4
  import { AlterLanguageChangeOwner } from "./language.alter.ts";
4
5
 
5
6
  describe.concurrent("language", () => {
6
7
  describe("alter", () => {
7
- test("change owner", () => {
8
+ test("change owner", async () => {
8
9
  const props: Omit<LanguageProps, "owner"> = {
9
10
  name: "plpgsql",
10
11
  is_trusted: true,
@@ -25,6 +26,8 @@ describe.concurrent("language", () => {
25
26
  owner: "new_owner",
26
27
  });
27
28
 
29
+ await assertValidSql(change.serialize());
30
+
28
31
  expect(change.serialize()).toBe(
29
32
  "ALTER LANGUAGE plpgsql OWNER TO new_owner",
30
33
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Language } from "../language.model.ts";
3
4
  import { CreateLanguage } from "./language.create.ts";
4
5
 
5
6
  describe("language", () => {
6
- test("create", () => {
7
+ test("create", async () => {
7
8
  const language = new Language({
8
9
  name: "plpgsql",
9
10
  is_trusted: true,
@@ -20,6 +21,8 @@ describe("language", () => {
20
21
  language,
21
22
  });
22
23
 
24
+ await assertValidSql(change.serialize());
25
+
23
26
  expect(change.serialize()).toBe(
24
27
  "CREATE TRUSTED LANGUAGE plpgsql HANDLER plpgsql_call_handler INLINE plpgsql_inline_handler VALIDATOR plpgsql_validator",
25
28
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { Language } from "../language.model.ts";
3
4
  import { DropLanguage } from "./language.drop.ts";
4
5
 
5
6
  describe("language", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const language = new Language({
8
9
  name: "plpgsql",
9
10
  is_trusted: true,
@@ -20,6 +21,8 @@ describe("language", () => {
20
21
  language,
21
22
  });
22
23
 
24
+ await assertValidSql(change.serialize());
25
+
23
26
  expect(change.serialize()).toBe("DROP LANGUAGE plpgsql");
24
27
  });
25
28
  });
@@ -1,7 +1,17 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import type { ObjectDiffContext } from "../diff-context.ts";
2
3
  import { AlterLanguageChangeOwner } from "./changes/language.alter.ts";
4
+ import {
5
+ CreateCommentOnLanguage,
6
+ DropCommentOnLanguage,
7
+ } from "./changes/language.comment.ts";
3
8
  import { CreateLanguage } from "./changes/language.create.ts";
4
9
  import { DropLanguage } from "./changes/language.drop.ts";
10
+ import {
11
+ GrantLanguagePrivileges,
12
+ RevokeGrantOptionLanguagePrivileges,
13
+ RevokeLanguagePrivileges,
14
+ } from "./changes/language.privilege.ts";
5
15
  import { diffLanguages } from "./language.diff.ts";
6
16
  import { Language, type LanguageProps } from "./language.model.ts";
7
17
 
@@ -17,13 +27,24 @@ const base: LanguageProps = {
17
27
  privileges: [],
18
28
  };
19
29
 
30
+ const makeLanguage = (override: Partial<LanguageProps> = {}) =>
31
+ new Language({
32
+ ...base,
33
+ ...override,
34
+ privileges: override.privileges ?? [...base.privileges],
35
+ });
36
+
37
+ const ctx: Pick<ObjectDiffContext, "version"> = {
38
+ version: 170000,
39
+ };
40
+
20
41
  describe.concurrent("language.diff", () => {
21
42
  test("create and drop", () => {
22
43
  const l = new Language(base);
23
- const created = diffLanguages({ version: 170000 }, {}, { [l.stableId]: l });
44
+ const created = diffLanguages(ctx, {}, { [l.stableId]: l });
24
45
  expect(created[0]).toBeInstanceOf(CreateLanguage);
25
46
 
26
- const dropped = diffLanguages({ version: 170000 }, { [l.stableId]: l }, {});
47
+ const dropped = diffLanguages(ctx, { [l.stableId]: l }, {});
27
48
  expect(dropped[0]).toBeInstanceOf(DropLanguage);
28
49
  });
29
50
 
@@ -31,7 +52,7 @@ describe.concurrent("language.diff", () => {
31
52
  const main = new Language(base);
32
53
  const branch = new Language({ ...base, owner: "o2" });
33
54
  const changes = diffLanguages(
34
- { version: 170000 },
55
+ ctx,
35
56
  { [main.stableId]: main },
36
57
  { [branch.stableId]: branch },
37
58
  );
@@ -42,7 +63,7 @@ describe.concurrent("language.diff", () => {
42
63
  const main = new Language(base);
43
64
  const branch = new Language({ ...base, call_handler: "handler()" });
44
65
  const changes = diffLanguages(
45
- { version: 170000 },
66
+ ctx,
46
67
  { [main.stableId]: main },
47
68
  { [branch.stableId]: branch },
48
69
  );
@@ -50,4 +71,65 @@ describe.concurrent("language.diff", () => {
50
71
  expect(changes[0]).toBeInstanceOf(DropLanguage);
51
72
  expect(changes[1]).toBeInstanceOf(CreateLanguage);
52
73
  });
74
+
75
+ test("create with comment emits create comment change", () => {
76
+ const l = makeLanguage({ comment: "my language" });
77
+ const changes = diffLanguages(ctx, {}, { [l.stableId]: l });
78
+ expect(changes[0]).toBeInstanceOf(CreateLanguage);
79
+ expect(changes.some((c) => c instanceof CreateCommentOnLanguage)).toBe(
80
+ true,
81
+ );
82
+ });
83
+
84
+ test("comment changes emit create/drop comment statements", () => {
85
+ const main = makeLanguage();
86
+ const withComment = makeLanguage({ comment: "lang comment" });
87
+
88
+ const addComment = diffLanguages(
89
+ ctx,
90
+ { [main.stableId]: main },
91
+ { [withComment.stableId]: withComment },
92
+ );
93
+ expect(addComment[0]).toBeInstanceOf(CreateCommentOnLanguage);
94
+
95
+ const dropComment = diffLanguages(
96
+ ctx,
97
+ { [withComment.stableId]: withComment },
98
+ { [main.stableId]: main },
99
+ );
100
+ expect(dropComment[0]).toBeInstanceOf(DropCommentOnLanguage);
101
+ });
102
+
103
+ test("privilege diffs emit grant, revoke, and revoke grant option statements", () => {
104
+ const main = makeLanguage({
105
+ privileges: [
106
+ { grantee: "role_usage", privilege: "USAGE", grantable: false },
107
+ { grantee: "role_with_option", privilege: "USAGE", grantable: true },
108
+ { grantee: "role_removed", privilege: "USAGE", grantable: false },
109
+ ],
110
+ });
111
+ const branch = makeLanguage({
112
+ privileges: [
113
+ { grantee: "role_usage", privilege: "USAGE", grantable: true },
114
+ { grantee: "role_with_option", privilege: "USAGE", grantable: false },
115
+ { grantee: "role_new", privilege: "USAGE", grantable: false },
116
+ ],
117
+ });
118
+
119
+ const changes = diffLanguages(
120
+ ctx,
121
+ { [main.stableId]: main },
122
+ { [branch.stableId]: branch },
123
+ );
124
+
125
+ expect(changes.some((c) => c instanceof GrantLanguagePrivileges)).toBe(
126
+ true,
127
+ );
128
+ expect(changes.some((c) => c instanceof RevokeLanguagePrivileges)).toBe(
129
+ true,
130
+ );
131
+ expect(
132
+ changes.some((c) => c instanceof RevokeGrantOptionLanguagePrivileges),
133
+ ).toBe(true);
134
+ });
53
135
  });
@@ -2,10 +2,10 @@ import type { Change } from "../../change.types.ts";
2
2
  import { diffObjects } from "../base.diff.ts";
3
3
  import {
4
4
  diffPrivileges,
5
+ emitObjectPrivilegeChanges,
5
6
  filterPublicBuiltInDefaults,
6
- groupPrivilegesByGrantable,
7
7
  } from "../base.privilege-diff.ts";
8
- import type { Role } from "../role/role.model.ts";
8
+ import type { ObjectDiffContext } from "../diff-context.ts";
9
9
  import { hasNonAlterableChanges } from "../utils.ts";
10
10
  import { AlterLanguageChangeOwner } from "./changes/language.alter.ts";
11
11
  import {
@@ -30,7 +30,7 @@ import type { Language } from "./language.model.ts";
30
30
  * @returns A list of changes to apply to main to make it match branch.
31
31
  */
32
32
  export function diffLanguages(
33
- ctx: { version: number; mainRoles?: Record<string, Role> },
33
+ ctx: Pick<ObjectDiffContext, "version">,
34
34
  main: Record<string, Language>,
35
35
  branch: Record<string, Language>,
36
36
  ): Change[] {
@@ -121,54 +121,22 @@ export function diffLanguages(
121
121
  mainPrivilegesFiltered,
122
122
  branchPrivilegesFiltered,
123
123
  branchLanguage.owner,
124
- ctx.mainRoles,
125
124
  );
126
125
 
127
- for (const [grantee, result] of privilegeResults) {
128
- // Generate grant changes
129
- if (result.grants.length > 0) {
130
- const grantGroups = groupPrivilegesByGrantable(result.grants);
131
- for (const [grantable, list] of grantGroups) {
132
- void grantable;
133
- changes.push(
134
- new GrantLanguagePrivileges({
135
- language: branchLanguage,
136
- grantee,
137
- privileges: list,
138
- version: ctx.version,
139
- }),
140
- );
141
- }
142
- }
143
-
144
- // Generate revoke changes
145
- if (result.revokes.length > 0) {
146
- const revokeGroups = groupPrivilegesByGrantable(result.revokes);
147
- for (const [grantable, list] of revokeGroups) {
148
- void grantable;
149
- changes.push(
150
- new RevokeLanguagePrivileges({
151
- language: mainLanguage,
152
- grantee,
153
- privileges: list,
154
- version: ctx.version,
155
- }),
156
- );
157
- }
158
- }
159
-
160
- // Generate revoke grant option changes
161
- if (result.revokeGrantOption.length > 0) {
162
- changes.push(
163
- new RevokeGrantOptionLanguagePrivileges({
164
- language: mainLanguage,
165
- grantee,
166
- privilegeNames: result.revokeGrantOption,
167
- version: ctx.version,
168
- }),
169
- );
170
- }
171
- }
126
+ changes.push(
127
+ ...(emitObjectPrivilegeChanges(
128
+ privilegeResults,
129
+ branchLanguage,
130
+ mainLanguage,
131
+ "language",
132
+ {
133
+ Grant: GrantLanguagePrivileges,
134
+ Revoke: RevokeLanguagePrivileges,
135
+ RevokeGrantOption: RevokeGrantOptionLanguagePrivileges,
136
+ },
137
+ ctx.version,
138
+ ) as Change[]),
139
+ );
172
140
  }
173
141
  }
174
142
 
@@ -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 {
3
4
  MaterializedView,
4
5
  type MaterializedViewProps,
@@ -10,7 +11,7 @@ import {
10
11
 
11
12
  describe.concurrent("materialized-view", () => {
12
13
  describe("alter", () => {
13
- test("change owner", () => {
14
+ test("change owner", async () => {
14
15
  const props: Omit<MaterializedViewProps, "owner"> = {
15
16
  schema: "public",
16
17
  name: "test_mv",
@@ -40,12 +41,14 @@ describe.concurrent("materialized-view", () => {
40
41
  owner: "new_owner",
41
42
  });
42
43
 
44
+ await assertValidSql(change.serialize());
45
+
43
46
  expect(change.serialize()).toBe(
44
47
  "ALTER MATERIALIZED VIEW public.test_mv OWNER TO new_owner",
45
48
  );
46
49
  });
47
50
 
48
- test("set storage params", () => {
51
+ test("set storage params", async () => {
49
52
  const props: Omit<MaterializedViewProps, "options"> = {
50
53
  schema: "public",
51
54
  name: "test_mv",
@@ -76,12 +79,14 @@ describe.concurrent("materialized-view", () => {
76
79
  keysToReset: [],
77
80
  });
78
81
 
82
+ await assertValidSql(change.serialize());
83
+
79
84
  expect(change.serialize()).toBe(
80
85
  "ALTER MATERIALIZED VIEW public.test_mv SET (fillfactor=90)",
81
86
  );
82
87
  });
83
88
 
84
- test("reset and set storage params", () => {
89
+ test("reset and set storage params", async () => {
85
90
  const props: Omit<MaterializedViewProps, "options"> = {
86
91
  schema: "public",
87
92
  name: "test_mv",
@@ -112,6 +117,8 @@ describe.concurrent("materialized-view", () => {
112
117
  keysToReset: ["autovacuum_enabled"],
113
118
  });
114
119
 
120
+ await assertValidSql(change.serialize());
121
+
115
122
  expect(change.serialize()).toBe(
116
123
  [
117
124
  "ALTER MATERIALIZED VIEW public.test_mv RESET (autovacuum_enabled)",
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { MaterializedView } from "../materialized-view.model.ts";
3
4
  import { CreateMaterializedView } from "./materialized-view.create.ts";
4
5
 
5
6
  describe("materialized-view", () => {
6
- test("create minimal", () => {
7
+ test("create minimal", async () => {
7
8
  const mv = new MaterializedView({
8
9
  schema: "public",
9
10
  name: "test_mv",
@@ -28,12 +29,14 @@ describe("materialized-view", () => {
28
29
 
29
30
  const change = new CreateMaterializedView({ materializedView: mv });
30
31
 
32
+ await assertValidSql(change.serialize());
33
+
31
34
  expect(change.serialize()).toBe(
32
35
  "CREATE MATERIALIZED VIEW public.test_mv AS SELECT * FROM test_table WITH NO DATA",
33
36
  );
34
37
  });
35
38
 
36
- test("create with all options", () => {
39
+ test("create with all options", async () => {
37
40
  const mv = new MaterializedView({
38
41
  schema: "public",
39
42
  name: "test_mv",
@@ -57,6 +60,8 @@ describe("materialized-view", () => {
57
60
 
58
61
  const change = new CreateMaterializedView({ materializedView: mv });
59
62
 
63
+ await assertValidSql(change.serialize());
64
+
60
65
  expect(change.serialize()).toBe(
61
66
  "CREATE MATERIALIZED VIEW public.test_mv WITH (fillfactor=90, autovacuum_enabled=false) AS SELECT * FROM test_table WITH DATA",
62
67
  );
@@ -1,9 +1,10 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { assertValidSql } from "../../../test-utils/assert-valid-sql.ts";
2
3
  import { MaterializedView } from "../materialized-view.model.ts";
3
4
  import { DropMaterializedView } from "./materialized-view.drop.ts";
4
5
 
5
6
  describe("materialized-view", () => {
6
- test("drop", () => {
7
+ test("drop", async () => {
7
8
  const materializedView = new MaterializedView({
8
9
  schema: "public",
9
10
  name: "test_mv",
@@ -29,6 +30,8 @@ describe("materialized-view", () => {
29
30
  materializedView,
30
31
  });
31
32
 
33
+ await assertValidSql(change.serialize());
34
+
32
35
  expect(change.serialize()).toBe("DROP MATERIALIZED VIEW public.test_mv");
33
36
  });
34
37
  });
@@ -4,8 +4,19 @@ import {
4
4
  AlterMaterializedViewChangeOwner,
5
5
  AlterMaterializedViewSetStorageParams,
6
6
  } from "./changes/materialized-view.alter.ts";
7
+ import {
8
+ CreateCommentOnMaterializedView,
9
+ CreateCommentOnMaterializedViewColumn,
10
+ DropCommentOnMaterializedView,
11
+ DropCommentOnMaterializedViewColumn,
12
+ } from "./changes/materialized-view.comment.ts";
7
13
  import { CreateMaterializedView } from "./changes/materialized-view.create.ts";
8
14
  import { DropMaterializedView } from "./changes/materialized-view.drop.ts";
15
+ import {
16
+ GrantMaterializedViewPrivileges,
17
+ RevokeGrantOptionMaterializedViewPrivileges,
18
+ RevokeMaterializedViewPrivileges,
19
+ } from "./changes/materialized-view.privilege.ts";
9
20
  import { diffMaterializedViews } from "./materialized-view.diff.ts";
10
21
  import {
11
22
  MaterializedView,
@@ -33,6 +44,33 @@ const base: MaterializedViewProps = {
33
44
  privileges: [],
34
45
  };
35
46
 
47
+ const baseColumn = {
48
+ name: "id",
49
+ position: 1,
50
+ data_type: "integer",
51
+ data_type_str: "integer",
52
+ is_custom_type: false,
53
+ custom_type_type: null,
54
+ custom_type_category: null,
55
+ custom_type_schema: null,
56
+ custom_type_name: null,
57
+ not_null: false,
58
+ is_identity: false,
59
+ is_identity_always: false,
60
+ is_generated: false,
61
+ collation: null,
62
+ default: null,
63
+ comment: null,
64
+ };
65
+
66
+ const makeMaterializedView = (override: Partial<MaterializedViewProps> = {}) =>
67
+ new MaterializedView({
68
+ ...base,
69
+ ...override,
70
+ privileges: override.privileges ?? [...base.privileges],
71
+ columns: override.columns ?? [...base.columns],
72
+ });
73
+
36
74
  const testContext = {
37
75
  version: 170000,
38
76
  currentUser: "postgres",
@@ -99,4 +137,128 @@ describe.concurrent("materialized-view.diff", () => {
99
137
  changes.some((c) => c instanceof AlterMaterializedViewSetStorageParams),
100
138
  ).toBe(true);
101
139
  });
140
+
141
+ test("create with comment and column comments", () => {
142
+ const mv = makeMaterializedView({
143
+ comment: "my matview",
144
+ columns: [
145
+ { ...baseColumn, comment: "id column" },
146
+ { ...baseColumn, name: "val", position: 2, comment: null },
147
+ ],
148
+ });
149
+ const changes = diffMaterializedViews(
150
+ testContext,
151
+ {},
152
+ { [mv.stableId]: mv },
153
+ );
154
+ expect(changes[0]).toBeInstanceOf(CreateMaterializedView);
155
+ expect(
156
+ changes.some((c) => c instanceof CreateCommentOnMaterializedView),
157
+ ).toBe(true);
158
+ expect(
159
+ changes.some((c) => c instanceof CreateCommentOnMaterializedViewColumn),
160
+ ).toBe(true);
161
+ });
162
+
163
+ test("create with privileges emits grant changes", () => {
164
+ const mv = makeMaterializedView({
165
+ privileges: [
166
+ { grantee: "role_select", privilege: "SELECT", grantable: false },
167
+ ],
168
+ });
169
+ const changes = diffMaterializedViews(
170
+ testContext,
171
+ {},
172
+ { [mv.stableId]: mv },
173
+ );
174
+ expect(changes[0]).toBeInstanceOf(CreateMaterializedView);
175
+ expect(
176
+ changes.some((c) => c instanceof GrantMaterializedViewPrivileges),
177
+ ).toBe(true);
178
+ });
179
+
180
+ test("comment changes emit create/drop comment statements", () => {
181
+ const main = makeMaterializedView();
182
+ const withComment = makeMaterializedView({ comment: "matview comment" });
183
+
184
+ const addComment = diffMaterializedViews(
185
+ testContext,
186
+ { [main.stableId]: main },
187
+ { [withComment.stableId]: withComment },
188
+ );
189
+ expect(addComment[0]).toBeInstanceOf(CreateCommentOnMaterializedView);
190
+
191
+ const dropComment = diffMaterializedViews(
192
+ testContext,
193
+ { [withComment.stableId]: withComment },
194
+ { [main.stableId]: main },
195
+ );
196
+ expect(dropComment[0]).toBeInstanceOf(DropCommentOnMaterializedView);
197
+ });
198
+
199
+ test("column comment changes emit create/drop column comment statements", () => {
200
+ const main = makeMaterializedView({
201
+ columns: [{ ...baseColumn, comment: null }],
202
+ });
203
+ const withColComment = makeMaterializedView({
204
+ columns: [{ ...baseColumn, comment: "id column" }],
205
+ });
206
+
207
+ const addColComment = diffMaterializedViews(
208
+ testContext,
209
+ { [main.stableId]: main },
210
+ { [withColComment.stableId]: withColComment },
211
+ );
212
+ expect(
213
+ addColComment.some(
214
+ (c) => c instanceof CreateCommentOnMaterializedViewColumn,
215
+ ),
216
+ ).toBe(true);
217
+
218
+ const dropColComment = diffMaterializedViews(
219
+ testContext,
220
+ { [withColComment.stableId]: withColComment },
221
+ { [main.stableId]: main },
222
+ );
223
+ expect(
224
+ dropColComment.some(
225
+ (c) => c instanceof DropCommentOnMaterializedViewColumn,
226
+ ),
227
+ ).toBe(true);
228
+ });
229
+
230
+ test("privilege diffs emit grant, revoke, and revoke grant option statements", () => {
231
+ const main = makeMaterializedView({
232
+ privileges: [
233
+ { grantee: "role_select", privilege: "SELECT", grantable: false },
234
+ { grantee: "role_with_option", privilege: "SELECT", grantable: true },
235
+ { grantee: "role_removed", privilege: "SELECT", grantable: false },
236
+ ],
237
+ });
238
+ const branch = makeMaterializedView({
239
+ privileges: [
240
+ { grantee: "role_select", privilege: "SELECT", grantable: true },
241
+ { grantee: "role_with_option", privilege: "SELECT", grantable: false },
242
+ { grantee: "role_new", privilege: "SELECT", grantable: false },
243
+ ],
244
+ });
245
+
246
+ const changes = diffMaterializedViews(
247
+ testContext,
248
+ { [main.stableId]: main },
249
+ { [branch.stableId]: branch },
250
+ );
251
+
252
+ expect(
253
+ changes.some((c) => c instanceof GrantMaterializedViewPrivileges),
254
+ ).toBe(true);
255
+ expect(
256
+ changes.some((c) => c instanceof RevokeMaterializedViewPrivileges),
257
+ ).toBe(true);
258
+ expect(
259
+ changes.some(
260
+ (c) => c instanceof RevokeGrantOptionMaterializedViewPrivileges,
261
+ ),
262
+ ).toBe(true);
263
+ });
102
264
  });