@supabase/pg-delta 1.0.0-alpha.3 → 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 (463) 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/objects/table/table.model.d.ts +4 -2
  7. package/dist/core/objects/table/table.model.js +3 -0
  8. package/dist/core/objects/trigger/changes/trigger.alter.js +23 -0
  9. package/dist/core/objects/trigger/changes/trigger.create.js +2 -1
  10. package/dist/core/objects/trigger/trigger.model.d.ts +1 -0
  11. package/dist/core/objects/trigger/trigger.model.js +3 -0
  12. package/dist/core/plan/apply.js +3 -3
  13. package/dist/core/plan/create.js +34 -15
  14. package/dist/core/plan/sql-format/constants.d.ts +2 -0
  15. package/dist/core/plan/sql-format/constants.js +11 -0
  16. package/dist/core/plan/sql-format/fixtures.d.ts +2 -0
  17. package/dist/core/plan/sql-format/fixtures.js +2449 -0
  18. package/dist/core/plan/sql-format/format-utils.d.ts +37 -0
  19. package/dist/core/plan/sql-format/format-utils.js +274 -0
  20. package/dist/core/plan/sql-format/formatters.d.ts +20 -0
  21. package/dist/core/plan/sql-format/formatters.js +737 -0
  22. package/dist/core/plan/sql-format/index.d.ts +2 -0
  23. package/dist/core/plan/sql-format/index.js +98 -0
  24. package/dist/core/plan/sql-format/keyword-case.d.ts +2 -0
  25. package/dist/core/plan/sql-format/keyword-case.js +868 -0
  26. package/dist/core/plan/sql-format/protect.d.ts +3 -0
  27. package/dist/core/plan/sql-format/protect.js +269 -0
  28. package/dist/core/plan/sql-format/sql-scanner.d.ts +59 -0
  29. package/dist/core/plan/sql-format/sql-scanner.js +202 -0
  30. package/dist/core/plan/sql-format/tokenizer.d.ts +22 -0
  31. package/dist/core/plan/sql-format/tokenizer.js +118 -0
  32. package/dist/core/plan/sql-format/types.d.ts +28 -0
  33. package/dist/core/plan/sql-format/types.js +1 -0
  34. package/dist/core/plan/sql-format/wrap.d.ts +2 -0
  35. package/dist/core/plan/sql-format/wrap.js +165 -0
  36. package/dist/core/plan/sql-format.d.ts +2 -0
  37. package/dist/core/plan/sql-format.js +1 -0
  38. package/dist/core/plan/statements.d.ts +2 -1
  39. package/dist/core/plan/statements.js +6 -2
  40. package/dist/core/postgres-config.d.ts +15 -0
  41. package/dist/core/postgres-config.js +30 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +1 -0
  44. package/package.json +37 -22
  45. package/src/cli/app.ts +28 -0
  46. package/src/cli/bin/cli.ts +9 -0
  47. package/src/cli/commands/apply.ts +101 -0
  48. package/src/cli/commands/plan.ts +195 -0
  49. package/src/cli/commands/sync.ts +185 -0
  50. package/src/cli/formatters/index.ts +5 -0
  51. package/src/cli/formatters/tree/tree-builder.ts +380 -0
  52. package/src/cli/formatters/tree/tree-renderer.ts +372 -0
  53. package/src/cli/formatters/tree/tree.ts +237 -0
  54. package/src/cli/utils/integrations.ts +42 -0
  55. package/src/cli/utils.ts +231 -0
  56. package/src/core/catalog.diff.ts +246 -0
  57. package/src/core/catalog.model.ts +384 -0
  58. package/src/core/change.types.ts +44 -0
  59. package/src/core/context.ts +26 -0
  60. package/src/core/depend.ts +1870 -0
  61. package/src/core/expand-replace-dependencies.ts +380 -0
  62. package/src/core/fingerprint.ts +204 -0
  63. package/src/core/integrations/filter/dsl.ts +204 -0
  64. package/src/core/integrations/filter/extractors.ts +145 -0
  65. package/src/core/integrations/filter/filter.types.ts +3 -0
  66. package/src/core/integrations/integration-dsl.ts +24 -0
  67. package/src/core/integrations/integration.types.ts +7 -0
  68. package/src/core/integrations/serialize/dsl.ts +77 -0
  69. package/src/core/integrations/serialize/serialize.types.ts +3 -0
  70. package/src/core/integrations/supabase.ts +121 -0
  71. package/src/core/objects/aggregate/aggregate.diff.test.ts +215 -0
  72. package/src/core/objects/aggregate/aggregate.diff.ts +278 -0
  73. package/src/core/objects/aggregate/aggregate.model.ts +317 -0
  74. package/src/core/objects/aggregate/changes/aggregate.alter.test.ts +64 -0
  75. package/src/core/objects/aggregate/changes/aggregate.alter.ts +32 -0
  76. package/src/core/objects/aggregate/changes/aggregate.base.ts +20 -0
  77. package/src/core/objects/aggregate/changes/aggregate.comment.test.ts +86 -0
  78. package/src/core/objects/aggregate/changes/aggregate.comment.ts +62 -0
  79. package/src/core/objects/aggregate/changes/aggregate.create.test.ts +101 -0
  80. package/src/core/objects/aggregate/changes/aggregate.create.ts +329 -0
  81. package/src/core/objects/aggregate/changes/aggregate.drop.test.ts +78 -0
  82. package/src/core/objects/aggregate/changes/aggregate.drop.ts +32 -0
  83. package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +130 -0
  84. package/src/core/objects/aggregate/changes/aggregate.privilege.ts +146 -0
  85. package/src/core/objects/aggregate/changes/aggregate.types.ts +12 -0
  86. package/src/core/objects/base.change.ts +62 -0
  87. package/src/core/objects/base.default-privileges.ts +204 -0
  88. package/src/core/objects/base.diff.ts +20 -0
  89. package/src/core/objects/base.model.ts +82 -0
  90. package/src/core/objects/base.privilege-diff.ts +299 -0
  91. package/src/core/objects/base.privilege.ts +184 -0
  92. package/src/core/objects/collation/changes/collation.alter.test.ts +63 -0
  93. package/src/core/objects/collation/changes/collation.alter.ts +79 -0
  94. package/src/core/objects/collation/changes/collation.base.ts +20 -0
  95. package/src/core/objects/collation/changes/collation.comment.ts +68 -0
  96. package/src/core/objects/collation/changes/collation.create.test.ts +51 -0
  97. package/src/core/objects/collation/changes/collation.create.ts +106 -0
  98. package/src/core/objects/collation/changes/collation.drop.test.ts +28 -0
  99. package/src/core/objects/collation/changes/collation.drop.ts +37 -0
  100. package/src/core/objects/collation/changes/collation.types.ts +10 -0
  101. package/src/core/objects/collation/collation.diff.test.ts +100 -0
  102. package/src/core/objects/collation/collation.diff.ts +126 -0
  103. package/src/core/objects/collation/collation.model.ts +224 -0
  104. package/src/core/objects/domain/changes/domain.alter.test.ts +316 -0
  105. package/src/core/objects/domain/changes/domain.alter.ts +286 -0
  106. package/src/core/objects/domain/changes/domain.base.ts +20 -0
  107. package/src/core/objects/domain/changes/domain.comment.ts +59 -0
  108. package/src/core/objects/domain/changes/domain.create.test.ts +65 -0
  109. package/src/core/objects/domain/changes/domain.create.ts +118 -0
  110. package/src/core/objects/domain/changes/domain.drop.test.ts +30 -0
  111. package/src/core/objects/domain/changes/domain.drop.ts +34 -0
  112. package/src/core/objects/domain/changes/domain.privilege.ts +171 -0
  113. package/src/core/objects/domain/changes/domain.types.ts +12 -0
  114. package/src/core/objects/domain/domain.diff.test.ts +284 -0
  115. package/src/core/objects/domain/domain.diff.ts +358 -0
  116. package/src/core/objects/domain/domain.model.ts +190 -0
  117. package/src/core/objects/event-trigger/changes/event-trigger.alter.test.ts +50 -0
  118. package/src/core/objects/event-trigger/changes/event-trigger.alter.ts +82 -0
  119. package/src/core/objects/event-trigger/changes/event-trigger.base.ts +20 -0
  120. package/src/core/objects/event-trigger/changes/event-trigger.comment.ts +66 -0
  121. package/src/core/objects/event-trigger/changes/event-trigger.create.test.ts +24 -0
  122. package/src/core/objects/event-trigger/changes/event-trigger.create.ts +72 -0
  123. package/src/core/objects/event-trigger/changes/event-trigger.drop.test.ts +22 -0
  124. package/src/core/objects/event-trigger/changes/event-trigger.drop.ts +34 -0
  125. package/src/core/objects/event-trigger/changes/event-trigger.types.ts +10 -0
  126. package/src/core/objects/event-trigger/event-trigger.diff.test.ts +126 -0
  127. package/src/core/objects/event-trigger/event-trigger.diff.ts +126 -0
  128. package/src/core/objects/event-trigger/event-trigger.model.ts +106 -0
  129. package/src/core/objects/extension/changes/extension.alter.test.ts +58 -0
  130. package/src/core/objects/extension/changes/extension.alter.ts +78 -0
  131. package/src/core/objects/extension/changes/extension.base.ts +20 -0
  132. package/src/core/objects/extension/changes/extension.comment.ts +64 -0
  133. package/src/core/objects/extension/changes/extension.create.test.ts +25 -0
  134. package/src/core/objects/extension/changes/extension.create.ts +63 -0
  135. package/src/core/objects/extension/changes/extension.drop.test.ts +23 -0
  136. package/src/core/objects/extension/changes/extension.drop.ts +34 -0
  137. package/src/core/objects/extension/changes/extension.types.ts +10 -0
  138. package/src/core/objects/extension/extension.diff.test.ts +42 -0
  139. package/src/core/objects/extension/extension.diff.ts +90 -0
  140. package/src/core/objects/extension/extension.model.ts +280 -0
  141. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +125 -0
  142. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +101 -0
  143. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.base.ts +20 -0
  144. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.comment.ts +72 -0
  145. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +125 -0
  146. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +95 -0
  147. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.test.ts +23 -0
  148. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.drop.ts +36 -0
  149. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.privilege.ts +172 -0
  150. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.types.ts +12 -0
  151. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.test.ts +179 -0
  152. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.diff.ts +341 -0
  153. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +149 -0
  154. package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper.types.ts +10 -0
  155. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +309 -0
  156. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +341 -0
  157. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +20 -0
  158. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.comment.ts +72 -0
  159. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +201 -0
  160. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +81 -0
  161. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.test.ts +43 -0
  162. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.drop.ts +37 -0
  163. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.privilege.ts +181 -0
  164. package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +12 -0
  165. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.test.ts +813 -0
  166. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +406 -0
  167. package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +242 -0
  168. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +168 -0
  169. package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +126 -0
  170. package/src/core/objects/foreign-data-wrapper/server/changes/server.base.ts +20 -0
  171. package/src/core/objects/foreign-data-wrapper/server/changes/server.comment.ts +60 -0
  172. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +131 -0
  173. package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +81 -0
  174. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.test.ts +24 -0
  175. package/src/core/objects/foreign-data-wrapper/server/changes/server.drop.ts +34 -0
  176. package/src/core/objects/foreign-data-wrapper/server/changes/server.privilege.ts +164 -0
  177. package/src/core/objects/foreign-data-wrapper/server/changes/server.types.ts +12 -0
  178. package/src/core/objects/foreign-data-wrapper/server/server.diff.test.ts +167 -0
  179. package/src/core/objects/foreign-data-wrapper/server/server.diff.ts +317 -0
  180. package/src/core/objects/foreign-data-wrapper/server/server.model.ts +133 -0
  181. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +82 -0
  182. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +69 -0
  183. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.base.ts +20 -0
  184. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +85 -0
  185. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +66 -0
  186. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.test.ts +53 -0
  187. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.drop.ts +40 -0
  188. package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.types.ts +8 -0
  189. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.test.ts +77 -0
  190. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.diff.ts +107 -0
  191. package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +96 -0
  192. package/src/core/objects/index/changes/index.alter.test.ts +200 -0
  193. package/src/core/objects/index/changes/index.alter.ts +144 -0
  194. package/src/core/objects/index/changes/index.base.ts +20 -0
  195. package/src/core/objects/index/changes/index.comment.ts +63 -0
  196. package/src/core/objects/index/changes/index.create.test.ts +66 -0
  197. package/src/core/objects/index/changes/index.create.ts +68 -0
  198. package/src/core/objects/index/changes/index.drop.test.ts +44 -0
  199. package/src/core/objects/index/changes/index.drop.ts +34 -0
  200. package/src/core/objects/index/changes/index.types.ts +6 -0
  201. package/src/core/objects/index/changes/utils.ts +16 -0
  202. package/src/core/objects/index/index.diff.test.ts +153 -0
  203. package/src/core/objects/index/index.diff.ts +243 -0
  204. package/src/core/objects/index/index.model.ts +370 -0
  205. package/src/core/objects/language/changes/language.alter.test.ts +33 -0
  206. package/src/core/objects/language/changes/language.alter.ts +53 -0
  207. package/src/core/objects/language/changes/language.base.ts +20 -0
  208. package/src/core/objects/language/changes/language.comment.ts +58 -0
  209. package/src/core/objects/language/changes/language.create.test.ts +27 -0
  210. package/src/core/objects/language/changes/language.create.ts +104 -0
  211. package/src/core/objects/language/changes/language.drop.test.ts +25 -0
  212. package/src/core/objects/language/changes/language.drop.ts +39 -0
  213. package/src/core/objects/language/changes/language.privilege.ts +172 -0
  214. package/src/core/objects/language/changes/language.types.ts +12 -0
  215. package/src/core/objects/language/language.diff.test.ts +53 -0
  216. package/src/core/objects/language/language.diff.ts +176 -0
  217. package/src/core/objects/language/language.model.ts +150 -0
  218. package/src/core/objects/materialized-view/changes/materialized-view.alter.test.ts +123 -0
  219. package/src/core/objects/materialized-view/changes/materialized-view.alter.ts +113 -0
  220. package/src/core/objects/materialized-view/changes/materialized-view.base.ts +20 -0
  221. package/src/core/objects/materialized-view/changes/materialized-view.comment.ts +176 -0
  222. package/src/core/objects/materialized-view/changes/materialized-view.create.test.ts +64 -0
  223. package/src/core/objects/materialized-view/changes/materialized-view.create.ts +93 -0
  224. package/src/core/objects/materialized-view/changes/materialized-view.drop.test.ts +34 -0
  225. package/src/core/objects/materialized-view/changes/materialized-view.drop.ts +60 -0
  226. package/src/core/objects/materialized-view/changes/materialized-view.privilege.ts +212 -0
  227. package/src/core/objects/materialized-view/changes/materialized-view.types.ts +12 -0
  228. package/src/core/objects/materialized-view/materialized-view.diff.test.ts +102 -0
  229. package/src/core/objects/materialized-view/materialized-view.diff.ts +451 -0
  230. package/src/core/objects/materialized-view/materialized-view.model.ts +258 -0
  231. package/src/core/objects/procedure/changes/procedure.alter.test.ts +1005 -0
  232. package/src/core/objects/procedure/changes/procedure.alter.ts +287 -0
  233. package/src/core/objects/procedure/changes/procedure.base.ts +20 -0
  234. package/src/core/objects/procedure/changes/procedure.comment.ts +70 -0
  235. package/src/core/objects/procedure/changes/procedure.create.test.ts +48 -0
  236. package/src/core/objects/procedure/changes/procedure.create.ts +92 -0
  237. package/src/core/objects/procedure/changes/procedure.drop.test.ts +85 -0
  238. package/src/core/objects/procedure/changes/procedure.drop.ts +49 -0
  239. package/src/core/objects/procedure/changes/procedure.privilege.ts +188 -0
  240. package/src/core/objects/procedure/changes/procedure.types.ts +12 -0
  241. package/src/core/objects/procedure/procedure.diff.test.ts +161 -0
  242. package/src/core/objects/procedure/procedure.diff.ts +404 -0
  243. package/src/core/objects/procedure/procedure.model.ts +264 -0
  244. package/src/core/objects/procedure/utils.ts +58 -0
  245. package/src/core/objects/publication/changes/publication.alter.test.ts +223 -0
  246. package/src/core/objects/publication/changes/publication.alter.ts +243 -0
  247. package/src/core/objects/publication/changes/publication.base.ts +20 -0
  248. package/src/core/objects/publication/changes/publication.comment.test.ts +70 -0
  249. package/src/core/objects/publication/changes/publication.comment.ts +64 -0
  250. package/src/core/objects/publication/changes/publication.create.test.ts +87 -0
  251. package/src/core/objects/publication/changes/publication.create.ts +82 -0
  252. package/src/core/objects/publication/changes/publication.drop.test.ts +46 -0
  253. package/src/core/objects/publication/changes/publication.drop.ts +29 -0
  254. package/src/core/objects/publication/changes/publication.types.ts +26 -0
  255. package/src/core/objects/publication/publication.diff.test.ts +292 -0
  256. package/src/core/objects/publication/publication.diff.ts +253 -0
  257. package/src/core/objects/publication/publication.model.ts +206 -0
  258. package/src/core/objects/publication/utils.ts +55 -0
  259. package/src/core/objects/rls-policy/changes/rls-policy.alter.test.ts +250 -0
  260. package/src/core/objects/rls-policy/changes/rls-policy.alter.ts +128 -0
  261. package/src/core/objects/rls-policy/changes/rls-policy.base.ts +20 -0
  262. package/src/core/objects/rls-policy/changes/rls-policy.comment.ts +69 -0
  263. package/src/core/objects/rls-policy/changes/rls-policy.create.test.ts +74 -0
  264. package/src/core/objects/rls-policy/changes/rls-policy.create.ts +100 -0
  265. package/src/core/objects/rls-policy/changes/rls-policy.drop.test.ts +28 -0
  266. package/src/core/objects/rls-policy/changes/rls-policy.drop.ts +39 -0
  267. package/src/core/objects/rls-policy/changes/rls-policy.types.ts +10 -0
  268. package/src/core/objects/rls-policy/rls-policy.diff.test.ts +79 -0
  269. package/src/core/objects/rls-policy/rls-policy.diff.ts +121 -0
  270. package/src/core/objects/rls-policy/rls-policy.model.ts +140 -0
  271. package/src/core/objects/role/changes/role.alter.test.ts +346 -0
  272. package/src/core/objects/role/changes/role.alter.ts +110 -0
  273. package/src/core/objects/role/changes/role.base.ts +24 -0
  274. package/src/core/objects/role/changes/role.comment.ts +55 -0
  275. package/src/core/objects/role/changes/role.create.test.ts +52 -0
  276. package/src/core/objects/role/changes/role.create.ts +102 -0
  277. package/src/core/objects/role/changes/role.drop.test.ts +29 -0
  278. package/src/core/objects/role/changes/role.drop.ts +34 -0
  279. package/src/core/objects/role/changes/role.privilege.ts +376 -0
  280. package/src/core/objects/role/changes/role.types.ts +12 -0
  281. package/src/core/objects/role/role.diff.test.ts +44 -0
  282. package/src/core/objects/role/role.diff.ts +479 -0
  283. package/src/core/objects/role/role.model.ts +344 -0
  284. package/src/core/objects/rule/changes/rule.alter.test.ts +78 -0
  285. package/src/core/objects/rule/changes/rule.alter.ts +72 -0
  286. package/src/core/objects/rule/changes/rule.base.ts +20 -0
  287. package/src/core/objects/rule/changes/rule.comment.test.ts +55 -0
  288. package/src/core/objects/rule/changes/rule.comment.ts +62 -0
  289. package/src/core/objects/rule/changes/rule.create.test.ts +59 -0
  290. package/src/core/objects/rule/changes/rule.create.ts +42 -0
  291. package/src/core/objects/rule/changes/rule.drop.test.ts +38 -0
  292. package/src/core/objects/rule/changes/rule.drop.ts +29 -0
  293. package/src/core/objects/rule/changes/rule.types.ts +12 -0
  294. package/src/core/objects/rule/rule.diff.test.ts +132 -0
  295. package/src/core/objects/rule/rule.diff.ts +79 -0
  296. package/src/core/objects/rule/rule.model.ts +173 -0
  297. package/src/core/objects/schema/changes/schema.alter.test.ts +28 -0
  298. package/src/core/objects/schema/changes/schema.alter.ts +45 -0
  299. package/src/core/objects/schema/changes/schema.base.ts +20 -0
  300. package/src/core/objects/schema/changes/schema.comment.ts +56 -0
  301. package/src/core/objects/schema/changes/schema.create.test.ts +22 -0
  302. package/src/core/objects/schema/changes/schema.create.ts +47 -0
  303. package/src/core/objects/schema/changes/schema.drop.test.ts +20 -0
  304. package/src/core/objects/schema/changes/schema.drop.ts +34 -0
  305. package/src/core/objects/schema/changes/schema.privilege.ts +175 -0
  306. package/src/core/objects/schema/changes/schema.types.ts +12 -0
  307. package/src/core/objects/schema/schema.diff.test.ts +42 -0
  308. package/src/core/objects/schema/schema.diff.ts +209 -0
  309. package/src/core/objects/schema/schema.model.ts +107 -0
  310. package/src/core/objects/sequence/changes/sequence.alter.test.ts +151 -0
  311. package/src/core/objects/sequence/changes/sequence.alter.ts +115 -0
  312. package/src/core/objects/sequence/changes/sequence.base.ts +20 -0
  313. package/src/core/objects/sequence/changes/sequence.comment.ts +60 -0
  314. package/src/core/objects/sequence/changes/sequence.create.test.ts +84 -0
  315. package/src/core/objects/sequence/changes/sequence.create.ts +111 -0
  316. package/src/core/objects/sequence/changes/sequence.drop.test.ts +32 -0
  317. package/src/core/objects/sequence/changes/sequence.drop.ts +37 -0
  318. package/src/core/objects/sequence/changes/sequence.privilege.ts +179 -0
  319. package/src/core/objects/sequence/changes/sequence.types.ts +12 -0
  320. package/src/core/objects/sequence/sequence.diff.test.ts +141 -0
  321. package/src/core/objects/sequence/sequence.diff.ts +359 -0
  322. package/src/core/objects/sequence/sequence.model.ts +185 -0
  323. package/src/core/objects/subscription/changes/subscription.alter.test.ts +124 -0
  324. package/src/core/objects/subscription/changes/subscription.alter.ts +110 -0
  325. package/src/core/objects/subscription/changes/subscription.base.ts +20 -0
  326. package/src/core/objects/subscription/changes/subscription.comment.test.ts +67 -0
  327. package/src/core/objects/subscription/changes/subscription.comment.ts +64 -0
  328. package/src/core/objects/subscription/changes/subscription.create.test.ts +77 -0
  329. package/src/core/objects/subscription/changes/subscription.create.ts +69 -0
  330. package/src/core/objects/subscription/changes/subscription.drop.test.ts +46 -0
  331. package/src/core/objects/subscription/changes/subscription.drop.ts +20 -0
  332. package/src/core/objects/subscription/changes/subscription.types.ts +22 -0
  333. package/src/core/objects/subscription/subscription.diff.test.ts +232 -0
  334. package/src/core/objects/subscription/subscription.diff.ts +241 -0
  335. package/src/core/objects/subscription/subscription.model.ts +190 -0
  336. package/src/core/objects/subscription/utils.ts +156 -0
  337. package/src/core/objects/table/changes/table.alter.test.ts +823 -0
  338. package/src/core/objects/table/changes/table.alter.ts +806 -0
  339. package/src/core/objects/table/changes/table.base.ts +20 -0
  340. package/src/core/objects/table/changes/table.comment.ts +266 -0
  341. package/src/core/objects/table/changes/table.create.test.ts +150 -0
  342. package/src/core/objects/table/changes/table.create.ts +188 -0
  343. package/src/core/objects/table/changes/table.drop.test.ts +34 -0
  344. package/src/core/objects/table/changes/table.drop.ts +45 -0
  345. package/src/core/objects/table/changes/table.privilege.ts +200 -0
  346. package/src/core/objects/table/changes/table.types.ts +12 -0
  347. package/src/core/objects/table/table.diff.test.ts +711 -0
  348. package/src/core/objects/table/table.diff.ts +953 -0
  349. package/src/core/objects/table/table.model.ts +460 -0
  350. package/src/core/objects/trigger/changes/trigger.alter.test.ts +46 -0
  351. package/src/core/objects/trigger/changes/trigger.alter.ts +76 -0
  352. package/src/core/objects/trigger/changes/trigger.base.ts +20 -0
  353. package/src/core/objects/trigger/changes/trigger.comment.ts +64 -0
  354. package/src/core/objects/trigger/changes/trigger.create.test.ts +43 -0
  355. package/src/core/objects/trigger/changes/trigger.create.ts +85 -0
  356. package/src/core/objects/trigger/changes/trigger.drop.test.ts +43 -0
  357. package/src/core/objects/trigger/changes/trigger.drop.ts +39 -0
  358. package/src/core/objects/trigger/changes/trigger.types.ts +10 -0
  359. package/src/core/objects/trigger/trigger.diff.test.ts +83 -0
  360. package/src/core/objects/trigger/trigger.diff.ts +116 -0
  361. package/src/core/objects/trigger/trigger.model.ts +252 -0
  362. package/src/core/objects/type/composite-type/changes/composite-type.alter.test.ts +202 -0
  363. package/src/core/objects/type/composite-type/changes/composite-type.alter.ts +174 -0
  364. package/src/core/objects/type/composite-type/changes/composite-type.base.ts +20 -0
  365. package/src/core/objects/type/composite-type/changes/composite-type.comment.ts +145 -0
  366. package/src/core/objects/type/composite-type/changes/composite-type.create.test.ts +101 -0
  367. package/src/core/objects/type/composite-type/changes/composite-type.create.ts +95 -0
  368. package/src/core/objects/type/composite-type/changes/composite-type.drop.test.ts +33 -0
  369. package/src/core/objects/type/composite-type/changes/composite-type.drop.ts +37 -0
  370. package/src/core/objects/type/composite-type/changes/composite-type.privilege.ts +175 -0
  371. package/src/core/objects/type/composite-type/changes/composite-type.types.ts +12 -0
  372. package/src/core/objects/type/composite-type/composite-type.diff.test.ts +191 -0
  373. package/src/core/objects/type/composite-type/composite-type.diff.ts +372 -0
  374. package/src/core/objects/type/composite-type/composite-type.model.ts +252 -0
  375. package/src/core/objects/type/enum/changes/enum.alter.test.ts +104 -0
  376. package/src/core/objects/type/enum/changes/enum.alter.ts +91 -0
  377. package/src/core/objects/type/enum/changes/enum.base.ts +20 -0
  378. package/src/core/objects/type/enum/changes/enum.comment.ts +64 -0
  379. package/src/core/objects/type/enum/changes/enum.create.test.ts +28 -0
  380. package/src/core/objects/type/enum/changes/enum.create.ts +56 -0
  381. package/src/core/objects/type/enum/changes/enum.drop.test.ts +25 -0
  382. package/src/core/objects/type/enum/changes/enum.drop.ts +34 -0
  383. package/src/core/objects/type/enum/changes/enum.privilege.ts +175 -0
  384. package/src/core/objects/type/enum/changes/enum.types.ts +12 -0
  385. package/src/core/objects/type/enum/enum.diff.test.ts +191 -0
  386. package/src/core/objects/type/enum/enum.diff.ts +396 -0
  387. package/src/core/objects/type/enum/enum.model.ts +194 -0
  388. package/src/core/objects/type/range/changes/range.alter.test.ts +27 -0
  389. package/src/core/objects/type/range/changes/range.alter.ts +51 -0
  390. package/src/core/objects/type/range/changes/range.base.ts +20 -0
  391. package/src/core/objects/type/range/changes/range.comment.ts +64 -0
  392. package/src/core/objects/type/range/changes/range.create.test.ts +51 -0
  393. package/src/core/objects/type/range/changes/range.create.ts +151 -0
  394. package/src/core/objects/type/range/changes/range.drop.test.ts +26 -0
  395. package/src/core/objects/type/range/changes/range.drop.ts +34 -0
  396. package/src/core/objects/type/range/changes/range.privilege.ts +175 -0
  397. package/src/core/objects/type/range/changes/range.types.ts +12 -0
  398. package/src/core/objects/type/range/range.diff.test.ts +70 -0
  399. package/src/core/objects/type/range/range.diff.ts +259 -0
  400. package/src/core/objects/type/range/range.model.ts +187 -0
  401. package/src/core/objects/type/type.types.ts +5 -0
  402. package/src/core/objects/utils.ts +171 -0
  403. package/src/core/objects/view/changes/view.alter.test.ts +110 -0
  404. package/src/core/objects/view/changes/view.alter.ts +112 -0
  405. package/src/core/objects/view/changes/view.base.ts +20 -0
  406. package/src/core/objects/view/changes/view.comment.ts +59 -0
  407. package/src/core/objects/view/changes/view.create.test.ts +65 -0
  408. package/src/core/objects/view/changes/view.create.ts +73 -0
  409. package/src/core/objects/view/changes/view.drop.test.ts +34 -0
  410. package/src/core/objects/view/changes/view.drop.ts +40 -0
  411. package/src/core/objects/view/changes/view.privilege.ts +200 -0
  412. package/src/core/objects/view/changes/view.types.ts +12 -0
  413. package/src/core/objects/view/view.diff.test.ts +91 -0
  414. package/src/core/objects/view/view.diff.ts +365 -0
  415. package/src/core/objects/view/view.model.ts +276 -0
  416. package/src/core/plan/apply.ts +190 -0
  417. package/src/core/plan/create.ts +432 -0
  418. package/src/core/plan/hierarchy.ts +574 -0
  419. package/src/core/plan/index.ts +29 -0
  420. package/src/core/plan/io.ts +20 -0
  421. package/src/core/plan/risk.ts +48 -0
  422. package/src/core/plan/serialize.ts +195 -0
  423. package/src/core/plan/sql-format/constants.ts +13 -0
  424. package/src/core/plan/sql-format/fixtures.ts +2806 -0
  425. package/src/core/plan/sql-format/format-comment-literals.test.ts +96 -0
  426. package/src/core/plan/sql-format/format-functions.test.ts +127 -0
  427. package/src/core/plan/sql-format/format-lowercase-coverage.test.ts +67 -0
  428. package/src/core/plan/sql-format/format-off.test.ts +809 -0
  429. package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +1056 -0
  430. package/src/core/plan/sql-format/format-pretty-narrow.test.ts +1283 -0
  431. package/src/core/plan/sql-format/format-pretty-preserve.test.ts +1052 -0
  432. package/src/core/plan/sql-format/format-pretty-upper.test.ts +1045 -0
  433. package/src/core/plan/sql-format/format-stress.test.ts +616 -0
  434. package/src/core/plan/sql-format/format-utils.test.ts +91 -0
  435. package/src/core/plan/sql-format/format-utils.ts +391 -0
  436. package/src/core/plan/sql-format/formatters.ts +921 -0
  437. package/src/core/plan/sql-format/index.ts +149 -0
  438. package/src/core/plan/sql-format/keyword-case.test.ts +118 -0
  439. package/src/core/plan/sql-format/keyword-case.ts +1085 -0
  440. package/src/core/plan/sql-format/protect.test.ts +127 -0
  441. package/src/core/plan/sql-format/protect.ts +337 -0
  442. package/src/core/plan/sql-format/sql-scanner.test.ts +240 -0
  443. package/src/core/plan/sql-format/sql-scanner.ts +252 -0
  444. package/src/core/plan/sql-format/tokenizer.test.ts +68 -0
  445. package/src/core/plan/sql-format/tokenizer.ts +152 -0
  446. package/src/core/plan/sql-format/types.ts +31 -0
  447. package/src/core/plan/sql-format/wrap.test.ts +119 -0
  448. package/src/core/plan/sql-format/wrap.ts +196 -0
  449. package/src/core/plan/sql-format.ts +2 -0
  450. package/src/core/plan/statements.ts +22 -0
  451. package/src/core/plan/types.ts +165 -0
  452. package/src/core/postgres-config.ts +169 -0
  453. package/src/core/sort/custom-constraints.ts +161 -0
  454. package/src/core/sort/debug-visualization.ts +239 -0
  455. package/src/core/sort/dependency-filter.ts +224 -0
  456. package/src/core/sort/graph-builder.ts +223 -0
  457. package/src/core/sort/graph-utils.ts +51 -0
  458. package/src/core/sort/logical-sort.ts +590 -0
  459. package/src/core/sort/sort-changes.ts +234 -0
  460. package/src/core/sort/topological-sort.ts +184 -0
  461. package/src/core/sort/types.ts +112 -0
  462. package/src/core/sort/utils.ts +69 -0
  463. package/src/index.ts +14 -0
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { Trigger } from "../trigger.model.ts";
3
+ import { CreateTrigger } from "./trigger.create.ts";
4
+
5
+ describe("trigger", () => {
6
+ test("create", () => {
7
+ const trigger = new Trigger({
8
+ schema: "public",
9
+ name: "test_trigger",
10
+ table_name: "test_table",
11
+ function_schema: "public",
12
+ function_name: "test_function",
13
+ trigger_type: (1 << 1) | (1 << 2) | (1 << 0), // BEFORE (1<<1) | INSERT (1<<2) | ROW (1<<0) = 7
14
+ enabled: "O",
15
+ is_internal: false,
16
+ deferrable: false,
17
+ initially_deferred: false,
18
+ argument_count: 0,
19
+ column_numbers: null,
20
+ arguments: [],
21
+ when_condition: null,
22
+ old_table: null,
23
+ new_table: null,
24
+ is_partition_clone: false,
25
+ parent_trigger_name: null,
26
+ parent_table_schema: null,
27
+ parent_table_name: null,
28
+ is_on_partitioned_table: false,
29
+ owner: "test",
30
+ definition:
31
+ "CREATE TRIGGER test_trigger BEFORE INSERT ON public.test_table FOR EACH ROW EXECUTE FUNCTION public.test_function()",
32
+ comment: null,
33
+ });
34
+
35
+ const change = new CreateTrigger({
36
+ trigger,
37
+ });
38
+
39
+ expect(change.serialize()).toBe(
40
+ "CREATE TRIGGER test_trigger BEFORE INSERT ON public.test_table FOR EACH ROW EXECUTE FUNCTION public.test_function()",
41
+ );
42
+ });
43
+ });
@@ -0,0 +1,85 @@
1
+ import type { TableLikeObject } from "../../base.model.ts";
2
+ import { stableId } from "../../utils.ts";
3
+ import type { Trigger } from "../trigger.model.ts";
4
+ import { CreateTriggerChange } from "./trigger.base.ts";
5
+
6
+ /**
7
+ * Create a trigger.
8
+ *
9
+ * @see https://www.postgresql.org/docs/17/sql-createtrigger.html
10
+ *
11
+ * Synopsis
12
+ * ```sql
13
+ * CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
14
+ * ON table_name
15
+ * [ FROM referenced_table_name ]
16
+ * [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
17
+ * [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
18
+ * [ FOR [ EACH ] { ROW | STATEMENT } ]
19
+ * [ WHEN ( condition ) ]
20
+ * EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )
21
+ *
22
+ * where event can be one of:
23
+ *
24
+ * INSERT
25
+ * UPDATE [ OF column_name [, ... ] ]
26
+ * DELETE
27
+ * TRUNCATE
28
+ * ```
29
+ */
30
+ export class CreateTrigger extends CreateTriggerChange {
31
+ public readonly trigger: Trigger;
32
+ public readonly indexableObject?: TableLikeObject;
33
+ public readonly orReplace?: boolean;
34
+ public readonly scope = "object" as const;
35
+
36
+ constructor(props: {
37
+ trigger: Trigger;
38
+ indexableObject?: TableLikeObject;
39
+ orReplace?: boolean;
40
+ }) {
41
+ super();
42
+ this.trigger = props.trigger;
43
+ this.indexableObject = props.indexableObject;
44
+ this.orReplace = props.orReplace;
45
+ }
46
+
47
+ get creates() {
48
+ return [this.trigger.stableId];
49
+ }
50
+
51
+ get requires() {
52
+ const dependencies = new Set<string>();
53
+
54
+ // Schema dependency
55
+ dependencies.add(stableId.schema(this.trigger.schema));
56
+
57
+ // Table dependency
58
+ dependencies.add(
59
+ stableId.table(this.trigger.schema, this.trigger.table_name),
60
+ );
61
+
62
+ // Function dependency
63
+ // Note: We can't build the exact procedure stableId without argument types.
64
+ // The trigger definition contains the full function call, but parsing it would be complex.
65
+ // For now, we rely on pg_depend extraction for procedure dependencies.
66
+ // If needed, we could parse the trigger definition to extract the full function signature.
67
+
68
+ // Owner dependency
69
+ dependencies.add(stableId.role(this.trigger.owner));
70
+
71
+ return Array.from(dependencies);
72
+ }
73
+
74
+ serialize(): string {
75
+ let definition = this.trigger.definition.trim();
76
+ const isConstraintTrigger = this.trigger.isConstraintTrigger;
77
+
78
+ definition = definition.replace(
79
+ /^CREATE\s+(?:OR\s+REPLACE\s+)?/i,
80
+ `CREATE ${this.orReplace && !isConstraintTrigger ? "OR REPLACE " : ""}`,
81
+ );
82
+
83
+ return definition;
84
+ }
85
+ }
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { Trigger } from "../trigger.model.ts";
3
+ import { DropTrigger } from "./trigger.drop.ts";
4
+
5
+ describe("trigger", () => {
6
+ test("drop", () => {
7
+ const trigger = new Trigger({
8
+ schema: "public",
9
+ name: "test_trigger",
10
+ table_name: "test_table",
11
+ function_schema: "public",
12
+ function_name: "test_function",
13
+ trigger_type: 66,
14
+ enabled: "O",
15
+ is_internal: false,
16
+ deferrable: false,
17
+ initially_deferred: false,
18
+ argument_count: 0,
19
+ column_numbers: null,
20
+ arguments: [],
21
+ when_condition: null,
22
+ old_table: null,
23
+ new_table: null,
24
+ is_partition_clone: false,
25
+ parent_trigger_name: null,
26
+ parent_table_schema: null,
27
+ parent_table_name: null,
28
+ is_on_partitioned_table: false,
29
+ owner: "test",
30
+ definition:
31
+ "CREATE TRIGGER test_trigger BEFORE UPDATE ON public.test_table FOR EACH ROW EXECUTE FUNCTION public.test_function()",
32
+ comment: null,
33
+ });
34
+
35
+ const change = new DropTrigger({
36
+ trigger,
37
+ });
38
+
39
+ expect(change.serialize()).toBe(
40
+ "DROP TRIGGER test_trigger ON public.test_table",
41
+ );
42
+ });
43
+ });
@@ -0,0 +1,39 @@
1
+ import type { Trigger } from "../trigger.model.ts";
2
+ import { DropTriggerChange } from "./trigger.base.ts";
3
+
4
+ /**
5
+ * Drop a trigger.
6
+ *
7
+ * @see https://www.postgresql.org/docs/17/sql-droptrigger.html
8
+ *
9
+ * Synopsis
10
+ * ```sql
11
+ * DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
12
+ * ```
13
+ */
14
+ export class DropTrigger extends DropTriggerChange {
15
+ public readonly trigger: Trigger;
16
+ public readonly scope = "object" as const;
17
+
18
+ constructor(props: { trigger: Trigger }) {
19
+ super();
20
+ this.trigger = props.trigger;
21
+ }
22
+
23
+ get drops() {
24
+ return [this.trigger.stableId];
25
+ }
26
+
27
+ get requires() {
28
+ return [this.trigger.stableId];
29
+ }
30
+
31
+ serialize(): string {
32
+ return [
33
+ "DROP TRIGGER",
34
+ this.trigger.name,
35
+ "ON",
36
+ `${this.trigger.schema}.${this.trigger.table_name}`,
37
+ ].join(" ");
38
+ }
39
+ }
@@ -0,0 +1,10 @@
1
+ import type { AlterTrigger } from "./trigger.alter.ts";
2
+ import type { CommentTrigger } from "./trigger.comment.ts";
3
+ import type { CreateTrigger } from "./trigger.create.ts";
4
+ import type { DropTrigger } from "./trigger.drop.ts";
5
+
6
+ export type TriggerChange =
7
+ | AlterTrigger
8
+ | CommentTrigger
9
+ | CreateTrigger
10
+ | DropTrigger;
@@ -0,0 +1,83 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { ReplaceTrigger } from "./changes/trigger.alter.ts";
3
+ import { CreateTrigger } from "./changes/trigger.create.ts";
4
+ import { DropTrigger } from "./changes/trigger.drop.ts";
5
+ import { diffTriggers } from "./trigger.diff.ts";
6
+ import { Trigger, type TriggerProps } from "./trigger.model.ts";
7
+
8
+ const base: Omit<
9
+ TriggerProps,
10
+ | "function_name"
11
+ | "column_numbers"
12
+ | "arguments"
13
+ | "when_condition"
14
+ | "old_table"
15
+ | "new_table"
16
+ > = {
17
+ schema: "public",
18
+ name: "trg",
19
+ table_name: "t",
20
+ function_schema: "public",
21
+ trigger_type: 1,
22
+ enabled: "O",
23
+ is_internal: false,
24
+ deferrable: false,
25
+ initially_deferred: false,
26
+ argument_count: 0,
27
+ is_partition_clone: false,
28
+ parent_trigger_name: null,
29
+ parent_table_schema: null,
30
+ parent_table_name: null,
31
+ is_on_partitioned_table: false,
32
+ owner: "o1",
33
+ definition: "CREATE TRIGGER trg ON t FOR EACH ROW EXECUTE FUNCTION fn1()",
34
+ comment: null,
35
+ };
36
+
37
+ describe.concurrent("trigger.diff", () => {
38
+ test("create and drop", () => {
39
+ const trg = new Trigger({
40
+ ...base,
41
+ function_name: "fn1",
42
+ column_numbers: null,
43
+ arguments: [],
44
+ when_condition: null,
45
+ old_table: null,
46
+ new_table: null,
47
+ });
48
+
49
+ const created = diffTriggers({}, { [trg.stableId]: trg });
50
+ expect(created[0]).toBeInstanceOf(CreateTrigger);
51
+
52
+ const dropped = diffTriggers({ [trg.stableId]: trg }, {});
53
+ expect(dropped[0]).toBeInstanceOf(DropTrigger);
54
+ });
55
+
56
+ test("replace when non-alterable changes", () => {
57
+ const main = new Trigger({
58
+ ...base,
59
+ function_name: "fn1",
60
+ column_numbers: null,
61
+ arguments: [],
62
+ when_condition: null,
63
+ old_table: null,
64
+ new_table: null,
65
+ });
66
+ const branch = new Trigger({
67
+ ...base,
68
+ function_name: "fn2",
69
+ column_numbers: null,
70
+ arguments: [],
71
+ when_condition: null,
72
+ old_table: null,
73
+ new_table: null,
74
+ });
75
+
76
+ const changes = diffTriggers(
77
+ { [main.stableId]: main },
78
+ { [branch.stableId]: branch },
79
+ );
80
+ expect(changes).toHaveLength(1);
81
+ expect(changes[0]).toBeInstanceOf(ReplaceTrigger);
82
+ });
83
+ });
@@ -0,0 +1,116 @@
1
+ import { diffObjects } from "../base.diff.ts";
2
+ import type { TableLikeObject } from "../base.model.ts";
3
+ import { deepEqual, hasNonAlterableChanges, stableId } from "../utils.ts";
4
+ import { ReplaceTrigger } from "./changes/trigger.alter.ts";
5
+ import {
6
+ CreateCommentOnTrigger,
7
+ DropCommentOnTrigger,
8
+ } from "./changes/trigger.comment.ts";
9
+ import { CreateTrigger } from "./changes/trigger.create.ts";
10
+ import { DropTrigger } from "./changes/trigger.drop.ts";
11
+ import type { TriggerChange } from "./changes/trigger.types.ts";
12
+ import type { Trigger } from "./trigger.model.ts";
13
+
14
+ /**
15
+ * Diff two sets of triggers from main and branch catalogs.
16
+ *
17
+ * @param main - The triggers in the main catalog.
18
+ * @param branch - The triggers in the branch catalog.
19
+ * @returns A list of changes to apply to main to make it match branch.
20
+ */
21
+ export function diffTriggers(
22
+ main: Record<string, Trigger>,
23
+ branch: Record<string, Trigger>,
24
+ branchIndexableObjects?: Record<string, TableLikeObject>,
25
+ ): TriggerChange[] {
26
+ const { created, dropped, altered } = diffObjects(main, branch);
27
+
28
+ const changes: TriggerChange[] = [];
29
+
30
+ for (const triggerId of created) {
31
+ const trigger = branch[triggerId];
32
+
33
+ // Skip trigger clones on partitions - they are automatically created when the parent trigger is created
34
+ if (trigger.is_partition_clone) {
35
+ continue;
36
+ }
37
+
38
+ const tableStableId = stableId.table(trigger.schema, trigger.table_name);
39
+ changes.push(
40
+ new CreateTrigger({
41
+ trigger: trigger,
42
+ indexableObject: branchIndexableObjects?.[tableStableId],
43
+ }),
44
+ );
45
+ if (trigger.comment !== null) {
46
+ changes.push(new CreateCommentOnTrigger({ trigger: trigger }));
47
+ }
48
+ }
49
+
50
+ for (const triggerId of dropped) {
51
+ const trigger = main[triggerId];
52
+
53
+ // Skip trigger clones on partitions - they are automatically dropped when the parent trigger is dropped
54
+ if (trigger.is_partition_clone) {
55
+ continue;
56
+ }
57
+
58
+ changes.push(new DropTrigger({ trigger }));
59
+ }
60
+
61
+ for (const triggerId of altered) {
62
+ const mainTrigger = main[triggerId];
63
+ const branchTrigger = branch[triggerId];
64
+
65
+ // Skip trigger clones on partitions - they are automatically updated when the parent trigger is updated
66
+ if (mainTrigger.is_partition_clone || branchTrigger.is_partition_clone) {
67
+ continue;
68
+ }
69
+
70
+ const NON_ALTERABLE_FIELDS: Array<keyof Trigger> = [
71
+ "function_schema",
72
+ "function_name",
73
+ "trigger_type",
74
+ "enabled",
75
+ "is_internal",
76
+ "deferrable",
77
+ "initially_deferred",
78
+ "argument_count",
79
+ "column_numbers",
80
+ "arguments",
81
+ "when_condition",
82
+ "old_table",
83
+ "new_table",
84
+ "owner",
85
+ ];
86
+ const shouldReplace = hasNonAlterableChanges(
87
+ mainTrigger,
88
+ branchTrigger,
89
+ NON_ALTERABLE_FIELDS,
90
+ { column_numbers: deepEqual, arguments: deepEqual },
91
+ );
92
+ if (shouldReplace) {
93
+ const tableStableId = stableId.table(
94
+ branchTrigger.schema,
95
+ branchTrigger.table_name,
96
+ );
97
+ changes.push(
98
+ new ReplaceTrigger({
99
+ trigger: branchTrigger,
100
+ indexableObject: branchIndexableObjects?.[tableStableId],
101
+ }),
102
+ );
103
+ } else {
104
+ // COMMENT
105
+ if (mainTrigger.comment !== branchTrigger.comment) {
106
+ if (branchTrigger.comment === null) {
107
+ changes.push(new DropCommentOnTrigger({ trigger: mainTrigger }));
108
+ } else {
109
+ changes.push(new CreateCommentOnTrigger({ trigger: branchTrigger }));
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ return changes;
116
+ }
@@ -0,0 +1,252 @@
1
+ import { sql } from "@ts-safeql/sql-tag";
2
+ import type { Pool } from "pg";
3
+ import z from "zod";
4
+ import { BasePgModel } from "../base.model.ts";
5
+
6
+ const TriggerEnabledSchema = z.enum([
7
+ "O", // ORIGIN - trigger fires in "origin" and "local" replica modes
8
+ "D", // DISABLED - trigger is disabled
9
+ "R", // REPLICA - trigger fires only in "replica" mode
10
+ "A", // ALWAYS - trigger fires regardless of replication mode
11
+ ]);
12
+
13
+ const triggerPropsSchema = z.object({
14
+ schema: z.string(),
15
+ name: z.string(),
16
+ table_name: z.string(),
17
+ function_schema: z.string(),
18
+ function_name: z.string(),
19
+ trigger_type: z.number(),
20
+ enabled: TriggerEnabledSchema,
21
+ is_internal: z.boolean(),
22
+ deferrable: z.boolean(),
23
+ initially_deferred: z.boolean(),
24
+ argument_count: z.number(),
25
+ column_numbers: z.array(z.number()).nullable(),
26
+ arguments: z.array(z.string()),
27
+ when_condition: z.string().nullable(),
28
+ old_table: z.string().nullable(),
29
+ new_table: z.string().nullable(),
30
+ is_partition_clone: z.boolean(),
31
+ parent_trigger_name: z.string().nullable(),
32
+ parent_table_schema: z.string().nullable(),
33
+ parent_table_name: z.string().nullable(),
34
+ is_on_partitioned_table: z.boolean(),
35
+ owner: z.string(),
36
+ definition: z.string(),
37
+ comment: z.string().nullable(),
38
+ });
39
+
40
+ export type TriggerProps = z.infer<typeof triggerPropsSchema>;
41
+
42
+ export class Trigger extends BasePgModel {
43
+ public readonly schema: TriggerProps["schema"];
44
+ public readonly name: TriggerProps["name"];
45
+ public readonly table_name: TriggerProps["table_name"];
46
+ public readonly function_schema: TriggerProps["function_schema"];
47
+ public readonly function_name: TriggerProps["function_name"];
48
+ public readonly trigger_type: TriggerProps["trigger_type"];
49
+ public readonly enabled: TriggerProps["enabled"];
50
+ public readonly is_internal: TriggerProps["is_internal"];
51
+ public readonly deferrable: TriggerProps["deferrable"];
52
+ public readonly initially_deferred: TriggerProps["initially_deferred"];
53
+ public readonly argument_count: TriggerProps["argument_count"];
54
+ public readonly column_numbers: TriggerProps["column_numbers"];
55
+ public readonly arguments: TriggerProps["arguments"];
56
+ public readonly when_condition: TriggerProps["when_condition"];
57
+ public readonly old_table: TriggerProps["old_table"];
58
+ public readonly new_table: TriggerProps["new_table"];
59
+ public readonly is_partition_clone: TriggerProps["is_partition_clone"];
60
+ public readonly parent_trigger_name: TriggerProps["parent_trigger_name"];
61
+ public readonly parent_table_schema: TriggerProps["parent_table_schema"];
62
+ public readonly parent_table_name: TriggerProps["parent_table_name"];
63
+ public readonly is_on_partitioned_table: TriggerProps["is_on_partitioned_table"];
64
+ public readonly owner: TriggerProps["owner"];
65
+ public readonly definition: TriggerProps["definition"];
66
+ public readonly comment: TriggerProps["comment"];
67
+
68
+ constructor(props: TriggerProps) {
69
+ super();
70
+
71
+ // Identity fields
72
+ this.schema = props.schema;
73
+ this.name = props.name;
74
+ this.table_name = props.table_name;
75
+
76
+ // Data fields
77
+ this.function_schema = props.function_schema;
78
+ this.function_name = props.function_name;
79
+ this.trigger_type = props.trigger_type;
80
+ this.enabled = props.enabled;
81
+ this.is_internal = props.is_internal;
82
+ this.deferrable = props.deferrable;
83
+ this.initially_deferred = props.initially_deferred;
84
+ this.argument_count = props.argument_count;
85
+ this.column_numbers = props.column_numbers;
86
+ this.arguments = props.arguments;
87
+ this.when_condition = props.when_condition;
88
+ this.old_table = props.old_table;
89
+ this.new_table = props.new_table;
90
+ this.is_partition_clone = props.is_partition_clone;
91
+ this.parent_trigger_name = props.parent_trigger_name;
92
+ this.parent_table_schema = props.parent_table_schema;
93
+ this.parent_table_name = props.parent_table_name;
94
+ this.is_on_partitioned_table = props.is_on_partitioned_table;
95
+ this.owner = props.owner;
96
+ this.definition = props.definition;
97
+ this.comment = props.comment;
98
+ }
99
+
100
+ get isConstraintTrigger(): boolean {
101
+ return /^CREATE\s+CONSTRAINT\s+TRIGGER/i.test(this.definition.trim());
102
+ }
103
+
104
+ get stableId(): `trigger:${string}` {
105
+ return `trigger:${this.schema}.${this.table_name}.${this.name}`;
106
+ }
107
+
108
+ get identityFields() {
109
+ return {
110
+ schema: this.schema,
111
+ name: this.name,
112
+ table_name: this.table_name,
113
+ };
114
+ }
115
+
116
+ get dataFields() {
117
+ return {
118
+ function_schema: this.function_schema,
119
+ function_name: this.function_name,
120
+ trigger_type: this.trigger_type,
121
+ enabled: this.enabled,
122
+ is_internal: this.is_internal,
123
+ deferrable: this.deferrable,
124
+ initially_deferred: this.initially_deferred,
125
+ argument_count: this.argument_count,
126
+ column_numbers: this.column_numbers,
127
+ arguments: this.arguments,
128
+ when_condition: this.when_condition,
129
+ old_table: this.old_table,
130
+ new_table: this.new_table,
131
+ is_partition_clone: this.is_partition_clone,
132
+ parent_trigger_name: this.parent_trigger_name,
133
+ parent_table_schema: this.parent_table_schema,
134
+ parent_table_name: this.parent_table_name,
135
+ is_on_partitioned_table: this.is_on_partitioned_table,
136
+ owner: this.owner,
137
+ comment: this.comment,
138
+ };
139
+ }
140
+ }
141
+
142
+ export async function extractTriggers(pool: Pool): Promise<Trigger[]> {
143
+ const { rows: triggerRows } = await pool.query<TriggerProps>(sql`
144
+ with extension_trigger_oids as (
145
+ select objid
146
+ from pg_depend d
147
+ where d.refclassid = 'pg_extension'::regclass
148
+ and d.classid = 'pg_trigger'::regclass
149
+ ),
150
+ extension_table_oids as (
151
+ select objid
152
+ from pg_depend d
153
+ where d.refclassid = 'pg_extension'::regclass
154
+ and d.classid = 'pg_class'::regclass
155
+ and d.deptype = 'e'
156
+ ),
157
+ extension_function_oids as (
158
+ select objid
159
+ from pg_depend d
160
+ where d.refclassid = 'pg_extension'::regclass
161
+ and d.classid = 'pg_proc'::regclass
162
+ )
163
+ select
164
+ tc.relnamespace::regnamespace::text as schema,
165
+ quote_ident(t.tgname) as name,
166
+ quote_ident(tc.relname) as table_name,
167
+
168
+ fc.pronamespace::regnamespace::text as function_schema,
169
+ quote_ident(fc.proname) as function_name,
170
+
171
+ t.tgtype as trigger_type,
172
+ t.tgenabled as enabled,
173
+ t.tgisinternal as is_internal,
174
+ t.tgdeferrable as deferrable,
175
+ t.tginitdeferred as initially_deferred,
176
+ t.tgnargs as argument_count,
177
+ t.tgattr as column_numbers,
178
+
179
+ case when t.tgnargs > 0
180
+ then array_fill(''::text, array[t.tgnargs])
181
+ else array[]::text[]
182
+ end as arguments,
183
+
184
+ -- identify triggers cloned onto partitions (created/attached partitions)
185
+ (t.tgparentid <> 0::oid) as is_partition_clone,
186
+ case when t.tgparentid <> 0::oid
187
+ then quote_ident(parent_t.tgname)
188
+ else null
189
+ end as parent_trigger_name,
190
+ case when t.tgparentid <> 0::oid
191
+ then parent_tc.relnamespace::regnamespace::text
192
+ else null
193
+ end as parent_table_schema,
194
+ case when t.tgparentid <> 0::oid
195
+ then quote_ident(parent_tc.relname)
196
+ else null
197
+ end as parent_table_name,
198
+
199
+ (tc.relkind = 'p') as is_on_partitioned_table,
200
+
201
+ (
202
+ case
203
+ when strpos(defn.definition, ' WHEN (') > 0
204
+ and strpos(defn.definition, ') EXECUTE') >
205
+ strpos(defn.definition, ' WHEN (') + 7
206
+ then substr(
207
+ defn.definition,
208
+ strpos(defn.definition, ' WHEN (') + 7,
209
+ strpos(defn.definition, ') EXECUTE')
210
+ - (strpos(defn.definition, ' WHEN (') + 7)
211
+ )
212
+ else null
213
+ end
214
+ ) as when_condition,
215
+
216
+ t.tgoldtable as old_table,
217
+ t.tgnewtable as new_table,
218
+ tc.relowner::regrole::text as owner,
219
+ defn.definition as definition,
220
+ obj_description(t.oid, 'pg_trigger') as comment
221
+
222
+ from pg_catalog.pg_trigger t
223
+ join pg_catalog.pg_class tc on tc.oid = t.tgrelid
224
+ join pg_catalog.pg_proc fc on fc.oid = t.tgfoid
225
+
226
+ -- compute trigger definition once
227
+ left join lateral (
228
+ select pg_get_triggerdef(t.oid, true) as definition
229
+ ) defn on true
230
+
231
+ -- parent trigger/table linkage for cloned (partition) triggers
232
+ left join pg_catalog.pg_trigger parent_t on parent_t.oid = t.tgparentid
233
+ left join pg_catalog.pg_class parent_tc on parent_tc.oid = parent_t.tgrelid
234
+
235
+ left join extension_trigger_oids e_trigger on t.oid = e_trigger.objid
236
+ left join extension_table_oids e_table on tc.oid = e_table.objid
237
+ left join extension_function_oids e_function on fc.oid = e_function.objid
238
+
239
+ where not tc.relnamespace::regnamespace::text like any(array['pg\\_%', 'information\\_schema'])
240
+ and e_trigger.objid is null
241
+ and e_table.objid is null
242
+ and e_function.objid is null
243
+ and not t.tgisinternal
244
+
245
+ order by 1, 2
246
+ `);
247
+ // Validate and parse each row using the Zod schema
248
+ const validatedRows = triggerRows.map((row: unknown) =>
249
+ triggerPropsSchema.parse(row),
250
+ );
251
+ return validatedRows.map((row: TriggerProps) => new Trigger(row));
252
+ }