@prisma/orm-target-postgres 0.16.0-dev.36

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 (279) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +23 -0
  3. package/dist/adapter-CWvVo0PV.d.mts +22 -0
  4. package/dist/adapter-CWvVo0PV.d.mts.map +1 -0
  5. package/dist/adapter-DhqcO3YO-jzwDVcCv.mjs +70 -0
  6. package/dist/adapter-DhqcO3YO-jzwDVcCv.mjs.map +1 -0
  7. package/dist/adapter.d.mts +12 -0
  8. package/dist/adapter.mjs +7 -0
  9. package/dist/adapter__adapter.d.mts +2 -0
  10. package/dist/adapter__adapter.mjs +2 -0
  11. package/dist/adapter__column-types.d.mts +2 -0
  12. package/dist/adapter__column-types.mjs +2 -0
  13. package/dist/adapter__control.d.mts +5 -0
  14. package/dist/adapter__control.mjs +441 -0
  15. package/dist/adapter__control.mjs.map +1 -0
  16. package/dist/adapter__operation-types.d.mts +2 -0
  17. package/dist/adapter__operation-types.mjs +1 -0
  18. package/dist/adapter__runtime.d.mts +2 -0
  19. package/dist/adapter__runtime.mjs +38 -0
  20. package/dist/adapter__runtime.mjs.map +1 -0
  21. package/dist/adapter__types.d.mts +4 -0
  22. package/dist/adapter__types.mjs +1 -0
  23. package/dist/authoring-03FwIL2k-kPjZAp3s.mjs +757 -0
  24. package/dist/authoring-03FwIL2k-kPjZAp3s.mjs.map +1 -0
  25. package/dist/canonicalize-CQlxSR4D-MnrT5gtW.d.mts +34 -0
  26. package/dist/canonicalize-CQlxSR4D-MnrT5gtW.d.mts.map +1 -0
  27. package/dist/canonicalize-CrN3u_xM-D4MrOqcB.mjs +59 -0
  28. package/dist/canonicalize-CrN3u_xM-D4MrOqcB.mjs.map +1 -0
  29. package/dist/codec-descriptor-Bec_zukr-BfvtUqhm.d.mts +37 -0
  30. package/dist/codec-descriptor-Bec_zukr-BfvtUqhm.d.mts.map +1 -0
  31. package/dist/codec-descriptor-Bg-_412t.d.mts +1 -0
  32. package/dist/codec-descriptor-CB6x0xEu-C-Zn2IEz.mjs +135 -0
  33. package/dist/codec-descriptor-CB6x0xEu-C-Zn2IEz.mjs.map +1 -0
  34. package/dist/codec-ids-CsOU3xDv-mPI0INiF.d.mts +33 -0
  35. package/dist/codec-ids-CsOU3xDv-mPI0INiF.d.mts.map +1 -0
  36. package/dist/codec-ids-fgafMLR7.d.mts +1 -0
  37. package/dist/codec-ids-tX7Svtz--BuOfRaVU.mjs +33 -0
  38. package/dist/codec-ids-tX7Svtz--BuOfRaVU.mjs.map +1 -0
  39. package/dist/codec-types-BHwY9Ff-.d.mts +2 -0
  40. package/dist/codec-types-mWhnDEAf-CAQzGFnF.d.mts +82 -0
  41. package/dist/codec-types-mWhnDEAf-CAQzGFnF.d.mts.map +1 -0
  42. package/dist/codecs-CBl0nD44-CaWPc1bd.mjs +1486 -0
  43. package/dist/codecs-CBl0nD44-CaWPc1bd.mjs.map +1 -0
  44. package/dist/codecs-CHIVTNZs.mjs +15 -0
  45. package/dist/codecs-CHIVTNZs.mjs.map +1 -0
  46. package/dist/codecs-Cvqvb9pV-Cdc51FKY.d.mts +589 -0
  47. package/dist/codecs-Cvqvb9pV-Cdc51FKY.d.mts.map +1 -0
  48. package/dist/codecs-DBn-uIv-.d.mts +15 -0
  49. package/dist/codecs-DBn-uIv-.d.mts.map +1 -0
  50. package/dist/column-types-BH-MU6uU.d.mts +108 -0
  51. package/dist/column-types-BH-MU6uU.d.mts.map +1 -0
  52. package/dist/column-types-CwAyCgp2.mjs +126 -0
  53. package/dist/column-types-CwAyCgp2.mjs.map +1 -0
  54. package/dist/contract-free-BZUS18FU.mjs +118 -0
  55. package/dist/contract-free-BZUS18FU.mjs.map +1 -0
  56. package/dist/contract-free-DzpGxLfb.d.mts +258 -0
  57. package/dist/contract-free-DzpGxLfb.d.mts.map +1 -0
  58. package/dist/control-2F195jJk.d.mts +11 -0
  59. package/dist/control-2F195jJk.d.mts.map +1 -0
  60. package/dist/control-6WFTtLAM.mjs +60 -0
  61. package/dist/control-6WFTtLAM.mjs.map +1 -0
  62. package/dist/control-B-FTbEnE.d.mts +22 -0
  63. package/dist/control-B-FTbEnE.d.mts.map +1 -0
  64. package/dist/control-D85zv_aY.d.mts +199 -0
  65. package/dist/control-D85zv_aY.d.mts.map +1 -0
  66. package/dist/control-DRMWptiJ.mjs +1355 -0
  67. package/dist/control-DRMWptiJ.mjs.map +1 -0
  68. package/dist/control-adapter-B9t0g7Pf-HrCxlM65.mjs +1901 -0
  69. package/dist/control-adapter-B9t0g7Pf-HrCxlM65.mjs.map +1 -0
  70. package/dist/control-policy-Cl3RRSPg-CT3QGpR3.mjs +1257 -0
  71. package/dist/control-policy-Cl3RRSPg-CT3QGpR3.mjs.map +1 -0
  72. package/dist/data-transform-BSM7TQpE.d.mts +1 -0
  73. package/dist/data-transform-ChZzy2dP-CxVCat_8.mjs +53 -0
  74. package/dist/data-transform-ChZzy2dP-CxVCat_8.mjs.map +1 -0
  75. package/dist/data-transform-Ck5FbyNO-BNE7QlAo.d.mts +38 -0
  76. package/dist/data-transform-Ck5FbyNO-BNE7QlAo.d.mts.map +1 -0
  77. package/dist/ddl-B4Rh8ntj.d.mts +1 -0
  78. package/dist/ddl-BdP4q3KY-Duef4uHw.mjs +395 -0
  79. package/dist/ddl-BdP4q3KY-Duef4uHw.mjs.map +1 -0
  80. package/dist/default-normalizer-B36TOul4.d.mts +31 -0
  81. package/dist/default-normalizer-B36TOul4.d.mts.map +1 -0
  82. package/dist/default-normalizer-Ba5ZebHM-isV86rjy.mjs +253 -0
  83. package/dist/default-normalizer-Ba5ZebHM-isV86rjy.mjs.map +1 -0
  84. package/dist/descriptor-meta-2IlVC6_d-DnV00Qd_.mjs +351 -0
  85. package/dist/descriptor-meta-2IlVC6_d-DnV00Qd_.mjs.map +1 -0
  86. package/dist/descriptor-meta-DnHabAS3-C53XXPQw.mjs +28 -0
  87. package/dist/descriptor-meta-DnHabAS3-C53XXPQw.mjs.map +1 -0
  88. package/dist/descriptor-meta-runtime-UwYdV8fD-B_m_Ha8r.mjs +13 -0
  89. package/dist/descriptor-meta-runtime-UwYdV8fD-B_m_Ha8r.mjs.map +1 -0
  90. package/dist/diff-database-schema-BfRs2vrG-D2o4KII0.mjs +390 -0
  91. package/dist/diff-database-schema-BfRs2vrG-D2o4KII0.mjs.map +1 -0
  92. package/dist/diff-database-schema-DsoNznGC.d.mts +38 -0
  93. package/dist/diff-database-schema-DsoNznGC.d.mts.map +1 -0
  94. package/dist/driver.d.mts +3 -0
  95. package/dist/driver.mjs +2 -0
  96. package/dist/driver__control.d.mts +2 -0
  97. package/dist/driver__control.mjs +2 -0
  98. package/dist/driver__runtime.d.mts +2 -0
  99. package/dist/driver__runtime.mjs +597 -0
  100. package/dist/driver__runtime.mjs.map +1 -0
  101. package/dist/errors-DCcVX4j1.d.mts +32 -0
  102. package/dist/errors-DCcVX4j1.d.mts.map +1 -0
  103. package/dist/errors-kYxOQjdD-D4T3rbVp.mjs +39 -0
  104. package/dist/errors-kYxOQjdD-D4T3rbVp.mjs.map +1 -0
  105. package/dist/issue-planner-jkY6p-Ca.d.mts +105 -0
  106. package/dist/issue-planner-jkY6p-Ca.d.mts.map +1 -0
  107. package/dist/migration-CBSAPE8S.d.mts +25 -0
  108. package/dist/migration-CBSAPE8S.d.mts.map +1 -0
  109. package/dist/migration-PTHAY9Cv.mjs +21 -0
  110. package/dist/migration-PTHAY9Cv.mjs.map +1 -0
  111. package/dist/namespace-ids-xtp_ZY86-Cpp8PTxD.mjs +7 -0
  112. package/dist/namespace-ids-xtp_ZY86-Cpp8PTxD.mjs.map +1 -0
  113. package/dist/native-type-normalizer-DqJlOTeX.d.mts +19 -0
  114. package/dist/native-type-normalizer-DqJlOTeX.d.mts.map +1 -0
  115. package/dist/native-type-normalizer-yvd3tqv-.mjs +38 -0
  116. package/dist/native-type-normalizer-yvd3tqv-.mjs.map +1 -0
  117. package/dist/nodes-BU-V-aZA-RqwPH68u.d.mts +235 -0
  118. package/dist/nodes-BU-V-aZA-RqwPH68u.d.mts.map +1 -0
  119. package/dist/nodes-DAvDJLvJ-BBdvFXNa.mjs +255 -0
  120. package/dist/nodes-DAvDJLvJ-BBdvFXNa.mjs.map +1 -0
  121. package/dist/normalize-error-CNjgVO71-CLlZ3CuJ.mjs +121 -0
  122. package/dist/normalize-error-CNjgVO71-CLlZ3CuJ.mjs.map +1 -0
  123. package/dist/op-factory-call-DifL68KT-Bo6pxs-R.mjs +2009 -0
  124. package/dist/op-factory-call-DifL68KT-Bo6pxs-R.mjs.map +1 -0
  125. package/dist/op-factory-call-FEA5mnWH.d.mts +1 -0
  126. package/dist/op-factory-call-jd4cgfjA-CyNT4YVn.d.mts +521 -0
  127. package/dist/op-factory-call-jd4cgfjA-CyNT4YVn.d.mts.map +1 -0
  128. package/dist/operation-types-BfRocNI8.d.mts +22 -0
  129. package/dist/operation-types-BfRocNI8.d.mts.map +1 -0
  130. package/dist/pack-DFM4tmob.d.mts +610 -0
  131. package/dist/pack-DFM4tmob.d.mts.map +1 -0
  132. package/dist/planner-Bmje9ii8-B99fEsNM.mjs +588 -0
  133. package/dist/planner-Bmje9ii8-B99fEsNM.mjs.map +1 -0
  134. package/dist/planner-DL4Bh5Nk.d.mts +163 -0
  135. package/dist/planner-DL4Bh5Nk.d.mts.map +1 -0
  136. package/dist/planner-ddl-builders-CbfICQfm-CxYiLrhX.mjs +102 -0
  137. package/dist/planner-ddl-builders-CbfICQfm-CxYiLrhX.mjs.map +1 -0
  138. package/dist/planner-ddl-builders-ijp60-JO.d.mts +19 -0
  139. package/dist/planner-ddl-builders-ijp60-JO.d.mts.map +1 -0
  140. package/dist/planner-identity-values-BmHn5C6U-BYBbUAyR.mjs +90 -0
  141. package/dist/planner-identity-values-BmHn5C6U-BYBbUAyR.mjs.map +1 -0
  142. package/dist/planner-identity-values-TfEhnoWa.d.mts +25 -0
  143. package/dist/planner-identity-values-TfEhnoWa.d.mts.map +1 -0
  144. package/dist/planner-produced-postgres-migration-B0PQLLUb-qsS6cQqX.d.mts +25 -0
  145. package/dist/planner-produced-postgres-migration-B0PQLLUb-qsS6cQqX.d.mts.map +1 -0
  146. package/dist/planner-produced-postgres-migration-C3GPZWeC.d.mts +1 -0
  147. package/dist/planner-produced-postgres-migration-Cicg2sXg-Ck9iDxGI.mjs +47 -0
  148. package/dist/planner-produced-postgres-migration-Cicg2sXg-Ck9iDxGI.mjs.map +1 -0
  149. package/dist/planner-schema-lookup-C4DHAddq.d.mts +21 -0
  150. package/dist/planner-schema-lookup-C4DHAddq.d.mts.map +1 -0
  151. package/dist/planner-schema-lookup-kMIVP2y--CdO4VlnF.mjs +57 -0
  152. package/dist/planner-schema-lookup-kMIVP2y--CdO4VlnF.mjs.map +1 -0
  153. package/dist/planner-sql-checks-CFgbRTJw.d.mts +20 -0
  154. package/dist/planner-sql-checks-CFgbRTJw.d.mts.map +1 -0
  155. package/dist/planner-sql-checks-DRc_78n8-C9nHOrvU.mjs +152 -0
  156. package/dist/planner-sql-checks-DRc_78n8-C9nHOrvU.mjs.map +1 -0
  157. package/dist/planner-target-details-HkP4RrRO-_xPQVPF0.d.mts +12 -0
  158. package/dist/planner-target-details-HkP4RrRO-_xPQVPF0.d.mts.map +1 -0
  159. package/dist/planner-type-resolution-Bt2f_q-F-C4T6YTae.mjs +15 -0
  160. package/dist/planner-type-resolution-Bt2f_q-F-C4T6YTae.mjs.map +1 -0
  161. package/dist/postgres-contract-view-2OP5JnXl-D2fpy4-8.d.mts +36 -0
  162. package/dist/postgres-contract-view-2OP5JnXl-D2fpy4-8.d.mts.map +1 -0
  163. package/dist/postgres-contract-view-FdLX7dV9-Cat1VKV9.mjs +144 -0
  164. package/dist/postgres-contract-view-FdLX7dV9-Cat1VKV9.mjs.map +1 -0
  165. package/dist/postgres-database-schema-node-CyfpHXDr-BqyozkQE.d.mts +285 -0
  166. package/dist/postgres-database-schema-node-CyfpHXDr-BqyozkQE.d.mts.map +1 -0
  167. package/dist/postgres-migration-CDJj7CvD-Bsqs_fVo.d.mts +260 -0
  168. package/dist/postgres-migration-CDJj7CvD-Bsqs_fVo.d.mts.map +1 -0
  169. package/dist/postgres-migration-CJshdIZn-DYYjgdD0.mjs +201 -0
  170. package/dist/postgres-migration-CJshdIZn-DYYjgdD0.mjs.map +1 -0
  171. package/dist/postgres-native-enum-CdP3b_-R-Cgz9KEKx.mjs +45 -0
  172. package/dist/postgres-native-enum-CdP3b_-R-Cgz9KEKx.mjs.map +1 -0
  173. package/dist/postgres-rls-policy-CnDxf3z9-C3LIHAIG.d.mts +61 -0
  174. package/dist/postgres-rls-policy-CnDxf3z9-C3LIHAIG.d.mts.map +1 -0
  175. package/dist/postgres-role-schema-node-B8Z5i5D--PObwlU2Z.mjs +204 -0
  176. package/dist/postgres-role-schema-node-B8Z5i5D--PObwlU2Z.mjs.map +1 -0
  177. package/dist/postgres-schema-KSzLDONj-CsXGoY8b.mjs +421 -0
  178. package/dist/postgres-schema-KSzLDONj-CsXGoY8b.mjs.map +1 -0
  179. package/dist/postgres-schema-Xsjt3RKO-Buv2X8ai.d.mts +269 -0
  180. package/dist/postgres-schema-Xsjt3RKO-Buv2X8ai.d.mts.map +1 -0
  181. package/dist/postgres-table-schema-node-BBkitBQh-DT1T5VWU.mjs +212 -0
  182. package/dist/postgres-table-schema-node-BBkitBQh-DT1T5VWU.mjs.map +1 -0
  183. package/dist/render-ops-DPwhZt2W.d.mts +11 -0
  184. package/dist/render-ops-DPwhZt2W.d.mts.map +1 -0
  185. package/dist/render-ops-DxzTxSsv-Bz85uUHk.mjs +34 -0
  186. package/dist/render-ops-DxzTxSsv-Bz85uUHk.mjs.map +1 -0
  187. package/dist/render-typescript-6sCFvMBh.d.mts +21 -0
  188. package/dist/render-typescript-6sCFvMBh.d.mts.map +1 -0
  189. package/dist/render-typescript-Cw3lFO28-Cx0lXWmv.mjs +117 -0
  190. package/dist/render-typescript-Cw3lFO28-Cx0lXWmv.mjs.map +1 -0
  191. package/dist/resolve-ddl-schema-CxqlLW47-0GiHRziS.mjs +22 -0
  192. package/dist/resolve-ddl-schema-CxqlLW47-0GiHRziS.mjs.map +1 -0
  193. package/dist/runtime-BbSRVwdd.d.mts +12 -0
  194. package/dist/runtime-BbSRVwdd.d.mts.map +1 -0
  195. package/dist/runtime-CDewySU9.d.mts +55 -0
  196. package/dist/runtime-CDewySU9.d.mts.map +1 -0
  197. package/dist/runtime-_TfO66h5.d.mts +32 -0
  198. package/dist/runtime-_TfO66h5.d.mts.map +1 -0
  199. package/dist/schema-ir-annotations-DuuYh0gl.d.mts +15 -0
  200. package/dist/schema-ir-annotations-DuuYh0gl.d.mts.map +1 -0
  201. package/dist/schema-node-kinds-qlnURWJy-Bo30pwTM.d.mts +30 -0
  202. package/dist/schema-node-kinds-qlnURWJy-Bo30pwTM.d.mts.map +1 -0
  203. package/dist/sql-utils-BnBlQxyh-DaX9Nb7Z.mjs +90 -0
  204. package/dist/sql-utils-BnBlQxyh-DaX9Nb7Z.mjs.map +1 -0
  205. package/dist/sql-utils-DW6fkczF.d.mts +62 -0
  206. package/dist/sql-utils-DW6fkczF.d.mts.map +1 -0
  207. package/dist/table-source-ikHOZmhD-DriY1Lcr.d.mts +15 -0
  208. package/dist/table-source-ikHOZmhD-DriY1Lcr.d.mts.map +1 -0
  209. package/dist/target.d.mts +47 -0
  210. package/dist/target.mjs +34 -0
  211. package/dist/target__codec-descriptor.d.mts +3 -0
  212. package/dist/target__codec-descriptor.mjs +2 -0
  213. package/dist/target__codec-ids.d.mts +3 -0
  214. package/dist/target__codec-ids.mjs +2 -0
  215. package/dist/target__codec-types.d.mts +4 -0
  216. package/dist/target__codec-types.mjs +1 -0
  217. package/dist/target__codecs.d.mts +3 -0
  218. package/dist/target__codecs.mjs +3 -0
  219. package/dist/target__contract-free.d.mts +3 -0
  220. package/dist/target__contract-free.mjs +4 -0
  221. package/dist/target__control.d.mts +2 -0
  222. package/dist/target__control.mjs +2 -0
  223. package/dist/target__data-transform.d.mts +3 -0
  224. package/dist/target__data-transform.mjs +2 -0
  225. package/dist/target__ddl.d.mts +4 -0
  226. package/dist/target__ddl.mjs +2 -0
  227. package/dist/target__default-normalizer.d.mts +2 -0
  228. package/dist/target__default-normalizer.mjs +2 -0
  229. package/dist/target__diff-database-schema.d.mts +2 -0
  230. package/dist/target__diff-database-schema.mjs +2 -0
  231. package/dist/target__errors.d.mts +2 -0
  232. package/dist/target__errors.mjs +2 -0
  233. package/dist/target__issue-planner.d.mts +2 -0
  234. package/dist/target__issue-planner.mjs +2 -0
  235. package/dist/target__migration.d.mts +4 -0
  236. package/dist/target__migration.mjs +5 -0
  237. package/dist/target__native-type-normalizer.d.mts +2 -0
  238. package/dist/target__native-type-normalizer.mjs +2 -0
  239. package/dist/target__op-factory-call.d.mts +3 -0
  240. package/dist/target__op-factory-call.mjs +2 -0
  241. package/dist/target__pack.d.mts +2 -0
  242. package/dist/target__pack.mjs +2 -0
  243. package/dist/target__planner-ddl-builders.d.mts +2 -0
  244. package/dist/target__planner-ddl-builders.mjs +2 -0
  245. package/dist/target__planner-identity-values.d.mts +2 -0
  246. package/dist/target__planner-identity-values.mjs +2 -0
  247. package/dist/target__planner-produced-postgres-migration.d.mts +3 -0
  248. package/dist/target__planner-produced-postgres-migration.mjs +2 -0
  249. package/dist/target__planner-schema-lookup.d.mts +2 -0
  250. package/dist/target__planner-schema-lookup.mjs +2 -0
  251. package/dist/target__planner-sql-checks.d.mts +2 -0
  252. package/dist/target__planner-sql-checks.mjs +2 -0
  253. package/dist/target__planner-target-details.d.mts +2 -0
  254. package/dist/target__planner-target-details.mjs +1 -0
  255. package/dist/target__planner.d.mts +2 -0
  256. package/dist/target__planner.mjs +3 -0
  257. package/dist/target__render-ops.d.mts +2 -0
  258. package/dist/target__render-ops.mjs +2 -0
  259. package/dist/target__render-typescript.d.mts +2 -0
  260. package/dist/target__render-typescript.mjs +2 -0
  261. package/dist/target__rls-canonicalize.d.mts +2 -0
  262. package/dist/target__rls-canonicalize.mjs +2 -0
  263. package/dist/target__runtime.d.mts +3 -0
  264. package/dist/target__runtime.mjs +23 -0
  265. package/dist/target__runtime.mjs.map +1 -0
  266. package/dist/target__schema-ir-annotations.d.mts +2 -0
  267. package/dist/target__schema-ir-annotations.mjs +2 -0
  268. package/dist/target__sql-utils.d.mts +2 -0
  269. package/dist/target__sql-utils.mjs +2 -0
  270. package/dist/target__types.d.mts +7 -0
  271. package/dist/target__types.mjs +5 -0
  272. package/dist/types-CkryN1AS-6MNZLjLY.d.mts +27 -0
  273. package/dist/types-CkryN1AS-6MNZLjLY.d.mts.map +1 -0
  274. package/dist/types-Cp_Jf2tk.d.mts +1 -0
  275. package/dist/types-ue6jkJyF-BQJzjx1P.d.mts +10 -0
  276. package/dist/types-ue6jkJyF-BQJzjx1P.d.mts.map +1 -0
  277. package/dist/types-xa86TkcV.d.mts +32 -0
  278. package/dist/types-xa86TkcV.d.mts.map +1 -0
  279. package/package.json +95 -0
@@ -0,0 +1,1901 @@
1
+ import { n as buildPostgresCodecDescriptorRegistry } from "./codec-descriptor-CB6x0xEu-C-Zn2IEz.mjs";
2
+ import { x as PG_TIMESTAMPTZ_CODEC_ID } from "./codec-ids-tX7Svtz--BuOfRaVU.mjs";
3
+ import { n as postgresError } from "./errors-kYxOQjdD-D4T3rbVp.mjs";
4
+ import { n as isPgEnumParams } from "./codecs-CBl0nD44-CaWPc1bd.mjs";
5
+ import { n as postgresCodecRegistry, t as postgresCodecDescriptorRegistry } from "./codecs-CHIVTNZs.mjs";
6
+ import { i as quoteQualifiedName, r as quoteIdentifier, t as escapeLiteral } from "./sql-utils-BnBlQxyh-DaX9Nb7Z.mjs";
7
+ import { a as jsonb, c as textArray, i as int8, l as timestamptz, n as buildSignMarkerBootstrapQueries, o as pgTable, r as int4, s as text, t as buildControlTableBootstrapQueries } from "./contract-free-BZUS18FU.mjs";
8
+ import { t as parsePostgresDefault } from "./default-normalizer-Ba5ZebHM-isV86rjy.mjs";
9
+ import { n as PostgresSchemaNodeKind, r as PostgresTableSchemaNode, t as PostgresNativeEnumSchemaNode } from "./postgres-table-schema-node-BBkitBQh-DT1T5VWU.mjs";
10
+ import { i as PostgresRoleSchemaNode, n as PostgresNamespaceSchemaNode, r as PostgresPolicySchemaNode, t as PostgresDatabaseSchemaNode } from "./postgres-role-schema-node-B8Z5i5D--PObwlU2Z.mjs";
11
+ import { t as normalizeSchemaNativeType } from "./native-type-normalizer-yvd3tqv-.mjs";
12
+ import { LiteralExpr, RawExpr, collectOrderedParamRefs, isDdlNode } from "@prisma/orm-family-sql/relational-core/ast";
13
+ import { blindCast } from "@prisma/orm-framework/utils/casts";
14
+ import { structuredError } from "@prisma/orm-framework/utils/structured-error";
15
+ import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
16
+ import { ifDefined } from "@prisma/orm-framework/utils/defined";
17
+ import { namingOfLiveName } from "@prisma/orm-family-sql/schema-ir/naming";
18
+ import { APP_SPACE_ID, extractCodecLookup } from "@prisma/orm-framework/components/control";
19
+ import { RelationalSchemaNodeKind } from "@prisma/orm-family-sql/schema-ir/types";
20
+ import { InternalError, assertNever } from "@prisma/orm-framework/utils/internal-error";
21
+ import { REFERENTIAL_ACTION_SQL } from "@prisma/orm-family-sql/contract/referential-action-sql";
22
+ import { parseMarkerRowSafely, rethrowMarkerReadError, withMarkerReadErrorHandling } from "@prisma/orm-framework/errors/execution";
23
+ import { parseContractMarkerRow } from "@prisma/orm-family-sql/family/verify";
24
+ import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma/orm-family-sql/runtime";
25
+ import { runtimeError } from "@prisma/orm-framework/components/runtime";
26
+ //#region ../../../3-targets/6-adapters/postgres/dist/control-adapter-B9t0g7Pf.mjs
27
+ function adapterError(code, message, options) {
28
+ return structuredError(code, message, options);
29
+ }
30
+ function buildPostgresCodecRegistry(descriptors) {
31
+ const descriptorRegistry = buildPostgresCodecDescriptorRegistry(descriptors);
32
+ const registry = {
33
+ ...extractCodecLookup([{
34
+ id: "postgres-codecs",
35
+ types: { codecTypes: { codecDescriptors: Array.from(descriptorRegistry.values()) } }
36
+ }]),
37
+ descriptorFor: (codecId) => descriptorRegistry.descriptorFor(codecId),
38
+ values: () => descriptorRegistry.values()
39
+ };
40
+ return Object.freeze(registry);
41
+ }
42
+ function assemblePostgresCodecRegistry(components) {
43
+ return buildPostgresCodecRegistry(components.flatMap((component) => component.types?.codecTypes?.codecDescriptors ?? []));
44
+ }
45
+ function createPostgresCodecRegistryWithBuiltins(codecDescriptors = []) {
46
+ return buildPostgresCodecRegistry([...postgresCodecDescriptorRegistry.values(), ...codecDescriptors]);
47
+ }
48
+ /**
49
+ * Build a coherent PostgreSQL codec registry populated with built-in descriptors only.
50
+ *
51
+ * The returned registry supports both ordinary codec materialization and PostgreSQL target behavior. Stack-composed paths build the same combined registry from their complete ordered descriptor contributions.
52
+ */
53
+ function createPostgresBuiltinCodecLookup() {
54
+ return createPostgresCodecRegistryWithBuiltins();
55
+ }
56
+ function ledgerOriginFromStored(originCoreHash) {
57
+ if (originCoreHash === null || originCoreHash === "" || originCoreHash === "empty") return null;
58
+ return originCoreHash;
59
+ }
60
+ const CONTROL_CODECS = createAstCodecRegistry(postgresCodecRegistry);
61
+ async function encodeControlQueryParams(lowered, ast, codecs = CONTROL_CODECS) {
62
+ return encodeParamsWithMetadata(lowered.params.map((slot) => {
63
+ if (slot.kind === "literal") return slot.value;
64
+ throw new InternalError(`control query lowered to a bind slot '${slot.name}', which is unsupported`);
65
+ }), deriveParamMetadata(ast), {}, codecs);
66
+ }
67
+ const marker = pgTable({
68
+ name: "marker",
69
+ schema: "prisma_contract"
70
+ }, {
71
+ space: text(),
72
+ core_hash: text(),
73
+ profile_hash: text(),
74
+ contract_json: jsonb({ nullable: true }),
75
+ canonical_version: int4({ nullable: true }),
76
+ updated_at: timestamptz(),
77
+ app_tag: text({ nullable: true }),
78
+ meta: jsonb({ nullable: true }),
79
+ invariants: textArray()
80
+ });
81
+ /**
82
+ * Writeable subset of the `prisma_contract.ledger` table. Omits the
83
+ * DB-generated `id` (bigserial) and `created_at` (default `now()`) so the
84
+ * insert path doesn't have to pass them.
85
+ */
86
+ const ledger = pgTable({
87
+ name: "ledger",
88
+ schema: "prisma_contract"
89
+ }, {
90
+ space: text(),
91
+ migration_name: text(),
92
+ migration_hash: text(),
93
+ origin_core_hash: text({ nullable: true }),
94
+ destination_core_hash: text(),
95
+ operations: jsonb()
96
+ });
97
+ /**
98
+ * Content-addressed contract store: one row per distinct contract, keyed
99
+ * by its storage hash. The ledger's `origin_core_hash` /
100
+ * `destination_core_hash` resolve here by hash equality, so both
101
+ * endpoints of every edge are direct lookups and a contract revisited by
102
+ * a rollback cycle is stored exactly once (upsert DO NOTHING).
103
+ */
104
+ const ledgerContract = pgTable({
105
+ name: "contract",
106
+ schema: "prisma_contract"
107
+ }, {
108
+ core_hash: text(),
109
+ contract_json: jsonb()
110
+ });
111
+ /**
112
+ * Read-side handle covering every column of `prisma_contract.ledger`,
113
+ * including the DB-generated `id` (for ORDER BY) and `created_at`.
114
+ */
115
+ const ledgerReadShape = pgTable({
116
+ name: "ledger",
117
+ schema: "prisma_contract"
118
+ }, {
119
+ id: int8(),
120
+ space: text(),
121
+ migration_name: text(),
122
+ migration_hash: text(),
123
+ origin_core_hash: text({ nullable: true }),
124
+ destination_core_hash: text(),
125
+ operations: jsonb(),
126
+ created_at: timestamptz()
127
+ });
128
+ const infoSchemaTables = pgTable({
129
+ name: "tables",
130
+ schema: "information_schema"
131
+ }, {
132
+ table_schema: text(),
133
+ table_name: text()
134
+ });
135
+ const NOW = new RawExpr({
136
+ parts: ["now()"],
137
+ returns: {
138
+ codecId: PG_TIMESTAMPTZ_CODEC_ID,
139
+ nullable: false
140
+ }
141
+ });
142
+ function mergeInvariants(current, incoming) {
143
+ return [.../* @__PURE__ */ new Set([...current, ...incoming])].sort();
144
+ }
145
+ async function execute(lower, driver, query) {
146
+ const lowered = lower(query);
147
+ const encoded = await encodeControlQueryParams(lowered, query);
148
+ return (await driver.query(lowered.sql, encoded)).rows;
149
+ }
150
+ /**
151
+ * Postgres native types whose unknown-OID parameter inference is reliable in arbitrary expression positions. Parameters bound to a descriptor whose `nativeTypeFor` result falls in this set are emitted as plain `$N`; everything else (including `json`, `jsonb`, extension types like `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the planner picks an unambiguous overload.
152
+ *
153
+ * `json` / `jsonb` are intentionally excluded despite being Postgres builtins: their operator overloads make context inference unreliable in expression positions (e.g. `$1 -> 'key'` is ambiguous between the two).
154
+ *
155
+ * Spellings match the target descriptors' `nativeTypeFor` results, not the `udt_name` abbreviations that ADR 205 used as illustrative shorthand. The registry-based cast policy compares against these strings directly.
156
+ */
157
+ const POSTGRES_INFERRABLE_NATIVE_TYPES = /* @__PURE__ */ new Set([
158
+ "integer",
159
+ "smallint",
160
+ "bigint",
161
+ "real",
162
+ "double precision",
163
+ "numeric",
164
+ "boolean",
165
+ "text",
166
+ "character",
167
+ "character varying",
168
+ "timestamp",
169
+ "timestamp without time zone",
170
+ "timestamp with time zone",
171
+ "time",
172
+ "timetz",
173
+ "interval",
174
+ "bit",
175
+ "bit varying"
176
+ ]);
177
+ function renderTypedParam(index, codecId, codecDescriptorRegistry, many, typeParams) {
178
+ if (codecId === void 0) return `$${index}`;
179
+ const descriptor = codecDescriptorRegistry.descriptorFor(codecId);
180
+ if (descriptor === void 0) throw adapterError("RUNTIME.PARAM_REF_MISSING_CODEC", `Postgres lowering: ParamRef carries codecId "${codecId}" but the validated PostgreSQL codec registry has no entry for it. This usually indicates a missing extension pack in the runtime stack — register the pack that contributes this codec (e.g. \`extensions: [pgvectorRuntime]\`), or use the codec directly from \`@internal/target-postgres/codecs\` if it's a builtin.`, { meta: { codecId } });
181
+ const ref = {
182
+ codecId,
183
+ ...ifDefined("many", many),
184
+ ...ifDefined("typeParams", typeParams)
185
+ };
186
+ const nativeType = descriptor.nativeTypeFor(ref);
187
+ const arraySuffix = many ? "[]" : "";
188
+ if (isPgEnumParams(typeParams)) return `$${index}::${quoteQualifiedName(nativeType)}${arraySuffix}`;
189
+ if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType) || many) return `$${index}::${nativeType}${arraySuffix}`;
190
+ return `$${index}`;
191
+ }
192
+ function unreachableKind(value) {
193
+ const candidate = value;
194
+ if (typeof candidate === "object" && candidate !== null && "kind" in candidate && typeof candidate.kind === "string") return candidate.kind;
195
+ return "unknown";
196
+ }
197
+ /**
198
+ * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.
199
+ *
200
+ * Shared between the runtime (`PostgresAdapterImpl.lower`) and control (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time paths produce byte-identical output for the same AST.
201
+ */
202
+ function renderLoweredSql(ast, contract, codecDescriptorRegistry) {
203
+ const orderedRefs = collectOrderedParamRefs(ast);
204
+ const indexMap = /* @__PURE__ */ new Map();
205
+ const params = orderedRefs.map((ref, i) => {
206
+ indexMap.set(ref, i + 1);
207
+ return ref.kind === "prepared-param-ref" ? {
208
+ kind: "bind",
209
+ name: ref.name
210
+ } : {
211
+ kind: "literal",
212
+ value: ref.value
213
+ };
214
+ });
215
+ const pim = {
216
+ indexMap,
217
+ codecDescriptorRegistry
218
+ };
219
+ const node = ast;
220
+ let sql;
221
+ switch (node.kind) {
222
+ case "select":
223
+ sql = renderSelect(node, contract, pim);
224
+ break;
225
+ case "insert":
226
+ sql = renderInsert(node, contract, pim);
227
+ break;
228
+ case "update":
229
+ sql = renderUpdate(node, contract, pim);
230
+ break;
231
+ case "delete":
232
+ sql = renderDelete(node, contract, pim);
233
+ break;
234
+ case "raw-sql":
235
+ sql = renderRawSql(node, contract, pim);
236
+ break;
237
+ // v8 ignore next 4
238
+ default: assertNever(node, `Unsupported AST node kind: ${unreachableKind(node)}`);
239
+ }
240
+ return Object.freeze({
241
+ sql,
242
+ params: Object.freeze(params)
243
+ });
244
+ }
245
+ function renderLimitOffset(keyword, value, contract, pim) {
246
+ if (value === void 0) return "";
247
+ if (typeof value === "number") return `${keyword} ${value}`;
248
+ return `${keyword} ${renderExpr(value, contract, pim)}`;
249
+ }
250
+ function renderSelect(ast, contract, pim) {
251
+ const sourcesByRef = collectTableSources(ast);
252
+ return [
253
+ `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, sourcesByRef, contract, pim)}${renderProjection(ast.projection, contract, pim)}`,
254
+ ast.from !== void 0 ? `FROM ${renderSource(ast.from, contract, pim)}` : "",
255
+ ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "",
256
+ ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "",
257
+ ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "",
258
+ ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "",
259
+ ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => {
260
+ return `${renderOrderByExpr(order.expr, sourcesByRef, contract, pim)} ${order.dir.toUpperCase()}`;
261
+ }).join(", ")}` : "",
262
+ renderLimitOffset("LIMIT", ast.limit, contract, pim),
263
+ renderLimitOffset("OFFSET", ast.offset, contract, pim)
264
+ ].filter((part) => part.length > 0).join(" ").trim();
265
+ }
266
+ /**
267
+ * Map a SELECT's table references (the FROM source and any JOIN sources) to their storage coordinate, keyed by the name a `ColumnRef.table` would carry (the alias when present, otherwise the table name). Derived-table sources are skipped — their columns are projected through a sub-select, not a base storage column, so the enum hook does not apply.
268
+ */
269
+ function collectTableSources(ast) {
270
+ const sources = /* @__PURE__ */ new Map();
271
+ const add = (source) => {
272
+ if (source.kind !== "table-source") return;
273
+ const ref = source.alias ?? source.name;
274
+ sources.set(ref, {
275
+ name: source.name,
276
+ namespaceId: source.namespaceId
277
+ });
278
+ };
279
+ if (ast.from !== void 0) add(ast.from);
280
+ for (const join of ast.joins ?? []) add(join.source);
281
+ return sources;
282
+ }
283
+ /**
284
+ * Ordered, codec-encoded values of the value-set a storage column restricts to, or `undefined` when the referenced column carries no value-set (the common, non-enum case). Resolves the column's storage coordinate from the SELECT's table sources, then the column's `valueSet` ref to the value-set's `values`.
285
+ */
286
+ function allStrings(values) {
287
+ return values.every((value) => typeof value === "string");
288
+ }
289
+ function resolveEnumOrderValues(ref, sourcesByRef, contract) {
290
+ const source = sourcesByRef.get(ref.table);
291
+ if (source === void 0 || source.namespaceId === void 0) return;
292
+ const sourceNs = contract.storage.namespaces[source.namespaceId];
293
+ const valueSet = (sourceNs !== void 0 ? sourceNs.entries.table?.[source.name]?.columns[ref.column] : void 0)?.valueSet;
294
+ if (valueSet === void 0) return;
295
+ const valueSetNs = contract.storage.namespaces[valueSet.namespaceId];
296
+ return valueSetNs !== void 0 ? valueSetNs.entries.valueSet?.[valueSet.entityName]?.values : void 0;
297
+ }
298
+ /**
299
+ * Ordered values for an unqualified ORDER BY column (an `identifier-ref`, the shape the sql-builder emits for `.orderBy('col')`). Scans every FROM/JOIN source for a column of that name. Resolves only when exactly one source has a column of that name and it carries a value-set; if more than one source has such a column the bare identifier is ambiguous (regardless of which are enum-backed), so it falls through to the plain column rendering.
300
+ */
301
+ function resolveEnumOrderValuesForIdentifier(name, sourcesByRef, contract) {
302
+ let matchedColumns = 0;
303
+ let resolved;
304
+ for (const source of sourcesByRef.values()) {
305
+ if (source.namespaceId === void 0) continue;
306
+ const identNs = contract.storage.namespaces[source.namespaceId];
307
+ const column = identNs !== void 0 ? identNs.entries.table?.[source.name]?.columns[name] : void 0;
308
+ if (column === void 0) continue;
309
+ matchedColumns += 1;
310
+ if (matchedColumns > 1) return;
311
+ const valueSet = column.valueSet;
312
+ if (valueSet === void 0) return;
313
+ const valueSetNs = contract.storage.namespaces[valueSet.namespaceId];
314
+ resolved = valueSetNs !== void 0 ? valueSetNs.entries.valueSet?.[valueSet.entityName]?.values : void 0;
315
+ }
316
+ return resolved;
317
+ }
318
+ /**
319
+ * Render an ORDER BY expression. A column reference onto an enum-restricted column sorts by declaration order via `array_position(ARRAY[…]::text[], <col>)` over the value-set's ordered values (NULLs return `NULL` from `array_position`, sorting per the clause's default NULL handling). Both qualified `column-ref`s and the unqualified `identifier-ref`s the sql-builder emits for `.orderBy('col')` are intercepted. Every other expression renders unchanged.
320
+ */
321
+ function renderOrderByExpr(expr, sourcesByRef, contract, pim) {
322
+ if (expr.kind === "column-ref") {
323
+ const orderValues = resolveEnumOrderValues(expr, sourcesByRef, contract);
324
+ if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${renderColumn(expr)})`;
325
+ }
326
+ if (expr.kind === "identifier-ref") {
327
+ const orderValues = resolveEnumOrderValuesForIdentifier(expr.name, sourcesByRef, contract);
328
+ if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${quoteIdentifier(expr.name)})`;
329
+ }
330
+ return renderExpr(expr, contract, pim);
331
+ }
332
+ function renderProjection(projection, contract, pim) {
333
+ return projection.map((item) => {
334
+ const alias = quoteIdentifier(item.alias);
335
+ if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${alias}`;
336
+ return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;
337
+ }).join(", ");
338
+ }
339
+ function renderReturning(items, contract, pim) {
340
+ return items.map((item) => {
341
+ if (item.expr.kind === "column-ref") {
342
+ const rendered = renderColumn(item.expr);
343
+ return item.expr.column === item.alias ? rendered : `${rendered} AS ${quoteIdentifier(item.alias)}`;
344
+ }
345
+ if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;
346
+ return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;
347
+ }).join(", ");
348
+ }
349
+ function renderDistinctPrefix(distinct, distinctOn, sourcesByRef, contract, pim) {
350
+ if (distinctOn && distinctOn.length > 0) return `DISTINCT ON (${distinctOn.map((expr) => renderOrderByExpr(expr, sourcesByRef, contract, pim)).join(", ")}) `;
351
+ if (distinct) return "DISTINCT ";
352
+ return "";
353
+ }
354
+ function hasExplicitSchema(table) {
355
+ return "schema" in table && typeof table.schema === "string";
356
+ }
357
+ function qualifyTableFromNamespaceCoordinate(table, contract) {
358
+ if (hasExplicitSchema(table)) return `${quoteIdentifier(table.schema)}.${quoteIdentifier(table.name)}`;
359
+ if (table.namespaceId === void 0) return quoteIdentifier(table.name);
360
+ const namespace = contract.storage.namespaces[table.namespaceId];
361
+ if (namespace === void 0) throw adapterError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not present as a Postgres schema on the contract`, { meta: {
362
+ table: table.name,
363
+ namespaceId: table.namespaceId,
364
+ reason: "not-present"
365
+ } });
366
+ const qualifyTable = namespace.qualifyTable;
367
+ if (qualifyTable === void 0) throw adapterError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not materialised as a Postgres schema on the contract`, { meta: {
368
+ table: table.name,
369
+ namespaceId: table.namespaceId,
370
+ reason: "not-materialised"
371
+ } });
372
+ return qualifyTable.call(namespace, table.name);
373
+ }
374
+ function renderTableSource(source, contract) {
375
+ const qualified = qualifyTableFromNamespaceCoordinate(source, contract);
376
+ if (!source.alias) return qualified;
377
+ return `${qualified} AS ${quoteIdentifier(source.alias)}`;
378
+ }
379
+ function renderSource(source, contract, pim) {
380
+ const node = source;
381
+ switch (node.kind) {
382
+ case "table-source": return renderTableSource(node, contract);
383
+ case "derived-table-source": return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;
384
+ case "function-source": {
385
+ const args = node.args.map((arg) => renderExpr(arg, contract, pim)).join(", ");
386
+ return `${`${node.fn}(${args})`}${node.ordinality ? " WITH ORDINALITY" : ""}${node.alias === void 0 ? "" : ` AS ${quoteIdentifier(node.alias)}`}${node.columnAliases === void 0 ? "" : `(${node.columnAliases.map((column) => quoteIdentifier(column)).join(", ")})`}`;
387
+ }
388
+ // v8 ignore next 4
389
+ default: assertNever(node, `Unsupported source node kind: ${unreachableKind(node)}`);
390
+ }
391
+ }
392
+ function assertScalarSubquery(query) {
393
+ if (query.projection.length !== 1) throw adapterError("RUNTIME.AST_INVALID", "Subquery expressions must project exactly one column", { meta: { node: "subquery-expr" } });
394
+ }
395
+ function renderSubqueryExpr(expr, contract, pim) {
396
+ assertScalarSubquery(expr.query);
397
+ return `(${renderSelect(expr.query, contract, pim)})`;
398
+ }
399
+ function renderWhere(expr, contract, pim) {
400
+ return renderExpr(expr, contract, pim);
401
+ }
402
+ function renderNullCheck(expr, contract, pim) {
403
+ const rendered = renderExpr(expr.expr, contract, pim);
404
+ const renderedExpr = isAtomicExpressionKind(expr.expr.kind) ? rendered : `(${rendered})`;
405
+ return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;
406
+ }
407
+ /**
408
+ * Atomic expression kinds whose rendered SQL is already self-delimited (a column reference, parameter, literal, function call, aggregate, etc.) and therefore does not need surrounding parentheses when used as the left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`, or as either operand of a binary infix operator.
409
+ *
410
+ * Anything not in this set is treated as composite (binary, AND/OR/NOT, EXISTS, nested IS NULL, subqueries, operation templates) and gets wrapped to preserve grouping.
411
+ */
412
+ function isAtomicExpressionKind(kind) {
413
+ switch (kind) {
414
+ case "column-ref":
415
+ case "identifier-ref":
416
+ case "param-ref":
417
+ case "prepared-param-ref":
418
+ case "literal":
419
+ case "aggregate":
420
+ case "window-func":
421
+ case "function-call":
422
+ case "cast":
423
+ case "case":
424
+ case "json-object":
425
+ case "json-array-agg":
426
+ case "list": return true;
427
+ case "subquery":
428
+ case "operation":
429
+ case "binary":
430
+ case "and":
431
+ case "or":
432
+ case "exists":
433
+ case "null-check":
434
+ case "not":
435
+ case "raw-expr": return false;
436
+ }
437
+ }
438
+ function renderBinary(expr, contract, pim) {
439
+ if (expr.right.kind === "list" && expr.right.values.length === 0) {
440
+ if (expr.op === "in") return "FALSE";
441
+ if (expr.op === "notIn") return "TRUE";
442
+ }
443
+ const leftExpr = expr.left;
444
+ const left = renderExpr(leftExpr, contract, pim);
445
+ const leftRendered = leftExpr.kind === "operation" || leftExpr.kind === "subquery" ? `(${left})` : left;
446
+ const rightNode = expr.right;
447
+ let right;
448
+ switch (rightNode.kind) {
449
+ case "list":
450
+ right = renderListLiteral(rightNode, contract, pim);
451
+ break;
452
+ case "literal":
453
+ right = renderLiteral(rightNode);
454
+ break;
455
+ case "column-ref":
456
+ right = renderColumn(rightNode);
457
+ break;
458
+ case "param-ref":
459
+ case "prepared-param-ref":
460
+ right = renderParamRef(rightNode, pim);
461
+ break;
462
+ default:
463
+ right = renderExpr(rightNode, contract, pim);
464
+ break;
465
+ }
466
+ return `${leftRendered} ${{
467
+ eq: "=",
468
+ neq: "!=",
469
+ gt: ">",
470
+ lt: "<",
471
+ gte: ">=",
472
+ lte: "<=",
473
+ like: "LIKE",
474
+ in: "IN",
475
+ notIn: "NOT IN"
476
+ }[expr.op]} ${right}`;
477
+ }
478
+ function renderListLiteral(expr, contract, pim) {
479
+ if (expr.values.length === 0) return "(NULL)";
480
+ return `(${expr.values.map((v) => {
481
+ if (v.kind === "param-ref" || v.kind === "prepared-param-ref") return renderParamRef(v, pim);
482
+ if (v.kind === "literal") return renderLiteral(v);
483
+ return renderExpr(v, contract, pim);
484
+ }).join(", ")})`;
485
+ }
486
+ function renderColumn(ref) {
487
+ if (ref.table === "excluded") return `excluded.${quoteIdentifier(ref.column)}`;
488
+ return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;
489
+ }
490
+ function renderAggregateExpr(expr, contract, pim) {
491
+ const fn = expr.fn.toUpperCase();
492
+ if (!expr.expr) return `${fn}(*)`;
493
+ return `${fn}(${renderExpr(expr.expr, contract, pim)})`;
494
+ }
495
+ function renderWindowFuncExpr(expr, contract, pim) {
496
+ return `${expr.fn.toUpperCase()}(${expr.args.map((arg) => renderExpr(arg, contract, pim)).join(", ")}) OVER (${[expr.partitionBy && expr.partitionBy.length > 0 ? `PARTITION BY ${expr.partitionBy.map((e) => renderExpr(e, contract, pim)).join(", ")}` : "", expr.orderBy && expr.orderBy.length > 0 ? `ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : ""].filter((part) => part.length > 0).join(" ")})`;
497
+ }
498
+ function renderFunctionCallExpr(expr, contract, pim) {
499
+ const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(", ");
500
+ return `${expr.fn}(${args})`;
501
+ }
502
+ function renderCastExpr(expr, contract, pim) {
503
+ return `CAST(${renderExpr(expr.expr, contract, pim)} AS ${expr.targetType})`;
504
+ }
505
+ function renderCaseExpr(expr, contract, pim) {
506
+ return `CASE ${expr.branches.map((branch) => `WHEN ${renderExpr(branch.condition, contract, pim)} THEN ${renderExpr(branch.value, contract, pim)}`).join(" ")}${expr.elseExpr === void 0 ? "" : ` ELSE ${renderExpr(expr.elseExpr, contract, pim)}`} END`;
507
+ }
508
+ function renderJsonValueProjection(projection, contract, pim) {
509
+ return projection.accept({
510
+ codec: ({ value, codec }) => renderExpr(projectJsonThroughCodec(value, codec, pim), contract, pim),
511
+ native: ({ value }) => renderExpr(value, contract, pim),
512
+ document: ({ value }) => renderExpr(value, contract, pim)
513
+ });
514
+ }
515
+ function projectJsonThroughCodec(value, codec, pim) {
516
+ const descriptor = pim.codecDescriptorRegistry.descriptorFor(codec.codecId);
517
+ if (descriptor === void 0) throw adapterError("RUNTIME.PARAM_REF_MISSING_CODEC", `Postgres lowering: a JSON projection carries codecId "${codec.codecId}" but the validated PostgreSQL codec registry has no entry for it. This usually indicates a missing extension pack in the runtime stack — register the pack that contributes this codec (e.g. \`extensions: [pgvectorRuntime]\`), or use the codec directly from \`@internal/target-postgres/codecs\` if it's a builtin.`, { meta: { codecId: codec.codecId } });
518
+ return descriptor.projectJson(value, codec);
519
+ }
520
+ function renderJsonObjectExpr(expr, contract, pim) {
521
+ return `json_build_object(${expr.entries.flatMap((entry) => {
522
+ return [`'${escapeLiteral(entry.key)}'`, renderJsonValueProjection(entry.value, contract, pim)];
523
+ }).join(", ")})`;
524
+ }
525
+ function renderOrderByItems(items, contract, pim) {
526
+ return items.map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`).join(", ");
527
+ }
528
+ function renderJsonArrayAggExpr(expr, contract, pim) {
529
+ const aggregateOrderBy = expr.orderBy && expr.orderBy.length > 0 ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : "";
530
+ const aggregated = `json_agg(${renderJsonValueProjection(expr.expr, contract, pim)}${aggregateOrderBy})`;
531
+ if (expr.onEmpty === "emptyArray") return `coalesce(${aggregated}, json_build_array())`;
532
+ return aggregated;
533
+ }
534
+ function renderExpr(expr, contract, pim) {
535
+ const node = expr;
536
+ switch (node.kind) {
537
+ case "column-ref": return renderColumn(node);
538
+ case "identifier-ref": return quoteIdentifier(node.name);
539
+ case "operation": return renderOperation(node, contract, pim);
540
+ case "subquery": return renderSubqueryExpr(node, contract, pim);
541
+ case "aggregate": return renderAggregateExpr(node, contract, pim);
542
+ case "window-func": return renderWindowFuncExpr(node, contract, pim);
543
+ case "function-call": return renderFunctionCallExpr(node, contract, pim);
544
+ case "cast": return renderCastExpr(node, contract, pim);
545
+ case "case": return renderCaseExpr(node, contract, pim);
546
+ case "json-object": return renderJsonObjectExpr(node, contract, pim);
547
+ case "json-array-agg": return renderJsonArrayAggExpr(node, contract, pim);
548
+ case "binary": return renderBinary(node, contract, pim);
549
+ case "and":
550
+ if (node.exprs.length === 0) return "TRUE";
551
+ return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" AND ")})`;
552
+ case "or":
553
+ if (node.exprs.length === 0) return "FALSE";
554
+ return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" OR ")})`;
555
+ case "exists": return `${node.notExists ? "NOT " : ""}EXISTS (${renderSelect(node.subquery, contract, pim)})`;
556
+ case "null-check": return renderNullCheck(node, contract, pim);
557
+ case "not": return `NOT (${renderExpr(node.expr, contract, pim)})`;
558
+ case "param-ref":
559
+ case "prepared-param-ref": return renderParamRef(node, pim);
560
+ case "literal": return renderLiteral(node);
561
+ case "list": return renderListLiteral(node, contract, pim);
562
+ case "raw-expr": return renderRawExpr(node, contract, pim);
563
+ // v8 ignore next 4
564
+ default: assertNever(node, `Unsupported expression node kind: ${unreachableKind(node)}`);
565
+ }
566
+ }
567
+ function renderParamRef(ref, pim) {
568
+ const index = pim.indexMap.get(ref);
569
+ if (index === void 0) throw new InternalError("ParamRef not found in index map");
570
+ if (ref.kind === "prepared-param-ref") return renderTypedParam(index, ref.codec.codecId, pim.codecDescriptorRegistry, ref.codec.many, ref.codec.typeParams);
571
+ if (ref.codec === void 0) throw runtimeError("RUNTIME.PARAM_REF_MISSING_CODEC", "Postgres renderer: ParamRef reached lowering without a bound CodecRef. Every column-bound ParamRef must carry a codec under the AST-bound codec contract. This usually indicates a builder path that constructed a ParamRef without threading the column codec.", {
572
+ paramIndex: index,
573
+ ...ifDefined("name", ref.name)
574
+ });
575
+ return renderTypedParam(index, ref.codec.codecId, pim.codecDescriptorRegistry, ref.codec.many, ref.codec.typeParams);
576
+ }
577
+ function renderLiteral(expr) {
578
+ if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
579
+ if (typeof expr.value === "number" || typeof expr.value === "boolean") return String(expr.value);
580
+ if (typeof expr.value === "bigint") return String(expr.value);
581
+ if (expr.value === null) return "NULL";
582
+ if (expr.value === void 0) return "NULL";
583
+ if (expr.value instanceof Date) return `'${escapeLiteral(expr.value.toISOString())}'`;
584
+ if (Array.isArray(expr.value)) return `ARRAY[${expr.value.map((v) => renderLiteral(new LiteralExpr(v))).join(", ")}]`;
585
+ const json = JSON.stringify(expr.value);
586
+ if (json === void 0) return "NULL";
587
+ return `'${escapeLiteral(json)}'`;
588
+ }
589
+ function renderOperation(expr, contract, pim) {
590
+ const self = renderExpr(expr.self, contract, pim);
591
+ const args = expr.args.map((arg) => {
592
+ return renderExpr(arg, contract, pim);
593
+ });
594
+ return expr.lowering.template.replace(/\{\{self\}\}|\{\{arg(\d+)\}\}/g, (token, argIndex) => {
595
+ if (token === "{{self}}") return self;
596
+ const arg = args[Number(argIndex)];
597
+ if (arg === void 0) throw adapterError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Operation lowering template for "${expr.method}" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`, { meta: { method: expr.method } });
598
+ return arg;
599
+ });
600
+ }
601
+ function renderJoin(join, contract, pim) {
602
+ return `${join.joinType.toUpperCase()} JOIN ${join.lateral ? "LATERAL " : ""}${renderSource(join.source, contract, pim)} ON ${renderJoinOn(join.on, contract, pim)}`;
603
+ }
604
+ function renderJoinOn(on, contract, pim) {
605
+ if (on.kind === "eq-col-join-on") return `${renderColumn(on.left)} = ${renderColumn(on.right)}`;
606
+ return renderWhere(on, contract, pim);
607
+ }
608
+ function getInsertColumnOrder(rows, contract, tableRef) {
609
+ const tableName = tableRef.name;
610
+ const orderedColumns = [];
611
+ const seenColumns = /* @__PURE__ */ new Set();
612
+ for (const row of rows) for (const column of Object.keys(row)) {
613
+ if (seenColumns.has(column)) continue;
614
+ seenColumns.add(column);
615
+ orderedColumns.push(column);
616
+ }
617
+ if (orderedColumns.length > 0) return orderedColumns;
618
+ let table;
619
+ if (tableRef.namespaceId !== void 0) {
620
+ const ns = contract.storage.namespaces[tableRef.namespaceId];
621
+ table = ns !== void 0 ? ns.entries.table?.[tableName] : void 0;
622
+ }
623
+ if (table === void 0) for (const ns of Object.values(contract.storage.namespaces)) {
624
+ const found = ns.entries.table?.[tableName];
625
+ if (found !== void 0) {
626
+ table = found;
627
+ break;
628
+ }
629
+ }
630
+ if (!table) throw adapterError("RUNTIME.AST_INVALID", `INSERT target table not found in contract storage: ${tableName}`, { meta: {
631
+ node: "insert",
632
+ table: tableName
633
+ } });
634
+ return Object.keys(table.columns);
635
+ }
636
+ function renderInsertValue(value, contract, pim) {
637
+ if (!value || value.kind === "default-value") return "DEFAULT";
638
+ switch (value.kind) {
639
+ case "param-ref":
640
+ case "prepared-param-ref": return renderParamRef(value, pim);
641
+ case "column-ref": return renderColumn(value);
642
+ case "raw-expr": return renderExpr(value, contract, pim);
643
+ // v8 ignore next 4
644
+ default: assertNever(value, `Unsupported value node in INSERT: ${unreachableKind(value)}`);
645
+ }
646
+ }
647
+ function renderInsert(ast, contract, pim) {
648
+ const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
649
+ const rows = ast.rows;
650
+ if (rows.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT requires at least one row", { meta: { node: "insert" } });
651
+ const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
652
+ return `${(() => {
653
+ if (!hasExplicitValues) {
654
+ if (rows.length === 1) return `INSERT INTO ${table} DEFAULT VALUES`;
655
+ const defaultColumns = getInsertColumnOrder(rows, contract, ast.table);
656
+ if (defaultColumns.length === 0) return `INSERT INTO ${table} VALUES ${rows.map(() => "()").join(", ")}`;
657
+ const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));
658
+ const defaultRow = `(${defaultColumns.map(() => "DEFAULT").join(", ")})`;
659
+ return `INSERT INTO ${table} (${quotedColumns.join(", ")}) VALUES ${rows.map(() => defaultRow).join(", ")}`;
660
+ }
661
+ const columnOrder = getInsertColumnOrder(rows, contract, ast.table);
662
+ const columns = columnOrder.map((column) => quoteIdentifier(column));
663
+ const values = rows.map((row) => {
664
+ return `(${columnOrder.map((column) => renderInsertValue(row[column], contract, pim)).join(", ")})`;
665
+ }).join(", ");
666
+ return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
667
+ })()}${ast.onConflict ? (() => {
668
+ const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
669
+ if (conflictColumns.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict requires at least one conflict column", { meta: { node: "insert-on-conflict" } });
670
+ const action = ast.onConflict.action;
671
+ switch (action.kind) {
672
+ case "do-nothing": return ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
673
+ case "do-update-set": {
674
+ const updateEntries = Object.entries(action.set);
675
+ if (updateEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict do-update-set requires at least one assignment", { meta: { node: "insert-on-conflict" } });
676
+ const updates = updateEntries.map(([colName, value]) => {
677
+ return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;
678
+ });
679
+ return ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
680
+ }
681
+ // v8 ignore next 4
682
+ default: assertNever(action, `Unsupported onConflict action: ${unreachableKind(action)}`);
683
+ }
684
+ })() : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
685
+ }
686
+ function renderUpdate(ast, contract, pim) {
687
+ const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
688
+ const setEntries = Object.entries(ast.set);
689
+ if (setEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "UPDATE requires at least one SET assignment", { meta: { node: "update" } });
690
+ const setClauses = setEntries.map(([col, val]) => {
691
+ return `${quoteIdentifier(col)} = ${renderExpr(val, contract, pim)}`;
692
+ });
693
+ const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : "";
694
+ const returningClause = ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : "";
695
+ return `UPDATE ${table} SET ${setClauses.join(", ")}${whereClause}${returningClause}`;
696
+ }
697
+ function renderDelete(ast, contract, pim) {
698
+ return `DELETE FROM ${qualifyTableFromNamespaceCoordinate(ast.table, contract)}${ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
699
+ }
700
+ function renderRawSql(ast, contract, pim) {
701
+ const out = [];
702
+ for (let i = 0; i < ast.fragments.length; i++) {
703
+ out.push(ast.fragments[i] ?? "");
704
+ if (i < ast.args.length) {
705
+ const arg = ast.args[i];
706
+ if (arg !== void 0) out.push(renderExpr(arg, contract, pim));
707
+ }
708
+ }
709
+ return out.join("");
710
+ }
711
+ function renderRawExpr(node, contract, pim) {
712
+ return node.parts.map((part) => typeof part === "string" ? part : renderExpr(part, contract, pim)).join("");
713
+ }
714
+ const POSTGRES_MARKER_TABLE = "prisma_contract.marker";
715
+ const POSTGRES_LEDGER_TABLE = "prisma_contract.ledger";
716
+ /**
717
+ * Postgres control plane adapter for control-plane operations like introspection.
718
+ * Provides target-specific implementations for control-plane domain actions.
719
+ */
720
+ var PostgresControlAdapter = class {
721
+ codecRegistry;
722
+ familyId = "sql";
723
+ targetId = "postgres";
724
+ constructor(codecRegistry) {
725
+ this.codecRegistry = codecRegistry;
726
+ }
727
+ /**
728
+ * Target-specific normalizer for raw Postgres default expressions.
729
+ * Used by schema verification to normalize raw defaults before comparison.
730
+ */
731
+ normalizeDefault = parsePostgresDefault;
732
+ /**
733
+ * Target-specific normalizer for Postgres schema native type names.
734
+ * Used by schema verification to normalize introspected type names
735
+ * before comparison with contract native types.
736
+ */
737
+ normalizeNativeType = normalizeSchemaNativeType;
738
+ bootstrapControlTableQueries() {
739
+ return buildControlTableBootstrapQueries();
740
+ }
741
+ bootstrapSignMarkerQueries() {
742
+ return buildSignMarkerBootstrapQueries();
743
+ }
744
+ /**
745
+ * Lower a SQL query AST into a Postgres-flavored `{ sql, params }` payload.
746
+ *
747
+ * Delegates to the shared `renderLoweredSql` renderer so the control adapter
748
+ * emits byte-identical SQL to `PostgresAdapterImpl.lower()` for the same AST
749
+ * and contract. Used at migration plan/emit time (e.g. by `dataTransform`)
750
+ * without instantiating the runtime adapter.
751
+ */
752
+ lower(ast, context) {
753
+ if (isDdlNode(ast)) throw adapterError("RUNTIME.DDL_UNSUPPORTED", "lower() cannot lower DDL: DDL default literals require inline codec encoding, which is async. Use lowerToExecuteRequest().", { meta: { surface: "control-adapter" } });
754
+ return renderLoweredSql(ast, blindCast(context.contract), this.codecRegistry);
755
+ }
756
+ /**
757
+ * Lower an AST all the way to a driver-ready statement. For DDL nodes,
758
+ * literal column defaults are formatted as inline SQL with proper quoting and
759
+ * `::nativeType` cast suffixes. For query ASTs, params are kept as `$N`
760
+ * placeholders; wire values go in `params`. Does NOT call `this.lower()` —
761
+ * independent implementation.
762
+ */
763
+ async lowerToExecuteRequest(ast, context) {
764
+ if (isDdlNode(ast)) return pgRenderDdlExecuteRequest(blindCast(ast), this.codecRegistry);
765
+ const lowered = renderLoweredSql(ast, blindCast(context?.contract), this.codecRegistry);
766
+ const params = await encodeControlQueryParams(lowered, ast, blindCast(this.codecRegistry));
767
+ return {
768
+ sql: lowered.sql,
769
+ params
770
+ };
771
+ }
772
+ /**
773
+ * Reads the contract marker from `prisma_contract.marker`. Probes
774
+ * `information_schema.tables` first so a fresh database (where the
775
+ * `prisma_contract` schema doesn't yet exist) returns `null` instead of a
776
+ * "relation does not exist" error — some Postgres wire-protocol clients
777
+ * (e.g. PGlite's TCP proxy) don't fully recover from extended-protocol
778
+ * parse errors, so we probe before reading.
779
+ */
780
+ async readMarker(driver, space) {
781
+ const result = await this.readMarkerDiscriminated(driver, space);
782
+ return result.kind === "present" ? result.record : null;
783
+ }
784
+ async readMarkerDiscriminated(driver, space) {
785
+ return withMarkerReadErrorHandling(() => this.readMarkerResult(driver, space), {
786
+ space,
787
+ markerLocation: POSTGRES_MARKER_TABLE
788
+ });
789
+ }
790
+ /**
791
+ * Reads every row from `prisma_contract.marker` and returns them keyed
792
+ * by `space`. Mirrors the existence probe in {@link readMarker}: a
793
+ * fresh database without the `prisma_contract` schema returns an empty
794
+ * map rather than raising "relation does not exist".
795
+ */
796
+ async readAllMarkers(driver) {
797
+ return withMarkerReadErrorHandling(() => this.readAllMarkersResult(driver), {
798
+ space: APP_SPACE_ID,
799
+ markerLocation: POSTGRES_MARKER_TABLE
800
+ });
801
+ }
802
+ async readAllMarkersResult(driver) {
803
+ const lower = (query) => this.lower(query, { contract: void 0 });
804
+ if ((await execute(lower, driver, infoSchemaTables.select(infoSchemaTables.table_schema).where(infoSchemaTables.table_schema.eq("prisma_contract").and(infoSchemaTables.table_name.eq("marker"))).build())).length === 0) return /* @__PURE__ */ new Map();
805
+ await this.assertMarkerTableHasSpaceColumn(driver, APP_SPACE_ID);
806
+ const rows = blindCast(await execute(lower, driver, marker.select(marker.space, marker.core_hash, marker.profile_hash, marker.contract_json, marker.canonical_version, marker.updated_at, marker.app_tag, marker.meta, marker.invariants).build()));
807
+ const out = /* @__PURE__ */ new Map();
808
+ for (const row of rows) out.set(row.space, parseMarkerRowSafely(row, parseContractMarkerRow, {
809
+ space: row.space,
810
+ markerLocation: POSTGRES_MARKER_TABLE
811
+ }));
812
+ return out;
813
+ }
814
+ /**
815
+ * Reads per-migration ledger rows from `prisma_contract.ledger` in apply
816
+ * order. Probes `information_schema.tables` first so a fresh database
817
+ * without the ledger table returns `[]` instead of raising "relation does
818
+ * not exist".
819
+ */
820
+ async readLedger(driver, space) {
821
+ return withMarkerReadErrorHandling(() => this.readLedgerResult(driver, space), {
822
+ space: space ?? "*",
823
+ markerLocation: POSTGRES_LEDGER_TABLE
824
+ });
825
+ }
826
+ async readLedgerResult(driver, space) {
827
+ const lower = (query) => this.lower(query, { contract: void 0 });
828
+ if ((await execute(lower, driver, infoSchemaTables.select(infoSchemaTables.table_schema).where(infoSchemaTables.table_schema.eq("prisma_contract").and(infoSchemaTables.table_name.eq("ledger"))).build())).length === 0) return [];
829
+ const base = ledgerReadShape.select(ledgerReadShape.space, ledgerReadShape.migration_name, ledgerReadShape.migration_hash, ledgerReadShape.origin_core_hash, ledgerReadShape.destination_core_hash, ledgerReadShape.operations, ledgerReadShape.created_at);
830
+ return blindCast(await execute(lower, driver, (space !== void 0 ? base.where(ledgerReadShape.space.eq(space)) : base).orderBy(ledgerReadShape.id).build())).map((row) => {
831
+ const appliedAt = row.created_at instanceof Date ? row.created_at : new Date(row.created_at);
832
+ return {
833
+ space: row.space,
834
+ migrationName: row.migration_name,
835
+ migrationHash: row.migration_hash,
836
+ from: ledgerOriginFromStored(row.origin_core_hash),
837
+ to: row.destination_core_hash,
838
+ appliedAt,
839
+ operationCount: Array.isArray(row.operations) ? row.operations.length : 0
840
+ };
841
+ });
842
+ }
843
+ /**
844
+ * Stamps the initial marker row for `space` via the shared contract-free DML
845
+ * builder, lowered through {@link lower} and executed on the driver. See the
846
+ * `SqlControlAdapter.initMarker` contract.
847
+ */
848
+ async insertMarker(driver, space, destination) {
849
+ await execute((query) => this.lower(query, { contract: void 0 }), driver, marker.insert({
850
+ space,
851
+ core_hash: destination.storageHash,
852
+ profile_hash: destination.profileHash,
853
+ contract_json: null,
854
+ canonical_version: null,
855
+ updated_at: NOW,
856
+ app_tag: null,
857
+ meta: {},
858
+ invariants: destination.invariants ?? []
859
+ }).build());
860
+ }
861
+ async initMarker(driver, space, destination) {
862
+ await execute((query) => this.lower(query, { contract: void 0 }), driver, marker.upsert({
863
+ space,
864
+ core_hash: destination.storageHash,
865
+ profile_hash: destination.profileHash,
866
+ contract_json: null,
867
+ canonical_version: null,
868
+ updated_at: NOW,
869
+ app_tag: null,
870
+ meta: {},
871
+ invariants: destination.invariants ?? []
872
+ }).onConflict(marker.space).doUpdate((excluded) => ({
873
+ core_hash: excluded.core_hash,
874
+ profile_hash: excluded.profile_hash,
875
+ contract_json: excluded.contract_json,
876
+ canonical_version: excluded.canonical_version,
877
+ updated_at: NOW,
878
+ app_tag: excluded.app_tag,
879
+ meta: excluded.meta,
880
+ invariants: excluded.invariants
881
+ })).build());
882
+ }
883
+ /**
884
+ * Compare-and-swap advance of the marker row for `space`. See the
885
+ * `SqlControlAdapter.updateMarker` contract.
886
+ */
887
+ async updateMarker(driver, space, expectedFrom, destination) {
888
+ const currentInvariants = destination.invariants === void 0 ? [] : (await this.readMarker(driver, space))?.invariants ?? [];
889
+ const mergedInvariants = destination.invariants === void 0 ? void 0 : mergeInvariants(currentInvariants, destination.invariants);
890
+ return (await execute((q) => this.lower(q, { contract: void 0 }), driver, marker.update().set({
891
+ core_hash: destination.storageHash,
892
+ profile_hash: destination.profileHash,
893
+ updated_at: NOW,
894
+ ...mergedInvariants !== void 0 ? { invariants: mergedInvariants } : {}
895
+ }).where(marker.space.eq(space).and(marker.core_hash.eq(expectedFrom))).returning(marker.space).build())).length > 0;
896
+ }
897
+ /**
898
+ * Appends a ledger entry for `space`. When the edge carries a
899
+ * destination contract snapshot, the content-addressed
900
+ * `prisma_contract.contract` store is populated first (keyed by the
901
+ * destination hash, DO NOTHING on revisit) so a reader never sees a
902
+ * ledger row whose stored destination contract is missing. See the
903
+ * `SqlControlAdapter.writeLedgerEntry` contract.
904
+ */
905
+ async writeLedgerEntry(driver, space, entry) {
906
+ const lower = (query) => this.lower(query, { contract: void 0 });
907
+ if (entry.destinationContractJson !== void 0) await execute(lower, driver, ledgerContract.upsert({
908
+ core_hash: entry.to,
909
+ contract_json: entry.destinationContractJson
910
+ }).onConflict(ledgerContract.core_hash).doNothing().build());
911
+ await execute(lower, driver, ledger.insert({
912
+ space,
913
+ migration_name: entry.migrationName,
914
+ migration_hash: entry.migrationHash,
915
+ origin_core_hash: entry.from,
916
+ destination_core_hash: entry.to,
917
+ operations: entry.operations
918
+ }).build());
919
+ }
920
+ async assertMarkerTableHasSpaceColumn(driver, space) {
921
+ const rows = (await driver.query(`select column_name
922
+ from information_schema.columns
923
+ where table_schema = 'prisma_contract'
924
+ and table_name = 'marker'`)).rows;
925
+ if (rows.length === 0) return;
926
+ if (!rows.every((row) => typeof row.column_name === "string")) return;
927
+ if (rows.some((row) => row.column_name === "space")) return;
928
+ rethrowMarkerReadError(/* @__PURE__ */ new Error("column \"space\" does not exist"), {
929
+ space,
930
+ markerLocation: POSTGRES_MARKER_TABLE
931
+ });
932
+ }
933
+ async readMarkerResult(driver, space) {
934
+ const lower = (query) => this.lower(query, { contract: void 0 });
935
+ if ((await execute(lower, driver, infoSchemaTables.select(infoSchemaTables.table_schema).where(infoSchemaTables.table_schema.eq("prisma_contract").and(infoSchemaTables.table_name.eq("marker"))).build())).length === 0) return { kind: "no-table" };
936
+ await this.assertMarkerTableHasSpaceColumn(driver, space);
937
+ const row = (await execute(lower, driver, marker.select(marker.core_hash, marker.profile_hash, marker.contract_json, marker.canonical_version, marker.updated_at, marker.app_tag, marker.meta, marker.invariants).where(marker.space.eq(space)).build()))[0];
938
+ if (!row) return { kind: "absent" };
939
+ return {
940
+ kind: "present",
941
+ record: parseContractMarkerRow(row)
942
+ };
943
+ }
944
+ /**
945
+ * Introspects a Postgres database schema and returns a raw SqlSchemaIR.
946
+ *
947
+ * This is a pure schema discovery operation that queries the Postgres catalog
948
+ * and returns the schema structure without type mapping or contract enrichment.
949
+ * Type mapping and enrichment are handled separately by enrichment helpers.
950
+ *
951
+ * When `contract` is provided and its storage declares more than one
952
+ * namespace (or any explicit bound namespace), the adapter walks every
953
+ * declared namespace and merges the per-schema introspection results
954
+ * into a single `SqlSchemaIR`. `UNBOUND_NAMESPACE_ID` resolves to the
955
+ * connection's `current_schema()` so late-bound tables follow the
956
+ * runtime `search_path`. When no contract is passed, the adapter falls
957
+ * back to introspecting the single `schema` argument (defaulting to
958
+ * `'public'`).
959
+ *
960
+ * Uses batched queries to minimize database round trips (6 queries per
961
+ * schema walked).
962
+ *
963
+ * @param driver - SqlControlDriverInstance<'postgres'> instance for executing queries
964
+ * @param contract - Optional contract for contract-guided introspection (multi-namespace walk, filtering)
965
+ * @param schema - Schema name to introspect when no contract is provided (defaults to 'public')
966
+ * @returns Promise resolving to SqlSchemaIR representing the live database schema
967
+ */
968
+ async introspect(driver, contract, schema = "public") {
969
+ const declaredNamespaces = extractContractNamespaceIds(contract);
970
+ const resolvedSchemas = declaredNamespaces.length > 0 ? await this.resolveNamespaceSchemas(driver, declaredNamespaces) : [schema];
971
+ const namespaces = {};
972
+ let pgVersion = "unknown";
973
+ for (const resolved of resolvedSchemas) {
974
+ const { namespace, pgVersion: version } = await this.introspectSchema(driver, resolved);
975
+ namespaces[resolved] = namespace;
976
+ pgVersion = version;
977
+ }
978
+ return new PostgresDatabaseSchemaNode({
979
+ namespaces,
980
+ roles: await this.introspectRoles(driver),
981
+ existingSchemas: await this.listExistingSchemas(driver),
982
+ pgVersion
983
+ });
984
+ }
985
+ /**
986
+ * Reads cluster-scoped database roles. Roles are not schema-qualified, so
987
+ * this is queried once for the whole database rather than per namespace.
988
+ */
989
+ async introspectRoles(driver) {
990
+ return (await driver.query(`SELECT rolname
991
+ FROM pg_catalog.pg_roles
992
+ WHERE rolname NOT LIKE 'pg_%'
993
+ AND rolname != 'postgres'
994
+ ORDER BY rolname`)).rows.map((row) => new PostgresRoleSchemaNode({
995
+ name: row.rolname,
996
+ namespaceId: UNBOUND_NAMESPACE_ID
997
+ }));
998
+ }
999
+ /**
1000
+ * Lists every non-system schema present in the connected database.
1001
+ * The introspection consumer (`verifyPostgresNamespacePresence`)
1002
+ * treats the result as the authoritative ground truth — declared
1003
+ * namespaces whose `ddlSchemaName` is missing from this list become
1004
+ * `missing_schema` issues, and the planner emits the matching
1005
+ * `CREATE SCHEMA` before table DDL.
1006
+ */
1007
+ async listExistingSchemas(driver) {
1008
+ return (await driver.query(`SELECT nspname
1009
+ FROM pg_catalog.pg_namespace
1010
+ WHERE nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
1011
+ AND nspname NOT LIKE 'pg_temp_%'
1012
+ AND nspname NOT LIKE 'pg_toast_temp_%'
1013
+ ORDER BY nspname`)).rows.map((row) => row.nspname);
1014
+ }
1015
+ /**
1016
+ * Resolves the declared namespace ids to their live DDL schema names,
1017
+ * mapping `UNBOUND_NAMESPACE_ID` to the connection's `current_schema()`
1018
+ * and de-duplicating. The caller introspects one namespace node per
1019
+ * resolved schema — there is no flat cross-schema merge, so two schemas
1020
+ * holding a same-named table no longer collide.
1021
+ */
1022
+ async resolveNamespaceSchemas(driver, namespaceIds) {
1023
+ const resolvedSchemas = [];
1024
+ for (const id of namespaceIds) if (id === UNBOUND_NAMESPACE_ID) {
1025
+ const { rows } = await driver.query("SELECT current_schema() AS current_schema");
1026
+ resolvedSchemas.push(rows[0]?.current_schema ?? "public");
1027
+ } else resolvedSchemas.push(id);
1028
+ return Array.from(new Set(resolvedSchemas));
1029
+ }
1030
+ /**
1031
+ * Introspects a single Postgres schema and returns the namespace node for
1032
+ * that schema (its tables, their policies, and its native enum type names),
1033
+ * alongside the cluster-scoped Postgres version. Used by `introspect` as
1034
+ * the per-namespace walk.
1035
+ */
1036
+ async introspectSchema(driver, schema) {
1037
+ const tablesResult = await driver.query(`SELECT table_name
1038
+ FROM information_schema.tables
1039
+ WHERE table_schema = $1
1040
+ AND table_type = 'BASE TABLE'
1041
+ ORDER BY table_name`, [schema]);
1042
+ const columnsResult = await driver.query(`SELECT
1043
+ c.table_name,
1044
+ column_name,
1045
+ data_type,
1046
+ udt_name,
1047
+ is_nullable,
1048
+ character_maximum_length,
1049
+ numeric_precision,
1050
+ numeric_scale,
1051
+ column_default,
1052
+ format_type(a.atttypid, a.atttypmod) AS formatted_type,
1053
+ a.attidentity
1054
+ FROM information_schema.columns c
1055
+ JOIN pg_catalog.pg_class cl
1056
+ ON cl.relname = c.table_name
1057
+ JOIN pg_catalog.pg_namespace ns
1058
+ ON ns.nspname = c.table_schema
1059
+ AND ns.oid = cl.relnamespace
1060
+ JOIN pg_catalog.pg_attribute a
1061
+ ON a.attrelid = cl.oid
1062
+ AND a.attname = c.column_name
1063
+ AND a.attnum > 0
1064
+ AND NOT a.attisdropped
1065
+ WHERE c.table_schema = $1
1066
+ ORDER BY c.table_name, c.ordinal_position`, [schema]);
1067
+ const pkResult = await driver.query(`SELECT
1068
+ cl.relname AS table_name,
1069
+ con.conname AS constraint_name,
1070
+ a.attname AS column_name,
1071
+ k.ord AS ordinal_position
1072
+ FROM pg_catalog.pg_constraint con
1073
+ JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
1074
+ JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
1075
+ JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
1076
+ JOIN pg_catalog.pg_attribute a
1077
+ ON a.attrelid = con.conrelid
1078
+ AND a.attnum = k.attnum
1079
+ WHERE ns.nspname = $1
1080
+ AND con.contype = 'p'
1081
+ ORDER BY cl.relname, k.ord`, [schema]);
1082
+ const fkResult = await driver.query(`SELECT
1083
+ cl.relname AS table_name,
1084
+ con.conname AS constraint_name,
1085
+ a.attname AS column_name,
1086
+ k.ord AS ordinal_position,
1087
+ ref_ns.nspname AS referenced_table_schema,
1088
+ ref_cl.relname AS referenced_table_name,
1089
+ ref_att.attname AS referenced_column_name,
1090
+ CASE con.confdeltype
1091
+ WHEN 'a' THEN 'NO ACTION'
1092
+ WHEN 'r' THEN 'RESTRICT'
1093
+ WHEN 'c' THEN 'CASCADE'
1094
+ WHEN 'n' THEN 'SET NULL'
1095
+ WHEN 'd' THEN 'SET DEFAULT'
1096
+ END AS delete_rule,
1097
+ CASE con.confupdtype
1098
+ WHEN 'a' THEN 'NO ACTION'
1099
+ WHEN 'r' THEN 'RESTRICT'
1100
+ WHEN 'c' THEN 'CASCADE'
1101
+ WHEN 'n' THEN 'SET NULL'
1102
+ WHEN 'd' THEN 'SET DEFAULT'
1103
+ END AS update_rule
1104
+ FROM pg_catalog.pg_constraint con
1105
+ JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
1106
+ JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
1107
+ JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
1108
+ JOIN pg_catalog.pg_attribute a
1109
+ ON a.attrelid = con.conrelid
1110
+ AND a.attnum = k.attnum
1111
+ JOIN pg_catalog.pg_class ref_cl
1112
+ ON ref_cl.oid = con.confrelid
1113
+ JOIN pg_catalog.pg_namespace ref_ns
1114
+ ON ref_ns.oid = ref_cl.relnamespace
1115
+ JOIN pg_catalog.pg_attribute ref_att
1116
+ ON ref_att.attrelid = con.confrelid
1117
+ AND ref_att.attnum = con.confkey[k.ord]
1118
+ WHERE ns.nspname = $1
1119
+ AND con.contype = 'f'
1120
+ ORDER BY cl.relname, con.conname, k.ord`, [schema]);
1121
+ const uniqueResult = await driver.query(`SELECT
1122
+ cl.relname AS table_name,
1123
+ con.conname AS constraint_name,
1124
+ a.attname AS column_name,
1125
+ k.ord AS ordinal_position
1126
+ FROM pg_catalog.pg_constraint con
1127
+ JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
1128
+ JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
1129
+ JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
1130
+ JOIN pg_catalog.pg_attribute a
1131
+ ON a.attrelid = con.conrelid
1132
+ AND a.attnum = k.attnum
1133
+ WHERE ns.nspname = $1
1134
+ AND con.contype = 'u'
1135
+ ORDER BY cl.relname, con.conname, k.ord`, [schema]);
1136
+ const indexResult = await driver.query(`SELECT
1137
+ i.tablename,
1138
+ i.indexname,
1139
+ ix.indisunique,
1140
+ pg_get_expr(ix.indpred, ix.indrelid) AS where_predicate,
1141
+ a.attname,
1142
+ CASE WHEN 0 = ANY(ix.indkey::int[]) THEN pg_get_indexdef(ix.indexrelid, k.ord::int, true) END AS element_def,
1143
+ k.ord AS index_position,
1144
+ am.amname,
1145
+ ic.reloptions
1146
+ FROM pg_indexes i
1147
+ JOIN pg_class ic ON ic.relname = i.indexname
1148
+ JOIN pg_namespace ins ON ins.oid = ic.relnamespace AND ins.nspname = $1
1149
+ JOIN pg_index ix ON ix.indexrelid = ic.oid
1150
+ JOIN pg_am am ON am.oid = ic.relam
1151
+ JOIN pg_class t ON t.oid = ix.indrelid
1152
+ JOIN pg_namespace tn ON tn.oid = t.relnamespace AND tn.nspname = $1
1153
+ JOIN LATERAL unnest(ix.indkey::int[]) WITH ORDINALITY AS k(attnum, ord) ON true
1154
+ LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum AND a.attnum > 0
1155
+ WHERE i.schemaname = $1
1156
+ AND NOT EXISTS (
1157
+ SELECT 1
1158
+ FROM pg_catalog.pg_constraint con
1159
+ WHERE con.conindid = ic.oid
1160
+ AND con.contype IN ('p', 'u', 'x')
1161
+ )
1162
+ ORDER BY i.tablename, i.indexname, k.ord`, [schema]);
1163
+ const checkResult = await driver.query(`SELECT
1164
+ cl.relname AS table_name,
1165
+ c.conname AS constraint_name,
1166
+ pg_get_constraintdef(c.oid) AS constraintdef
1167
+ FROM pg_catalog.pg_constraint c
1168
+ JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid
1169
+ JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
1170
+ WHERE ns.nspname = $1
1171
+ AND c.contype = 'c'
1172
+ ORDER BY cl.relname, c.conname`, [schema]);
1173
+ const columnsByTable = groupBy(columnsResult.rows, "table_name");
1174
+ const pksByTable = groupBy(pkResult.rows, "table_name");
1175
+ const fksByTable = groupBy(fkResult.rows, "table_name");
1176
+ const uniquesByTable = groupBy(uniqueResult.rows, "table_name");
1177
+ const indexesByTable = groupBy(indexResult.rows, "tablename");
1178
+ const checksByTable = groupBy(checkResult.rows, "table_name");
1179
+ const pkConstraintsByTable = /* @__PURE__ */ new Map();
1180
+ for (const row of pkResult.rows) {
1181
+ let constraints = pkConstraintsByTable.get(row.table_name);
1182
+ if (!constraints) {
1183
+ constraints = /* @__PURE__ */ new Set();
1184
+ pkConstraintsByTable.set(row.table_name, constraints);
1185
+ }
1186
+ constraints.add(row.constraint_name);
1187
+ }
1188
+ const tableInputs = {};
1189
+ for (const tableRow of tablesResult.rows) {
1190
+ const tableName = tableRow.table_name;
1191
+ const columns = {};
1192
+ for (const colRow of columnsByTable.get(tableName) ?? []) {
1193
+ let nativeType = colRow.udt_name;
1194
+ const formattedType = colRow.formatted_type ? normalizeFormattedType(colRow.formatted_type, colRow.data_type, colRow.udt_name) : null;
1195
+ if (formattedType) nativeType = formattedType;
1196
+ else if (colRow.data_type === "character varying" || colRow.data_type === "character") if (colRow.character_maximum_length) nativeType = `${colRow.data_type}(${colRow.character_maximum_length})`;
1197
+ else nativeType = colRow.data_type;
1198
+ else if (colRow.data_type === "numeric" || colRow.data_type === "decimal") if (colRow.numeric_precision && colRow.numeric_scale !== null) nativeType = `${colRow.data_type}(${colRow.numeric_precision},${colRow.numeric_scale})`;
1199
+ else if (colRow.numeric_precision) nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;
1200
+ else nativeType = colRow.data_type;
1201
+ else nativeType = colRow.udt_name || colRow.data_type;
1202
+ const many = nativeType.endsWith("[]") ? true : void 0;
1203
+ if (many) nativeType = normalizeSchemaNativeType(nativeType.slice(0, -2));
1204
+ const resolvedNativeType = `${normalizeSchemaNativeType(nativeType)}${many ? "[]" : ""}`;
1205
+ const rawDefault = colRow.column_default ?? void 0;
1206
+ const resolvedDefault = colRow.attidentity === "a" || colRow.attidentity === "d" ? {
1207
+ kind: "function",
1208
+ expression: "autoincrement()"
1209
+ } : rawDefault !== void 0 ? parsePostgresDefault(rawDefault, resolvedNativeType) : void 0;
1210
+ columns[colRow.column_name] = {
1211
+ name: colRow.column_name,
1212
+ nativeType,
1213
+ nullable: colRow.is_nullable === "YES",
1214
+ ...ifDefined("default", rawDefault),
1215
+ ...ifDefined("many", many),
1216
+ resolvedNativeType,
1217
+ ...ifDefined("resolvedDefault", resolvedDefault)
1218
+ };
1219
+ }
1220
+ const pkRows = [...pksByTable.get(tableName) ?? []];
1221
+ const primaryKeyColumns = pkRows.sort((a, b) => a.ordinal_position - b.ordinal_position).map((row) => row.column_name);
1222
+ const primaryKey = primaryKeyColumns.length > 0 ? {
1223
+ columns: primaryKeyColumns,
1224
+ ...pkRows[0]?.constraint_name ? { name: pkRows[0].constraint_name } : {},
1225
+ dependsOn: postgresColumnDependsOn(schema, tableName, primaryKeyColumns)
1226
+ } : void 0;
1227
+ const foreignKeysMap = /* @__PURE__ */ new Map();
1228
+ for (const fkRow of fksByTable.get(tableName) ?? []) {
1229
+ const existing = foreignKeysMap.get(fkRow.constraint_name);
1230
+ if (existing) {
1231
+ existing.columns.push(fkRow.column_name);
1232
+ existing.referencedColumns.push(fkRow.referenced_column_name);
1233
+ } else foreignKeysMap.set(fkRow.constraint_name, {
1234
+ columns: [fkRow.column_name],
1235
+ referencedTable: fkRow.referenced_table_name,
1236
+ referencedSchema: fkRow.referenced_table_schema,
1237
+ referencedColumns: [fkRow.referenced_column_name],
1238
+ name: fkRow.constraint_name,
1239
+ deleteRule: fkRow.delete_rule,
1240
+ updateRule: fkRow.update_rule
1241
+ });
1242
+ }
1243
+ const foreignKeys = Array.from(foreignKeysMap.values()).map((fk) => ({
1244
+ columns: Object.freeze([...fk.columns]),
1245
+ referencedTable: fk.referencedTable,
1246
+ referencedSchema: fk.referencedSchema,
1247
+ referencedColumns: Object.freeze([...fk.referencedColumns]),
1248
+ name: fk.name,
1249
+ ...ifDefined("onDelete", mapReferentialAction(fk.deleteRule)),
1250
+ ...ifDefined("onUpdate", mapReferentialAction(fk.updateRule)),
1251
+ dependsOn: [postgresTableDependsOn(fk.referencedSchema, fk.referencedTable), ...postgresColumnDependsOn(schema, tableName, fk.columns)]
1252
+ }));
1253
+ const pkConstraints = pkConstraintsByTable.get(tableName) ?? /* @__PURE__ */ new Set();
1254
+ const uniquesMap = /* @__PURE__ */ new Map();
1255
+ for (const uniqueRow of uniquesByTable.get(tableName) ?? []) {
1256
+ if (pkConstraints.has(uniqueRow.constraint_name)) continue;
1257
+ const existing = uniquesMap.get(uniqueRow.constraint_name);
1258
+ if (existing) existing.columns.push(uniqueRow.column_name);
1259
+ else uniquesMap.set(uniqueRow.constraint_name, {
1260
+ columns: [uniqueRow.column_name],
1261
+ name: uniqueRow.constraint_name
1262
+ });
1263
+ }
1264
+ const uniques = Array.from(uniquesMap.values()).map((uq) => ({
1265
+ columns: Object.freeze([...uq.columns]),
1266
+ name: uq.name,
1267
+ dependsOn: postgresColumnDependsOn(schema, tableName, uq.columns)
1268
+ }));
1269
+ const indexesMap = /* @__PURE__ */ new Map();
1270
+ for (const idxRow of indexesByTable.get(tableName) ?? []) {
1271
+ const existing = indexesMap.get(idxRow.indexname);
1272
+ if (existing) existing.elements.push({
1273
+ attname: idxRow.attname,
1274
+ elementDef: idxRow.element_def
1275
+ });
1276
+ else {
1277
+ const indexType = idxRow.amname ?? void 0;
1278
+ const indexOptions = parsePgReloptions(idxRow.reloptions, idxRow.indexname);
1279
+ indexesMap.set(idxRow.indexname, {
1280
+ name: idxRow.indexname,
1281
+ elements: [{
1282
+ attname: idxRow.attname,
1283
+ elementDef: idxRow.element_def
1284
+ }],
1285
+ unique: idxRow.indisunique,
1286
+ where: idxRow.where_predicate,
1287
+ type: indexType,
1288
+ options: indexOptions
1289
+ });
1290
+ }
1291
+ }
1292
+ const indexes = Array.from(indexesMap.values()).map((idx) => {
1293
+ const isExpression = idx.elements.some((el) => el.attname === null);
1294
+ const columnNames = idx.elements.flatMap((el) => el.attname !== null ? [el.attname] : []);
1295
+ const base = {
1296
+ naming: namingOfLiveName(idx.name),
1297
+ where: idx.where ?? void 0,
1298
+ unique: idx.unique,
1299
+ partial: idx.where !== null,
1300
+ type: idx.type,
1301
+ options: idx.options,
1302
+ annotations: void 0,
1303
+ dependsOn: postgresColumnDependsOn(schema, tableName, isExpression ? Object.keys(columns) : columnNames)
1304
+ };
1305
+ return isExpression ? {
1306
+ ...base,
1307
+ expression: idx.elements.map((el) => el.elementDef ?? "").join(", ")
1308
+ } : {
1309
+ ...base,
1310
+ columns: Object.freeze([...columnNames])
1311
+ };
1312
+ });
1313
+ const checksForTable = [];
1314
+ for (const checkRow of checksByTable.get(tableName) ?? []) {
1315
+ const parsed = parseCheckConstraintDef(checkRow.constraintdef);
1316
+ if (parsed) checksForTable.push({
1317
+ name: checkRow.constraint_name,
1318
+ column: parsed.column,
1319
+ permittedValues: parsed.permittedValues
1320
+ });
1321
+ }
1322
+ tableInputs[tableName] = {
1323
+ name: tableName,
1324
+ columns,
1325
+ ...ifDefined("primaryKey", primaryKey),
1326
+ foreignKeys,
1327
+ uniques,
1328
+ indexes,
1329
+ ...ifDefined("checks", checksForTable.length > 0 ? checksForTable : void 0)
1330
+ };
1331
+ }
1332
+ const enums = (await driver.query(`SELECT t.typname, array_agg(e.enumlabel ORDER BY e.enumsortorder) AS enumvalues
1333
+ FROM pg_catalog.pg_type t
1334
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
1335
+ JOIN pg_catalog.pg_enum e ON e.enumtypid = t.oid
1336
+ WHERE t.typtype = 'e'
1337
+ AND n.nspname = $1
1338
+ GROUP BY t.typname
1339
+ ORDER BY t.typname`, [schema])).rows.map((r) => new PostgresNativeEnumSchemaNode({
1340
+ typeName: r.typname,
1341
+ namespaceId: schema,
1342
+ members: parsePgNameArray(r.enumvalues)
1343
+ }));
1344
+ const policiesResult = await driver.query(`SELECT schemaname, tablename, policyname, cmd, roles, qual, with_check, permissive
1345
+ FROM pg_catalog.pg_policies
1346
+ WHERE schemaname = $1
1347
+ ORDER BY tablename, policyname`, [schema]);
1348
+ const policiesByTable = /* @__PURE__ */ new Map();
1349
+ for (const row of policiesResult.rows) {
1350
+ const operation = mapPgCmd(row.cmd);
1351
+ const policyRoles = [...new Set(parsePgNameArray(row.roles).map((r) => r.toLowerCase()))].sort();
1352
+ const permissive = row.permissive.toUpperCase() === "PERMISSIVE";
1353
+ const policy = new PostgresPolicySchemaNode({
1354
+ naming: namingOfLiveName(row.policyname),
1355
+ tableName: row.tablename,
1356
+ namespaceId: row.schemaname,
1357
+ operation,
1358
+ roles: policyRoles,
1359
+ using: row.qual ?? void 0,
1360
+ withCheck: row.with_check ?? void 0,
1361
+ permissive,
1362
+ dependsOn: [postgresTableDependsOn(row.schemaname, row.tablename), ...policyRoles.map(postgresRoleDependsOn)]
1363
+ });
1364
+ const list = policiesByTable.get(row.tablename) ?? [];
1365
+ list.push(policy);
1366
+ policiesByTable.set(row.tablename, list);
1367
+ }
1368
+ const rlsEnabledResult = await driver.query(`SELECT c.relname AS tablename, c.relrowsecurity AS rls_enabled
1369
+ FROM pg_catalog.pg_class c
1370
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
1371
+ WHERE n.nspname = $1
1372
+ AND c.relkind IN ('r', 'p')
1373
+ ORDER BY c.relname`, [schema]);
1374
+ const rlsEnabledByTable = new Map(rlsEnabledResult.rows.map((row) => [row.tablename, row.rls_enabled]));
1375
+ const tables = {};
1376
+ for (const [tableName, input] of Object.entries(tableInputs)) tables[tableName] = new PostgresTableSchemaNode({
1377
+ ...input,
1378
+ policies: policiesByTable.get(tableName) ?? [],
1379
+ rlsEnabled: rlsEnabledByTable.get(tableName) ?? false
1380
+ });
1381
+ return {
1382
+ namespace: new PostgresNamespaceSchemaNode({
1383
+ schemaName: schema,
1384
+ tables,
1385
+ nativeEnums: enums
1386
+ }),
1387
+ pgVersion: await this.getPostgresVersion(driver)
1388
+ };
1389
+ }
1390
+ /**
1391
+ * Gets the Postgres version from the database.
1392
+ */
1393
+ async getPostgresVersion(driver) {
1394
+ return ((await driver.query("SELECT version() AS version", [])).rows[0]?.version ?? "").match(/PostgreSQL (\d+\.\d+)/)?.[1] ?? "unknown";
1395
+ }
1396
+ };
1397
+ /**
1398
+ * Normalises a `name[]` column value from `pg_policies.roles`.
1399
+ *
1400
+ * The `pg` client's type-parser registry handles `text[]` (OID 1009) but not
1401
+ * `name[]` (OID 1003). When the parser is absent the raw Postgres text-array
1402
+ * literal (`{role1,role2}`) is returned as a string instead of a JS array.
1403
+ * This function accepts either form and returns a plain string array.
1404
+ *
1405
+ * The string branch honors Postgres array-literal quoting: an element
1406
+ * containing a comma, quote, backslash, brace, or significant whitespace is
1407
+ * emitted double-quoted with `\"` / `\\` escapes, and unquoted elements are
1408
+ * whitespace-trimmed — so a label like `in progress` or `say "hi"` parses to
1409
+ * its true value instead of being split or kept escaped.
1410
+ */
1411
+ function parsePgNameArray(value) {
1412
+ if (Array.isArray(value)) return value.map(String);
1413
+ if (typeof value !== "string") return [];
1414
+ const trimmed = value.trim();
1415
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return [];
1416
+ const inner = trimmed.slice(1, -1);
1417
+ if (inner === "") return [];
1418
+ const elements = [];
1419
+ let current = "";
1420
+ let inQuotes = false;
1421
+ let wasQuoted = false;
1422
+ const pushCurrent = () => {
1423
+ elements.push(wasQuoted ? current : current.trim());
1424
+ current = "";
1425
+ wasQuoted = false;
1426
+ };
1427
+ let i = 0;
1428
+ while (i < inner.length) {
1429
+ const char = inner.charAt(i);
1430
+ if (inQuotes) {
1431
+ if (char === "\\") {
1432
+ current += inner[i + 1] ?? "";
1433
+ i += 2;
1434
+ continue;
1435
+ }
1436
+ if (char === "\"") {
1437
+ inQuotes = false;
1438
+ i++;
1439
+ continue;
1440
+ }
1441
+ current += char;
1442
+ i++;
1443
+ continue;
1444
+ }
1445
+ if (char === "\"") {
1446
+ inQuotes = true;
1447
+ wasQuoted = true;
1448
+ i++;
1449
+ continue;
1450
+ }
1451
+ if (char === ",") {
1452
+ pushCurrent();
1453
+ i++;
1454
+ continue;
1455
+ }
1456
+ current += char;
1457
+ i++;
1458
+ }
1459
+ if (inQuotes) return [];
1460
+ pushCurrent();
1461
+ return elements;
1462
+ }
1463
+ /**
1464
+ * Maps `pg_policies.cmd` text values to the `RlsPolicyOperation` union.
1465
+ * The `pg_policies` view renders the internal command code as an uppercase
1466
+ * English keyword; this function lowercases to match the IR type.
1467
+ */
1468
+ function mapPgCmd(cmd) {
1469
+ switch (cmd.toUpperCase()) {
1470
+ case "SELECT": return "select";
1471
+ case "INSERT": return "insert";
1472
+ case "UPDATE": return "update";
1473
+ case "DELETE": return "delete";
1474
+ default: return "all";
1475
+ }
1476
+ }
1477
+ /**
1478
+ * Extracts the namespace coordinate ids declared on a contract's storage,
1479
+ * or returns an empty array when no contract (or no storage / namespaces)
1480
+ * is present. Used by `PostgresControlAdapter.introspect` to decide
1481
+ * between the multi-namespace walk and the single-schema fallback.
1482
+ */
1483
+ function extractContractNamespaceIds(contract) {
1484
+ if (contract === null || typeof contract !== "object") return [];
1485
+ const storage = contract.storage;
1486
+ if (storage === null || typeof storage !== "object") return [];
1487
+ const namespaces = storage.namespaces;
1488
+ if (namespaces === null || typeof namespaces !== "object") return [];
1489
+ return Object.keys(namespaces);
1490
+ }
1491
+ function normalizeFormattedType(formattedType, dataType, udtName) {
1492
+ if (formattedType.endsWith("[]")) return `${normalizeFormattedType(formattedType.slice(0, -2), dataType, udtName)}[]`;
1493
+ if (formattedType === "integer") return "int4";
1494
+ if (formattedType === "smallint") return "int2";
1495
+ if (formattedType === "bigint") return "int8";
1496
+ if (formattedType === "real") return "float4";
1497
+ if (formattedType === "double precision") return "float8";
1498
+ if (formattedType === "boolean") return "bool";
1499
+ if (formattedType.startsWith("varchar")) return formattedType.replace("varchar", "character varying");
1500
+ if (formattedType.startsWith("bpchar")) return formattedType.replace("bpchar", "character");
1501
+ if (formattedType.startsWith("varbit")) return formattedType.replace("varbit", "bit varying");
1502
+ if (dataType === "timestamp with time zone" || udtName === "timestamptz") return formattedType.replace("timestamp", "timestamptz").replace(" with time zone", "").trim();
1503
+ if (dataType === "timestamp without time zone" || udtName === "timestamp") return formattedType.replace(" without time zone", "").trim();
1504
+ if (dataType === "time with time zone" || udtName === "timetz") return formattedType.replace("time", "timetz").replace(" with time zone", "").trim();
1505
+ if (dataType === "time without time zone" || udtName === "time") return formattedType.replace(" without time zone", "").trim();
1506
+ if (formattedType.startsWith("\"") && formattedType.endsWith("\"")) return formattedType.slice(1, -1);
1507
+ return formattedType;
1508
+ }
1509
+ const PG_REFERENTIAL_ACTION_MAP = {
1510
+ "NO ACTION": "noAction",
1511
+ RESTRICT: "restrict",
1512
+ CASCADE: "cascade",
1513
+ "SET NULL": "setNull",
1514
+ "SET DEFAULT": "setDefault"
1515
+ };
1516
+ /**
1517
+ * Maps a Postgres referential action rule to the canonical SqlReferentialAction.
1518
+ * Returns undefined for 'NO ACTION' (the database default) to keep the IR sparse.
1519
+ * Throws for unrecognized rules to prevent silent data loss.
1520
+ */
1521
+ function mapReferentialAction(rule) {
1522
+ const mapped = PG_REFERENTIAL_ACTION_MAP[rule];
1523
+ if (mapped === void 0) throw adapterError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Unknown PostgreSQL referential action rule: "${rule}". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`, { meta: { rule } });
1524
+ if (mapped === "noAction") return void 0;
1525
+ return mapped;
1526
+ }
1527
+ /**
1528
+ * A FK/policy dependency chain, mirroring the shape the expected-side
1529
+ * derivation stamps (`contractToPostgresDatabaseSchemaNode`): the database
1530
+ * root's fixed sentinel id, then the namespace, then the table.
1531
+ */
1532
+ function postgresTableDependsOn(namespaceId, tableName) {
1533
+ return [
1534
+ {
1535
+ nodeKind: PostgresSchemaNodeKind.database,
1536
+ id: "database"
1537
+ },
1538
+ {
1539
+ nodeKind: PostgresSchemaNodeKind.namespace,
1540
+ id: namespaceId
1541
+ },
1542
+ {
1543
+ nodeKind: PostgresSchemaNodeKind.table,
1544
+ id: tableName
1545
+ }
1546
+ ];
1547
+ }
1548
+ /** A policy's dependency chain onto one of the roles it grants to. */
1549
+ function postgresRoleDependsOn(role) {
1550
+ return [{
1551
+ nodeKind: PostgresSchemaNodeKind.database,
1552
+ id: "database"
1553
+ }, {
1554
+ nodeKind: PostgresSchemaNodeKind.role,
1555
+ id: role
1556
+ }];
1557
+ }
1558
+ /**
1559
+ * The chains from a table-child object (foreign key, index, unique, primary
1560
+ * key) to each of the own columns it is built on — the introspection-side
1561
+ * mirror of `contractToPostgresDatabaseSchemaNode`'s `columnDependsOn`. An
1562
+ * object is dropped before the columns it covers.
1563
+ */
1564
+ function postgresColumnDependsOn(namespaceId, tableName, columns) {
1565
+ return columns.map((column) => [...postgresTableDependsOn(namespaceId, tableName), {
1566
+ nodeKind: RelationalSchemaNodeKind.column,
1567
+ id: `column:${column}`
1568
+ }]);
1569
+ }
1570
+ /**
1571
+ * Groups an array of objects by a specified key.
1572
+ * Returns a Map for O(1) lookup by group key.
1573
+ */
1574
+ /**
1575
+ * Parses a `pg_class.reloptions` array into a `Record<string, string>`.
1576
+ *
1577
+ * Postgres returns reloptions as a `text[]` whose entries are `key=value`
1578
+ * strings; the value side is always a string regardless of the underlying
1579
+ * scalar type. The verifier compares contract options to introspected
1580
+ * options after coercing both sides to strings, so keeping the raw text
1581
+ * here is correct.
1582
+ *
1583
+ * Returns `undefined` when the input is null/empty (no WITH clause).
1584
+ */
1585
+ function parsePgReloptions(reloptions, indexName) {
1586
+ if (!reloptions || reloptions.length === 0) return;
1587
+ const result = {};
1588
+ for (const entry of reloptions) {
1589
+ const eq = entry.indexOf("=");
1590
+ if (eq === -1) throw adapterError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Postgres introspection: malformed reloption entry "${entry}" on index "${indexName}" (expected "key=value")`, { meta: {
1591
+ entry,
1592
+ indexName
1593
+ } });
1594
+ const key = entry.slice(0, eq);
1595
+ result[key] = entry.slice(eq + 1);
1596
+ }
1597
+ return Object.keys(result).length > 0 ? result : void 0;
1598
+ }
1599
+ function groupBy(items, key) {
1600
+ const map = /* @__PURE__ */ new Map();
1601
+ for (const item of items) {
1602
+ const groupKey = item[key];
1603
+ let group = map.get(groupKey);
1604
+ if (!group) {
1605
+ group = [];
1606
+ map.set(groupKey, group);
1607
+ }
1608
+ group.push(item);
1609
+ }
1610
+ return map;
1611
+ }
1612
+ /**
1613
+ * Parses a Postgres check-constraint definition string (as returned by
1614
+ * `pg_get_constraintdef`) into a column name and permitted values array.
1615
+ *
1616
+ * Handles two shapes that Postgres emits for enum-style checks:
1617
+ *
1618
+ * 1. `= ANY (ARRAY[...])` — Postgres rewrites `col IN ('a','b')` to this form:
1619
+ * `CHECK ((col = ANY (ARRAY['a'::text, 'b'::text])))`
1620
+ *
1621
+ * 2. `IN (...)` — stays as-is when written directly:
1622
+ * `CHECK ((col IN ('a', 'b')))`
1623
+ *
1624
+ * Column names may be plain identifiers (`status`) or double-quoted identifiers
1625
+ * (`"my-col"`). Double-quoted identifiers with embedded `""` are un-escaped to a
1626
+ * single `"`.
1627
+ *
1628
+ * String literal values may contain Postgres-style doubled single-quotes (`''`),
1629
+ * which are un-escaped to a single `'` (e.g. `O''Brien` → `O'Brien`).
1630
+ *
1631
+ * Returns `{ column, permittedValues }` when the predicate matches one of
1632
+ * the two recognised shapes. Returns `undefined` for anything else (e.g.
1633
+ * a free-form SQL predicate that wasn't emitted by this slice).
1634
+ */
1635
+ function parseCheckConstraintDef(constraintdef) {
1636
+ const afterCheck = constraintdef.replace(/^CHECK\s*\(/i, "").replace(/\)$/, "").trim();
1637
+ const inner = afterCheck.startsWith("(") && afterCheck.endsWith(")") ? afterCheck.slice(1, -1).trim() : afterCheck;
1638
+ const anyArrayMatch = inner.match(/^(?:"((?:[^"]|"")*)"|(\w+))\s*=\s*ANY\s*\(\s*ARRAY\s*\[(.+)\]\s*\)\s*$/i);
1639
+ if (anyArrayMatch) {
1640
+ const column = anyArrayMatch[1] !== void 0 ? anyArrayMatch[1].replace(/""/g, "\"") : anyArrayMatch[2];
1641
+ const arrayBody = anyArrayMatch[3];
1642
+ if (!column || !arrayBody) return void 0;
1643
+ const permittedValues = extractArrayLiterals(arrayBody);
1644
+ return permittedValues ? {
1645
+ column,
1646
+ permittedValues
1647
+ } : void 0;
1648
+ }
1649
+ const inMatch = inner.match(/^(?:"((?:[^"]|"")*)"|(\w+))\s+IN\s*\((.+)\)\s*$/i);
1650
+ if (inMatch) {
1651
+ const column = inMatch[1] !== void 0 ? inMatch[1].replace(/""/g, "\"") : inMatch[2];
1652
+ const listBody = inMatch[3];
1653
+ if (!column || !listBody) return void 0;
1654
+ const permittedValues = extractQuotedLiterals(listBody);
1655
+ return permittedValues ? {
1656
+ column,
1657
+ permittedValues
1658
+ } : void 0;
1659
+ }
1660
+ }
1661
+ /**
1662
+ * Extracts string literals from an `ARRAY[...]` body.
1663
+ * Handles `'value'::type` casts by stripping the cast part.
1664
+ * Postgres stores single quotes inside values as doubled single-quotes (`''`);
1665
+ * each extracted value is un-escaped so `O''Brien` becomes `O'Brien`.
1666
+ */
1667
+ function extractArrayLiterals(arrayBody) {
1668
+ const values = [...arrayBody.matchAll(/'((?:[^'\\]|\\.|'')*)'\s*(?:::[^\s,\]]+)?/g)].map((m) => (m[1] ?? "").replace(/''/g, "'"));
1669
+ return values.length > 0 ? values : void 0;
1670
+ }
1671
+ /**
1672
+ * Extracts string literals from an `IN (...)` list.
1673
+ * Handles single-quoted literals with possible escaped quotes.
1674
+ * Postgres stores single quotes inside values as doubled single-quotes (`''`);
1675
+ * each extracted value is un-escaped so `O''Brien` becomes `O'Brien`.
1676
+ */
1677
+ function extractQuotedLiterals(listBody) {
1678
+ const values = [...listBody.matchAll(/'((?:[^'\\]|\\.|'')*)'/g)].map((m) => (m[1] ?? "").replace(/''/g, "'"));
1679
+ return values.length > 0 ? values : void 0;
1680
+ }
1681
+ function pgIsTextLikeNativeType(nativeType) {
1682
+ return nativeType === "text" || nativeType === "varchar" || nativeType.startsWith("varchar(") || nativeType === "character varying" || nativeType.startsWith("character varying(") || nativeType === "char" || nativeType.startsWith("char(") || nativeType === "character" || nativeType.startsWith("character(");
1683
+ }
1684
+ function pgRenderArrayElement(el) {
1685
+ if (el === null) return "NULL";
1686
+ if (typeof el === "number" || typeof el === "boolean") return String(el);
1687
+ if (typeof el === "string") return `'${escapeLiteral(el)}'`;
1688
+ return `'${escapeLiteral(JSON.stringify(el))}'`;
1689
+ }
1690
+ function pgRenderArrayLiteral(elements) {
1691
+ if (elements.length === 0) return "'{}'";
1692
+ return `ARRAY[${elements.map(pgRenderArrayElement).join(", ")}]`;
1693
+ }
1694
+ function pgInlineLiteral(wire, nativeType) {
1695
+ if (wire === null) return "NULL";
1696
+ if (typeof wire === "boolean") return wire ? "true" : "false";
1697
+ if (typeof wire === "number") {
1698
+ if (!Number.isFinite(wire)) throw adapterError("CONTRACT.DEFAULT_INVALID", `pgRenderDdlExecuteRequest: non-finite number wire value ${String(wire)} cannot be emitted as a DEFAULT literal for native type "${nativeType}"`, { meta: { nativeType } });
1699
+ return String(wire);
1700
+ }
1701
+ if (typeof wire === "bigint") return String(wire);
1702
+ if (wire instanceof Date) {
1703
+ if (Number.isNaN(wire.getTime())) throw adapterError("CONTRACT.DEFAULT_INVALID", `pgRenderDdlExecuteRequest: invalid Date value cannot be emitted as a DEFAULT literal for native type "${nativeType}"`, { meta: { nativeType } });
1704
+ const quoted = `'${escapeLiteral(wire.toISOString())}'`;
1705
+ return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
1706
+ }
1707
+ if (typeof wire === "string") {
1708
+ const quoted = `'${escapeLiteral(wire)}'`;
1709
+ return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
1710
+ }
1711
+ if (wire instanceof Uint8Array) return `'\\x${Array.from(wire).map((b) => b.toString(16).padStart(2, "0")).join("")}'::${nativeType}`;
1712
+ if (Array.isArray(wire) && nativeType.endsWith("[]")) return pgRenderArrayLiteral(wire);
1713
+ if (typeof wire === "object") return `${`'${escapeLiteral(JSON.stringify(wire))}'`}::${nativeType}`;
1714
+ throw adapterError("CONTRACT.PACK_CONTRIBUTION_INVALID", `pgRenderDdlExecuteRequest: unexpected wire type "${typeof wire}" for native type "${nativeType}"`, { meta: {
1715
+ wireType: typeof wire,
1716
+ nativeType
1717
+ } });
1718
+ }
1719
+ async function pgRenderDdlColumnDefault(def, nativeType, codecLookup, codecRef) {
1720
+ if (def.kind === "function") {
1721
+ if (def.expression === "autoincrement()") return "";
1722
+ return `DEFAULT (${def.expression})`;
1723
+ }
1724
+ if (codecRef !== void 0) {
1725
+ const codec = codecLookup.get(codecRef.codecId);
1726
+ if (codec !== void 0) return `DEFAULT ${pgInlineLiteral(await codec.encode(def.value, {}), nativeType)}`;
1727
+ }
1728
+ return `DEFAULT ${pgInlineLiteral(def.value, nativeType)}`;
1729
+ }
1730
+ async function pgRenderDdlColumn(column, codecLookup) {
1731
+ const parts = [quoteIdentifier(column.name), column.type];
1732
+ if (column.default) {
1733
+ const clause = await pgRenderDdlColumnDefault(column.default, column.type, codecLookup, column.codecRef);
1734
+ if (clause.length > 0) parts.push(clause);
1735
+ }
1736
+ if (column.notNull) parts.push("NOT NULL");
1737
+ if (column.primaryKey) parts.push("PRIMARY KEY");
1738
+ return parts.join(" ");
1739
+ }
1740
+ function pgRenderDdlConstraint(constraint) {
1741
+ if (constraint.kind === "primary-key") {
1742
+ const cols = constraint.columns.map(quoteIdentifier).join(", ");
1743
+ if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} PRIMARY KEY (${cols})`;
1744
+ return `PRIMARY KEY (${cols})`;
1745
+ }
1746
+ if (constraint.kind === "foreign-key") {
1747
+ let sql = `FOREIGN KEY (${constraint.columns.map(quoteIdentifier).join(", ")}) REFERENCES ${constraint.refTable.split(".").map(quoteIdentifier).join(".")} (${constraint.refColumns.map(quoteIdentifier).join(", ")})`;
1748
+ if (constraint.onDelete !== void 0) sql += ` ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`;
1749
+ if (constraint.onUpdate !== void 0) sql += ` ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`;
1750
+ if (constraint.name !== void 0) sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
1751
+ return sql;
1752
+ }
1753
+ if (constraint.kind === "check-expression") return `CONSTRAINT ${quoteIdentifier(constraint.name)} CHECK (${constraint.expression})`;
1754
+ const cols = constraint.columns.map(quoteIdentifier).join(", ");
1755
+ if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
1756
+ return `UNIQUE (${cols})`;
1757
+ }
1758
+ async function pgRenderCreateTable(node, codecLookup) {
1759
+ const ifNotExists = node.ifNotExists ? "IF NOT EXISTS " : "";
1760
+ const tableRef = node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}` : quoteIdentifier(node.table);
1761
+ const columnDefs = await Promise.all(node.columns.map((col) => pgRenderDdlColumn(col, codecLookup)));
1762
+ const constraintDefs = node.constraints !== void 0 ? node.constraints.map(pgRenderDdlConstraint) : [];
1763
+ return {
1764
+ sql: `CREATE TABLE ${ifNotExists}${tableRef} (\n ${[...columnDefs, ...constraintDefs].join(",\n ")}\n)`,
1765
+ params: []
1766
+ };
1767
+ }
1768
+ function pgRenderCreateSchema(node) {
1769
+ return {
1770
+ sql: `CREATE SCHEMA ${node.ifNotExists ? "IF NOT EXISTS " : ""}${quoteIdentifier(node.schema)}`,
1771
+ params: []
1772
+ };
1773
+ }
1774
+ function pgRenderCreateType(node) {
1775
+ return {
1776
+ sql: `CREATE TYPE ${node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.name)}` : quoteIdentifier(node.name)} AS ENUM (${node.values.map((value) => `'${escapeLiteral(value)}'`).join(", ")})`,
1777
+ params: []
1778
+ };
1779
+ }
1780
+ function pgRenderDropType(node) {
1781
+ return {
1782
+ sql: `DROP TYPE ${node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.name)}` : quoteIdentifier(node.name)}`,
1783
+ params: []
1784
+ };
1785
+ }
1786
+ async function pgRenderAlterTable(node, codecLookup) {
1787
+ const tableRef = node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}` : quoteIdentifier(node.table);
1788
+ const actionVisitor = {
1789
+ async addColumn(action) {
1790
+ return `ADD COLUMN ${await pgRenderDdlColumn(action.column, codecLookup)}`;
1791
+ },
1792
+ dropDefault(action) {
1793
+ return Promise.resolve(`ALTER COLUMN ${quoteIdentifier(action.columnName)} DROP DEFAULT`);
1794
+ }
1795
+ };
1796
+ return {
1797
+ sql: `ALTER TABLE ${tableRef} ${(await Promise.all(node.actions.map((a) => a.accept(actionVisitor)))).join(", ")}`,
1798
+ params: []
1799
+ };
1800
+ }
1801
+ const POLICY_OPERATION_SQL = {
1802
+ select: "SELECT",
1803
+ insert: "INSERT",
1804
+ update: "UPDATE",
1805
+ delete: "DELETE",
1806
+ all: "ALL"
1807
+ };
1808
+ function pgRenderCreatePolicy(node) {
1809
+ const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
1810
+ const permissiveness = node.permissive ? "PERMISSIVE" : "RESTRICTIVE";
1811
+ const command = POLICY_OPERATION_SQL[node.operation];
1812
+ const roles = node.roles.length === 0 ? "PUBLIC" : node.roles.join(", ");
1813
+ let sql = `CREATE POLICY ${quoteIdentifier(node.name)} ON ${tableRef} AS ${permissiveness} FOR ${command} TO ${roles}`;
1814
+ if (node.using !== void 0) sql += ` USING (${node.using})`;
1815
+ if (node.withCheck !== void 0) sql += ` WITH CHECK (${node.withCheck})`;
1816
+ return {
1817
+ sql,
1818
+ params: []
1819
+ };
1820
+ }
1821
+ function pgRenderDropPolicy(node) {
1822
+ const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
1823
+ return {
1824
+ sql: `DROP POLICY ${quoteIdentifier(node.name)} ON ${tableRef}`,
1825
+ params: []
1826
+ };
1827
+ }
1828
+ function pgRenderAlterPolicyRename(node) {
1829
+ const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
1830
+ return {
1831
+ sql: `ALTER POLICY ${quoteIdentifier(node.name)} ON ${tableRef} RENAME TO ${quoteIdentifier(node.newName)}`,
1832
+ params: []
1833
+ };
1834
+ }
1835
+ /**
1836
+ * Renders one index reloption value: strings single-quote-escaped, finite
1837
+ * numbers verbatim, booleans in the `on`/`off` catalog spelling (the
1838
+ * canonical form the wire hash and the option equality commit to).
1839
+ */
1840
+ function pgRenderIndexOptionValue(key, value) {
1841
+ if (typeof value === "string") return `'${escapeLiteral(value)}'`;
1842
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
1843
+ if (typeof value === "boolean") return value ? "on" : "off";
1844
+ throw postgresError("CONTRACT.INDEX_INVALID", `Index option "${key}" must be a string, finite number, or boolean; got ${typeof value}`, { meta: {
1845
+ key,
1846
+ valueType: typeof value
1847
+ } });
1848
+ }
1849
+ /** Qualifies an object name; an absent schema renders it unqualified (unbound namespace). */
1850
+ function pgQualify(schema, name) {
1851
+ return schema === void 0 ? quoteIdentifier(name) : `${quoteIdentifier(schema)}.${quoteIdentifier(name)}`;
1852
+ }
1853
+ function pgRenderCreateIndex(node) {
1854
+ const elementList = "columns" in node.elements ? node.elements.columns.map(quoteIdentifier).join(", ") : node.elements.expression;
1855
+ const unique = node.unique ? "UNIQUE " : "";
1856
+ const using = node.type !== void 0 ? ` USING ${quoteIdentifier(node.type)}` : "";
1857
+ const withClause = node.options !== void 0 && Object.keys(node.options).length > 0 ? ` WITH (${Object.entries(node.options).map(([key, value]) => `${quoteIdentifier(key)} = ${pgRenderIndexOptionValue(key, value)}`).join(", ")})` : "";
1858
+ const whereClause = node.where !== void 0 ? ` WHERE (${node.where})` : "";
1859
+ return {
1860
+ sql: `CREATE ${unique}INDEX ${quoteIdentifier(node.name)} ON ${pgQualify(node.schema, node.table)}${using} (${elementList})${withClause}${whereClause}`,
1861
+ params: []
1862
+ };
1863
+ }
1864
+ function pgRenderDropIndex(node) {
1865
+ return {
1866
+ sql: `DROP INDEX ${pgQualify(node.schema, node.name)}`,
1867
+ params: []
1868
+ };
1869
+ }
1870
+ function pgRenderAlterIndexRename(node) {
1871
+ return {
1872
+ sql: `ALTER INDEX ${pgQualify(node.schema, node.from)} RENAME TO ${quoteIdentifier(node.to)}`,
1873
+ params: []
1874
+ };
1875
+ }
1876
+ function pgRenderDisableRowLevelSecurity(node) {
1877
+ return {
1878
+ sql: `ALTER TABLE ${`${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`} DISABLE ROW LEVEL SECURITY`,
1879
+ params: []
1880
+ };
1881
+ }
1882
+ async function pgRenderDdlExecuteRequest(ast, codecLookup) {
1883
+ return ast.accept({
1884
+ createTable: (node) => pgRenderCreateTable(node, codecLookup),
1885
+ createSchema: (node) => Promise.resolve(pgRenderCreateSchema(node)),
1886
+ createType: (node) => Promise.resolve(pgRenderCreateType(node)),
1887
+ dropType: (node) => Promise.resolve(pgRenderDropType(node)),
1888
+ alterTable: (node) => pgRenderAlterTable(node, codecLookup),
1889
+ createPolicy: (node) => Promise.resolve(pgRenderCreatePolicy(node)),
1890
+ dropPolicy: (node) => Promise.resolve(pgRenderDropPolicy(node)),
1891
+ alterPolicyRename: (node) => Promise.resolve(pgRenderAlterPolicyRename(node)),
1892
+ createIndex: (node) => Promise.resolve(pgRenderCreateIndex(node)),
1893
+ dropIndex: (node) => Promise.resolve(pgRenderDropIndex(node)),
1894
+ alterIndexRename: (node) => Promise.resolve(pgRenderAlterIndexRename(node)),
1895
+ disableRowLevelSecurity: (node) => Promise.resolve(pgRenderDisableRowLevelSecurity(node))
1896
+ });
1897
+ }
1898
+ //#endregion
1899
+ export { createPostgresCodecRegistryWithBuiltins as a, createPostgresBuiltinCodecLookup as i, adapterError as n, renderLoweredSql as o, assemblePostgresCodecRegistry as r, PostgresControlAdapter as t };
1900
+
1901
+ //# sourceMappingURL=control-adapter-B9t0g7Pf-HrCxlM65.mjs.map