@prisma-next/target-postgres 0.13.0-dev.34 → 0.13.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 (83) hide show
  1. package/dist/contract-free.d.mts +147 -14
  2. package/dist/contract-free.d.mts.map +1 -1
  3. package/dist/contract-free.mjs +3 -16
  4. package/dist/contract-free.mjs.map +1 -1
  5. package/dist/control.mjs +2 -2
  6. package/dist/ddl-QDyOSeLc.mjs +251 -0
  7. package/dist/ddl-QDyOSeLc.mjs.map +1 -0
  8. package/dist/{issue-planner-DsjB7xDj.mjs → issue-planner-CoI_0uM1.mjs} +9 -119
  9. package/dist/issue-planner-CoI_0uM1.mjs.map +1 -0
  10. package/dist/issue-planner.d.mts +2 -2
  11. package/dist/issue-planner.d.mts.map +1 -1
  12. package/dist/issue-planner.mjs +1 -1
  13. package/dist/migration.d.mts +4 -80
  14. package/dist/migration.d.mts.map +1 -1
  15. package/dist/migration.mjs +3 -3
  16. package/dist/{op-factory-call-CjR846f7.mjs → op-factory-call-B1bXWtfa.mjs} +551 -241
  17. package/dist/op-factory-call-B1bXWtfa.mjs.map +1 -0
  18. package/dist/{op-factory-call-CdtMyrlU.d.mts → op-factory-call-DmQEc3XV.d.mts} +111 -20
  19. package/dist/op-factory-call-DmQEc3XV.d.mts.map +1 -0
  20. package/dist/op-factory-call.d.mts +1 -1
  21. package/dist/op-factory-call.mjs +1 -1
  22. package/dist/{planner-_FOL4I21.mjs → planner-DS5XBhmi.mjs} +4 -4
  23. package/dist/{planner-_FOL4I21.mjs.map → planner-DS5XBhmi.mjs.map} +1 -1
  24. package/dist/{planner-produced-postgres-migration-BmCpyWLJ.mjs → planner-produced-postgres-migration-DTwCCek_.mjs} +2 -2
  25. package/dist/{planner-produced-postgres-migration-BmCpyWLJ.mjs.map → planner-produced-postgres-migration-DTwCCek_.mjs.map} +1 -1
  26. package/dist/{planner-produced-postgres-migration-wLhnJMMA.d.mts → planner-produced-postgres-migration-QqHa2C2l.d.mts} +2 -2
  27. package/dist/{planner-produced-postgres-migration-wLhnJMMA.d.mts.map → planner-produced-postgres-migration-QqHa2C2l.d.mts.map} +1 -1
  28. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  29. package/dist/planner-produced-postgres-migration.mjs +1 -1
  30. package/dist/planner-sql-checks-jqUUGyQR.mjs +152 -0
  31. package/dist/planner-sql-checks-jqUUGyQR.mjs.map +1 -0
  32. package/dist/planner-sql-checks.d.mts +1 -47
  33. package/dist/planner-sql-checks.d.mts.map +1 -1
  34. package/dist/planner-sql-checks.mjs +2 -2
  35. package/dist/planner.d.mts +1 -1
  36. package/dist/planner.mjs +1 -1
  37. package/dist/{postgres-contract-serializer-CyAe8ZFv.mjs → postgres-contract-serializer-E92REOFk.mjs} +3 -3
  38. package/dist/postgres-contract-serializer-E92REOFk.mjs.map +1 -0
  39. package/dist/postgres-migration-Y4YBJqkS.d.mts +181 -0
  40. package/dist/postgres-migration-Y4YBJqkS.d.mts.map +1 -0
  41. package/dist/postgres-migration-otiaw3Ru.mjs +145 -0
  42. package/dist/postgres-migration-otiaw3Ru.mjs.map +1 -0
  43. package/dist/{postgres-schema-CTKYiTHu.mjs → postgres-schema-COGZ1ark.mjs} +71 -29
  44. package/dist/postgres-schema-COGZ1ark.mjs.map +1 -0
  45. package/dist/runtime.mjs +1 -1
  46. package/dist/table-source-BvFo7gVs.d.mts +15 -0
  47. package/dist/table-source-BvFo7gVs.d.mts.map +1 -0
  48. package/dist/types.d.mts +28 -8
  49. package/dist/types.d.mts.map +1 -1
  50. package/dist/types.mjs +1 -1
  51. package/package.json +17 -17
  52. package/src/contract-free/checks.ts +363 -0
  53. package/src/core/migrations/op-factory-call.ts +417 -94
  54. package/src/core/migrations/operations/columns.ts +175 -140
  55. package/src/core/migrations/operations/constraints.ts +79 -108
  56. package/src/core/migrations/operations/dependencies.ts +16 -14
  57. package/src/core/migrations/operations/indexes.ts +31 -28
  58. package/src/core/migrations/operations/shared.ts +2 -2
  59. package/src/core/migrations/operations/tables.ts +13 -14
  60. package/src/core/migrations/planner-recipes.ts +42 -33
  61. package/src/core/migrations/planner-sql-checks.ts +1 -172
  62. package/src/core/migrations/planner-strategies.ts +25 -73
  63. package/src/core/migrations/postgres-migration.ts +272 -7
  64. package/src/core/postgres-contract-serializer.ts +1 -1
  65. package/src/core/postgres-schema.ts +70 -52
  66. package/src/exports/contract-free.ts +21 -0
  67. package/src/exports/migration.ts +1 -22
  68. package/src/exports/planner-sql-checks.ts +0 -7
  69. package/dist/ddl-DY2R_Yqz.mjs +0 -45
  70. package/dist/ddl-DY2R_Yqz.mjs.map +0 -1
  71. package/dist/issue-planner-DsjB7xDj.mjs.map +0 -1
  72. package/dist/op-factory-call-CdtMyrlU.d.mts.map +0 -1
  73. package/dist/op-factory-call-CjR846f7.mjs.map +0 -1
  74. package/dist/planner-sql-checks-CJJtPfDH.mjs +0 -272
  75. package/dist/planner-sql-checks-CJJtPfDH.mjs.map +0 -1
  76. package/dist/postgres-contract-serializer-CyAe8ZFv.mjs.map +0 -1
  77. package/dist/postgres-migration-DLXL0GBf.d.mts +0 -77
  78. package/dist/postgres-migration-DLXL0GBf.d.mts.map +0 -1
  79. package/dist/postgres-migration-dG-J0aI8.mjs +0 -75
  80. package/dist/postgres-migration-dG-J0aI8.mjs.map +0 -1
  81. package/dist/postgres-schema-CTKYiTHu.mjs.map +0 -1
  82. package/dist/shared-jcsbXxiW.d.mts +0 -25
  83. package/dist/shared-jcsbXxiW.d.mts.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import type { CodecControlHooks } from '@prisma-next/family-sql/control';
2
2
  import type { StorageColumn, StorageTypeInstance } from '@prisma-next/sql-contract/types';
3
3
  import { postgresCreateNamespace } from '../postgres-schema';
4
- import { escapeLiteral, quoteIdentifier } from '../sql-utils';
4
+ import { quoteIdentifier } from '../sql-utils';
5
5
  import { resolveColumnTypeMetadata } from './planner-type-resolution';
6
6
 
7
7
  /**
@@ -19,105 +19,6 @@ export function qualifyTableName(schema: string, table: string): string {
19
19
  return postgresCreateNamespace({ id: schema, entries: { table: {} } }).qualifyTable(table);
20
20
  }
21
21
 
22
- export function toRegclassLiteral(schema: string, name: string): string {
23
- return postgresCreateNamespace({ id: schema, entries: { table: {} } }).regclassLiteral(name);
24
- }
25
-
26
- /**
27
- * When `table` is omitted the check matches by name + schema across all tables.
28
- * Pass `table` to scope the check to a single table (prevents false matches on
29
- * identically-named constraints in different tables).
30
- */
31
- export function constraintExistsCheck({
32
- constraintName,
33
- schema,
34
- table,
35
- exists = true,
36
- }: {
37
- constraintName: string;
38
- schema: string;
39
- table?: string;
40
- exists?: boolean;
41
- }): string {
42
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
43
- const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';
44
- const tableFilter = table
45
- ? `AND c.conrelid = to_regclass(${namespace.regclassLiteral(table)})`
46
- : '';
47
- return `SELECT ${existsClause} (
48
- SELECT 1 FROM pg_constraint c
49
- JOIN pg_namespace n ON c.connamespace = n.oid
50
- WHERE c.conname = '${escapeLiteral(constraintName)}'
51
- AND n.nspname = ${namespace.schemaSqlExpression()}
52
- ${tableFilter}
53
- )`;
54
- }
55
-
56
- export function columnExistsCheck({
57
- schema,
58
- table,
59
- column,
60
- exists = true,
61
- }: {
62
- schema: string;
63
- table: string;
64
- column: string;
65
- exists?: boolean;
66
- }): string {
67
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
68
- const existsClause = exists ? '' : 'NOT ';
69
- return `SELECT ${existsClause}EXISTS (
70
- SELECT 1
71
- FROM information_schema.columns
72
- WHERE table_schema = ${namespace.schemaSqlExpression()}
73
- AND table_name = '${escapeLiteral(table)}'
74
- AND column_name = '${escapeLiteral(column)}'
75
- )`;
76
- }
77
-
78
- export function columnNullabilityCheck({
79
- schema,
80
- table,
81
- column,
82
- nullable,
83
- }: {
84
- schema: string;
85
- table: string;
86
- column: string;
87
- nullable: boolean;
88
- }): string {
89
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
90
- const expected = nullable ? 'YES' : 'NO';
91
- return `SELECT EXISTS (
92
- SELECT 1
93
- FROM information_schema.columns
94
- WHERE table_schema = ${namespace.schemaSqlExpression()}
95
- AND table_name = '${escapeLiteral(table)}'
96
- AND column_name = '${escapeLiteral(column)}'
97
- AND is_nullable = '${expected}'
98
- )`;
99
- }
100
-
101
- export function tableIsEmptyCheck(qualifiedTableName: string): string {
102
- return `SELECT NOT EXISTS (SELECT 1 FROM ${qualifiedTableName} LIMIT 1)`;
103
- }
104
-
105
- export function columnHasNoDefaultCheck(opts: {
106
- schema: string;
107
- table: string;
108
- column: string;
109
- }): string {
110
- const namespace = postgresCreateNamespace({ id: opts.schema, entries: { table: {} } });
111
- return `SELECT NOT EXISTS (
112
- SELECT 1
113
- FROM information_schema.columns
114
- WHERE table_schema = ${namespace.schemaSqlExpression()}
115
- AND table_name = '${escapeLiteral(opts.table)}'
116
- AND column_name = '${escapeLiteral(opts.column)}'
117
- AND column_default IS NOT NULL
118
- )`;
119
- }
120
-
121
22
  const FORMAT_TYPE_DISPLAY: ReadonlyMap<string, string> = new Map([
122
23
  ['int2', 'smallint'],
123
24
  ['int4', 'integer'],
@@ -266,75 +167,3 @@ export function buildExpectedFormatType(
266
167
 
267
168
  return FORMAT_TYPE_DISPLAY.get(resolved.nativeType) ?? resolved.nativeType;
268
169
  }
269
-
270
- export function columnTypeCheck({
271
- schema,
272
- table,
273
- column,
274
- expectedType,
275
- }: {
276
- schema: string;
277
- table: string;
278
- column: string;
279
- expectedType: string;
280
- }): string {
281
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
282
- return `SELECT EXISTS (
283
- SELECT 1
284
- FROM pg_attribute a
285
- JOIN pg_class c ON c.oid = a.attrelid
286
- JOIN pg_namespace n ON n.oid = c.relnamespace
287
- WHERE n.nspname = ${namespace.schemaSqlExpression()}
288
- AND c.relname = '${escapeLiteral(table)}'
289
- AND a.attname = '${escapeLiteral(column)}'
290
- AND format_type(a.atttypid, a.atttypmod) = '${escapeLiteral(expectedType)}'
291
- AND NOT a.attisdropped
292
- )`;
293
- }
294
-
295
- export function columnDefaultExistsCheck({
296
- schema,
297
- table,
298
- column,
299
- exists = true,
300
- }: {
301
- schema: string;
302
- table: string;
303
- column: string;
304
- exists?: boolean;
305
- }): string {
306
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
307
- const nullCheck = exists ? 'IS NOT NULL' : 'IS NULL';
308
- return `SELECT EXISTS (
309
- SELECT 1
310
- FROM information_schema.columns
311
- WHERE table_schema = ${namespace.schemaSqlExpression()}
312
- AND table_name = '${escapeLiteral(table)}'
313
- AND column_name = '${escapeLiteral(column)}'
314
- AND column_default ${nullCheck}
315
- )`;
316
- }
317
-
318
- export function tableHasPrimaryKeyCheck(
319
- schema: string,
320
- table: string,
321
- exists: boolean,
322
- constraintName?: string,
323
- ): string {
324
- const namespace = postgresCreateNamespace({ id: schema, entries: { table: {} } });
325
- const comparison = exists ? '' : 'NOT ';
326
- const constraintFilter = constraintName
327
- ? `AND c2.relname = '${escapeLiteral(constraintName)}'`
328
- : '';
329
- return `SELECT ${comparison}EXISTS (
330
- SELECT 1
331
- FROM pg_index i
332
- JOIN pg_class c ON c.oid = i.indrelid
333
- JOIN pg_namespace n ON n.oid = c.relnamespace
334
- LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
335
- WHERE n.nspname = ${namespace.schemaSqlExpression()}
336
- AND c.relname = '${escapeLiteral(table)}'
337
- AND i.indisprimary
338
- ${constraintFilter}
339
- )`;
340
- }
@@ -43,6 +43,8 @@ import { isPostgresSchema } from '../postgres-schema';
43
43
  import {
44
44
  AddCheckConstraintCall,
45
45
  AddColumnCall,
46
+ AddNotNullColumnDirectCall,
47
+ AddNotNullColumnWithTempDefaultCall,
46
48
  AlterColumnTypeCall,
47
49
  DataTransformCall,
48
50
  DropCheckConstraintCall,
@@ -53,18 +55,8 @@ import {
53
55
  } from './op-factory-call';
54
56
  import { buildAddColumnSql, buildColumnTypeSql } from './planner-ddl-builders';
55
57
  import { resolveIdentityValue } from './planner-identity-values';
56
- import {
57
- buildAddColumnOperationIdentity,
58
- buildAddNotNullColumnWithTemporaryDefaultOperation,
59
- } from './planner-recipes';
60
58
  import { buildSchemaLookupMap, hasForeignKey, hasUniqueConstraint } from './planner-schema-lookup';
61
- import {
62
- buildExpectedFormatType,
63
- columnExistsCheck,
64
- columnNullabilityCheck,
65
- qualifyTableName,
66
- tableIsEmptyCheck,
67
- } from './planner-sql-checks';
59
+ import { buildExpectedFormatType, qualifyTableName } from './planner-sql-checks';
68
60
  import { buildTargetDetails, type PostgresPlanTargetDetails } from './planner-target-details';
69
61
  import { resolveColumnTypeMetadata } from './planner-type-resolution';
70
62
 
@@ -595,74 +587,34 @@ export const notNullAddColumnCallStrategy: CallMigrationStrategy = (issues, ctx)
595
587
 
596
588
  if (canUseSharedTempDefault && temporaryDefault !== null) {
597
589
  calls.push(
598
- new RawSqlCall(
599
- buildAddNotNullColumnWithTemporaryDefaultOperation({
600
- schema: schemaForTable,
601
- tableName: issue.table,
602
- columnName: issue.column,
603
- column,
604
- codecHooks: mutableCodecHooks,
605
- storageTypes: mutableStorageTypes,
606
- temporaryDefault,
607
- }),
608
- ),
590
+ new AddNotNullColumnWithTempDefaultCall({
591
+ schemaName: schemaForTable,
592
+ tableName: issue.table,
593
+ columnName: issue.column,
594
+ column,
595
+ codecHooks: mutableCodecHooks,
596
+ storageTypes: mutableStorageTypes,
597
+ temporaryDefault,
598
+ }),
609
599
  );
610
600
  continue;
611
601
  }
612
602
 
613
603
  const qualified = qualifyTableName(schemaForTable, issue.table);
614
604
  calls.push(
615
- new RawSqlCall({
616
- ...buildAddColumnOperationIdentity(schemaForTable, issue.table, issue.column),
617
- operationClass: 'additive',
618
- precheck: [
619
- {
620
- description: `ensure column "${issue.column}" is missing`,
621
- sql: columnExistsCheck({
622
- schema: schemaForTable,
623
- table: issue.table,
624
- column: issue.column,
625
- exists: false,
626
- }),
627
- },
628
- {
629
- description: `ensure table "${issue.table}" is empty before adding NOT NULL column without default`,
630
- sql: tableIsEmptyCheck(qualified),
631
- },
632
- ],
633
- execute: [
634
- {
635
- description: `add column "${issue.column}"`,
636
- sql: buildAddColumnSql(
637
- qualified,
638
- issue.column,
639
- column,
640
- mutableCodecHooks,
641
- undefined,
642
- mutableStorageTypes,
643
- ),
644
- },
645
- ],
646
- postcheck: [
647
- {
648
- description: `verify column "${issue.column}" exists`,
649
- sql: columnExistsCheck({
650
- schema: schemaForTable,
651
- table: issue.table,
652
- column: issue.column,
653
- }),
654
- },
655
- {
656
- description: `verify column "${issue.column}" is NOT NULL`,
657
- sql: columnNullabilityCheck({
658
- schema: schemaForTable,
659
- table: issue.table,
660
- column: issue.column,
661
- nullable: false,
662
- }),
663
- },
664
- ],
665
- }),
605
+ new AddNotNullColumnDirectCall(
606
+ schemaForTable,
607
+ issue.table,
608
+ issue.column,
609
+ buildAddColumnSql(
610
+ qualified,
611
+ issue.column,
612
+ column,
613
+ mutableCodecHooks,
614
+ undefined,
615
+ mutableStorageTypes,
616
+ ),
617
+ ),
666
618
  );
667
619
  }
668
620
 
@@ -3,12 +3,34 @@ import type { SqlMigrationPlanOperation } from '@prisma-next/family-sql/control'
3
3
  import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
4
4
  import { Migration as SqlMigration } from '@prisma-next/family-sql/migration';
5
5
  import type { ControlStack } from '@prisma-next/framework-components/control';
6
- import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
7
6
  import type { SqlStorage } from '@prisma-next/sql-contract/types';
8
7
  import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
9
8
  import { errorPostgresMigrationStackMissing } from '../errors';
10
- import { AddColumnCall, CreateSchemaCall, CreateTableCall } from './op-factory-call';
9
+ import {
10
+ AddCheckConstraintCall,
11
+ AddColumnCall,
12
+ AddForeignKeyCall,
13
+ AddPrimaryKeyCall,
14
+ AddUniqueCall,
15
+ AlterColumnTypeCall,
16
+ type AlterColumnTypeOptions,
17
+ CreateIndexCall,
18
+ CreateSchemaCall,
19
+ CreateTableCall,
20
+ DropCheckConstraintCall,
21
+ DropColumnCall,
22
+ DropConstraintCall,
23
+ DropDefaultCall,
24
+ DropIndexCall,
25
+ DropNotNullCall,
26
+ DropTableCall,
27
+ SetDefaultCall,
28
+ SetNotNullCall,
29
+ } from './op-factory-call';
11
30
  import { type DataTransformOptions, dataTransform } from './operations/data-transform';
31
+ import { installExtension } from './operations/dependencies';
32
+ import type { CreateIndexExtras } from './operations/indexes';
33
+ import type { ForeignKeySpec } from './operations/shared';
12
34
  import type { PostgresPlanTargetDetails } from './planner-target-details';
13
35
 
14
36
  /**
@@ -30,6 +52,13 @@ import type { PostgresPlanTargetDetails } from './planner-target-details';
30
52
  * instance method forwards to the free `dataTransform` factory with that
31
53
  * stored adapter, so user migrations can write `this.dataTransform(...)`
32
54
  * without threading the adapter through every call.
55
+ *
56
+ * Every method requires an explicit `schema`. Postgres migrations name their
57
+ * schema deliberately — there is no default and no `search_path`-relative
58
+ * option. A migration that left the schema unspecified would resolve against
59
+ * whatever `search_path` the connection happened to carry, and that ambiguity
60
+ * is an antipattern in a migration. (The unbound/unspecified namespace concept
61
+ * remains for SQLite, which has no schemas, and for Mongo's connection `db`.)
33
62
  */
34
63
  export abstract class PostgresMigration extends SqlMigration<
35
64
  PostgresPlanTargetDetails,
@@ -77,7 +106,7 @@ export abstract class PostgresMigration extends SqlMigration<
77
106
  * Throws if no adapter is present (i.e. migration instantiated without a stack).
78
107
  */
79
108
  protected createTable(options: {
80
- readonly schema?: string;
109
+ readonly schema: string;
81
110
  readonly table: string;
82
111
  readonly ifNotExists?: boolean;
83
112
  readonly columns: readonly DdlColumn[];
@@ -87,7 +116,7 @@ export abstract class PostgresMigration extends SqlMigration<
87
116
  throw errorPostgresMigrationStackMissing();
88
117
  }
89
118
  return new CreateTableCall(
90
- options.schema ?? UNBOUND_NAMESPACE_ID,
119
+ options.schema,
91
120
  options.table,
92
121
  options.columns,
93
122
  options.constraints,
@@ -110,17 +139,253 @@ export abstract class PostgresMigration extends SqlMigration<
110
139
  }
111
140
 
112
141
  protected addColumn(options: {
113
- readonly schema?: string;
142
+ readonly schema: string;
114
143
  readonly table: string;
115
144
  readonly column: DdlColumn;
116
145
  }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
117
146
  if (!this.controlAdapter) {
118
147
  throw errorPostgresMigrationStackMissing();
119
148
  }
120
- return new AddColumnCall(
121
- options.schema ?? UNBOUND_NAMESPACE_ID,
149
+ return new AddColumnCall(options.schema, options.table, options.column).toOp(
150
+ this.controlAdapter,
151
+ );
152
+ }
153
+
154
+ protected addPrimaryKey(options: {
155
+ readonly schema: string;
156
+ readonly table: string;
157
+ readonly constraint: string;
158
+ readonly columns: readonly string[];
159
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
160
+ if (!this.controlAdapter) {
161
+ throw errorPostgresMigrationStackMissing();
162
+ }
163
+ return new AddPrimaryKeyCall(
164
+ options.schema,
165
+ options.table,
166
+ options.constraint,
167
+ options.columns,
168
+ ).toOp(this.controlAdapter);
169
+ }
170
+
171
+ protected addUnique(options: {
172
+ readonly schema: string;
173
+ readonly table: string;
174
+ readonly constraint: string;
175
+ readonly columns: readonly string[];
176
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
177
+ if (!this.controlAdapter) {
178
+ throw errorPostgresMigrationStackMissing();
179
+ }
180
+ return new AddUniqueCall(
181
+ options.schema,
182
+ options.table,
183
+ options.constraint,
184
+ options.columns,
185
+ ).toOp(this.controlAdapter);
186
+ }
187
+
188
+ protected addForeignKey(options: {
189
+ readonly schema: string;
190
+ readonly table: string;
191
+ readonly foreignKey: ForeignKeySpec;
192
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
193
+ if (!this.controlAdapter) {
194
+ throw errorPostgresMigrationStackMissing();
195
+ }
196
+ return new AddForeignKeyCall(options.schema, options.table, options.foreignKey).toOp(
197
+ this.controlAdapter,
198
+ );
199
+ }
200
+
201
+ protected addCheckConstraint(options: {
202
+ readonly schema: string;
203
+ readonly table: string;
204
+ readonly constraint: string;
205
+ readonly column: string;
206
+ readonly values: readonly string[];
207
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
208
+ if (!this.controlAdapter) {
209
+ throw errorPostgresMigrationStackMissing();
210
+ }
211
+ return new AddCheckConstraintCall(
212
+ options.schema,
213
+ options.table,
214
+ options.constraint,
215
+ options.column,
216
+ options.values,
217
+ ).toOp(this.controlAdapter);
218
+ }
219
+
220
+ protected dropCheckConstraint(options: {
221
+ readonly schema: string;
222
+ readonly table: string;
223
+ readonly constraint: string;
224
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
225
+ if (!this.controlAdapter) {
226
+ throw errorPostgresMigrationStackMissing();
227
+ }
228
+ return new DropCheckConstraintCall(options.schema, options.table, options.constraint).toOp(
229
+ this.controlAdapter,
230
+ );
231
+ }
232
+
233
+ protected dropConstraint(options: {
234
+ readonly schema: string;
235
+ readonly table: string;
236
+ readonly constraint: string;
237
+ readonly kind?: 'foreignKey' | 'unique' | 'primaryKey';
238
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
239
+ if (!this.controlAdapter) {
240
+ throw errorPostgresMigrationStackMissing();
241
+ }
242
+ return new DropConstraintCall(
243
+ options.schema,
244
+ options.table,
245
+ options.constraint,
246
+ options.kind ?? 'unique',
247
+ ).toOp(this.controlAdapter);
248
+ }
249
+
250
+ protected dropTable(options: {
251
+ readonly schema: string;
252
+ readonly table: string;
253
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
254
+ if (!this.controlAdapter) {
255
+ throw errorPostgresMigrationStackMissing();
256
+ }
257
+ return new DropTableCall(options.schema, options.table).toOp(this.controlAdapter);
258
+ }
259
+
260
+ protected dropColumn(options: {
261
+ readonly schema: string;
262
+ readonly table: string;
263
+ readonly column: string;
264
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
265
+ if (!this.controlAdapter) {
266
+ throw errorPostgresMigrationStackMissing();
267
+ }
268
+ return new DropColumnCall(options.schema, options.table, options.column).toOp(
269
+ this.controlAdapter,
270
+ );
271
+ }
272
+
273
+ protected alterColumnType(options: {
274
+ readonly schema: string;
275
+ readonly table: string;
276
+ readonly column: string;
277
+ readonly options: AlterColumnTypeOptions;
278
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
279
+ if (!this.controlAdapter) {
280
+ throw errorPostgresMigrationStackMissing();
281
+ }
282
+ return new AlterColumnTypeCall(
283
+ options.schema,
122
284
  options.table,
123
285
  options.column,
286
+ options.options,
124
287
  ).toOp(this.controlAdapter);
125
288
  }
289
+
290
+ protected setNotNull(options: {
291
+ readonly schema: string;
292
+ readonly table: string;
293
+ readonly column: string;
294
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
295
+ if (!this.controlAdapter) {
296
+ throw errorPostgresMigrationStackMissing();
297
+ }
298
+ return new SetNotNullCall(options.schema, options.table, options.column).toOp(
299
+ this.controlAdapter,
300
+ );
301
+ }
302
+
303
+ protected dropNotNull(options: {
304
+ readonly schema: string;
305
+ readonly table: string;
306
+ readonly column: string;
307
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
308
+ if (!this.controlAdapter) {
309
+ throw errorPostgresMigrationStackMissing();
310
+ }
311
+ return new DropNotNullCall(options.schema, options.table, options.column).toOp(
312
+ this.controlAdapter,
313
+ );
314
+ }
315
+
316
+ protected setDefault(options: {
317
+ readonly schema: string;
318
+ readonly table: string;
319
+ readonly column: string;
320
+ readonly defaultSql: string;
321
+ readonly operationClass?: 'additive' | 'widening';
322
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
323
+ if (!this.controlAdapter) {
324
+ throw errorPostgresMigrationStackMissing();
325
+ }
326
+ return new SetDefaultCall(
327
+ options.schema,
328
+ options.table,
329
+ options.column,
330
+ options.defaultSql,
331
+ options.operationClass,
332
+ ).toOp(this.controlAdapter);
333
+ }
334
+
335
+ protected dropDefault(options: {
336
+ readonly schema: string;
337
+ readonly table: string;
338
+ readonly column: string;
339
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
340
+ if (!this.controlAdapter) {
341
+ throw errorPostgresMigrationStackMissing();
342
+ }
343
+ return new DropDefaultCall(options.schema, options.table, options.column).toOp(
344
+ this.controlAdapter,
345
+ );
346
+ }
347
+
348
+ protected createIndex(options: {
349
+ readonly schema: string;
350
+ readonly table: string;
351
+ readonly index: string;
352
+ readonly columns: readonly string[];
353
+ readonly extras?: CreateIndexExtras;
354
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
355
+ if (!this.controlAdapter) {
356
+ throw errorPostgresMigrationStackMissing();
357
+ }
358
+ return new CreateIndexCall(
359
+ options.schema,
360
+ options.table,
361
+ options.index,
362
+ options.columns,
363
+ options.extras,
364
+ ).toOp(this.controlAdapter);
365
+ }
366
+
367
+ protected dropIndex(options: {
368
+ readonly schema: string;
369
+ readonly table: string;
370
+ readonly index: string;
371
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
372
+ if (!this.controlAdapter) {
373
+ throw errorPostgresMigrationStackMissing();
374
+ }
375
+ return new DropIndexCall(options.schema, options.table, options.index).toOp(
376
+ this.controlAdapter,
377
+ );
378
+ }
379
+
380
+ protected installExtension(options: {
381
+ readonly extensionName: string;
382
+ readonly invariantId: string;
383
+ readonly id: string;
384
+ readonly label?: string;
385
+ }): Promise<SqlMigrationPlanOperation<PostgresPlanTargetDetails>> {
386
+ if (!this.controlAdapter) {
387
+ throw errorPostgresMigrationStackMissing();
388
+ }
389
+ return installExtension(options, this.controlAdapter);
390
+ }
126
391
  }
@@ -39,7 +39,7 @@ function isAuthoringEntityTypeFactoryOutput(
39
39
  * Walks a pack's entity-type namespace tree and emits hydration factories
40
40
  * keyed by the descriptor's `discriminator`. Used for `storage.types`
41
41
  * (codec-triple hydration). Namespace entries hydration dispatches by
42
- * entries key, not discriminator — handled by `hydrateEntriesKind`.
42
+ * entries key, not discriminator — handled by `hydrateNamespaceEntities`.
43
43
  */
44
44
  function collectStorageTypesHydrators(
45
45
  namespace: AuthoringEntityTypeNamespace,