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

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 (464) hide show
  1. package/README.md +22 -0
  2. package/dist/cli/bin/cli.js +0 -0
  3. package/dist/cli/commands/plan.js +21 -0
  4. package/dist/cli/utils.d.ts +2 -0
  5. package/dist/cli/utils.js +1 -1
  6. package/dist/core/integrations/supabase.js +2 -0
  7. package/dist/core/objects/table/table.model.d.ts +4 -2
  8. package/dist/core/objects/table/table.model.js +3 -0
  9. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  10. package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
  11. package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
  12. package/dist/core/objects/trigger/trigger.model.js +3 -0
  13. package/dist/core/plan/apply.js +3 -3
  14. package/dist/core/plan/create.js +34 -15
  15. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  16. package/dist/core/plan/sql-format/constants.js +11 -0
  17. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  18. package/dist/core/plan/sql-format/fixtures.js +2449 -0
  19. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  20. package/dist/core/plan/sql-format/format-utils.js +274 -0
  21. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  22. package/dist/core/plan/sql-format/formatters.js +737 -0
  23. package/dist/core/plan/sql-format/index.d.ts +2 -0
  24. package/dist/core/plan/sql-format/index.js +98 -0
  25. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  26. package/dist/core/plan/sql-format/keyword-case.js +868 -0
  27. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  28. package/dist/core/plan/sql-format/protect.js +269 -0
  29. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  30. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  31. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  32. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  33. package/dist/core/plan/sql-format/types.d.ts +28 -0
  34. package/dist/core/plan/sql-format/types.js +1 -0
  35. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  36. package/dist/core/plan/sql-format/wrap.js +165 -0
  37. package/dist/core/plan/sql-format.d.ts +2 -0
  38. package/dist/core/plan/sql-format.js +1 -0
  39. package/dist/core/plan/statements.d.ts +2 -1
  40. package/dist/core/plan/statements.js +6 -2
  41. package/dist/core/postgres-config.d.ts +15 -0
  42. package/dist/core/postgres-config.js +30 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.js +1 -0
  45. package/package.json +37 -22
  46. package/src/cli/app.ts +28 -0
  47. package/src/cli/bin/cli.ts +9 -0
  48. package/src/cli/commands/apply.ts +101 -0
  49. package/src/cli/commands/plan.ts +195 -0
  50. package/src/cli/commands/sync.ts +185 -0
  51. package/src/cli/formatters/index.ts +5 -0
  52. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  53. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  54. package/src/cli/formatters/tree/tree.ts +237 -0
  55. package/src/cli/utils/integrations.ts +42 -0
  56. package/src/cli/utils.ts +231 -0
  57. package/src/core/catalog.diff.ts +246 -0
  58. package/src/core/catalog.model.ts +384 -0
  59. package/src/core/change.types.ts +44 -0
  60. package/src/core/context.ts +26 -0
  61. package/src/core/depend.ts +1870 -0
  62. package/src/core/expand-replace-dependencies.ts +380 -0
  63. package/src/core/fingerprint.ts +204 -0
  64. package/src/core/integrations/filter/dsl.ts +204 -0
  65. package/src/core/integrations/filter/extractors.ts +145 -0
  66. package/src/core/integrations/filter/filter.types.ts +3 -0
  67. package/src/core/integrations/integration-dsl.ts +24 -0
  68. package/src/core/integrations/integration.types.ts +7 -0
  69. package/src/core/integrations/serialize/dsl.ts +77 -0
  70. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  71. package/src/core/integrations/supabase.ts +121 -0
  72. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  73. package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
  74. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  75. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
  76. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  77. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  78. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
  79. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  80. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
  81. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  82. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
  83. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  84. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
  85. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  86. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  87. package/src/core/objects/base.change.ts +62 -0
  88. package/src/core/objects/base.default-privileges.ts +204 -0
  89. package/src/core/objects/base.diff.ts +20 -0
  90. package/src/core/objects/base.model.ts +82 -0
  91. package/src/core/objects/base.privilege-diff.ts +299 -0
  92. package/src/core/objects/base.privilege.ts +184 -0
  93. package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
  94. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  95. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  96. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  97. package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
  98. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  99. package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
  100. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  101. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  102. package/src/core/objects/collation/collation.diff.test.ts +100 -0
  103. package/src/core/objects/collation/collation.diff.ts +126 -0
  104. package/src/core/objects/collation/collation.model.ts +224 -0
  105. package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
  106. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  107. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  108. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  109. package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
  110. package/src/core/objects/domain/changes/domain.create.ts +118 -0
  111. package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
  112. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  113. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  114. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  115. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  116. package/src/core/objects/domain/domain.diff.ts +358 -0
  117. package/src/core/objects/domain/domain.model.ts +190 -0
  118. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
  119. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  120. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  121. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  122. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
  123. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  124. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
  125. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  126. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  127. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
  128. package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
  129. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  130. package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
  131. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  132. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  133. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  134. package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
  135. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  136. package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
  137. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  138. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  139. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  140. package/src/core/objects/extension/extension.diff.ts +90 -0
  141. package/src/core/objects/extension/extension.model.ts +280 -0
  142. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
  143. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  144. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  145. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  146. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
  147. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
  149. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  151. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  152. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
  153. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
  154. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  155. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  156. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
  157. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  158. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  159. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  160. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
  161. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  162. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
  163. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  164. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  165. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  166. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  167. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
  168. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  169. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
  170. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  171. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  172. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  173. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
  174. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  175. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
  176. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  177. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  178. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  179. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
  180. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
  181. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  182. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
  183. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  184. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  185. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
  186. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  187. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
  188. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  189. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  190. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  191. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  192. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  193. package/src/core/objects/index/changes/index.alter.test.ts +200 -0
  194. package/src/core/objects/index/changes/index.alter.ts +144 -0
  195. package/src/core/objects/index/changes/index.base.ts +20 -0
  196. package/src/core/objects/index/changes/index.comment.ts +63 -0
  197. package/src/core/objects/index/changes/index.create.test.ts +66 -0
  198. package/src/core/objects/index/changes/index.create.ts +68 -0
  199. package/src/core/objects/index/changes/index.drop.test.ts +44 -0
  200. package/src/core/objects/index/changes/index.drop.ts +34 -0
  201. package/src/core/objects/index/changes/index.types.ts +6 -0
  202. package/src/core/objects/index/changes/utils.ts +16 -0
  203. package/src/core/objects/index/index.diff.test.ts +153 -0
  204. package/src/core/objects/index/index.diff.ts +243 -0
  205. package/src/core/objects/index/index.model.ts +370 -0
  206. package/src/core/objects/language/changes/language.alter.test.ts +33 -0
  207. package/src/core/objects/language/changes/language.alter.ts +53 -0
  208. package/src/core/objects/language/changes/language.base.ts +20 -0
  209. package/src/core/objects/language/changes/language.comment.ts +58 -0
  210. package/src/core/objects/language/changes/language.create.test.ts +27 -0
  211. package/src/core/objects/language/changes/language.create.ts +104 -0
  212. package/src/core/objects/language/changes/language.drop.test.ts +25 -0
  213. package/src/core/objects/language/changes/language.drop.ts +39 -0
  214. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  215. package/src/core/objects/language/changes/language.types.ts +12 -0
  216. package/src/core/objects/language/language.diff.test.ts +53 -0
  217. package/src/core/objects/language/language.diff.ts +176 -0
  218. package/src/core/objects/language/language.model.ts +150 -0
  219. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
  220. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  221. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  222. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  223. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
  224. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  225. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
  226. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  227. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  228. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  229. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
  230. package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
  231. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  232. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
  233. package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
  234. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  235. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  236. package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
  237. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  238. package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
  239. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  240. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  241. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  242. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  243. package/src/core/objects/procedure/procedure.diff.ts +404 -0
  244. package/src/core/objects/procedure/procedure.model.ts +264 -0
  245. package/src/core/objects/procedure/utils.ts +58 -0
  246. package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
  247. package/src/core/objects/publication/changes/publication.alter.ts +243 -0
  248. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  249. package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
  250. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  251. package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
  252. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  253. package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
  254. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  255. package/src/core/objects/publication/changes/publication.types.ts +26 -0
  256. package/src/core/objects/publication/publication.diff.test.ts +292 -0
  257. package/src/core/objects/publication/publication.diff.ts +253 -0
  258. package/src/core/objects/publication/publication.model.ts +206 -0
  259. package/src/core/objects/publication/utils.ts +55 -0
  260. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
  261. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  262. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  263. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  264. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
  265. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  266. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
  267. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  268. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  269. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  270. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  271. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  272. package/src/core/objects/role/changes/role.alter.test.ts +346 -0
  273. package/src/core/objects/role/changes/role.alter.ts +110 -0
  274. package/src/core/objects/role/changes/role.base.ts +24 -0
  275. package/src/core/objects/role/changes/role.comment.ts +55 -0
  276. package/src/core/objects/role/changes/role.create.test.ts +52 -0
  277. package/src/core/objects/role/changes/role.create.ts +102 -0
  278. package/src/core/objects/role/changes/role.drop.test.ts +29 -0
  279. package/src/core/objects/role/changes/role.drop.ts +34 -0
  280. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  281. package/src/core/objects/role/changes/role.types.ts +12 -0
  282. package/src/core/objects/role/role.diff.test.ts +44 -0
  283. package/src/core/objects/role/role.diff.ts +479 -0
  284. package/src/core/objects/role/role.model.ts +344 -0
  285. package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
  286. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  287. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  288. package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
  289. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  290. package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
  291. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  292. package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
  293. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  294. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  295. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  296. package/src/core/objects/rule/rule.diff.ts +79 -0
  297. package/src/core/objects/rule/rule.model.ts +173 -0
  298. package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
  299. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  300. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  301. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  302. package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
  303. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  304. package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
  305. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  306. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  307. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  308. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  309. package/src/core/objects/schema/schema.diff.ts +209 -0
  310. package/src/core/objects/schema/schema.model.ts +107 -0
  311. package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
  312. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  313. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  314. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  315. package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
  316. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  317. package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
  318. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  319. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  320. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  321. package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
  322. package/src/core/objects/sequence/sequence.diff.ts +359 -0
  323. package/src/core/objects/sequence/sequence.model.ts +185 -0
  324. package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
  325. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  326. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  327. package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
  328. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  329. package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
  330. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  331. package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
  332. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  333. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  334. package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
  335. package/src/core/objects/subscription/subscription.diff.ts +241 -0
  336. package/src/core/objects/subscription/subscription.model.ts +190 -0
  337. package/src/core/objects/subscription/utils.ts +156 -0
  338. package/src/core/objects/table/changes/table.alter.test.ts +823 -0
  339. package/src/core/objects/table/changes/table.alter.ts +806 -0
  340. package/src/core/objects/table/changes/table.base.ts +20 -0
  341. package/src/core/objects/table/changes/table.comment.ts +266 -0
  342. package/src/core/objects/table/changes/table.create.test.ts +150 -0
  343. package/src/core/objects/table/changes/table.create.ts +188 -0
  344. package/src/core/objects/table/changes/table.drop.test.ts +34 -0
  345. package/src/core/objects/table/changes/table.drop.ts +45 -0
  346. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  347. package/src/core/objects/table/changes/table.types.ts +12 -0
  348. package/src/core/objects/table/table.diff.test.ts +711 -0
  349. package/src/core/objects/table/table.diff.ts +953 -0
  350. package/src/core/objects/table/table.model.ts +460 -0
  351. package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
  352. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  353. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  354. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  355. package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
  356. package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
  357. package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
  358. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  359. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  360. package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
  361. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  362. package/src/core/objects/trigger/trigger.model.ts +252 -0
  363. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
  364. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  365. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  366. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  367. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
  368. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  369. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
  370. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  371. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  372. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  373. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
  374. package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
  375. package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
  376. package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
  377. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  378. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  379. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  380. package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
  381. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  382. package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
  383. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  384. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  385. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  386. package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
  387. package/src/core/objects/type/enum/enum.diff.ts +396 -0
  388. package/src/core/objects/type/enum/enum.model.ts +194 -0
  389. package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
  390. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  391. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  392. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  393. package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
  394. package/src/core/objects/type/range/changes/range.create.ts +151 -0
  395. package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
  396. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  397. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  398. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  399. package/src/core/objects/type/range/range.diff.test.ts +70 -0
  400. package/src/core/objects/type/range/range.diff.ts +259 -0
  401. package/src/core/objects/type/range/range.model.ts +187 -0
  402. package/src/core/objects/type/type.types.ts +5 -0
  403. package/src/core/objects/utils.ts +171 -0
  404. package/src/core/objects/view/changes/view.alter.test.ts +110 -0
  405. package/src/core/objects/view/changes/view.alter.ts +112 -0
  406. package/src/core/objects/view/changes/view.base.ts +20 -0
  407. package/src/core/objects/view/changes/view.comment.ts +59 -0
  408. package/src/core/objects/view/changes/view.create.test.ts +65 -0
  409. package/src/core/objects/view/changes/view.create.ts +73 -0
  410. package/src/core/objects/view/changes/view.drop.test.ts +34 -0
  411. package/src/core/objects/view/changes/view.drop.ts +40 -0
  412. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  413. package/src/core/objects/view/changes/view.types.ts +12 -0
  414. package/src/core/objects/view/view.diff.test.ts +91 -0
  415. package/src/core/objects/view/view.diff.ts +365 -0
  416. package/src/core/objects/view/view.model.ts +276 -0
  417. package/src/core/plan/apply.ts +190 -0
  418. package/src/core/plan/create.ts +432 -0
  419. package/src/core/plan/hierarchy.ts +574 -0
  420. package/src/core/plan/index.ts +29 -0
  421. package/src/core/plan/io.ts +20 -0
  422. package/src/core/plan/risk.ts +48 -0
  423. package/src/core/plan/serialize.ts +195 -0
  424. package/src/core/plan/sql-format/constants.ts +13 -0
  425. package/src/core/plan/sql-format/fixtures.ts +2806 -0
  426. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  427. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  428. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
  429. package/src/core/plan/sql-format/format-off.test.ts +809 -0
  430. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
  431. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
  432. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
  433. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
  434. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  435. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  436. package/src/core/plan/sql-format/format-utils.ts +391 -0
  437. package/src/core/plan/sql-format/formatters.ts +921 -0
  438. package/src/core/plan/sql-format/index.ts +149 -0
  439. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  440. package/src/core/plan/sql-format/keyword-case.ts +1085 -0
  441. package/src/core/plan/sql-format/protect.test.ts +127 -0
  442. package/src/core/plan/sql-format/protect.ts +337 -0
  443. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  444. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  445. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  446. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  447. package/src/core/plan/sql-format/types.ts +31 -0
  448. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  449. package/src/core/plan/sql-format/wrap.ts +196 -0
  450. package/src/core/plan/sql-format.ts +2 -0
  451. package/src/core/plan/statements.ts +22 -0
  452. package/src/core/plan/types.ts +165 -0
  453. package/src/core/postgres-config.ts +169 -0
  454. package/src/core/sort/custom-constraints.ts +161 -0
  455. package/src/core/sort/debug-visualization.ts +239 -0
  456. package/src/core/sort/dependency-filter.ts +224 -0
  457. package/src/core/sort/graph-builder.ts +223 -0
  458. package/src/core/sort/graph-utils.ts +51 -0
  459. package/src/core/sort/logical-sort.ts +590 -0
  460. package/src/core/sort/sort-changes.ts +234 -0
  461. package/src/core/sort/topological-sort.ts +184 -0
  462. package/src/core/sort/types.ts +112 -0
  463. package/src/core/sort/utils.ts +69 -0
  464. package/src/index.ts +14 -0
@@ -0,0 +1,179 @@
1
+ import {
2
+ formatObjectPrivilegeList,
3
+ getObjectKindPrefix,
4
+ } from "../../base.privilege.ts";
5
+ import { stableId } from "../../utils.ts";
6
+ import type { Sequence } from "../sequence.model.ts";
7
+ import { AlterSequenceChange } from "./sequence.base.ts";
8
+
9
+ export type SequencePrivilege =
10
+ | GrantSequencePrivileges
11
+ | RevokeSequencePrivileges
12
+ | RevokeGrantOptionSequencePrivileges;
13
+
14
+ /**
15
+ * Grant privileges on a sequence.
16
+ *
17
+ * @see https://www.postgresql.org/docs/17/sql-grant.html
18
+ *
19
+ * Synopsis
20
+ * ```sql
21
+ * GRANT { { USAGE | SELECT | UPDATE }
22
+ * [, ...] | ALL [ PRIVILEGES ] }
23
+ * ON { SEQUENCE sequence_name [, ...]
24
+ * | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
25
+ * TO role_specification [, ...] [ WITH GRANT OPTION ]
26
+ * [ GRANTED BY role_specification ]
27
+ * ```
28
+ */
29
+ export class GrantSequencePrivileges extends AlterSequenceChange {
30
+ public readonly sequence: Sequence;
31
+ public readonly grantee: string;
32
+ public readonly privileges: { privilege: string; grantable: boolean }[];
33
+ public readonly version: number | undefined;
34
+ public readonly scope = "privilege" as const;
35
+
36
+ constructor(props: {
37
+ sequence: Sequence;
38
+ grantee: string;
39
+ privileges: { privilege: string; grantable: boolean }[];
40
+ version?: number;
41
+ }) {
42
+ super();
43
+ this.sequence = props.sequence;
44
+ this.grantee = props.grantee;
45
+ this.privileges = props.privileges;
46
+ this.version = props.version;
47
+ }
48
+
49
+ get creates() {
50
+ return [stableId.acl(this.sequence.stableId, this.grantee)];
51
+ }
52
+
53
+ get requires() {
54
+ return [this.sequence.stableId, stableId.role(this.grantee)];
55
+ }
56
+
57
+ serialize(): string {
58
+ const hasGrantable = this.privileges.some((p) => p.grantable);
59
+ const hasBase = this.privileges.some((p) => !p.grantable);
60
+ if (hasGrantable && hasBase) {
61
+ throw new Error(
62
+ "GrantSequencePrivileges expects privileges with uniform grantable flag",
63
+ );
64
+ }
65
+ const withGrant = hasGrantable ? " WITH GRANT OPTION" : "";
66
+ const kindPrefix = getObjectKindPrefix("SEQUENCE");
67
+ const list = this.privileges.map((p) => p.privilege);
68
+ const privSql = formatObjectPrivilegeList("SEQUENCE", list, this.version);
69
+ const sequenceName = `${this.sequence.schema}.${this.sequence.name}`;
70
+ return `GRANT ${privSql} ${kindPrefix} ${sequenceName} TO ${this.grantee}${withGrant}`;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Revoke privileges on a sequence.
76
+ *
77
+ * @see https://www.postgresql.org/docs/17/sql-revoke.html
78
+ *
79
+ * Synopsis
80
+ * ```sql
81
+ * REVOKE [ GRANT OPTION FOR ]
82
+ * { { USAGE | SELECT | UPDATE }
83
+ * [, ...] | ALL [ PRIVILEGES ] }
84
+ * ON { SEQUENCE sequence_name [, ...]
85
+ * | ALL SEQUENCES IN SCHEMA schema_name [, ...] }
86
+ * FROM role_specification [, ...]
87
+ * [ GRANTED BY role_specification ]
88
+ * [ CASCADE | RESTRICT ]
89
+ * ```
90
+ */
91
+ export class RevokeSequencePrivileges extends AlterSequenceChange {
92
+ public readonly sequence: Sequence;
93
+ public readonly grantee: string;
94
+ public readonly privileges: { privilege: string; grantable: boolean }[];
95
+ public readonly version: number | undefined;
96
+ public readonly scope = "privilege" as const;
97
+
98
+ constructor(props: {
99
+ sequence: Sequence;
100
+ grantee: string;
101
+ privileges: { privilege: string; grantable: boolean }[];
102
+ version?: number;
103
+ }) {
104
+ super();
105
+ this.sequence = props.sequence;
106
+ this.grantee = props.grantee;
107
+ this.privileges = props.privileges;
108
+ this.version = props.version;
109
+ }
110
+
111
+ get drops() {
112
+ // Return ACL ID for dependency tracking, even though this is an ALTER operation
113
+ // Phase assignment now uses operation type, so this won't affect phase placement
114
+ return [stableId.acl(this.sequence.stableId, this.grantee)];
115
+ }
116
+
117
+ get requires() {
118
+ return [
119
+ stableId.acl(this.sequence.stableId, this.grantee),
120
+ this.sequence.stableId,
121
+ stableId.role(this.grantee),
122
+ ];
123
+ }
124
+
125
+ serialize(): string {
126
+ const kindPrefix = getObjectKindPrefix("SEQUENCE");
127
+ const list = this.privileges.map((p) => p.privilege);
128
+ const privSql = formatObjectPrivilegeList("SEQUENCE", list, this.version);
129
+ const sequenceName = `${this.sequence.schema}.${this.sequence.name}`;
130
+ return `REVOKE ${privSql} ${kindPrefix} ${sequenceName} FROM ${this.grantee}`;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Revoke grant option for privileges on a sequence.
136
+ *
137
+ * This removes the ability to grant the privilege to others, but keeps the privilege itself.
138
+ *
139
+ * @see https://www.postgresql.org/docs/17/sql-revoke.html
140
+ */
141
+ export class RevokeGrantOptionSequencePrivileges extends AlterSequenceChange {
142
+ public readonly sequence: Sequence;
143
+ public readonly grantee: string;
144
+ public readonly privilegeNames: string[];
145
+ public readonly version: number | undefined;
146
+ public readonly scope = "privilege" as const;
147
+
148
+ constructor(props: {
149
+ sequence: Sequence;
150
+ grantee: string;
151
+ privilegeNames: string[];
152
+ version?: number;
153
+ }) {
154
+ super();
155
+ this.sequence = props.sequence;
156
+ this.grantee = props.grantee;
157
+ this.privilegeNames = [...new Set(props.privilegeNames)].sort();
158
+ this.version = props.version;
159
+ }
160
+
161
+ get requires() {
162
+ return [
163
+ stableId.acl(this.sequence.stableId, this.grantee),
164
+ this.sequence.stableId,
165
+ stableId.role(this.grantee),
166
+ ];
167
+ }
168
+
169
+ serialize(): string {
170
+ const kindPrefix = getObjectKindPrefix("SEQUENCE");
171
+ const privSql = formatObjectPrivilegeList(
172
+ "SEQUENCE",
173
+ this.privilegeNames,
174
+ this.version,
175
+ );
176
+ const sequenceName = `${this.sequence.schema}.${this.sequence.name}`;
177
+ return `REVOKE GRANT OPTION FOR ${privSql} ${kindPrefix} ${sequenceName} FROM ${this.grantee}`;
178
+ }
179
+ }
@@ -0,0 +1,12 @@
1
+ import type { AlterSequence } from "./sequence.alter.ts";
2
+ import type { CommentSequence } from "./sequence.comment.ts";
3
+ import type { CreateSequence } from "./sequence.create.ts";
4
+ import type { DropSequence } from "./sequence.drop.ts";
5
+ import type { SequencePrivilege } from "./sequence.privilege.ts";
6
+
7
+ export type SequenceChange =
8
+ | AlterSequence
9
+ | CommentSequence
10
+ | CreateSequence
11
+ | DropSequence
12
+ | SequencePrivilege;
@@ -0,0 +1,141 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { DefaultPrivilegeState } from "../base.default-privileges.ts";
3
+ import type { Table } from "../table/table.model.ts";
4
+ import {
5
+ AlterSequenceSetOptions,
6
+ AlterSequenceSetOwnedBy,
7
+ } from "./changes/sequence.alter.ts";
8
+ import { CreateSequence } from "./changes/sequence.create.ts";
9
+ import { DropSequence } from "./changes/sequence.drop.ts";
10
+ import { diffSequences } from "./sequence.diff.ts";
11
+ import { Sequence, type SequenceProps } from "./sequence.model.ts";
12
+
13
+ const base: SequenceProps = {
14
+ schema: "public",
15
+ name: "seq1",
16
+ data_type: "bigint",
17
+ start_value: 1,
18
+ minimum_value: 1n,
19
+ maximum_value: 1000n,
20
+ increment: 1,
21
+ cycle_option: false,
22
+ cache_size: 1,
23
+ persistence: "p",
24
+ owned_by_schema: null,
25
+ owned_by_table: null,
26
+ owned_by_column: null,
27
+ comment: null,
28
+ privileges: [],
29
+ owner: "test",
30
+ };
31
+
32
+ const testContext = {
33
+ version: 170000,
34
+ currentUser: "postgres",
35
+ defaultPrivilegeState: new DefaultPrivilegeState({}),
36
+ mainRoles: {},
37
+ };
38
+
39
+ describe.concurrent("sequence.diff", () => {
40
+ test("create and drop", () => {
41
+ const s = new Sequence(base);
42
+ const created = diffSequences(testContext, {}, { [s.stableId]: s });
43
+ expect(created[0]).toBeInstanceOf(CreateSequence);
44
+ const dropped = diffSequences(testContext, { [s.stableId]: s }, {});
45
+ expect(dropped[0]).toBeInstanceOf(DropSequence);
46
+ });
47
+
48
+ test("alter owned by", () => {
49
+ const main = new Sequence(base);
50
+ const branch = new Sequence({
51
+ ...base,
52
+ owned_by_schema: "public",
53
+ owned_by_table: "t",
54
+ owned_by_column: "id",
55
+ });
56
+ const changes = diffSequences(
57
+ testContext,
58
+ { [main.stableId]: main },
59
+ { [branch.stableId]: branch },
60
+ );
61
+ expect(changes[0]).toBeInstanceOf(AlterSequenceSetOwnedBy);
62
+ });
63
+
64
+ test("alter options via diff", () => {
65
+ const main = new Sequence(base);
66
+ const branch = new Sequence({
67
+ ...base,
68
+ increment: 2,
69
+ minimum_value: 5n,
70
+ maximum_value: 500n,
71
+ start_value: 10,
72
+ cache_size: 3,
73
+ cycle_option: true,
74
+ });
75
+ const changes = diffSequences(
76
+ testContext,
77
+ { [main.stableId]: main },
78
+ { [branch.stableId]: branch },
79
+ );
80
+ expect(changes.some((c) => c instanceof AlterSequenceSetOptions)).toBe(
81
+ true,
82
+ );
83
+ });
84
+
85
+ test("drop and create when non-alterable property changes", () => {
86
+ const main = new Sequence(base);
87
+ const branch = new Sequence({
88
+ ...base,
89
+ data_type: "integer",
90
+ persistence: "u",
91
+ });
92
+ const changes = diffSequences(
93
+ testContext,
94
+ { [main.stableId]: main },
95
+ { [branch.stableId]: branch },
96
+ );
97
+ expect(changes[0]).toBeInstanceOf(DropSequence);
98
+ expect(changes[1]).toBeInstanceOf(CreateSequence);
99
+ });
100
+
101
+ test("skip DROP SEQUENCE when owned by table being dropped", () => {
102
+ const ownedSequence = new Sequence({
103
+ ...base,
104
+ owned_by_schema: "public",
105
+ owned_by_table: "users",
106
+ owned_by_column: "id",
107
+ });
108
+ // When the owning table is not in branch catalog (being dropped),
109
+ // DROP SEQUENCE should not be generated (PostgreSQL auto-drops it)
110
+ const changes = diffSequences(
111
+ testContext,
112
+ { [ownedSequence.stableId]: ownedSequence },
113
+ {}, // branch has no sequences (sequence was auto-dropped)
114
+ {}, // branch has no tables (table is being dropped)
115
+ );
116
+ // Should not generate DROP SEQUENCE since table is being dropped
117
+ expect(changes).toHaveLength(0);
118
+ });
119
+
120
+ test("generate DROP SEQUENCE when owned by table that still exists", () => {
121
+ const ownedSequence = new Sequence({
122
+ ...base,
123
+ owned_by_schema: "public",
124
+ owned_by_table: "users",
125
+ owned_by_column: "id",
126
+ });
127
+ // When the owning table still exists in branch catalog,
128
+ // DROP SEQUENCE should be generated
129
+ const changes = diffSequences(
130
+ testContext,
131
+ { [ownedSequence.stableId]: ownedSequence },
132
+ {}, // branch has no sequences
133
+ {
134
+ "table:public.users": {} as Table, // table still exists
135
+ },
136
+ );
137
+ // Should generate DROP SEQUENCE since table still exists
138
+ expect(changes).toHaveLength(1);
139
+ expect(changes[0]).toBeInstanceOf(DropSequence);
140
+ });
141
+ });
@@ -0,0 +1,359 @@
1
+ import type { DefaultPrivilegeState } from "../base.default-privileges.ts";
2
+ import { diffObjects } from "../base.diff.ts";
3
+ import {
4
+ diffPrivileges,
5
+ groupPrivilegesByGrantable,
6
+ } from "../base.privilege-diff.ts";
7
+ import type { Role } from "../role/role.model.ts";
8
+ import type { Table } from "../table/table.model.ts";
9
+ import { hasNonAlterableChanges } from "../utils.ts";
10
+ import {
11
+ AlterSequenceSetOptions,
12
+ AlterSequenceSetOwnedBy,
13
+ } from "./changes/sequence.alter.ts";
14
+ import {
15
+ CreateCommentOnSequence,
16
+ DropCommentOnSequence,
17
+ } from "./changes/sequence.comment.ts";
18
+ import { CreateSequence } from "./changes/sequence.create.ts";
19
+ import { DropSequence } from "./changes/sequence.drop.ts";
20
+ import {
21
+ GrantSequencePrivileges,
22
+ RevokeGrantOptionSequencePrivileges,
23
+ RevokeSequencePrivileges,
24
+ } from "./changes/sequence.privilege.ts";
25
+ import type { SequenceChange } from "./changes/sequence.types.ts";
26
+ import type { Sequence } from "./sequence.model.ts";
27
+
28
+ /**
29
+ * Diff two sets of sequences from main and branch catalogs.
30
+ *
31
+ * @param ctx - Context containing version, currentUser, and defaultPrivilegeState
32
+ * @param main - The sequences in the main catalog.
33
+ * @param branch - The sequences in the branch catalog.
34
+ * @param branchTables - The tables in the branch catalog (used to check if owning tables are being dropped).
35
+ * @returns A list of changes to apply to main to make it match branch.
36
+ */
37
+ export function diffSequences(
38
+ ctx: {
39
+ version: number;
40
+ currentUser: string;
41
+ defaultPrivilegeState: DefaultPrivilegeState;
42
+ mainRoles: Record<string, Role>;
43
+ },
44
+ main: Record<string, Sequence>,
45
+ branch: Record<string, Sequence>,
46
+ branchTables: Record<string, Table> = {},
47
+ ): SequenceChange[] {
48
+ const { created, dropped, altered } = diffObjects(main, branch);
49
+
50
+ const changes: SequenceChange[] = [];
51
+
52
+ for (const sequenceId of created) {
53
+ const createdSeq = branch[sequenceId];
54
+ changes.push(new CreateSequence({ sequence: createdSeq }));
55
+ if (createdSeq.comment !== null) {
56
+ changes.push(new CreateCommentOnSequence({ sequence: createdSeq }));
57
+ }
58
+ // If the created sequence is OWNED BY a column, emit an ALTER to set it
59
+ if (
60
+ createdSeq.owned_by_schema !== null &&
61
+ createdSeq.owned_by_table !== null &&
62
+ createdSeq.owned_by_column !== null
63
+ ) {
64
+ changes.push(
65
+ new AlterSequenceSetOwnedBy({
66
+ sequence: createdSeq,
67
+ ownedBy: {
68
+ schema: createdSeq.owned_by_schema,
69
+ table: createdSeq.owned_by_table,
70
+ column: createdSeq.owned_by_column,
71
+ } as { schema: string; table: string; column: string },
72
+ }),
73
+ );
74
+ }
75
+
76
+ // PRIVILEGES: For created objects, compare against default privileges state
77
+ // The migration script will run ALTER DEFAULT PRIVILEGES before CREATE (via constraint spec),
78
+ // so objects are created with the default privileges state in effect.
79
+ // We compare default privileges against desired privileges to generate REVOKE/GRANT statements
80
+ // needed to reach the final desired state.
81
+ const effectiveDefaults = ctx.defaultPrivilegeState.getEffectiveDefaults(
82
+ ctx.currentUser,
83
+ "sequence",
84
+ createdSeq.schema ?? "",
85
+ );
86
+ const desiredPrivileges = createdSeq.privileges;
87
+ // Filter out owner privileges - owner always has ALL privileges implicitly
88
+ // and shouldn't be compared. Use the sequence owner as the reference.
89
+ // Superuser privileges are filtered inside diffPrivileges.
90
+ const privilegeResults = diffPrivileges(
91
+ effectiveDefaults,
92
+ desiredPrivileges,
93
+ createdSeq.owner,
94
+ ctx.mainRoles,
95
+ );
96
+
97
+ // Generate grant changes
98
+ for (const [grantee, result] of privilegeResults) {
99
+ if (result.grants.length > 0) {
100
+ const grantGroups = groupPrivilegesByGrantable(result.grants);
101
+ for (const [grantable, list] of grantGroups) {
102
+ void grantable;
103
+ changes.push(
104
+ new GrantSequencePrivileges({
105
+ sequence: createdSeq,
106
+ grantee,
107
+ privileges: list,
108
+ version: ctx.version,
109
+ }),
110
+ );
111
+ }
112
+ }
113
+
114
+ // Generate revoke changes
115
+ if (result.revokes.length > 0) {
116
+ const revokeGroups = groupPrivilegesByGrantable(result.revokes);
117
+ for (const [grantable, list] of revokeGroups) {
118
+ void grantable;
119
+ changes.push(
120
+ new RevokeSequencePrivileges({
121
+ sequence: createdSeq,
122
+ grantee,
123
+ privileges: list,
124
+ version: ctx.version,
125
+ }),
126
+ );
127
+ }
128
+ }
129
+
130
+ // Generate revoke grant option changes
131
+ if (result.revokeGrantOption.length > 0) {
132
+ changes.push(
133
+ new RevokeGrantOptionSequencePrivileges({
134
+ sequence: createdSeq,
135
+ grantee,
136
+ privilegeNames: result.revokeGrantOption,
137
+ version: ctx.version,
138
+ }),
139
+ );
140
+ }
141
+ }
142
+ }
143
+
144
+ for (const sequenceId of dropped) {
145
+ const sequence = main[sequenceId];
146
+ // Skip generating DROP SEQUENCE if the sequence is owned by a table that's being dropped.
147
+ // PostgreSQL automatically drops sequences owned by tables when the table is dropped,
148
+ // so generating DROP SEQUENCE would cause an error (sequence doesn't exist).
149
+ if (
150
+ sequence.owned_by_schema &&
151
+ sequence.owned_by_table &&
152
+ sequence.owned_by_column
153
+ ) {
154
+ const ownedByTableId = `table:${sequence.owned_by_schema}.${sequence.owned_by_table}`;
155
+ // If the owning table doesn't exist in branch catalog, it's being dropped
156
+ // and will auto-drop this sequence, so skip generating DROP SEQUENCE
157
+ if (!(ownedByTableId in branchTables)) {
158
+ continue;
159
+ }
160
+ }
161
+ changes.push(new DropSequence({ sequence }));
162
+ }
163
+
164
+ for (const sequenceId of altered) {
165
+ const mainSequence = main[sequenceId];
166
+ const branchSequence = branch[sequenceId];
167
+
168
+ // Check if non-alterable properties have changed
169
+ // These require dropping and recreating the sequence
170
+ const NON_ALTERABLE_FIELDS: Array<keyof Sequence> = [
171
+ "data_type",
172
+ "persistence",
173
+ ];
174
+ const nonAlterablePropsChanged = hasNonAlterableChanges(
175
+ mainSequence,
176
+ branchSequence,
177
+ NON_ALTERABLE_FIELDS,
178
+ );
179
+
180
+ if (nonAlterablePropsChanged) {
181
+ // Replace the entire sequence (drop + create)
182
+ changes.push(
183
+ new DropSequence({ sequence: mainSequence }),
184
+ new CreateSequence({ sequence: branchSequence }),
185
+ );
186
+ // Re-apply OWNED BY if present on branch
187
+ if (
188
+ branchSequence.owned_by_schema !== null &&
189
+ branchSequence.owned_by_table !== null &&
190
+ branchSequence.owned_by_column !== null
191
+ ) {
192
+ changes.push(
193
+ new AlterSequenceSetOwnedBy({
194
+ sequence: branchSequence,
195
+ ownedBy: {
196
+ schema: branchSequence.owned_by_schema,
197
+ table: branchSequence.owned_by_table,
198
+ column: branchSequence.owned_by_column,
199
+ } as { schema: string; table: string; column: string },
200
+ }),
201
+ );
202
+ } else if (
203
+ mainSequence.owned_by_schema !== null ||
204
+ mainSequence.owned_by_table !== null ||
205
+ mainSequence.owned_by_column !== null
206
+ ) {
207
+ // If main had ownership but branch removed it, emit OWNED BY NONE
208
+ changes.push(
209
+ new AlterSequenceSetOwnedBy({
210
+ sequence: mainSequence,
211
+ ownedBy: null,
212
+ }),
213
+ );
214
+ }
215
+ } else {
216
+ // Only alterable properties changed - emit ALTER for options/owner
217
+ const optionsChanged =
218
+ mainSequence.increment !== branchSequence.increment ||
219
+ mainSequence.minimum_value !== branchSequence.minimum_value ||
220
+ mainSequence.maximum_value !== branchSequence.maximum_value ||
221
+ mainSequence.start_value !== branchSequence.start_value ||
222
+ mainSequence.cache_size !== branchSequence.cache_size ||
223
+ mainSequence.cycle_option !== branchSequence.cycle_option;
224
+
225
+ if (optionsChanged) {
226
+ const options: string[] = [];
227
+ if (mainSequence.increment !== branchSequence.increment) {
228
+ options.push("INCREMENT BY", String(branchSequence.increment));
229
+ }
230
+ if (mainSequence.minimum_value !== branchSequence.minimum_value) {
231
+ const defaultMin = BigInt(1);
232
+ if (branchSequence.minimum_value === defaultMin) {
233
+ options.push("NO MINVALUE");
234
+ } else {
235
+ options.push("MINVALUE", branchSequence.minimum_value.toString());
236
+ }
237
+ }
238
+ if (mainSequence.maximum_value !== branchSequence.maximum_value) {
239
+ const defaultMax =
240
+ branchSequence.data_type === "integer"
241
+ ? BigInt("2147483647")
242
+ : BigInt("9223372036854775807");
243
+ if (branchSequence.maximum_value === defaultMax) {
244
+ options.push("NO MAXVALUE");
245
+ } else {
246
+ options.push("MAXVALUE", branchSequence.maximum_value.toString());
247
+ }
248
+ }
249
+ if (mainSequence.start_value !== branchSequence.start_value) {
250
+ options.push("START WITH", String(branchSequence.start_value));
251
+ }
252
+ if (mainSequence.cache_size !== branchSequence.cache_size) {
253
+ options.push("CACHE", String(branchSequence.cache_size));
254
+ }
255
+ if (mainSequence.cycle_option !== branchSequence.cycle_option) {
256
+ options.push(branchSequence.cycle_option ? "CYCLE" : "NO CYCLE");
257
+ }
258
+ changes.push(
259
+ new AlterSequenceSetOptions({ sequence: mainSequence, options }),
260
+ );
261
+ }
262
+
263
+ const ownedByChanged =
264
+ mainSequence.owned_by_schema !== branchSequence.owned_by_schema ||
265
+ mainSequence.owned_by_table !== branchSequence.owned_by_table ||
266
+ mainSequence.owned_by_column !== branchSequence.owned_by_column;
267
+
268
+ if (ownedByChanged) {
269
+ const ownedBy =
270
+ branchSequence.owned_by_schema &&
271
+ branchSequence.owned_by_table &&
272
+ branchSequence.owned_by_column
273
+ ? {
274
+ schema: branchSequence.owned_by_schema,
275
+ table: branchSequence.owned_by_table,
276
+ column: branchSequence.owned_by_column,
277
+ }
278
+ : null;
279
+ changes.push(
280
+ new AlterSequenceSetOwnedBy({ sequence: mainSequence, ownedBy }),
281
+ );
282
+ }
283
+
284
+ // COMMENT
285
+ if (mainSequence.comment !== branchSequence.comment) {
286
+ if (branchSequence.comment === null) {
287
+ changes.push(new DropCommentOnSequence({ sequence: mainSequence }));
288
+ } else {
289
+ changes.push(
290
+ new CreateCommentOnSequence({ sequence: branchSequence }),
291
+ );
292
+ }
293
+ }
294
+
295
+ // PRIVILEGES
296
+ // Filter out owner privileges - owner always has ALL privileges implicitly
297
+ // and shouldn't be compared. Use branch owner as the reference.
298
+ // Superuser privileges are filtered inside diffPrivileges.
299
+ const privilegeResults = diffPrivileges(
300
+ mainSequence.privileges,
301
+ branchSequence.privileges,
302
+ branchSequence.owner,
303
+ ctx.mainRoles,
304
+ );
305
+
306
+ for (const [grantee, result] of privilegeResults) {
307
+ // Generate grant changes
308
+ if (result.grants.length > 0) {
309
+ const grantGroups = groupPrivilegesByGrantable(result.grants);
310
+ for (const [grantable, list] of grantGroups) {
311
+ void grantable;
312
+ changes.push(
313
+ new GrantSequencePrivileges({
314
+ sequence: branchSequence,
315
+ grantee,
316
+ privileges: list,
317
+ version: ctx.version,
318
+ }),
319
+ );
320
+ }
321
+ }
322
+
323
+ // Generate revoke changes
324
+ if (result.revokes.length > 0) {
325
+ const revokeGroups = groupPrivilegesByGrantable(result.revokes);
326
+ for (const [grantable, list] of revokeGroups) {
327
+ void grantable;
328
+ changes.push(
329
+ new RevokeSequencePrivileges({
330
+ sequence: mainSequence,
331
+ grantee,
332
+ privileges: list,
333
+ version: ctx.version,
334
+ }),
335
+ );
336
+ }
337
+ }
338
+
339
+ // Generate revoke grant option changes
340
+ if (result.revokeGrantOption.length > 0) {
341
+ changes.push(
342
+ new RevokeGrantOptionSequencePrivileges({
343
+ sequence: mainSequence,
344
+ grantee,
345
+ privilegeNames: result.revokeGrantOption,
346
+ version: ctx.version,
347
+ }),
348
+ );
349
+ }
350
+ }
351
+
352
+ // Note: Sequence renaming would also use ALTER SEQUENCE ... RENAME TO ...
353
+ // But since our Sequence model uses 'name' as the identity field,
354
+ // a name change would be handled as drop + create by diffObjects()
355
+ }
356
+ }
357
+
358
+ return changes;
359
+ }