@prisma-next/target-postgres 0.14.0-dev.8 → 0.14.0-dev.80

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 (266) hide show
  1. package/dist/authoring-Bi9aa8zG.mjs +574 -0
  2. package/dist/authoring-Bi9aa8zG.mjs.map +1 -0
  3. package/dist/canonicalize-CAbXtVtB.d.mts +37 -0
  4. package/dist/canonicalize-CAbXtVtB.d.mts.map +1 -0
  5. package/dist/{codec-ids-CnXu9Qy3.d.mts → codec-ids-BzrFF-I4.d.mts} +3 -2
  6. package/dist/codec-ids-BzrFF-I4.d.mts.map +1 -0
  7. package/dist/{codec-ids-BvytN2P8.mjs → codec-ids-C_-Hj6bL.mjs} +3 -2
  8. package/dist/codec-ids-C_-Hj6bL.mjs.map +1 -0
  9. package/dist/codec-ids.d.mts +2 -2
  10. package/dist/codec-ids.mjs +2 -2
  11. package/dist/{codec-types-DHCkwPKE.d.mts → codec-types-BiIWziRO.d.mts} +3 -2
  12. package/dist/codec-types-BiIWziRO.d.mts.map +1 -0
  13. package/dist/codec-types.d.mts +1 -1
  14. package/dist/codecs-BemGS69L.mjs +927 -0
  15. package/dist/codecs-BemGS69L.mjs.map +1 -0
  16. package/dist/{codecs--0A5_4Bq.d.mts → codecs-Cm-nS4mQ.d.mts} +111 -4
  17. package/dist/codecs-Cm-nS4mQ.d.mts.map +1 -0
  18. package/dist/codecs.d.mts +2 -2
  19. package/dist/codecs.mjs +3 -757
  20. package/dist/codecs.mjs.map +1 -1
  21. package/dist/contract-free.d.mts +33 -3
  22. package/dist/contract-free.d.mts.map +1 -1
  23. package/dist/contract-free.mjs +23 -7
  24. package/dist/contract-free.mjs.map +1 -1
  25. package/dist/control-policy-5LE2kwfb.mjs +1285 -0
  26. package/dist/control-policy-5LE2kwfb.mjs.map +1 -0
  27. package/dist/control.d.mts +2 -2
  28. package/dist/control.d.mts.map +1 -1
  29. package/dist/control.mjs +866 -36
  30. package/dist/control.mjs.map +1 -1
  31. package/dist/data-transform-BOWpliq8.mjs.map +1 -1
  32. package/dist/{data-transform-DDgWdB5o.d.mts → data-transform-DPzwBMhW.d.mts} +3 -3
  33. package/dist/{data-transform-DDgWdB5o.d.mts.map → data-transform-DPzwBMhW.d.mts.map} +1 -1
  34. package/dist/data-transform.d.mts +1 -1
  35. package/dist/{ddl-QDyOSeLc.mjs → ddl-BQzITB_e.mjs} +128 -6
  36. package/dist/ddl-BQzITB_e.mjs.map +1 -0
  37. package/dist/ddl.d.mts +3 -2
  38. package/dist/ddl.mjs +2 -2
  39. package/dist/default-normalizer.d.mts +1 -1
  40. package/dist/default-normalizer.d.mts.map +1 -1
  41. package/dist/default-normalizer.mjs +247 -1
  42. package/dist/default-normalizer.mjs.map +1 -0
  43. package/dist/descriptor-meta-DzL6vXAz.mjs +22 -0
  44. package/dist/descriptor-meta-DzL6vXAz.mjs.map +1 -0
  45. package/dist/descriptor-meta-runtime-UwYdV8fD.mjs +12 -0
  46. package/dist/descriptor-meta-runtime-UwYdV8fD.mjs.map +1 -0
  47. package/dist/diff-database-schema-DULhiCNM.mjs +305 -0
  48. package/dist/diff-database-schema-DULhiCNM.mjs.map +1 -0
  49. package/dist/diff-database-schema.d.mts +46 -0
  50. package/dist/diff-database-schema.d.mts.map +1 -0
  51. package/dist/diff-database-schema.mjs +2 -0
  52. package/dist/errors-DO-w0EUS.mjs +35 -0
  53. package/dist/errors-DO-w0EUS.mjs.map +1 -0
  54. package/dist/errors.d.mts +11 -9
  55. package/dist/errors.d.mts.map +1 -1
  56. package/dist/errors.mjs +1 -1
  57. package/dist/issue-planner.d.mts +35 -11
  58. package/dist/issue-planner.d.mts.map +1 -1
  59. package/dist/issue-planner.mjs +2 -2
  60. package/dist/migration.d.mts +5 -5
  61. package/dist/migration.d.mts.map +1 -1
  62. package/dist/migration.mjs +4 -4
  63. package/dist/namespace-ids-xtp_ZY86.mjs +7 -0
  64. package/dist/namespace-ids-xtp_ZY86.mjs.map +1 -0
  65. package/dist/native-type-normalizer.mjs +37 -1
  66. package/dist/native-type-normalizer.mjs.map +1 -0
  67. package/dist/nodes-Bc2N3tMy.d.mts +170 -0
  68. package/dist/nodes-Bc2N3tMy.d.mts.map +1 -0
  69. package/dist/nodes-DJC5B8Id.mjs +192 -0
  70. package/dist/nodes-DJC5B8Id.mjs.map +1 -0
  71. package/dist/{op-factory-call-DmQEc3XV.d.mts → op-factory-call-Bn9zDx4_.d.mts} +114 -15
  72. package/dist/op-factory-call-Bn9zDx4_.d.mts.map +1 -0
  73. package/dist/{op-factory-call-D_p5vxwt.mjs → op-factory-call-D6yu-PlS.mjs} +469 -32
  74. package/dist/op-factory-call-D6yu-PlS.mjs.map +1 -0
  75. package/dist/op-factory-call.d.mts +2 -2
  76. package/dist/op-factory-call.mjs +2 -2
  77. package/dist/pack.d.mts +300 -3
  78. package/dist/pack.d.mts.map +1 -1
  79. package/dist/pack.mjs +1 -1
  80. package/dist/planner-DwDxdYxi.mjs +390 -0
  81. package/dist/planner-DwDxdYxi.mjs.map +1 -0
  82. package/dist/{planner-ddl-builders-B2wOwLqI.mjs → planner-ddl-builders-BKlmGDJl.mjs} +17 -28
  83. package/dist/planner-ddl-builders-BKlmGDJl.mjs.map +1 -0
  84. package/dist/planner-ddl-builders.d.mts +4 -6
  85. package/dist/planner-ddl-builders.d.mts.map +1 -1
  86. package/dist/planner-ddl-builders.mjs +2 -2
  87. package/dist/planner-identity-values-CJPha2Sz.mjs.map +1 -1
  88. package/dist/planner-identity-values.d.mts +8 -2
  89. package/dist/planner-identity-values.d.mts.map +1 -1
  90. package/dist/planner-identity-values.mjs +2 -2
  91. package/dist/{planner-produced-postgres-migration-QqHa2C2l.d.mts → planner-produced-postgres-migration-BEY1T0Xm.d.mts} +4 -4
  92. package/dist/{planner-produced-postgres-migration-QqHa2C2l.d.mts.map → planner-produced-postgres-migration-BEY1T0Xm.d.mts.map} +1 -1
  93. package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs → planner-produced-postgres-migration-BGPpq56_.mjs} +3 -3
  94. package/dist/{planner-produced-postgres-migration-Cji5vxUf.mjs.map → planner-produced-postgres-migration-BGPpq56_.mjs.map} +1 -1
  95. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  96. package/dist/planner-produced-postgres-migration.mjs +1 -1
  97. package/dist/{planner-sql-checks-jqUUGyQR.mjs → planner-sql-checks-CDXn2uaS.mjs} +5 -5
  98. package/dist/{planner-sql-checks-jqUUGyQR.mjs.map → planner-sql-checks-CDXn2uaS.mjs.map} +1 -1
  99. package/dist/planner-sql-checks.d.mts +2 -2
  100. package/dist/planner-sql-checks.d.mts.map +1 -1
  101. package/dist/planner-sql-checks.mjs +1 -1
  102. package/dist/{planner-target-details-CIY6tLeo.d.mts → planner-target-details-HkP4RrRO.d.mts} +2 -2
  103. package/dist/planner-target-details-HkP4RrRO.d.mts.map +1 -0
  104. package/dist/planner-target-details.d.mts +1 -1
  105. package/dist/planner.d.mts +72 -17
  106. package/dist/planner.d.mts.map +1 -1
  107. package/dist/planner.mjs +3 -2
  108. package/dist/{postgres-contract-serializer-k3TAcPMY.mjs → postgres-contract-view-C3LPCLP_.mjs} +45 -41
  109. package/dist/postgres-contract-view-C3LPCLP_.mjs.map +1 -0
  110. package/dist/postgres-contract-view-C9j5cqP0.d.mts +34 -0
  111. package/dist/postgres-contract-view-C9j5cqP0.d.mts.map +1 -0
  112. package/dist/postgres-database-schema-node-CJv5bfbs.d.mts +262 -0
  113. package/dist/postgres-database-schema-node-CJv5bfbs.d.mts.map +1 -0
  114. package/dist/{postgres-migration-Y4YBJqkS.d.mts → postgres-migration-DbckK1su.d.mts} +58 -9
  115. package/dist/postgres-migration-DbckK1su.d.mts.map +1 -0
  116. package/dist/{postgres-migration-B5jKrXv3.mjs → postgres-migration-et1td40f.mjs} +78 -45
  117. package/dist/postgres-migration-et1td40f.mjs.map +1 -0
  118. package/dist/postgres-native-enum-BwVNf0Ku.mjs +45 -0
  119. package/dist/postgres-native-enum-BwVNf0Ku.mjs.map +1 -0
  120. package/dist/postgres-rls-policy--CSddvMR.d.mts +52 -0
  121. package/dist/postgres-rls-policy--CSddvMR.d.mts.map +1 -0
  122. package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs +190 -0
  123. package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs.map +1 -0
  124. package/dist/postgres-schema-DKq6s1P3.d.mts +269 -0
  125. package/dist/postgres-schema-DKq6s1P3.d.mts.map +1 -0
  126. package/dist/{postgres-schema-COGZ1ark.mjs → postgres-schema-DYATroNx.mjs} +200 -11
  127. package/dist/postgres-schema-DYATroNx.mjs.map +1 -0
  128. package/dist/postgres-table-schema-node-D6LvInCe.mjs +216 -0
  129. package/dist/postgres-table-schema-node-D6LvInCe.mjs.map +1 -0
  130. package/dist/render-ops.d.mts +1 -1
  131. package/dist/{render-typescript-KMgosran.mjs → render-typescript-7yqILcwr.mjs} +45 -16
  132. package/dist/render-typescript-7yqILcwr.mjs.map +1 -0
  133. package/dist/render-typescript.mjs +1 -1
  134. package/dist/resolve-ddl-schema-DpGte50u.mjs +22 -0
  135. package/dist/resolve-ddl-schema-DpGte50u.mjs.map +1 -0
  136. package/dist/rls-canonicalize.d.mts +20 -0
  137. package/dist/rls-canonicalize.d.mts.map +1 -0
  138. package/dist/rls-canonicalize.mjs +2 -0
  139. package/dist/runtime.d.mts +6 -8
  140. package/dist/runtime.d.mts.map +1 -1
  141. package/dist/runtime.mjs +3 -3
  142. package/dist/runtime.mjs.map +1 -1
  143. package/dist/schema-ir-annotations.d.mts +15 -0
  144. package/dist/schema-ir-annotations.d.mts.map +1 -0
  145. package/dist/schema-ir-annotations.mjs +2 -0
  146. package/dist/{sql-utils-DcfMz4MQ.mjs → sql-utils-SU4FDvIV.mjs} +12 -3
  147. package/dist/{sql-utils-DcfMz4MQ.mjs.map → sql-utils-SU4FDvIV.mjs.map} +1 -1
  148. package/dist/sql-utils.d.mts +8 -1
  149. package/dist/sql-utils.d.mts.map +1 -1
  150. package/dist/sql-utils.mjs +2 -2
  151. package/dist/types.d.mts +4 -140
  152. package/dist/types.mjs +5 -2
  153. package/dist/wire-name-rHHtr1h0.mjs +75 -0
  154. package/dist/wire-name-rHHtr1h0.mjs.map +1 -0
  155. package/package.json +26 -20
  156. package/src/contract-free/checks.ts +153 -0
  157. package/src/contract-free/control-bootstrap.ts +20 -3
  158. package/src/contract-free/ddl.ts +98 -1
  159. package/src/core/authoring.ts +509 -2
  160. package/src/core/codec-helpers.ts +33 -7
  161. package/src/core/codec-ids.ts +1 -0
  162. package/src/core/codec-type-map.ts +2 -0
  163. package/src/core/codecs.ts +193 -12
  164. package/src/core/ddl/nodes.ts +185 -2
  165. package/src/core/default-normalizer.ts +122 -2
  166. package/src/core/descriptor-meta.ts +10 -1
  167. package/src/core/entity-kinds.ts +41 -0
  168. package/src/core/errors.ts +14 -12
  169. package/src/core/migrations/bound-schema.ts +10 -0
  170. package/src/core/migrations/column-ddl-rendering.ts +117 -0
  171. package/src/core/migrations/contract-to-postgres-database-schema-node.ts +189 -0
  172. package/src/core/migrations/control-policy.ts +217 -65
  173. package/src/core/migrations/diff-database-schema.ts +252 -0
  174. package/src/core/migrations/issue-planner.ts +817 -656
  175. package/src/core/migrations/op-factory-call.ts +383 -23
  176. package/src/core/migrations/operations/columns.ts +24 -12
  177. package/src/core/migrations/operations/constraints.ts +1 -1
  178. package/src/core/migrations/operations/data-transform.ts +6 -0
  179. package/src/core/migrations/operations/dependencies.ts +2 -1
  180. package/src/core/migrations/operations/native-enum-types.ts +62 -0
  181. package/src/core/migrations/operations/rls.ts +187 -0
  182. package/src/core/migrations/operations/shared.ts +0 -30
  183. package/src/core/migrations/planner-ddl-builders.ts +31 -59
  184. package/src/core/migrations/planner-identity-values.ts +1 -1
  185. package/src/core/migrations/planner-recipes.ts +31 -13
  186. package/src/core/migrations/planner-sql-checks.ts +1 -1
  187. package/src/core/migrations/planner-strategies.ts +248 -216
  188. package/src/core/migrations/planner-target-details.ts +3 -1
  189. package/src/core/migrations/planner.ts +357 -67
  190. package/src/core/migrations/postgres-migration.ts +118 -86
  191. package/src/core/migrations/render-typescript.ts +42 -15
  192. package/src/core/migrations/resolve-ddl-schema.ts +26 -0
  193. package/src/core/migrations/runner.ts +11 -16
  194. package/src/core/migrations/verify-postgres-namespaces.ts +46 -31
  195. package/src/core/namespace-ids.ts +3 -0
  196. package/src/core/postgres-contract-serializer.ts +46 -71
  197. package/src/core/postgres-contract-view.ts +48 -0
  198. package/src/core/postgres-native-enum.ts +61 -0
  199. package/src/core/postgres-rls-enablement.ts +34 -0
  200. package/src/core/postgres-rls-policy.ts +64 -0
  201. package/src/core/postgres-role.ts +59 -0
  202. package/src/core/postgres-schema-verifier.ts +10 -7
  203. package/src/core/postgres-schema.ts +85 -15
  204. package/src/core/postgres-validators.ts +34 -0
  205. package/src/core/psl-infer/infer-psl-contract.ts +1273 -0
  206. package/src/core/psl-infer/postgres-default-mapping.ts +16 -0
  207. package/src/core/psl-infer/postgres-type-map.ts +128 -0
  208. package/src/core/rls/canonicalize.ts +48 -0
  209. package/src/core/rls/wire-name.ts +33 -0
  210. package/src/core/schema-ir/node-storage-coordinate.ts +26 -0
  211. package/src/core/schema-ir/postgres-database-schema-node.ts +61 -0
  212. package/src/core/schema-ir/postgres-namespace-schema-node.ts +70 -0
  213. package/src/core/schema-ir/postgres-native-enum-schema-node.ts +83 -0
  214. package/src/core/schema-ir/postgres-policy-schema-node.ts +90 -0
  215. package/src/core/schema-ir/postgres-role-schema-node.ts +65 -0
  216. package/src/core/schema-ir/postgres-table-schema-node.ts +140 -0
  217. package/src/core/schema-ir/schema-node-kinds.ts +122 -0
  218. package/src/core/sql-utils.ts +15 -2
  219. package/src/exports/codecs.ts +3 -0
  220. package/src/exports/contract-free.ts +11 -1
  221. package/src/exports/control.ts +27 -33
  222. package/src/exports/ddl.ts +8 -0
  223. package/src/exports/diff-database-schema.ts +7 -0
  224. package/src/exports/issue-planner.ts +1 -1
  225. package/src/exports/migration.ts +1 -0
  226. package/src/exports/op-factory-call.ts +4 -0
  227. package/src/exports/planner-ddl-builders.ts +0 -2
  228. package/src/exports/planner-identity-values.ts +4 -1
  229. package/src/exports/planner.ts +1 -0
  230. package/src/exports/rls-canonicalize.ts +7 -0
  231. package/src/exports/runtime.ts +1 -0
  232. package/src/exports/schema-ir-annotations.ts +1 -0
  233. package/src/exports/sql-utils.ts +1 -0
  234. package/src/exports/types.ts +37 -0
  235. package/dist/codec-ids-BvytN2P8.mjs.map +0 -1
  236. package/dist/codec-ids-CnXu9Qy3.d.mts.map +0 -1
  237. package/dist/codec-types-DHCkwPKE.d.mts.map +0 -1
  238. package/dist/codecs--0A5_4Bq.d.mts.map +0 -1
  239. package/dist/ddl-QDyOSeLc.mjs.map +0 -1
  240. package/dist/default-normalizer-DyyCHQWs.mjs +0 -131
  241. package/dist/default-normalizer-DyyCHQWs.mjs.map +0 -1
  242. package/dist/descriptor-meta-CpGygXpI.mjs +0 -140
  243. package/dist/descriptor-meta-CpGygXpI.mjs.map +0 -1
  244. package/dist/errors-CUk87ByX.mjs +0 -33
  245. package/dist/errors-CUk87ByX.mjs.map +0 -1
  246. package/dist/issue-planner-DL6g3CmE.mjs +0 -824
  247. package/dist/issue-planner-DL6g3CmE.mjs.map +0 -1
  248. package/dist/native-type-normalizer-Bc9XJzWC.mjs +0 -38
  249. package/dist/native-type-normalizer-Bc9XJzWC.mjs.map +0 -1
  250. package/dist/nodes-Bbhs2rwj.mjs +0 -76
  251. package/dist/nodes-Bbhs2rwj.mjs.map +0 -1
  252. package/dist/nodes-pLeLgdis.d.mts +0 -67
  253. package/dist/nodes-pLeLgdis.d.mts.map +0 -1
  254. package/dist/op-factory-call-D_p5vxwt.mjs.map +0 -1
  255. package/dist/op-factory-call-DmQEc3XV.d.mts.map +0 -1
  256. package/dist/planner-Bs_baQax.mjs +0 -324
  257. package/dist/planner-Bs_baQax.mjs.map +0 -1
  258. package/dist/planner-ddl-builders-B2wOwLqI.mjs.map +0 -1
  259. package/dist/planner-target-details-CIY6tLeo.d.mts.map +0 -1
  260. package/dist/postgres-contract-serializer-k3TAcPMY.mjs.map +0 -1
  261. package/dist/postgres-migration-B5jKrXv3.mjs.map +0 -1
  262. package/dist/postgres-migration-Y4YBJqkS.d.mts.map +0 -1
  263. package/dist/postgres-schema-COGZ1ark.mjs.map +0 -1
  264. package/dist/render-typescript-KMgosran.mjs.map +0 -1
  265. package/dist/types.d.mts.map +0 -1
  266. package/src/core/postgres-enum-type-schema.ts +0 -17
@@ -0,0 +1,187 @@
1
+ import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
2
+ import { ifDefined } from '@prisma-next/utils/defined';
3
+ import { rlsEnabledAst, rlsPolicyExistsAst } from '../../../contract-free/checks';
4
+ import {
5
+ alterPolicyRename,
6
+ createPolicy,
7
+ disableRowLevelSecurity as disableRowLevelSecurityDdl,
8
+ dropPolicy,
9
+ } from '../../../contract-free/ddl';
10
+ import type { PostgresRlsPolicy } from '../../postgres-rls-policy';
11
+ import { qualifyTableName } from '../planner-sql-checks';
12
+ import { type Op, step, targetDetails } from './shared';
13
+
14
+ const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_$]*$/;
15
+
16
+ function validateRoleName(role: string): string {
17
+ if (!PLAIN_IDENTIFIER.test(role)) {
18
+ throw new Error(
19
+ `Invalid role name ${JSON.stringify(role)}: role names must be plain SQL identifiers matching ^[A-Za-z_][A-Za-z0-9_$]*$`,
20
+ );
21
+ }
22
+ return role;
23
+ }
24
+
25
+ export async function createRlsPolicy(
26
+ schemaName: string,
27
+ tableName: string,
28
+ policy: PostgresRlsPolicy,
29
+ lowerer: ExecuteRequestLowerer,
30
+ ): Promise<Op> {
31
+ const validatedRoles = policy.roles.map(validateRoleName);
32
+ const ddlNode = createPolicy({
33
+ schema: schemaName,
34
+ table: tableName,
35
+ name: policy.name,
36
+ permissive: policy.permissive,
37
+ operation: policy.operation,
38
+ roles: validatedRoles,
39
+ ...ifDefined('using', policy.using),
40
+ ...ifDefined('withCheck', policy.withCheck),
41
+ });
42
+ const checks = rlsPolicyExistsAst({
43
+ schema: schemaName,
44
+ table: tableName,
45
+ policyName: policy.name,
46
+ });
47
+ const absent = await lowerer.lowerToExecuteRequest(checks.policyAbsent());
48
+ const execute = await lowerer.lowerToExecuteRequest(ddlNode);
49
+ const present = await lowerer.lowerToExecuteRequest(checks.policyPresent());
50
+ return {
51
+ id: `rlsPolicy.${schemaName}.${tableName}.${policy.name}`,
52
+ label: `Create RLS policy "${policy.name}" on "${tableName}"`,
53
+ operationClass: 'additive',
54
+ target: targetDetails('rlsPolicy', policy.name, schemaName, tableName),
55
+ precheck: [
56
+ step(`ensure RLS policy "${policy.name}" does not exist`, absent.sql, absent.params),
57
+ ],
58
+ execute: [step(`create RLS policy "${policy.name}"`, execute.sql, execute.params)],
59
+ postcheck: [step(`verify RLS policy "${policy.name}" exists`, present.sql, present.params)],
60
+ };
61
+ }
62
+
63
+ export async function dropRlsPolicy(
64
+ schemaName: string,
65
+ tableName: string,
66
+ policyName: string,
67
+ lowerer: ExecuteRequestLowerer,
68
+ ): Promise<Op> {
69
+ const ddlNode = dropPolicy({ schema: schemaName, table: tableName, name: policyName });
70
+ const checks = rlsPolicyExistsAst({ schema: schemaName, table: tableName, policyName });
71
+ const present = await lowerer.lowerToExecuteRequest(checks.policyPresent());
72
+ const execute = await lowerer.lowerToExecuteRequest(ddlNode);
73
+ const absent = await lowerer.lowerToExecuteRequest(checks.policyAbsent());
74
+ return {
75
+ id: `rlsPolicy.${schemaName}.${tableName}.${policyName}.drop`,
76
+ label: `Drop RLS policy "${policyName}" on "${tableName}"`,
77
+ operationClass: 'destructive',
78
+ target: targetDetails('rlsPolicy', policyName, schemaName, tableName),
79
+ precheck: [step(`ensure RLS policy "${policyName}" exists`, present.sql, present.params)],
80
+ execute: [step(`drop RLS policy "${policyName}"`, execute.sql, execute.params)],
81
+ postcheck: [step(`verify RLS policy "${policyName}" is absent`, absent.sql, absent.params)],
82
+ };
83
+ }
84
+
85
+ export async function enableRowLevelSecurity(
86
+ schemaName: string,
87
+ tableName: string,
88
+ lowerer: ExecuteRequestLowerer,
89
+ ): Promise<Op> {
90
+ const checks = rlsEnabledAst(schemaName, tableName);
91
+ const disabled = await lowerer.lowerToExecuteRequest(checks.rlsDisabled());
92
+ const enabled = await lowerer.lowerToExecuteRequest(checks.rlsEnabled());
93
+ return {
94
+ id: `rowLevelSecurity.${schemaName}.${tableName}`,
95
+ label: `Enable row-level security on "${tableName}"`,
96
+ operationClass: 'additive',
97
+ target: targetDetails('rowLevelSecurity', tableName, schemaName),
98
+ precheck: [
99
+ step(`check RLS is not already enabled on "${tableName}"`, disabled.sql, disabled.params),
100
+ ],
101
+ execute: [
102
+ step(
103
+ `enable row-level security on "${tableName}"`,
104
+ `ALTER TABLE ${qualifyTableName(schemaName, tableName)} ENABLE ROW LEVEL SECURITY`,
105
+ ),
106
+ ],
107
+ postcheck: [
108
+ step(`verify row-level security is enabled on "${tableName}"`, enabled.sql, enabled.params),
109
+ ],
110
+ };
111
+ }
112
+
113
+ export async function disableRowLevelSecurity(
114
+ schemaName: string,
115
+ tableName: string,
116
+ lowerer: ExecuteRequestLowerer,
117
+ ): Promise<Op> {
118
+ const ddlNode = disableRowLevelSecurityDdl({ schema: schemaName, table: tableName });
119
+ const checks = rlsEnabledAst(schemaName, tableName);
120
+ const enabled = await lowerer.lowerToExecuteRequest(checks.rlsEnabled());
121
+ const execute = await lowerer.lowerToExecuteRequest(ddlNode);
122
+ const disabled = await lowerer.lowerToExecuteRequest(checks.rlsDisabled());
123
+ return {
124
+ id: `rowLevelSecurity.${schemaName}.${tableName}.disable`,
125
+ label: `Disable row-level security on "${tableName}"`,
126
+ operationClass: 'destructive',
127
+ target: targetDetails('rowLevelSecurity', tableName, schemaName),
128
+ precheck: [
129
+ step(`check RLS is currently enabled on "${tableName}"`, enabled.sql, enabled.params),
130
+ ],
131
+ execute: [step(`disable row-level security on "${tableName}"`, execute.sql, execute.params)],
132
+ postcheck: [
133
+ step(
134
+ `verify row-level security is disabled on "${tableName}"`,
135
+ disabled.sql,
136
+ disabled.params,
137
+ ),
138
+ ],
139
+ };
140
+ }
141
+
142
+ export async function renameRlsPolicy(
143
+ schemaName: string,
144
+ tableName: string,
145
+ oldPolicyName: string,
146
+ newPolicyName: string,
147
+ lowerer: ExecuteRequestLowerer,
148
+ ): Promise<Op> {
149
+ const ddlNode = alterPolicyRename({
150
+ schema: schemaName,
151
+ table: tableName,
152
+ name: oldPolicyName,
153
+ newName: newPolicyName,
154
+ });
155
+ const oldChecks = rlsPolicyExistsAst({
156
+ schema: schemaName,
157
+ table: tableName,
158
+ policyName: oldPolicyName,
159
+ });
160
+ const newChecks = rlsPolicyExistsAst({
161
+ schema: schemaName,
162
+ table: tableName,
163
+ policyName: newPolicyName,
164
+ });
165
+ const oldPresent = await lowerer.lowerToExecuteRequest(oldChecks.policyPresent());
166
+ const execute = await lowerer.lowerToExecuteRequest(ddlNode);
167
+ const newPresent = await lowerer.lowerToExecuteRequest(newChecks.policyPresent());
168
+ return {
169
+ id: `rlsPolicy.${schemaName}.${tableName}.${oldPolicyName}.rename`,
170
+ label: `Rename RLS policy "${oldPolicyName}" to "${newPolicyName}" on "${tableName}"`,
171
+ operationClass: 'widening',
172
+ target: targetDetails('rlsPolicy', newPolicyName, schemaName, tableName),
173
+ precheck: [
174
+ step(`ensure RLS policy "${oldPolicyName}" exists`, oldPresent.sql, oldPresent.params),
175
+ ],
176
+ execute: [
177
+ step(
178
+ `rename RLS policy "${oldPolicyName}" to "${newPolicyName}"`,
179
+ execute.sql,
180
+ execute.params,
181
+ ),
182
+ ],
183
+ postcheck: [
184
+ step(`verify RLS policy "${newPolicyName}" exists`, newPresent.sql, newPresent.params),
185
+ ],
186
+ };
187
+ }
@@ -1,30 +1,10 @@
1
1
  import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';
2
2
  import type { ReferentialAction } from '@prisma-next/sql-contract/types';
3
3
  import { ifDefined } from '@prisma-next/utils/defined';
4
- import { quoteIdentifier } from '../../sql-utils';
5
4
  import type { OperationClass, PostgresPlanTargetDetails } from '../planner-target-details';
6
5
 
7
6
  export type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
8
7
 
9
- /**
10
- * Literal-args shape for a column definition consumed by `addColumn` and
11
- * similar operations. Fully materialized: codec expansion and default
12
- * rendering have already happened in the wrapper.
13
- *
14
- * - `typeSql` is the column's DDL type string (e.g. `"integer"`, `"SERIAL"`,
15
- * `"varchar(100)"`), already produced by `buildColumnTypeSql` in the
16
- * call-factory wrapper.
17
- * - `defaultSql` is the full `DEFAULT …` clause (e.g. `"DEFAULT 42"`) or an
18
- * empty string when the column has no default, matching
19
- * `buildColumnDefaultSql`'s output.
20
- */
21
- export interface ColumnSpec {
22
- readonly name: string;
23
- readonly typeSql: string;
24
- readonly defaultSql: string;
25
- readonly nullable: boolean;
26
- }
27
-
28
8
  /**
29
9
  * Literal-args shape for a foreign key definition. `references.schema`
30
10
  * carries the target table's namespace (schema) coordinate so the rendered
@@ -57,13 +37,3 @@ export function targetDetails(
57
37
  details: { schema, objectType, name, ...ifDefined('table', table) },
58
38
  };
59
39
  }
60
-
61
- export function renderColumnDefinition(column: ColumnSpec): string {
62
- const parts = [
63
- quoteIdentifier(column.name),
64
- column.typeSql,
65
- column.defaultSql,
66
- column.nullable ? '' : 'NOT NULL',
67
- ].filter(Boolean);
68
- return parts.join(' ');
69
- }
@@ -1,43 +1,10 @@
1
1
  import type { CodecControlHooks } from '@prisma-next/family-sql/control';
2
- import type {
3
- StorageColumn,
4
- StorageTable,
5
- StorageTypeInstance,
6
- } from '@prisma-next/sql-contract/types';
2
+ import type { StorageColumn, StorageTypeInstance } from '@prisma-next/sql-contract/types';
7
3
  import { ifDefined } from '@prisma-next/utils/defined';
8
- import { escapeLiteral, quoteIdentifier } from '../sql-utils';
4
+ import { escapeLiteral, quoteIdentifier, quoteQualifiedName } from '../sql-utils';
9
5
  import type { PostgresColumnDefault } from '../types';
10
6
  import { resolveColumnTypeMetadata } from './planner-type-resolution';
11
7
 
12
- export function buildCreateTableSql(
13
- qualifiedTableName: string,
14
- table: StorageTable,
15
- codecHooks: ReadonlyMap<string, CodecControlHooks>,
16
- storageTypes: Record<string, StorageTypeInstance> = {},
17
- ): string {
18
- const columnDefinitions = Object.entries(table.columns).map(
19
- ([columnName, column]: [string, StorageColumn]) => {
20
- const parts = [
21
- quoteIdentifier(columnName),
22
- buildColumnTypeSql(column, codecHooks, storageTypes),
23
- buildColumnDefaultSql(column.default, column),
24
- column.nullable ? '' : 'NOT NULL',
25
- ].filter(Boolean);
26
- return parts.join(' ');
27
- },
28
- );
29
-
30
- const constraintDefinitions: string[] = [];
31
- if (table.primaryKey) {
32
- constraintDefinitions.push(
33
- `PRIMARY KEY (${table.primaryKey.columns.map(quoteIdentifier).join(', ')})`,
34
- );
35
- }
36
-
37
- const allDefinitions = [...columnDefinitions, ...constraintDefinitions];
38
- return `CREATE TABLE ${qualifiedTableName} (\n ${allDefinitions.join(',\n ')}\n)`;
39
- }
40
-
41
8
  /**
42
9
  * Pattern for safe PostgreSQL type names.
43
10
  * Allows letters, digits, underscores, spaces (for "double precision", "character varying"),
@@ -98,17 +65,28 @@ export function buildColumnTypeSql(
98
65
  }
99
66
  }
100
67
 
68
+ // A column whose codec supplied a `typeParams.typeName` references a named
69
+ // database type (e.g. a native enum), not a parameterized builtin: render it
70
+ // as its quoted, schema-qualified type-name identifier. DDL-render only — the
71
+ // verify comparison value (`resolvedNativeType`) stays the bare name the
72
+ // family expander produces, matching introspection.
73
+ if (typeof resolved.typeParams?.['typeName'] === 'string') {
74
+ const quoted = quoteQualifiedName(resolved.nativeType);
75
+ return column.many ? `${quoted}[]` : quoted;
76
+ }
77
+
101
78
  const expanded = expandParameterizedTypeSql(resolved, codecHooks);
102
79
  if (expanded !== null) {
103
- return expanded;
80
+ return column.many ? `${expanded}[]` : expanded;
104
81
  }
105
82
 
106
83
  if (column.typeRef) {
107
- return quoteIdentifier(resolved.nativeType);
84
+ const base = quoteQualifiedName(resolved.nativeType);
85
+ return column.many ? `${base}[]` : base;
108
86
  }
109
87
 
110
88
  assertSafeNativeType(resolved.nativeType);
111
- return resolved.nativeType;
89
+ return column.many ? `${resolved.nativeType}[]` : resolved.nativeType;
112
90
  }
113
91
 
114
92
  function expandParameterizedTypeSql(
@@ -150,7 +128,7 @@ function expandParameterizedTypeSql(
150
128
  /** Autoincrement columns use SERIAL types, so this returns empty for them. */
151
129
  export function buildColumnDefaultSql(
152
130
  columnDefault: PostgresColumnDefault | undefined,
153
- column?: StorageColumn,
131
+ column?: Pick<StorageColumn, 'many' | 'nativeType'>,
154
132
  ): string {
155
133
  if (!columnDefault) {
156
134
  return '';
@@ -171,9 +149,16 @@ export function buildColumnDefaultSql(
171
149
  }
172
150
  }
173
151
 
174
- export function renderDefaultLiteral(value: unknown, column?: StorageColumn): string {
152
+ export function renderDefaultLiteral(
153
+ value: unknown,
154
+ column?: Pick<StorageColumn, 'many' | 'nativeType'>,
155
+ ): string {
175
156
  const isJsonColumn = column?.nativeType === 'json' || column?.nativeType === 'jsonb';
176
157
 
158
+ if (column?.many && Array.isArray(value)) {
159
+ return renderArrayLiteralDefault(value);
160
+ }
161
+
177
162
  if (value instanceof Date) {
178
163
  return `'${escapeLiteral(value.toISOString())}'`;
179
164
  }
@@ -193,23 +178,10 @@ export function renderDefaultLiteral(value: unknown, column?: StorageColumn): st
193
178
  return `'${escapeLiteral(json)}'`;
194
179
  }
195
180
 
196
- export function buildAddColumnSql(
197
- qualifiedTableName: string,
198
- columnName: string,
199
- column: StorageColumn,
200
- codecHooks: ReadonlyMap<string, CodecControlHooks>,
201
- temporaryDefault?: string | null,
202
- storageTypes: Record<string, StorageTypeInstance> = {},
203
- ): string {
204
- const typeSql = buildColumnTypeSql(column, codecHooks, storageTypes);
205
- const defaultSql =
206
- buildColumnDefaultSql(column.default, column) ||
207
- (temporaryDefault ? `DEFAULT ${temporaryDefault}` : '');
208
- const parts = [
209
- `ALTER TABLE ${qualifiedTableName}`,
210
- `ADD COLUMN ${quoteIdentifier(columnName)} ${typeSql}`,
211
- defaultSql,
212
- column.nullable ? '' : 'NOT NULL',
213
- ].filter(Boolean);
214
- return parts.join(' ');
181
+ function renderArrayLiteralDefault(elements: unknown[]): string {
182
+ if (elements.length === 0) {
183
+ return "'{}'";
184
+ }
185
+ const rendered = elements.map((el) => renderDefaultLiteral(el)).join(', ');
186
+ return `ARRAY[${rendered}]`;
215
187
  }
@@ -9,7 +9,7 @@ import { ifDefined } from '@prisma-next/utils/defined';
9
9
  */
10
10
  export function resolveIdentityValue(
11
11
  column: StorageColumn,
12
- codecHooks: Map<string, CodecControlHooks>,
12
+ codecHooks: ReadonlyMap<string, CodecControlHooks>,
13
13
  storageTypes: Record<string, StorageTypeInstance> = {},
14
14
  ): string | null {
15
15
  const referencedType = column.typeRef ? storageTypes[column.typeRef] : undefined;
@@ -1,15 +1,18 @@
1
1
  import type { CodecControlHooks, SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';
2
2
  import type { ExecuteRequestLowerer } from '@prisma-next/family-sql/control-adapter';
3
3
  import type { StorageColumn, StorageTypeInstance } from '@prisma-next/sql-contract/types';
4
+ import { FunctionColumnDefault } from '@prisma-next/sql-relational-core/ast';
5
+ import { col } from '@prisma-next/sql-relational-core/contract-free';
6
+ import { ifDefined } from '@prisma-next/utils/defined';
4
7
  import {
5
8
  columnDefaultAst,
6
9
  columnExistsAst,
7
10
  columnNullabilityAst,
8
11
  } from '../../contract-free/checks';
9
- import { quoteIdentifier } from '../sql-utils';
12
+ import * as contractFreeDdl from '../../contract-free/ddl';
13
+ import { boundSchema } from './bound-schema';
10
14
  import { step } from './operations/shared';
11
- import { buildAddColumnSql } from './planner-ddl-builders';
12
- import { qualifyTableName } from './planner-sql-checks';
15
+ import { buildColumnTypeSql } from './planner-ddl-builders';
13
16
  import { buildTargetDetails, type PostgresPlanTargetDetails } from './planner-target-details';
14
17
 
15
18
  export function buildAddColumnOperationIdentity(
@@ -51,7 +54,29 @@ export async function buildAddNotNullColumnWithTemporaryDefaultOperation(options
51
54
  temporaryDefault,
52
55
  lowerer,
53
56
  } = options;
54
- const qualified = qualifyTableName(schema, tableName);
57
+
58
+ // The recipe handles NOT NULL columns that carry no contract default, so the
59
+ // temporary backfill value is the only default. It is a pre-rendered SQL
60
+ // fragment (e.g. `''`, `0`, `'{}'::jsonb`), carried verbatim as a
61
+ // `FunctionColumnDefault` so the adapter emits it as a `DEFAULT (...)` clause.
62
+ const ddlColumn = col(columnName, buildColumnTypeSql(column, codecHooks, storageTypes), {
63
+ notNull: true,
64
+ default: new FunctionColumnDefault(temporaryDefault),
65
+ });
66
+ const addColumn = await lowerer.lowerToExecuteRequest(
67
+ contractFreeDdl.alterTable({
68
+ ...ifDefined('schema', boundSchema(schema)),
69
+ table: tableName,
70
+ actions: [contractFreeDdl.addColumnAction(ddlColumn)],
71
+ }),
72
+ );
73
+ const dropTempDefault = await lowerer.lowerToExecuteRequest(
74
+ contractFreeDdl.alterTable({
75
+ ...ifDefined('schema', boundSchema(schema)),
76
+ table: tableName,
77
+ actions: [contractFreeDdl.dropDefaultAction(columnName)],
78
+ }),
79
+ );
55
80
 
56
81
  const absent = await lowerer.lowerToExecuteRequest(
57
82
  columnExistsAst({ schema, table: tableName, column: columnName }).columnAbsent(),
@@ -73,18 +98,11 @@ export async function buildAddNotNullColumnWithTemporaryDefaultOperation(options
73
98
  execute: [
74
99
  {
75
100
  description: `add column "${columnName}"`,
76
- sql: buildAddColumnSql(
77
- qualified,
78
- columnName,
79
- column,
80
- codecHooks,
81
- temporaryDefault,
82
- storageTypes,
83
- ),
101
+ sql: addColumn.sql,
84
102
  },
85
103
  {
86
104
  description: `drop temporary default from column "${columnName}"`,
87
- sql: `ALTER TABLE ${qualified} ALTER COLUMN ${quoteIdentifier(columnName)} DROP DEFAULT`,
105
+ sql: dropTempDefault.sql,
88
106
  },
89
107
  ],
90
108
  postcheck: [
@@ -145,7 +145,7 @@ function formatUserDefinedTypeName(identifier: string): string {
145
145
 
146
146
  export function buildExpectedFormatType(
147
147
  column: StorageColumn,
148
- codecHooks: Map<string, CodecControlHooks>,
148
+ codecHooks: ReadonlyMap<string, CodecControlHooks>,
149
149
  storageTypes: Record<string, StorageTypeInstance> = {},
150
150
  ): string {
151
151
  const resolved = resolveColumnTypeMetadata(column, storageTypes);