@prisma-next/target-postgres 0.13.0 → 0.14.0-dev.2

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 (190) hide show
  1. package/dist/{codec-ids-CTikp1if.mjs → codec-ids-BvytN2P8.mjs} +3 -3
  2. package/dist/codec-ids-BvytN2P8.mjs.map +1 -0
  3. package/dist/{codec-ids-B1vOchLE.d.mts → codec-ids-CnXu9Qy3.d.mts} +3 -3
  4. package/dist/codec-ids-CnXu9Qy3.d.mts.map +1 -0
  5. package/dist/codec-ids.d.mts +2 -2
  6. package/dist/codec-ids.mjs +2 -2
  7. package/dist/{codec-types-CnFiNML4.d.mts → codec-types-DHCkwPKE.d.mts} +3 -3
  8. package/dist/{codec-types-CnFiNML4.d.mts.map → codec-types-DHCkwPKE.d.mts.map} +1 -1
  9. package/dist/codec-types.d.mts +1 -1
  10. package/dist/{codecs-CBpEv4s5.d.mts → codecs--0A5_4Bq.d.mts} +26 -23
  11. package/dist/codecs--0A5_4Bq.d.mts.map +1 -0
  12. package/dist/codecs.d.mts +2 -2
  13. package/dist/codecs.mjs +28 -35
  14. package/dist/codecs.mjs.map +1 -1
  15. package/dist/contract-free.d.mts +163 -15
  16. package/dist/contract-free.d.mts.map +1 -1
  17. package/dist/contract-free.mjs +4 -17
  18. package/dist/contract-free.mjs.map +1 -1
  19. package/dist/control.d.mts.map +1 -1
  20. package/dist/control.mjs +21 -27
  21. package/dist/control.mjs.map +1 -1
  22. package/dist/{data-transform-D25tLeYU.mjs → data-transform-BOWpliq8.mjs} +9 -17
  23. package/dist/data-transform-BOWpliq8.mjs.map +1 -0
  24. package/dist/{data-transform-DGOqcLrf.d.mts → data-transform-DDgWdB5o.d.mts} +2 -2
  25. package/dist/data-transform-DDgWdB5o.d.mts.map +1 -0
  26. package/dist/data-transform.d.mts +1 -1
  27. package/dist/data-transform.mjs +1 -1
  28. package/dist/ddl-QDyOSeLc.mjs +251 -0
  29. package/dist/ddl-QDyOSeLc.mjs.map +1 -0
  30. package/dist/ddl.d.mts +2 -2
  31. package/dist/ddl.mjs +2 -2
  32. package/dist/descriptor-meta-CpGygXpI.mjs +140 -0
  33. package/dist/descriptor-meta-CpGygXpI.mjs.map +1 -0
  34. package/dist/{issue-planner-Br0pt1Ea.mjs → issue-planner-DL6g3CmE.mjs} +52 -366
  35. package/dist/issue-planner-DL6g3CmE.mjs.map +1 -0
  36. package/dist/issue-planner.d.mts +8 -11
  37. package/dist/issue-planner.d.mts.map +1 -1
  38. package/dist/issue-planner.mjs +1 -1
  39. package/dist/migration.d.mts +5 -92
  40. package/dist/migration.d.mts.map +1 -1
  41. package/dist/migration.mjs +4 -4
  42. package/dist/{nodes-DZk2JZG3.mjs → nodes-Bbhs2rwj.mjs} +31 -2
  43. package/dist/nodes-Bbhs2rwj.mjs.map +1 -0
  44. package/dist/{nodes-779hmCfL.d.mts → nodes-pLeLgdis.d.mts} +30 -3
  45. package/dist/nodes-pLeLgdis.d.mts.map +1 -0
  46. package/dist/{op-factory-call-D2aAUhmS.mjs → op-factory-call-D_p5vxwt.mjs} +601 -418
  47. package/dist/op-factory-call-D_p5vxwt.mjs.map +1 -0
  48. package/dist/{op-factory-call-DMA86_2D.d.mts → op-factory-call-DmQEc3XV.d.mts} +119 -72
  49. package/dist/op-factory-call-DmQEc3XV.d.mts.map +1 -0
  50. package/dist/op-factory-call.d.mts +2 -2
  51. package/dist/op-factory-call.mjs +2 -2
  52. package/dist/pack.d.mts +36 -15
  53. package/dist/pack.d.mts.map +1 -1
  54. package/dist/pack.mjs +1 -1
  55. package/dist/{planner-CAYPJObw.mjs → planner-Bs_baQax.mjs} +25 -45
  56. package/dist/planner-Bs_baQax.mjs.map +1 -0
  57. package/dist/{planner-ddl-builders-Cw2n2llW.mjs → planner-ddl-builders-B2wOwLqI.mjs} +2 -2
  58. package/dist/planner-ddl-builders-B2wOwLqI.mjs.map +1 -0
  59. package/dist/planner-ddl-builders.d.mts +4 -4
  60. package/dist/planner-ddl-builders.d.mts.map +1 -1
  61. package/dist/planner-ddl-builders.mjs +1 -1
  62. package/dist/{planner-identity-values-BIpa5p2I.mjs → planner-identity-values-CJPha2Sz.mjs} +3 -9
  63. package/dist/planner-identity-values-CJPha2Sz.mjs.map +1 -0
  64. package/dist/planner-identity-values.d.mts +1 -1
  65. package/dist/planner-identity-values.d.mts.map +1 -1
  66. package/dist/planner-identity-values.mjs +1 -1
  67. package/dist/{planner-produced-postgres-migration-NSEhWL0L.mjs → planner-produced-postgres-migration-Cji5vxUf.mjs} +6 -4
  68. package/dist/planner-produced-postgres-migration-Cji5vxUf.mjs.map +1 -0
  69. package/dist/{planner-produced-postgres-migration-B4EDvLdz.d.mts → planner-produced-postgres-migration-QqHa2C2l.d.mts} +5 -6
  70. package/dist/planner-produced-postgres-migration-QqHa2C2l.d.mts.map +1 -0
  71. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  72. package/dist/planner-produced-postgres-migration.mjs +1 -1
  73. package/dist/planner-sql-checks-jqUUGyQR.mjs +152 -0
  74. package/dist/planner-sql-checks-jqUUGyQR.mjs.map +1 -0
  75. package/dist/planner-sql-checks.d.mts +3 -49
  76. package/dist/planner-sql-checks.d.mts.map +1 -1
  77. package/dist/planner-sql-checks.mjs +2 -2
  78. package/dist/{planner-type-resolution-836DExFN.mjs → planner-type-resolution-Bt2f_q-F.mjs} +1 -6
  79. package/dist/planner-type-resolution-Bt2f_q-F.mjs.map +1 -0
  80. package/dist/planner.d.mts +4 -4
  81. package/dist/planner.d.mts.map +1 -1
  82. package/dist/planner.mjs +1 -1
  83. package/dist/{postgres-contract-serializer-DYTyXjPf.mjs → postgres-contract-serializer-k3TAcPMY.mjs} +30 -37
  84. package/dist/postgres-contract-serializer-k3TAcPMY.mjs.map +1 -0
  85. package/dist/postgres-migration-B5jKrXv3.mjs +145 -0
  86. package/dist/postgres-migration-B5jKrXv3.mjs.map +1 -0
  87. package/dist/postgres-migration-Y4YBJqkS.d.mts +181 -0
  88. package/dist/postgres-migration-Y4YBJqkS.d.mts.map +1 -0
  89. package/dist/{postgres-schema-BuxCxbvB.mjs → postgres-schema-COGZ1ark.mjs} +82 -23
  90. package/dist/postgres-schema-COGZ1ark.mjs.map +1 -0
  91. package/dist/{render-ops-BpjstrKQ.mjs → render-ops-BREh1kHe.mjs} +10 -5
  92. package/dist/render-ops-BREh1kHe.mjs.map +1 -0
  93. package/dist/render-ops.d.mts +2 -2
  94. package/dist/render-ops.d.mts.map +1 -1
  95. package/dist/render-ops.mjs +1 -1
  96. package/dist/runtime.d.mts +1 -0
  97. package/dist/runtime.d.mts.map +1 -1
  98. package/dist/runtime.mjs +2 -2
  99. package/dist/table-source-BvFo7gVs.d.mts +15 -0
  100. package/dist/table-source-BvFo7gVs.d.mts.map +1 -0
  101. package/dist/types.d.mts +34 -19
  102. package/dist/types.d.mts.map +1 -1
  103. package/dist/types.mjs +2 -3
  104. package/package.json +17 -18
  105. package/src/contract-free/checks.ts +363 -0
  106. package/src/contract-free/ddl.ts +28 -1
  107. package/src/core/authoring.ts +43 -44
  108. package/src/core/codec-helpers.ts +0 -17
  109. package/src/core/codec-ids.ts +1 -1
  110. package/src/core/codec-type-map.ts +2 -2
  111. package/src/core/codecs.ts +43 -48
  112. package/src/core/ddl/nodes.ts +59 -1
  113. package/src/core/migrations/control-policy.ts +17 -47
  114. package/src/core/migrations/issue-planner.ts +34 -70
  115. package/src/core/migrations/op-factory-call.ts +486 -215
  116. package/src/core/migrations/operations/columns.ts +175 -140
  117. package/src/core/migrations/operations/constraints.ts +79 -108
  118. package/src/core/migrations/operations/data-transform.ts +15 -18
  119. package/src/core/migrations/operations/dependencies.ts +16 -14
  120. package/src/core/migrations/operations/indexes.ts +31 -28
  121. package/src/core/migrations/operations/shared.ts +2 -2
  122. package/src/core/migrations/operations/tables.ts +13 -14
  123. package/src/core/migrations/planner-ddl-builders.ts +3 -4
  124. package/src/core/migrations/planner-identity-values.ts +4 -28
  125. package/src/core/migrations/planner-produced-postgres-migration.ts +15 -7
  126. package/src/core/migrations/planner-recipes.ts +44 -39
  127. package/src/core/migrations/planner-sql-checks.ts +3 -178
  128. package/src/core/migrations/planner-strategies.ts +76 -449
  129. package/src/core/migrations/planner-type-resolution.ts +2 -20
  130. package/src/core/migrations/planner.ts +6 -6
  131. package/src/core/migrations/postgres-migration.ts +287 -7
  132. package/src/core/migrations/render-ops.ts +26 -13
  133. package/src/core/migrations/runner.ts +26 -20
  134. package/src/core/postgres-contract-serializer.ts +37 -54
  135. package/src/core/postgres-enum-type-schema.ts +17 -0
  136. package/src/core/postgres-schema.ts +86 -46
  137. package/src/exports/codecs.ts +2 -2
  138. package/src/exports/contract-free.ts +22 -1
  139. package/src/exports/control.ts +0 -22
  140. package/src/exports/ddl.ts +4 -0
  141. package/src/exports/migration.ts +1 -29
  142. package/src/exports/op-factory-call.ts +0 -4
  143. package/src/exports/planner-sql-checks.ts +0 -7
  144. package/src/exports/types.ts +0 -1
  145. package/dist/codec-ids-B1vOchLE.d.mts.map +0 -1
  146. package/dist/codec-ids-CTikp1if.mjs.map +0 -1
  147. package/dist/codecs-CBpEv4s5.d.mts.map +0 -1
  148. package/dist/data-transform-D25tLeYU.mjs.map +0 -1
  149. package/dist/data-transform-DGOqcLrf.d.mts.map +0 -1
  150. package/dist/ddl-77SyXgFt.mjs +0 -30
  151. package/dist/ddl-77SyXgFt.mjs.map +0 -1
  152. package/dist/descriptor-meta-DKmj-IMN.mjs +0 -14
  153. package/dist/descriptor-meta-DKmj-IMN.mjs.map +0 -1
  154. package/dist/descriptor-meta-runtime-My8_s4cs.mjs +0 -130
  155. package/dist/descriptor-meta-runtime-My8_s4cs.mjs.map +0 -1
  156. package/dist/enum-planning-BCyvlFHk.mjs +0 -0
  157. package/dist/enum-planning-BCyvlFHk.mjs.map +0 -1
  158. package/dist/enum-planning.d.mts +0 -86
  159. package/dist/enum-planning.d.mts.map +0 -1
  160. package/dist/enum-planning.mjs +0 -2
  161. package/dist/issue-planner-Br0pt1Ea.mjs.map +0 -1
  162. package/dist/nodes-779hmCfL.d.mts.map +0 -1
  163. package/dist/nodes-DZk2JZG3.mjs.map +0 -1
  164. package/dist/op-factory-call-D2aAUhmS.mjs.map +0 -1
  165. package/dist/op-factory-call-DMA86_2D.d.mts.map +0 -1
  166. package/dist/planner-CAYPJObw.mjs.map +0 -1
  167. package/dist/planner-ddl-builders-Cw2n2llW.mjs.map +0 -1
  168. package/dist/planner-identity-values-BIpa5p2I.mjs.map +0 -1
  169. package/dist/planner-produced-postgres-migration-B4EDvLdz.d.mts.map +0 -1
  170. package/dist/planner-produced-postgres-migration-NSEhWL0L.mjs.map +0 -1
  171. package/dist/planner-sql-checks-DAdhnI2c.mjs +0 -272
  172. package/dist/planner-sql-checks-DAdhnI2c.mjs.map +0 -1
  173. package/dist/planner-type-resolution-836DExFN.mjs.map +0 -1
  174. package/dist/postgres-contract-serializer-DYTyXjPf.mjs.map +0 -1
  175. package/dist/postgres-enum-type-BVn63a89.d.mts +0 -72
  176. package/dist/postgres-enum-type-BVn63a89.d.mts.map +0 -1
  177. package/dist/postgres-enum-type-DPKqCBem.mjs +0 -62
  178. package/dist/postgres-enum-type-DPKqCBem.mjs.map +0 -1
  179. package/dist/postgres-migration-COore9Mz.mjs +0 -71
  180. package/dist/postgres-migration-COore9Mz.mjs.map +0 -1
  181. package/dist/postgres-migration-DZ_gLUOW.d.mts +0 -72
  182. package/dist/postgres-migration-DZ_gLUOW.d.mts.map +0 -1
  183. package/dist/postgres-schema-BuxCxbvB.mjs.map +0 -1
  184. package/dist/render-ops-BpjstrKQ.mjs.map +0 -1
  185. package/dist/shared-DarONYBZ.d.mts +0 -43
  186. package/dist/shared-DarONYBZ.d.mts.map +0 -1
  187. package/src/core/migrations/enum-planning.ts +0 -213
  188. package/src/core/migrations/operations/enums.ts +0 -114
  189. package/src/core/postgres-enum-type.ts +0 -89
  190. package/src/exports/enum-planning.ts +0 -11
@@ -21,13 +21,14 @@
21
21
  */
22
22
 
23
23
  import { errorUnfilledPlaceholder } from '@prisma-next/errors/migration';
24
- import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';
25
- import type { Lowerer } from '@prisma-next/family-sql/control-adapter';
24
+ import type { CodecControlHooks, SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';
25
+ import type { ExecuteRequestLowerer, Lowerer } from '@prisma-next/family-sql/control-adapter';
26
26
  import type {
27
27
  OpFactoryCall as FrameworkOpFactoryCall,
28
28
  MigrationOperationClass,
29
29
  } from '@prisma-next/framework-components/control';
30
30
  import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
31
+ import type { StorageColumn, StorageTypeInstance } from '@prisma-next/sql-contract/types';
31
32
  import type {
32
33
  AnyDdlColumnDefault,
33
34
  DdlColumn,
@@ -36,11 +37,13 @@ import type {
36
37
  import { FunctionColumnDefault, LiteralColumnDefault } from '@prisma-next/sql-relational-core/ast';
37
38
  import { type ImportRequirement, jsonToTsSource, TsExpression } from '@prisma-next/ts-render';
38
39
  import { blindCast } from '@prisma-next/utils/casts';
40
+ import { ifDefined } from '@prisma-next/utils/defined';
41
+ import { columnExistsAst, tableExistsAst } from '../../contract-free/checks';
39
42
  import * as contractFreeDdl from '../../contract-free/ddl';
40
43
  import { escapeLiteral, quoteIdentifier } from '../sql-utils';
41
44
  import type { PostgresColumnDefault } from '../types';
42
45
  import {
43
- addColumn,
46
+ addNotNullColumnDirect,
44
47
  alterColumnType,
45
48
  dropColumn,
46
49
  dropDefault,
@@ -57,12 +60,11 @@ import {
57
60
  dropConstraint,
58
61
  } from './operations/constraints';
59
62
  import { createExtension } from './operations/dependencies';
60
- import { addEnumValues, createEnumType, dropEnumType, renameType } from './operations/enums';
61
63
  import { createIndex, dropIndex } from './operations/indexes';
62
- import type { ColumnSpec, ForeignKeySpec } from './operations/shared';
64
+ import type { ForeignKeySpec } from './operations/shared';
63
65
  import { step, targetDetails } from './operations/shared';
64
66
  import { dropTable } from './operations/tables';
65
- import { toRegclassLiteral } from './planner-sql-checks';
67
+ import { buildAddNotNullColumnWithTemporaryDefaultOperation } from './planner-recipes';
66
68
  import type { PostgresPlanTargetDetails } from './planner-target-details';
67
69
 
68
70
  type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
@@ -81,11 +83,15 @@ type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
81
83
  // transitive package on disk.
82
84
  const POSTGRES_MIGRATION_FACADE = '@prisma-next/postgres/migration';
83
85
 
86
+ function boundSchema(schemaName: string): string | undefined {
87
+ return schemaName === UNBOUND_NAMESPACE_ID ? undefined : schemaName;
88
+ }
89
+
84
90
  abstract class PostgresOpFactoryCallNode extends TsExpression implements FrameworkOpFactoryCall {
85
91
  abstract readonly factoryName: string;
86
92
  abstract readonly operationClass: MigrationOperationClass;
87
93
  abstract readonly label: string;
88
- abstract toOp(lowerer?: Lowerer): Op;
94
+ abstract toOp(lowerer?: Lowerer): Op | Promise<Op>;
89
95
 
90
96
  importRequirements(): readonly ImportRequirement[] {
91
97
  return [{ moduleSpecifier: POSTGRES_MIGRATION_FACADE, symbol: this.factoryName }];
@@ -140,6 +146,7 @@ function renderDdlColumnAsTsCall(col: DdlColumn): string {
140
146
  if (col.notNull) opts.push('notNull: true');
141
147
  if (col.primaryKey) opts.push('primaryKey: true');
142
148
  if (col.default) opts.push(`default: ${renderDdlColumnDefault(col.default)}`);
149
+ if (col.codecRef) opts.push(`codecRef: ${jsonToTsSource(col.codecRef)}`);
143
150
  const optsStr = opts.length > 0 ? `, { ${opts.join(', ')} }` : '';
144
151
  return `col(${jsonToTsSource(col.name)}, ${jsonToTsSource(col.type)}${optsStr})`;
145
152
  }
@@ -213,40 +220,39 @@ export class CreateTableCall extends PostgresOpFactoryCallNode {
213
220
  this.freeze();
214
221
  }
215
222
 
216
- toOp(lowerer?: Lowerer): Op {
223
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
217
224
  if (lowerer === undefined) {
218
225
  throw new Error(
219
226
  `CreateTableCall.toOp: a DDL lowerer is required on the Postgres planner path (table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
220
227
  );
221
228
  }
222
229
  const ddlNode = contractFreeDdl.createTable({
223
- ...(this.schemaName !== UNBOUND_NAMESPACE_ID ? { schema: this.schemaName } : {}),
230
+ ...ifDefined('schema', boundSchema(this.schemaName)),
224
231
  table: this.tableName,
225
232
  columns: this.columns,
226
- ...(this.constraints ? { constraints: this.constraints } : {}),
233
+ ...ifDefined('constraints', this.constraints),
227
234
  });
228
- const { sql } = lowerer.lower(ddlNode, { contract: {} });
235
+ const statement = await lowerer.lowerToExecuteRequest(ddlNode);
229
236
  const schemaName = this.schemaName;
230
237
  const tableName = this.tableName;
238
+ const checks = tableExistsAst(schemaName, tableName);
239
+ const absent = await lowerer.lowerToExecuteRequest(checks.tableAbsent());
240
+ const present = await lowerer.lowerToExecuteRequest(checks.tablePresent());
231
241
  return {
232
242
  id: `table.${tableName}`,
233
243
  label: `Create table "${tableName}"`,
234
244
  summary: `Creates table "${tableName}"`,
235
245
  operationClass: 'additive',
236
246
  target: targetDetails('table', tableName, schemaName),
237
- precheck: [
238
- step(
239
- `ensure table "${tableName}" does not exist`,
240
- `SELECT to_regclass(${toRegclassLiteral(schemaName, tableName)}) IS NULL`,
241
- ),
242
- ],
243
- execute: [step(`create table "${tableName}"`, sql)],
244
- postcheck: [
245
- step(
246
- `verify table "${tableName}" exists`,
247
- `SELECT to_regclass(${toRegclassLiteral(schemaName, tableName)}) IS NOT NULL`,
248
- ),
247
+ precheck: [step(`ensure table "${tableName}" does not exist`, absent.sql, absent.params)],
248
+ execute: [
249
+ {
250
+ description: `create table "${tableName}"`,
251
+ sql: statement.sql,
252
+ params: statement.params ?? [],
253
+ },
249
254
  ],
255
+ postcheck: [step(`verify table "${tableName}" exists`, present.sql, present.params)],
250
256
  };
251
257
  }
252
258
 
@@ -297,12 +303,26 @@ export class DropTableCall extends PostgresOpFactoryCallNode {
297
303
  this.freeze();
298
304
  }
299
305
 
300
- toOp(): Op {
301
- return dropTable(this.schemaName, this.tableName);
306
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
307
+ if (lowerer === undefined) {
308
+ throw new Error(
309
+ `DropTableCall.toOp: a lowerer is required on the Postgres planner path (table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
310
+ );
311
+ }
312
+ return dropTable(this.schemaName, this.tableName, lowerer);
302
313
  }
303
314
 
304
315
  renderTypeScript(): string {
305
- return `dropTable(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)})`;
316
+ const opts: string[] = [];
317
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
318
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
319
+ }
320
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
321
+ return `this.dropTable({ ${opts.join(', ')} })`;
322
+ }
323
+
324
+ override importRequirements(): readonly ImportRequirement[] {
325
+ return [];
306
326
  }
307
327
  }
308
328
 
@@ -315,10 +335,10 @@ export class AddColumnCall extends PostgresOpFactoryCallNode {
315
335
  readonly operationClass = 'additive' as const;
316
336
  readonly schemaName: string;
317
337
  readonly tableName: string;
318
- readonly column: ColumnSpec;
338
+ readonly column: DdlColumn;
319
339
  readonly label: string;
320
340
 
321
- constructor(schemaName: string, tableName: string, column: ColumnSpec) {
341
+ constructor(schemaName: string, tableName: string, column: DdlColumn) {
322
342
  super();
323
343
  this.schemaName = schemaName;
324
344
  this.tableName = tableName;
@@ -327,12 +347,53 @@ export class AddColumnCall extends PostgresOpFactoryCallNode {
327
347
  this.freeze();
328
348
  }
329
349
 
330
- toOp(): Op {
331
- return addColumn(this.schemaName, this.tableName, this.column);
350
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
351
+ if (lowerer === undefined) {
352
+ throw new Error(
353
+ `AddColumnCall.toOp: a DDL lowerer is required on the Postgres planner path (column "${this.column.name}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
354
+ );
355
+ }
356
+ const ddlNode = contractFreeDdl.alterTable({
357
+ ...ifDefined('schema', boundSchema(this.schemaName)),
358
+ table: this.tableName,
359
+ actions: [contractFreeDdl.addColumnAction(this.column)],
360
+ });
361
+ const statement = await lowerer.lowerToExecuteRequest(ddlNode);
362
+ const schemaName = this.schemaName;
363
+ const tableName = this.tableName;
364
+ const columnName = this.column.name;
365
+ const colChecks = columnExistsAst({ schema: schemaName, table: tableName, column: columnName });
366
+ const absent = await lowerer.lowerToExecuteRequest(colChecks.columnAbsent());
367
+ const present = await lowerer.lowerToExecuteRequest(colChecks.columnPresent());
368
+ return {
369
+ id: `column.${schemaName}.${tableName}.${columnName}`,
370
+ label: `Add column "${columnName}" to "${tableName}"`,
371
+ operationClass: 'additive',
372
+ target: targetDetails('column', columnName, schemaName, tableName),
373
+ precheck: [step(`ensure column "${columnName}" is missing`, absent.sql, absent.params)],
374
+ execute: [step(`add column "${columnName}"`, statement.sql)],
375
+ postcheck: [step(`verify column "${columnName}" exists`, present.sql, present.params)],
376
+ };
332
377
  }
333
378
 
334
379
  renderTypeScript(): string {
335
- return `addColumn(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.column)})`;
380
+ const opts: string[] = [];
381
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
382
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
383
+ }
384
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
385
+ opts.push(`column: ${renderDdlColumnAsTsCall(this.column)}`);
386
+ return `this.addColumn({ ${opts.join(', ')} })`;
387
+ }
388
+
389
+ override importRequirements(): readonly ImportRequirement[] {
390
+ const req: ImportRequirement[] = [
391
+ { moduleSpecifier: POSTGRES_MIGRATION_FACADE, symbol: 'col' },
392
+ ];
393
+ for (const sym of defaultImportSymbols([this.column])) {
394
+ req.push({ moduleSpecifier: POSTGRES_MIGRATION_FACADE, symbol: sym });
395
+ }
396
+ return req;
336
397
  }
337
398
  }
338
399
 
@@ -353,12 +414,27 @@ export class DropColumnCall extends PostgresOpFactoryCallNode {
353
414
  this.freeze();
354
415
  }
355
416
 
356
- toOp(): Op {
357
- return dropColumn(this.schemaName, this.tableName, this.columnName);
417
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
418
+ if (lowerer === undefined) {
419
+ throw new Error(
420
+ `DropColumnCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
421
+ );
422
+ }
423
+ return dropColumn(this.schemaName, this.tableName, this.columnName, lowerer);
358
424
  }
359
425
 
360
426
  renderTypeScript(): string {
361
- return `dropColumn(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.columnName)})`;
427
+ const opts: string[] = [];
428
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
429
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
430
+ }
431
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
432
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
433
+ return `this.dropColumn({ ${opts.join(', ')} })`;
434
+ }
435
+
436
+ override importRequirements(): readonly ImportRequirement[] {
437
+ return [];
362
438
  }
363
439
  }
364
440
 
@@ -393,12 +469,28 @@ export class AlterColumnTypeCall extends PostgresOpFactoryCallNode {
393
469
  this.freeze();
394
470
  }
395
471
 
396
- toOp(): Op {
397
- return alterColumnType(this.schemaName, this.tableName, this.columnName, this.options);
472
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
473
+ if (lowerer === undefined) {
474
+ throw new Error(
475
+ `AlterColumnTypeCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
476
+ );
477
+ }
478
+ return alterColumnType(this.schemaName, this.tableName, this.columnName, this.options, lowerer);
398
479
  }
399
480
 
400
481
  renderTypeScript(): string {
401
- return `alterColumnType(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.columnName)}, ${jsonToTsSource(this.options)})`;
482
+ const opts: string[] = [];
483
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
484
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
485
+ }
486
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
487
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
488
+ opts.push(`options: ${jsonToTsSource(this.options)}`);
489
+ return `this.alterColumnType({ ${opts.join(', ')} })`;
490
+ }
491
+
492
+ override importRequirements(): readonly ImportRequirement[] {
493
+ return [];
402
494
  }
403
495
  }
404
496
 
@@ -419,12 +511,27 @@ export class SetNotNullCall extends PostgresOpFactoryCallNode {
419
511
  this.freeze();
420
512
  }
421
513
 
422
- toOp(): Op {
423
- return setNotNull(this.schemaName, this.tableName, this.columnName);
514
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
515
+ if (lowerer === undefined) {
516
+ throw new Error(
517
+ `SetNotNullCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
518
+ );
519
+ }
520
+ return setNotNull(this.schemaName, this.tableName, this.columnName, lowerer);
424
521
  }
425
522
 
426
523
  renderTypeScript(): string {
427
- return `setNotNull(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.columnName)})`;
524
+ const opts: string[] = [];
525
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
526
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
527
+ }
528
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
529
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
530
+ return `this.setNotNull({ ${opts.join(', ')} })`;
531
+ }
532
+
533
+ override importRequirements(): readonly ImportRequirement[] {
534
+ return [];
428
535
  }
429
536
  }
430
537
 
@@ -445,12 +552,27 @@ export class DropNotNullCall extends PostgresOpFactoryCallNode {
445
552
  this.freeze();
446
553
  }
447
554
 
448
- toOp(): Op {
449
- return dropNotNull(this.schemaName, this.tableName, this.columnName);
555
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
556
+ if (lowerer === undefined) {
557
+ throw new Error(
558
+ `DropNotNullCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
559
+ );
560
+ }
561
+ return dropNotNull(this.schemaName, this.tableName, this.columnName, lowerer);
450
562
  }
451
563
 
452
564
  renderTypeScript(): string {
453
- return `dropNotNull(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.columnName)})`;
565
+ const opts: string[] = [];
566
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
567
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
568
+ }
569
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
570
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
571
+ return `this.dropNotNull({ ${opts.join(', ')} })`;
572
+ }
573
+
574
+ override importRequirements(): readonly ImportRequirement[] {
575
+ return [];
454
576
  }
455
577
  }
456
578
 
@@ -480,27 +602,38 @@ export class SetDefaultCall extends PostgresOpFactoryCallNode {
480
602
  this.freeze();
481
603
  }
482
604
 
483
- toOp(): Op {
605
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
606
+ if (lowerer === undefined) {
607
+ throw new Error(
608
+ `SetDefaultCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
609
+ );
610
+ }
484
611
  return setDefault(
485
612
  this.schemaName,
486
613
  this.tableName,
487
614
  this.columnName,
488
615
  this.defaultSql,
616
+ lowerer,
489
617
  this.operationClass,
490
618
  );
491
619
  }
492
620
 
493
621
  renderTypeScript(): string {
494
- const args = [
495
- jsonToTsSource(this.schemaName),
496
- jsonToTsSource(this.tableName),
497
- jsonToTsSource(this.columnName),
498
- jsonToTsSource(this.defaultSql),
499
- ];
622
+ const opts: string[] = [];
623
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
624
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
625
+ }
626
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
627
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
628
+ opts.push(`defaultSql: ${jsonToTsSource(this.defaultSql)}`);
500
629
  if (this.operationClass !== 'additive') {
501
- args.push(jsonToTsSource(this.operationClass));
630
+ opts.push(`operationClass: ${jsonToTsSource(this.operationClass)}`);
502
631
  }
503
- return `setDefault(${args.join(', ')})`;
632
+ return `this.setDefault({ ${opts.join(', ')} })`;
633
+ }
634
+
635
+ override importRequirements(): readonly ImportRequirement[] {
636
+ return [];
504
637
  }
505
638
  }
506
639
 
@@ -521,12 +654,154 @@ export class DropDefaultCall extends PostgresOpFactoryCallNode {
521
654
  this.freeze();
522
655
  }
523
656
 
524
- toOp(): Op {
525
- return dropDefault(this.schemaName, this.tableName, this.columnName);
657
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
658
+ if (lowerer === undefined) {
659
+ throw new Error(
660
+ `DropDefaultCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
661
+ );
662
+ }
663
+ return dropDefault(this.schemaName, this.tableName, this.columnName, lowerer);
526
664
  }
527
665
 
528
666
  renderTypeScript(): string {
529
- return `dropDefault(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.columnName)})`;
667
+ const opts: string[] = [];
668
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
669
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
670
+ }
671
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
672
+ opts.push(`column: ${jsonToTsSource(this.columnName)}`);
673
+ return `this.dropDefault({ ${opts.join(', ')} })`;
674
+ }
675
+
676
+ override importRequirements(): readonly ImportRequirement[] {
677
+ return [];
678
+ }
679
+ }
680
+
681
+ // ============================================================================
682
+ // NOT NULL column additions (planner-internal; no authored surface)
683
+ // ============================================================================
684
+
685
+ /**
686
+ * Planner-internal call for adding a NOT NULL column (no contract default) to
687
+ * a table that must be empty at migration time. Carries the raw ADD COLUMN SQL
688
+ * (produced by `buildAddColumnSql` at plan time — deferred from slice-7 typed
689
+ * DDL) plus the parameters needed to lower the typed pre/postchecks at render
690
+ * time.
691
+ *
692
+ * No authored `PostgresMigration` method: this call is only emitted by the
693
+ * planner, never hand-written by migration authors.
694
+ */
695
+ export class AddNotNullColumnDirectCall extends PostgresOpFactoryCallNode {
696
+ readonly factoryName = 'rawSql' as const;
697
+ readonly operationClass = 'additive' as const;
698
+ readonly schemaName: string;
699
+ readonly tableName: string;
700
+ readonly columnName: string;
701
+ readonly executeStepSql: string;
702
+ readonly label: string;
703
+
704
+ constructor(schemaName: string, tableName: string, columnName: string, executeStepSql: string) {
705
+ super();
706
+ this.schemaName = schemaName;
707
+ this.tableName = tableName;
708
+ this.columnName = columnName;
709
+ this.executeStepSql = executeStepSql;
710
+ this.label = `Add column ${columnName} to ${tableName}`;
711
+ this.freeze();
712
+ }
713
+
714
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
715
+ if (lowerer === undefined) {
716
+ throw new Error(
717
+ `AddNotNullColumnDirectCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
718
+ );
719
+ }
720
+ return addNotNullColumnDirect(
721
+ this.schemaName,
722
+ this.tableName,
723
+ this.columnName,
724
+ this.executeStepSql,
725
+ lowerer,
726
+ );
727
+ }
728
+
729
+ renderTypeScript(): string {
730
+ return `rawSql(${jsonToTsSource({ id: `column.${this.tableName}.${this.columnName}`, label: this.label, operationClass: 'additive' })})`;
731
+ }
732
+
733
+ override importRequirements(): readonly ImportRequirement[] {
734
+ return [];
735
+ }
736
+ }
737
+
738
+ /**
739
+ * Planner-internal call for adding a NOT NULL column (no contract default)
740
+ * using a temporary default value for non-empty tables. Carries all parameters
741
+ * needed for `buildAddNotNullColumnWithTemporaryDefaultOperation`; the typed
742
+ * pre/postchecks are lowered at render time via `toOp(lowerer)`. The execute
743
+ * SQL (`buildAddColumnSql`) is still raw per slice-7 deferral.
744
+ *
745
+ * No authored `PostgresMigration` method: this call is only emitted by the
746
+ * planner, never hand-written by migration authors.
747
+ */
748
+ export class AddNotNullColumnWithTempDefaultCall extends PostgresOpFactoryCallNode {
749
+ readonly factoryName = 'rawSql' as const;
750
+ readonly operationClass = 'additive' as const;
751
+ readonly schemaName: string;
752
+ readonly tableName: string;
753
+ readonly columnName: string;
754
+ readonly column: StorageColumn;
755
+ readonly codecHooks: Map<string, CodecControlHooks>;
756
+ readonly storageTypes: Record<string, StorageTypeInstance>;
757
+ readonly temporaryDefault: string;
758
+ readonly label: string;
759
+
760
+ constructor(options: {
761
+ readonly schemaName: string;
762
+ readonly tableName: string;
763
+ readonly columnName: string;
764
+ readonly column: StorageColumn;
765
+ readonly codecHooks: Map<string, CodecControlHooks>;
766
+ readonly storageTypes: Record<string, StorageTypeInstance>;
767
+ readonly temporaryDefault: string;
768
+ }) {
769
+ super();
770
+ this.schemaName = options.schemaName;
771
+ this.tableName = options.tableName;
772
+ this.columnName = options.columnName;
773
+ this.column = options.column;
774
+ this.codecHooks = options.codecHooks;
775
+ this.storageTypes = options.storageTypes;
776
+ this.temporaryDefault = options.temporaryDefault;
777
+ this.label = `Add column ${options.columnName} to ${options.tableName}`;
778
+ this.freeze();
779
+ }
780
+
781
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
782
+ if (lowerer === undefined) {
783
+ throw new Error(
784
+ `AddNotNullColumnWithTempDefaultCall.toOp: a lowerer is required on the Postgres planner path (column "${this.columnName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
785
+ );
786
+ }
787
+ return buildAddNotNullColumnWithTemporaryDefaultOperation({
788
+ schema: this.schemaName,
789
+ tableName: this.tableName,
790
+ columnName: this.columnName,
791
+ column: this.column,
792
+ codecHooks: this.codecHooks,
793
+ storageTypes: this.storageTypes,
794
+ temporaryDefault: this.temporaryDefault,
795
+ lowerer,
796
+ });
797
+ }
798
+
799
+ renderTypeScript(): string {
800
+ return `rawSql(${jsonToTsSource({ id: `column.${this.tableName}.${this.columnName}`, label: this.label, operationClass: 'additive' })})`;
801
+ }
802
+
803
+ override importRequirements(): readonly ImportRequirement[] {
804
+ return [];
530
805
  }
531
806
  }
532
807
 
@@ -534,6 +809,20 @@ export class DropDefaultCall extends PostgresOpFactoryCallNode {
534
809
  // Constraints
535
810
  // ============================================================================
536
811
 
812
+ function constraintCallOptions(
813
+ schemaName: string,
814
+ tableName: string,
815
+ constraintName: string,
816
+ ): string {
817
+ const opts: string[] = [];
818
+ if (schemaName !== UNBOUND_NAMESPACE_ID) {
819
+ opts.push(`schema: ${jsonToTsSource(schemaName)}`);
820
+ }
821
+ opts.push(`table: ${jsonToTsSource(tableName)}`);
822
+ opts.push(`constraint: ${jsonToTsSource(constraintName)}`);
823
+ return opts.join(', ');
824
+ }
825
+
537
826
  export class AddPrimaryKeyCall extends PostgresOpFactoryCallNode {
538
827
  readonly factoryName = 'addPrimaryKey' as const;
539
828
  readonly operationClass = 'additive' as const;
@@ -558,12 +847,27 @@ export class AddPrimaryKeyCall extends PostgresOpFactoryCallNode {
558
847
  this.freeze();
559
848
  }
560
849
 
561
- toOp(): Op {
562
- return addPrimaryKey(this.schemaName, this.tableName, this.constraintName, this.columns);
850
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
851
+ if (lowerer === undefined) {
852
+ throw new Error(
853
+ `AddPrimaryKeyCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
854
+ );
855
+ }
856
+ return addPrimaryKey(
857
+ this.schemaName,
858
+ this.tableName,
859
+ this.constraintName,
860
+ this.columns,
861
+ lowerer,
862
+ );
563
863
  }
564
864
 
565
865
  renderTypeScript(): string {
566
- return `addPrimaryKey(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)}, ${jsonToTsSource(this.columns)})`;
866
+ return `this.addPrimaryKey({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)}, columns: ${jsonToTsSource(this.columns)} })`;
867
+ }
868
+
869
+ override importRequirements(): readonly ImportRequirement[] {
870
+ return [];
567
871
  }
568
872
  }
569
873
 
@@ -591,12 +895,21 @@ export class AddUniqueCall extends PostgresOpFactoryCallNode {
591
895
  this.freeze();
592
896
  }
593
897
 
594
- toOp(): Op {
595
- return addUnique(this.schemaName, this.tableName, this.constraintName, this.columns);
898
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
899
+ if (lowerer === undefined) {
900
+ throw new Error(
901
+ `AddUniqueCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
902
+ );
903
+ }
904
+ return addUnique(this.schemaName, this.tableName, this.constraintName, this.columns, lowerer);
596
905
  }
597
906
 
598
907
  renderTypeScript(): string {
599
- return `addUnique(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)}, ${jsonToTsSource(this.columns)})`;
908
+ return `this.addUnique({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)}, columns: ${jsonToTsSource(this.columns)} })`;
909
+ }
910
+
911
+ override importRequirements(): readonly ImportRequirement[] {
912
+ return [];
600
913
  }
601
914
  }
602
915
 
@@ -617,12 +930,27 @@ export class AddForeignKeyCall extends PostgresOpFactoryCallNode {
617
930
  this.freeze();
618
931
  }
619
932
 
620
- toOp(): Op {
621
- return addForeignKey(this.schemaName, this.tableName, this.fk);
933
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
934
+ if (lowerer === undefined) {
935
+ throw new Error(
936
+ `AddForeignKeyCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.fk.name}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
937
+ );
938
+ }
939
+ return addForeignKey(this.schemaName, this.tableName, this.fk, lowerer);
622
940
  }
623
941
 
624
942
  renderTypeScript(): string {
625
- return `addForeignKey(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.fk)})`;
943
+ const opts: string[] = [];
944
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
945
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
946
+ }
947
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
948
+ opts.push(`foreignKey: ${jsonToTsSource(this.fk)}`);
949
+ return `this.addForeignKey({ ${opts.join(', ')} })`;
950
+ }
951
+
952
+ override importRequirements(): readonly ImportRequirement[] {
953
+ return [];
626
954
  }
627
955
  }
628
956
 
@@ -650,20 +978,25 @@ export class DropConstraintCall extends PostgresOpFactoryCallNode {
650
978
  this.freeze();
651
979
  }
652
980
 
653
- toOp(): Op {
654
- return dropConstraint(this.schemaName, this.tableName, this.constraintName, this.kind);
981
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
982
+ if (lowerer === undefined) {
983
+ throw new Error(
984
+ `DropConstraintCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
985
+ );
986
+ }
987
+ return dropConstraint(this.schemaName, this.tableName, this.constraintName, lowerer, this.kind);
655
988
  }
656
989
 
657
990
  renderTypeScript(): string {
658
- const args = [
659
- jsonToTsSource(this.schemaName),
660
- jsonToTsSource(this.tableName),
661
- jsonToTsSource(this.constraintName),
662
- ];
991
+ const opts = [constraintCallOptions(this.schemaName, this.tableName, this.constraintName)];
663
992
  if (this.kind !== 'unique') {
664
- args.push(jsonToTsSource(this.kind));
993
+ opts.push(`kind: ${jsonToTsSource(this.kind)}`);
665
994
  }
666
- return `dropConstraint(${args.join(', ')})`;
995
+ return `this.dropConstraint({ ${opts.join(', ')} })`;
996
+ }
997
+
998
+ override importRequirements(): readonly ImportRequirement[] {
999
+ return [];
667
1000
  }
668
1001
  }
669
1002
 
@@ -694,18 +1027,28 @@ export class AddCheckConstraintCall extends PostgresOpFactoryCallNode {
694
1027
  this.freeze();
695
1028
  }
696
1029
 
697
- toOp(): Op {
1030
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
1031
+ if (lowerer === undefined) {
1032
+ throw new Error(
1033
+ `AddCheckConstraintCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
1034
+ );
1035
+ }
698
1036
  return addCheckConstraint(
699
1037
  this.schemaName,
700
1038
  this.tableName,
701
1039
  this.constraintName,
702
1040
  this.column,
703
1041
  this.values,
1042
+ lowerer,
704
1043
  );
705
1044
  }
706
1045
 
707
1046
  renderTypeScript(): string {
708
- return `addCheckConstraint(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)}, ${jsonToTsSource(this.column)}, ${jsonToTsSource(this.values)})`;
1047
+ return `this.addCheckConstraint({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)}, column: ${jsonToTsSource(this.column)}, values: ${jsonToTsSource(this.values)} })`;
1048
+ }
1049
+
1050
+ override importRequirements(): readonly ImportRequirement[] {
1051
+ return [];
709
1052
  }
710
1053
  }
711
1054
 
@@ -726,12 +1069,21 @@ export class DropCheckConstraintCall extends PostgresOpFactoryCallNode {
726
1069
  this.freeze();
727
1070
  }
728
1071
 
729
- toOp(): Op {
730
- return dropCheckConstraint(this.schemaName, this.tableName, this.constraintName);
1072
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
1073
+ if (lowerer === undefined) {
1074
+ throw new Error(
1075
+ `DropCheckConstraintCall.toOp: a lowerer is required on the Postgres planner path (constraint "${this.constraintName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
1076
+ );
1077
+ }
1078
+ return dropCheckConstraint(this.schemaName, this.tableName, this.constraintName, lowerer);
731
1079
  }
732
1080
 
733
1081
  renderTypeScript(): string {
734
- return `dropCheckConstraint(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.constraintName)})`;
1082
+ return `this.dropCheckConstraint({ ${constraintCallOptions(this.schemaName, this.tableName, this.constraintName)} })`;
1083
+ }
1084
+
1085
+ override importRequirements(): readonly ImportRequirement[] {
1086
+ return [];
735
1087
  }
736
1088
  }
737
1089
 
@@ -746,8 +1098,8 @@ export class CreateIndexCall extends PostgresOpFactoryCallNode {
746
1098
  readonly tableName: string;
747
1099
  readonly indexName: string;
748
1100
  readonly columns: readonly string[];
749
- // Named indexType (not typeName) to avoid collision with CreateEnumTypeCall.typeName,
750
- // which identifies a CREATE TYPE target and is read by `locationForCall` in issue-planner.ts.
1101
+ // Named indexType (not typeName): `locationForCall` in issue-planner.ts reads
1102
+ // a call's `typeName` as a CREATE TYPE target location, which an index is not.
751
1103
  readonly indexType: string | undefined;
752
1104
  readonly options: Record<string, unknown> | undefined;
753
1105
  readonly label: string;
@@ -770,27 +1122,44 @@ export class CreateIndexCall extends PostgresOpFactoryCallNode {
770
1122
  this.freeze();
771
1123
  }
772
1124
 
773
- toOp(): Op {
1125
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
1126
+ if (lowerer === undefined) {
1127
+ throw new Error(
1128
+ `CreateIndexCall.toOp: a lowerer is required on the Postgres planner path (index "${this.indexName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
1129
+ );
1130
+ }
774
1131
  const extras: { type?: string; options?: Record<string, unknown> } = {};
775
1132
  if (this.indexType !== undefined) extras.type = this.indexType;
776
1133
  if (this.options !== undefined) extras.options = this.options;
777
- return createIndex(this.schemaName, this.tableName, this.indexName, this.columns, extras);
1134
+ return createIndex(
1135
+ this.schemaName,
1136
+ this.tableName,
1137
+ this.indexName,
1138
+ this.columns,
1139
+ lowerer,
1140
+ extras,
1141
+ );
778
1142
  }
779
1143
 
780
1144
  renderTypeScript(): string {
781
- const args = [
782
- jsonToTsSource(this.schemaName),
783
- jsonToTsSource(this.tableName),
784
- jsonToTsSource(this.indexName),
785
- jsonToTsSource(this.columns),
786
- ];
1145
+ const opts: string[] = [];
1146
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
1147
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
1148
+ }
1149
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
1150
+ opts.push(`index: ${jsonToTsSource(this.indexName)}`);
1151
+ opts.push(`columns: ${jsonToTsSource(this.columns)}`);
787
1152
  if (this.indexType !== undefined || this.options !== undefined) {
788
1153
  const extrasParts: string[] = [];
789
1154
  if (this.indexType !== undefined) extrasParts.push(`type: ${jsonToTsSource(this.indexType)}`);
790
1155
  if (this.options !== undefined) extrasParts.push(`options: ${jsonToTsSource(this.options)}`);
791
- args.push(`{ ${extrasParts.join(', ')} }`);
1156
+ opts.push(`extras: { ${extrasParts.join(', ')} }`);
792
1157
  }
793
- return `createIndex(${args.join(', ')})`;
1158
+ return `this.createIndex({ ${opts.join(', ')} })`;
1159
+ }
1160
+
1161
+ override importRequirements(): readonly ImportRequirement[] {
1162
+ return [];
794
1163
  }
795
1164
  }
796
1165
 
@@ -811,129 +1180,27 @@ export class DropIndexCall extends PostgresOpFactoryCallNode {
811
1180
  this.freeze();
812
1181
  }
813
1182
 
814
- toOp(): Op {
815
- return dropIndex(this.schemaName, this.tableName, this.indexName);
816
- }
817
-
818
- renderTypeScript(): string {
819
- return `dropIndex(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.indexName)})`;
820
- }
821
- }
822
-
823
- // ============================================================================
824
- // Enum types
825
- // ============================================================================
826
-
827
- export class CreateEnumTypeCall extends PostgresOpFactoryCallNode {
828
- readonly factoryName = 'createEnumType' as const;
829
- readonly operationClass = 'additive' as const;
830
- readonly schemaName: string;
831
- readonly typeName: string;
832
- readonly nativeType: string;
833
- readonly values: readonly string[];
834
- readonly label: string;
835
-
836
- constructor(
837
- schemaName: string,
838
- typeName: string,
839
- values: readonly string[],
840
- nativeType: string = typeName,
841
- ) {
842
- super();
843
- this.schemaName = schemaName;
844
- this.typeName = typeName;
845
- this.nativeType = nativeType;
846
- this.values = values;
847
- this.label = `Create enum type "${typeName}"`;
848
- this.freeze();
849
- }
850
-
851
- toOp(): Op {
852
- return createEnumType(this.schemaName, this.typeName, this.values, this.nativeType);
853
- }
854
-
855
- renderTypeScript(): string {
856
- const nativeArg =
857
- this.nativeType === this.typeName ? '' : `, ${jsonToTsSource(this.nativeType)}`;
858
- return `createEnumType(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.typeName)}, ${jsonToTsSource(this.values)}${nativeArg})`;
859
- }
860
- }
861
-
862
- export class AddEnumValuesCall extends PostgresOpFactoryCallNode {
863
- readonly factoryName = 'addEnumValues' as const;
864
- readonly operationClass = 'additive' as const;
865
- readonly schemaName: string;
866
- readonly typeName: string;
867
- readonly nativeType: string;
868
- readonly values: readonly string[];
869
- readonly label: string;
870
-
871
- constructor(schemaName: string, typeName: string, nativeType: string, values: readonly string[]) {
872
- super();
873
- this.schemaName = schemaName;
874
- this.typeName = typeName;
875
- this.nativeType = nativeType;
876
- this.values = values;
877
- this.label = `Add values to enum type "${typeName}": ${values.join(', ')}`;
878
- this.freeze();
879
- }
880
-
881
- toOp(): Op {
882
- return addEnumValues(this.schemaName, this.typeName, this.nativeType, this.values);
883
- }
884
-
885
- renderTypeScript(): string {
886
- return `addEnumValues(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.typeName)}, ${jsonToTsSource(this.nativeType)}, ${jsonToTsSource(this.values)})`;
887
- }
888
- }
889
-
890
- export class DropEnumTypeCall extends PostgresOpFactoryCallNode {
891
- readonly factoryName = 'dropEnumType' as const;
892
- readonly operationClass = 'destructive' as const;
893
- readonly schemaName: string;
894
- readonly typeName: string;
895
- readonly label: string;
896
-
897
- constructor(schemaName: string, typeName: string) {
898
- super();
899
- this.schemaName = schemaName;
900
- this.typeName = typeName;
901
- this.label = `Drop enum type "${typeName}"`;
902
- this.freeze();
903
- }
904
-
905
- toOp(): Op {
906
- return dropEnumType(this.schemaName, this.typeName);
1183
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
1184
+ if (lowerer === undefined) {
1185
+ throw new Error(
1186
+ `DropIndexCall.toOp: a lowerer is required on the Postgres planner path (index "${this.indexName}" on table "${this.tableName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
1187
+ );
1188
+ }
1189
+ return dropIndex(this.schemaName, this.tableName, this.indexName, lowerer);
907
1190
  }
908
1191
 
909
1192
  renderTypeScript(): string {
910
- return `dropEnumType(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.typeName)})`;
911
- }
912
- }
913
-
914
- export class RenameTypeCall extends PostgresOpFactoryCallNode {
915
- readonly factoryName = 'renameType' as const;
916
- readonly operationClass = 'destructive' as const;
917
- readonly schemaName: string;
918
- readonly fromName: string;
919
- readonly toName: string;
920
- readonly label: string;
921
-
922
- constructor(schemaName: string, fromName: string, toName: string) {
923
- super();
924
- this.schemaName = schemaName;
925
- this.fromName = fromName;
926
- this.toName = toName;
927
- this.label = `Rename type "${fromName}" to "${toName}"`;
928
- this.freeze();
929
- }
930
-
931
- toOp(): Op {
932
- return renameType(this.schemaName, this.fromName, this.toName);
1193
+ const opts: string[] = [];
1194
+ if (this.schemaName !== UNBOUND_NAMESPACE_ID) {
1195
+ opts.push(`schema: ${jsonToTsSource(this.schemaName)}`);
1196
+ }
1197
+ opts.push(`table: ${jsonToTsSource(this.tableName)}`);
1198
+ opts.push(`index: ${jsonToTsSource(this.indexName)}`);
1199
+ return `this.dropIndex({ ${opts.join(', ')} })`;
933
1200
  }
934
1201
 
935
- renderTypeScript(): string {
936
- return `renameType(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.fromName)}, ${jsonToTsSource(this.toName)})`;
1202
+ override importRequirements(): readonly ImportRequirement[] {
1203
+ return [];
937
1204
  }
938
1205
  }
939
1206
 
@@ -1016,14 +1283,14 @@ export class CreateSchemaCall extends PostgresOpFactoryCallNode {
1016
1283
  this.freeze();
1017
1284
  }
1018
1285
 
1019
- toOp(lowerer?: Lowerer): Op {
1286
+ async toOp(lowerer?: ExecuteRequestLowerer): Promise<Op> {
1020
1287
  if (lowerer === undefined) {
1021
1288
  throw new Error(
1022
1289
  `CreateSchemaCall.toOp: a DDL lowerer is required on the Postgres planner path (schema "${this.schemaName}"). Pass the control adapter to createPostgresMigrationPlanner.`,
1023
1290
  );
1024
1291
  }
1025
1292
  const ddlNode = contractFreeDdl.createSchema({ schema: this.schemaName, ifNotExists: true });
1026
- const { sql } = lowerer.lower(ddlNode, { contract: {} });
1293
+ const statement = await lowerer.lowerToExecuteRequest(ddlNode);
1027
1294
  const schemaName = this.schemaName;
1028
1295
  return {
1029
1296
  id: `schema.${schemaName}`,
@@ -1031,7 +1298,13 @@ export class CreateSchemaCall extends PostgresOpFactoryCallNode {
1031
1298
  operationClass: 'additive',
1032
1299
  target: { id: 'postgres' },
1033
1300
  precheck: [],
1034
- execute: [step(`Create schema "${schemaName}"`, sql)],
1301
+ execute: [
1302
+ {
1303
+ description: `Create schema "${schemaName}"`,
1304
+ sql: statement.sql,
1305
+ params: statement.params ?? [],
1306
+ },
1307
+ ],
1035
1308
  postcheck: [],
1036
1309
  };
1037
1310
  }
@@ -1113,6 +1386,8 @@ export type PostgresOpFactoryCall =
1113
1386
  | DropNotNullCall
1114
1387
  | SetDefaultCall
1115
1388
  | DropDefaultCall
1389
+ | AddNotNullColumnDirectCall
1390
+ | AddNotNullColumnWithTempDefaultCall
1116
1391
  | AddPrimaryKeyCall
1117
1392
  | AddForeignKeyCall
1118
1393
  | AddUniqueCall
@@ -1121,10 +1396,6 @@ export type PostgresOpFactoryCall =
1121
1396
  | CreateIndexCall
1122
1397
  | DropIndexCall
1123
1398
  | DropConstraintCall
1124
- | CreateEnumTypeCall
1125
- | AddEnumValuesCall
1126
- | DropEnumTypeCall
1127
- | RenameTypeCall
1128
1399
  | RawSqlCall
1129
1400
  | CreateExtensionCall
1130
1401
  | CreateSchemaCall