@prisma-next/target-postgres 0.4.0-dev.8 → 0.4.1
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.
- package/dist/control.d.mts +1 -9
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +1693 -4798
- package/dist/control.mjs.map +1 -1
- package/dist/migration.d.mts +164 -0
- package/dist/migration.d.mts.map +1 -0
- package/dist/migration.mjs +446 -0
- package/dist/migration.mjs.map +1 -0
- package/dist/planner-target-details-MXb3oeul.d.mts +11 -0
- package/dist/planner-target-details-MXb3oeul.d.mts.map +1 -0
- package/dist/postgres-migration-BsHJHV9O.mjs +2793 -0
- package/dist/postgres-migration-BsHJHV9O.mjs.map +1 -0
- package/package.json +21 -19
- package/src/core/migrations/issue-planner.ts +832 -0
- package/src/core/migrations/op-factory-call.ts +862 -0
- package/src/core/migrations/operations/columns.ts +285 -0
- package/src/core/migrations/operations/constraints.ts +191 -0
- package/src/core/migrations/operations/data-transform.ts +113 -0
- package/src/core/migrations/operations/dependencies.ts +36 -0
- package/src/core/migrations/operations/enums.ts +113 -0
- package/src/core/migrations/operations/indexes.ts +61 -0
- package/src/core/migrations/operations/raw.ts +15 -0
- package/src/core/migrations/operations/shared.ts +67 -0
- package/src/core/migrations/operations/tables.ts +63 -0
- package/src/core/migrations/planner-produced-postgres-migration.ts +67 -0
- package/src/core/migrations/planner-strategies.ts +592 -151
- package/src/core/migrations/planner-target-details.ts +0 -6
- package/src/core/migrations/planner.ts +63 -781
- package/src/core/migrations/postgres-migration.ts +20 -0
- package/src/core/migrations/render-ops.ts +9 -0
- package/src/core/migrations/render-typescript.ts +95 -0
- package/src/exports/control.ts +9 -142
- package/src/exports/migration.ts +40 -0
- package/dist/migration-builders.d.mts +0 -88
- package/dist/migration-builders.d.mts.map +0 -1
- package/dist/migration-builders.mjs +0 -3
- package/dist/operation-descriptors-CxymFSgK.mjs +0 -52
- package/dist/operation-descriptors-CxymFSgK.mjs.map +0 -1
- package/src/core/migrations/descriptor-planner.ts +0 -464
- package/src/core/migrations/operation-descriptors.ts +0 -166
- package/src/core/migrations/operation-resolver.ts +0 -929
- package/src/core/migrations/planner-reconciliation.ts +0 -798
- package/src/core/migrations/scaffolding.ts +0 -140
- package/src/exports/migration-builders.ts +0 -56
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { t as PostgresPlanTargetDetails } from "./planner-target-details-MXb3oeul.mjs";
|
|
2
|
+
import { SqlMigrationPlanOperation } from "@prisma-next/family-sql/control";
|
|
3
|
+
import { placeholder } from "@prisma-next/errors/migration";
|
|
4
|
+
import { Migration } from "@prisma-next/family-sql/migration";
|
|
5
|
+
import { Contract } from "@prisma-next/contract/types";
|
|
6
|
+
import { ReferentialAction, SqlStorage } from "@prisma-next/sql-contract/types";
|
|
7
|
+
import { DataTransformOperation } from "@prisma-next/framework-components/control";
|
|
8
|
+
import { SqlQueryPlan } from "@prisma-next/sql-relational-core/plan";
|
|
9
|
+
|
|
10
|
+
//#region src/core/migrations/operations/shared.d.ts
|
|
11
|
+
type Op = SqlMigrationPlanOperation<PostgresPlanTargetDetails>;
|
|
12
|
+
/**
|
|
13
|
+
* Literal-args shape for a column definition consumed by `createTable` and
|
|
14
|
+
* `addColumn`. Fully materialized: codec expansion and default rendering have
|
|
15
|
+
* already happened in the wrapper.
|
|
16
|
+
*
|
|
17
|
+
* - `typeSql` is the column's DDL type string (e.g. `"integer"`, `"SERIAL"`,
|
|
18
|
+
* `"varchar(100)"`), already produced by `buildColumnTypeSql` in the
|
|
19
|
+
* call-factory wrapper.
|
|
20
|
+
* - `defaultSql` is the full `DEFAULT …` clause (e.g. `"DEFAULT 42"`) or an
|
|
21
|
+
* empty string when the column has no default, matching
|
|
22
|
+
* `buildColumnDefaultSql`'s output.
|
|
23
|
+
*/
|
|
24
|
+
interface ColumnSpec {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly typeSql: string;
|
|
27
|
+
readonly defaultSql: string;
|
|
28
|
+
readonly nullable: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Literal-args shape for a foreign key definition. The referenced table is
|
|
32
|
+
* assumed to live in the same schema as the constrained table.
|
|
33
|
+
*/
|
|
34
|
+
interface ForeignKeySpec {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly columns: readonly string[];
|
|
37
|
+
readonly references: {
|
|
38
|
+
readonly table: string;
|
|
39
|
+
readonly columns: readonly string[];
|
|
40
|
+
};
|
|
41
|
+
readonly onDelete?: ReferentialAction;
|
|
42
|
+
readonly onUpdate?: ReferentialAction;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/core/migrations/operations/columns.d.ts
|
|
46
|
+
declare function addColumn(schemaName: string, tableName: string, column: ColumnSpec): Op;
|
|
47
|
+
declare function dropColumn(schemaName: string, tableName: string, columnName: string): Op;
|
|
48
|
+
/**
|
|
49
|
+
* `qualifiedTargetType` is the new column type as it appears in the
|
|
50
|
+
* `ALTER COLUMN TYPE` clause (schema-qualified for user-defined types, raw
|
|
51
|
+
* native name for built-ins). `formatTypeExpected` is the unqualified
|
|
52
|
+
* `format_type` form used in the postcheck. `rawTargetTypeForLabel` is the
|
|
53
|
+
* string appearing in the human-readable label (typically `toType` when
|
|
54
|
+
* explicit, else the column's native type).
|
|
55
|
+
*/
|
|
56
|
+
declare function alterColumnType(schemaName: string, tableName: string, columnName: string, options: {
|
|
57
|
+
readonly qualifiedTargetType: string;
|
|
58
|
+
readonly formatTypeExpected: string;
|
|
59
|
+
readonly rawTargetTypeForLabel: string;
|
|
60
|
+
readonly using?: string;
|
|
61
|
+
}): Op;
|
|
62
|
+
declare function setNotNull(schemaName: string, tableName: string, columnName: string): Op;
|
|
63
|
+
declare function dropNotNull(schemaName: string, tableName: string, columnName: string): Op;
|
|
64
|
+
/**
|
|
65
|
+
* `defaultSql` is the full `DEFAULT …` clause as produced by
|
|
66
|
+
* `buildColumnDefaultSql` — e.g. `"DEFAULT 42"`,
|
|
67
|
+
* `"DEFAULT (CURRENT_TIMESTAMP)"`, or `"DEFAULT nextval('seq'::regclass)"`.
|
|
68
|
+
*
|
|
69
|
+
* `operationClass` defaults to `'additive'` (setting a default on a column
|
|
70
|
+
* that currently has none). The reconciliation planner passes `'widening'`
|
|
71
|
+
* when the column already has a different default — policy enforcement
|
|
72
|
+
* treats that as a widening change rather than an additive one.
|
|
73
|
+
*/
|
|
74
|
+
declare function setDefault(schemaName: string, tableName: string, columnName: string, defaultSql: string, operationClass?: 'additive' | 'widening'): Op;
|
|
75
|
+
declare function dropDefault(schemaName: string, tableName: string, columnName: string): Op;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/core/migrations/operations/constraints.d.ts
|
|
78
|
+
declare function addPrimaryKey(schemaName: string, tableName: string, constraintName: string, columns: readonly string[]): Op;
|
|
79
|
+
declare function addUnique(schemaName: string, tableName: string, constraintName: string, columns: readonly string[]): Op;
|
|
80
|
+
declare function addForeignKey(schemaName: string, tableName: string, fk: ForeignKeySpec): Op;
|
|
81
|
+
/**
|
|
82
|
+
* `kind` feeds the operation's `target.details.objectType`. Descriptor-flow
|
|
83
|
+
* does not carry kind information in its drop-constraint descriptor, so the
|
|
84
|
+
* default is `'unique'`. The reconciliation planner passes the correct kind
|
|
85
|
+
* (`'foreignKey'`, `'primaryKey'`, or `'unique'`) based on the `SchemaIssue`
|
|
86
|
+
* that produced the drop.
|
|
87
|
+
*/
|
|
88
|
+
declare function dropConstraint(schemaName: string, tableName: string, constraintName: string, kind?: 'foreignKey' | 'unique' | 'primaryKey'): Op;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/core/migrations/operations/data-transform.d.ts
|
|
91
|
+
interface Buildable<R = unknown> {
|
|
92
|
+
build(): SqlQueryPlan<R>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A single-closure producer of a SQL query plan. Shared between
|
|
96
|
+
* `check` and each `run` entry.
|
|
97
|
+
*/
|
|
98
|
+
type DataTransformClosure = () => SqlQueryPlan | Buildable;
|
|
99
|
+
interface DataTransformOptions {
|
|
100
|
+
/** Optional pre-flight query. `undefined` means "no check". */
|
|
101
|
+
readonly check?: DataTransformClosure;
|
|
102
|
+
/** One or more mutation queries to execute. */
|
|
103
|
+
readonly run: DataTransformClosure | readonly DataTransformClosure[];
|
|
104
|
+
}
|
|
105
|
+
declare function dataTransform<TContract extends Contract<SqlStorage>>(contract: TContract, name: string, options: DataTransformOptions): DataTransformOperation;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/core/migrations/operations/dependencies.d.ts
|
|
108
|
+
declare function createExtension(extensionName: string): Op;
|
|
109
|
+
declare function createSchema(schemaName: string): Op;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/core/migrations/operations/enums.d.ts
|
|
112
|
+
declare function createEnumType(schemaName: string, typeName: string, values: readonly string[]): Op;
|
|
113
|
+
/**
|
|
114
|
+
* `typeName` is the contract-facing type name (used for id/label).
|
|
115
|
+
* `nativeType` is the Postgres type name to mutate (may differ for external types).
|
|
116
|
+
*/
|
|
117
|
+
declare function addEnumValues(schemaName: string, typeName: string, nativeType: string, values: readonly string[]): Op;
|
|
118
|
+
declare function dropEnumType(schemaName: string, typeName: string): Op;
|
|
119
|
+
declare function renameType(schemaName: string, fromName: string, toName: string): Op;
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/core/migrations/operations/indexes.d.ts
|
|
122
|
+
declare function createIndex(schemaName: string, tableName: string, indexName: string, columns: readonly string[]): Op;
|
|
123
|
+
declare function dropIndex(schemaName: string, tableName: string, indexName: string): Op;
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/core/migrations/operations/raw.d.ts
|
|
126
|
+
/**
|
|
127
|
+
* Identity factory for an already-materialized `SqlMigrationPlanOperation`.
|
|
128
|
+
*
|
|
129
|
+
* The planner uses this via `liftOpToCall` to carry ops produced by SQL
|
|
130
|
+
* family methods, codec control hooks, and component database dependencies
|
|
131
|
+
* alongside migration IR without reverse-engineering them. Users writing
|
|
132
|
+
* raw migrations can pass a full op shape directly — typically built by
|
|
133
|
+
* composing SQL family helpers — to author a migration that bypasses the
|
|
134
|
+
* structured call classes.
|
|
135
|
+
*/
|
|
136
|
+
declare function rawSql(op: Op): Op;
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/core/migrations/operations/tables.d.ts
|
|
139
|
+
declare function createTable(schemaName: string, tableName: string, columns: ReadonlyArray<ColumnSpec>, primaryKey?: {
|
|
140
|
+
readonly columns: readonly string[];
|
|
141
|
+
}): Op;
|
|
142
|
+
declare function dropTable(schemaName: string, tableName: string): Op;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/core/migrations/postgres-migration.d.ts
|
|
145
|
+
/**
|
|
146
|
+
* Target-owned base class for Postgres migrations.
|
|
147
|
+
*
|
|
148
|
+
* Fixes the `SqlMigration` generic to `PostgresPlanTargetDetails` and the
|
|
149
|
+
* abstract `targetId` to the Postgres target-id string literal, so both
|
|
150
|
+
* user-authored migrations and renderer-generated scaffolds (the output of
|
|
151
|
+
* `renderCallsToTypeScript`) can extend `PostgresMigration` directly without
|
|
152
|
+
* redeclaring target-local identity.
|
|
153
|
+
*
|
|
154
|
+
* Mirrors `MongoMigration` in `@prisma-next/family-mongo`: the renderer
|
|
155
|
+
* emits `extends Migration` against a target-specific re-export of this
|
|
156
|
+
* class from `@prisma-next/target-postgres/migration`, keeping the
|
|
157
|
+
* authoring surface target-scoped rather than family-scoped.
|
|
158
|
+
*/
|
|
159
|
+
declare abstract class PostgresMigration extends Migration<PostgresPlanTargetDetails> {
|
|
160
|
+
readonly targetId: "postgres";
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
export { type DataTransformClosure, type DataTransformOptions, PostgresMigration as Migration, addColumn, addEnumValues, addForeignKey, addPrimaryKey, addUnique, alterColumnType, createEnumType, createExtension, createIndex, createSchema, createTable, dataTransform, dropColumn, dropConstraint, dropDefault, dropEnumType, dropIndex, dropNotNull, dropTable, placeholder, rawSql, renameType, setDefault, setNotNull };
|
|
164
|
+
//# sourceMappingURL=migration.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/migrations/operations/shared.ts","../src/core/migrations/operations/columns.ts","../src/core/migrations/operations/constraints.ts","../src/core/migrations/operations/data-transform.ts","../src/core/migrations/operations/dependencies.ts","../src/core/migrations/operations/enums.ts","../src/core/migrations/operations/indexes.ts","../src/core/migrations/operations/raw.ts","../src/core/migrations/operations/tables.ts","../src/core/migrations/postgres-migration.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;KAMY,EAAA,GAAK,0BAA0B;;;;;;;AAA3C;AAcA;AAWA;;;;ACrBgB,UDUC,UAAA,CCVwD;EAoCzD,SAAA,IAAU,EAAA,MAAA;EAyCV,SAAA,OAAA,EAAe,MAAA;EA+Cf,SAAA,UAAU,EAAA,MAA6D;EAqCvE,SAAA,QAAW,EAAA,OAA6D;AA2CxF;AAuCA;;;;ACvNgB,UFPC,cAAA,CEYd;EAkCa,SAAA,IAAS,EAAA,MAAA;EAuCT,SAAA,OAAa,EAAA,SAAA,MAA4C,EAAA;EAsCzD,SAAA,UAAc,EAAA;;;;EC1HpB,SAAA,QAAS,CAAA,EHMG,iBGLX;EAOC,SAAA,QAAA,CAAA,EHDU,iBGCmB;AAEzC;;;iBFhCgB,SAAA,gDAAyD,aAAa;iBAoCtE,UAAA,6DAAuE;;;;;;;;ADxCvF;AAciB,iBCmED,eAAA,CDnEW,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAAA;EAWV,SAAA,mBAAc,EAOT,MAAA;;;;AC5BtB,CAAA,CAAA,EAuFG,EAvFa;AAoCA,iBAwFA,UAAA,CAxFyE,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,CAAA,EAwFF,EAxFE;AAyCzE,iBAoFA,WAAA,CA1Eb,UAAE,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,CAAA,EA0EmF,EA1EnF;AAqCL;AAqCA;AA2CA;AAuCA;;;;ACvNA;AAuCA;AAuCA;AAsCgB,iBD4DA,UAAA,CCvDb,UAAE,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,cAAA,CAAA,EAAA,UAAA,GAAA,UAAA,CAAA,ED6DF,EC7DE;iBD8FW,WAAA,6DAAwE;;;iBCvNxE,aAAA,6FAKb;iBAkCa,SAAA,6FAKb;iBAkCa,aAAA,4CAAyD,iBAAiB;;;;;;;AF9G1F;AAciB,iBEsID,cAAA,CFtIW,UAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,MAAA,EAAA,IAAA,CAAA,EAAA,YAAA,GAAA,QAAA,GAAA,YAAA,CAAA,EE2IxB,EF3IwB;;;UGYjB;WACC,aAAa;ADKxB;AAuCA;AAuCA;AAsCA;;KClHY,oBAAA,SAA6B,eAAe;UAEvC,oBAAA;EAVP;EAQE,SAAA,KAAA,CAAA,EAIO,oBAJsB;EAExB;EAEE,SAAA,GAAA,EAEH,oBAFG,GAAA,SAE6B,oBAF7B,EAAA;;AAE6B,iBAYhC,aAZgC,CAAA,kBAYA,QAZA,CAYS,UAZT,CAAA,CAAA,CAAA,QAAA,EAapC,SAboC,EAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAerC,oBAfqC,CAAA,EAgB7C,sBAhB6C;;;iBC3ChC,eAAA,yBAAwC;iBAiBxC,YAAA,sBAAkC;;;iBCNlC,cAAA,mEAIb;;;;;iBA8Ba,aAAA,uFAKb;iBAsBa,YAAA,wCAAoD;iBAepD,UAAA,wDAAkE;;;iBCtFlE,WAAA,wFAKb;iBA6Ba,SAAA,4DAAqE;;;;;;;;;;;;ANhCrF;AAciB,iBORD,MAAA,CPQW,EAAA,EORA,EPQA,CAAA,EORK,EPQL;;;iBQhBX,WAAA,iDAGL,cAAc;;IAEtB;iBAgCa,SAAA,yCAAkD;;;;;;;;;;;ARnClE;AAcA;AAWA;;;;ACrBgB,uBQOM,iBAAA,SAA0B,SRPwC,CQO3B,yBRP2B,CAAA,CAAA;EAoCxE,SAAA,QAAU,EAAA,UAA+D;AAyCzF"}
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import { F as escapeLiteral, I as quoteIdentifier, M as codecDefinitions, N as PG_JSONB_CODEC_ID, P as PG_JSON_CODEC_ID, S as setNotNull, _ as alterColumnType, a as dropIndex, b as dropNotNull, c as dropEnumType, d as createSchema, f as addForeignKey, g as addColumn, h as dropConstraint, i as createIndex, l as renameType, m as addUnique, n as createTable, o as addEnumValues, p as addPrimaryKey, r as dropTable, s as createEnumType, t as PostgresMigration, u as createExtension, v as dropColumn, x as setDefault, y as dropDefault } from "./postgres-migration-BsHJHV9O.mjs";
|
|
2
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
3
|
+
import { LiteralExpr, createCodecRegistry } from "@prisma-next/sql-relational-core/ast";
|
|
4
|
+
import { errorDataTransformContractMismatch, placeholder } from "@prisma-next/errors/migration";
|
|
5
|
+
import { lowerSqlPlan } from "@prisma-next/sql-runtime";
|
|
6
|
+
|
|
7
|
+
//#region ../../6-adapters/postgres/dist/adapter-Du9Hr9Rl.mjs
|
|
8
|
+
const VECTOR_CODEC_ID = "pg/vector@1";
|
|
9
|
+
function getCodecParamCast(codecId) {
|
|
10
|
+
if (codecId === VECTOR_CODEC_ID) return "vector";
|
|
11
|
+
if (codecId === PG_JSON_CODEC_ID) return "json";
|
|
12
|
+
if (codecId === PG_JSONB_CODEC_ID) return "jsonb";
|
|
13
|
+
}
|
|
14
|
+
function renderTypedParam(index, codecId) {
|
|
15
|
+
const cast = getCodecParamCast(codecId);
|
|
16
|
+
return cast ? `$${index}::${cast}` : `$${index}`;
|
|
17
|
+
}
|
|
18
|
+
const defaultCapabilities = Object.freeze({
|
|
19
|
+
postgres: {
|
|
20
|
+
orderBy: true,
|
|
21
|
+
limit: true,
|
|
22
|
+
lateral: true,
|
|
23
|
+
jsonAgg: true,
|
|
24
|
+
returning: true
|
|
25
|
+
},
|
|
26
|
+
sql: {
|
|
27
|
+
enums: true,
|
|
28
|
+
returning: true,
|
|
29
|
+
defaultInInsert: true
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const parameterizedCodecs = Object.values(codecDefinitions).map((definition) => definition.codec).filter((codec$1) => codec$1.paramsSchema !== void 0).map((codec$1) => Object.freeze({
|
|
33
|
+
codecId: codec$1.id,
|
|
34
|
+
paramsSchema: codec$1.paramsSchema,
|
|
35
|
+
...ifDefined("init", codec$1.init)
|
|
36
|
+
}));
|
|
37
|
+
var PostgresAdapterImpl = class {
|
|
38
|
+
familyId = "sql";
|
|
39
|
+
targetId = "postgres";
|
|
40
|
+
profile;
|
|
41
|
+
codecRegistry = (() => {
|
|
42
|
+
const registry = createCodecRegistry();
|
|
43
|
+
for (const definition of Object.values(codecDefinitions)) registry.register(definition.codec);
|
|
44
|
+
return registry;
|
|
45
|
+
})();
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.profile = Object.freeze({
|
|
48
|
+
id: options?.profileId ?? "postgres/default@1",
|
|
49
|
+
target: "postgres",
|
|
50
|
+
capabilities: defaultCapabilities,
|
|
51
|
+
codecs: () => this.codecRegistry,
|
|
52
|
+
readMarkerStatement: () => ({
|
|
53
|
+
sql: "select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta from prisma_contract.marker where id = $1",
|
|
54
|
+
params: [1]
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
parameterizedCodecs() {
|
|
59
|
+
return parameterizedCodecs;
|
|
60
|
+
}
|
|
61
|
+
lower(ast, context) {
|
|
62
|
+
const collectedParamRefs = ast.collectParamRefs();
|
|
63
|
+
const paramIndexMap = /* @__PURE__ */ new Map();
|
|
64
|
+
const params = [];
|
|
65
|
+
for (const ref of collectedParamRefs) {
|
|
66
|
+
if (paramIndexMap.has(ref)) continue;
|
|
67
|
+
paramIndexMap.set(ref, params.length + 1);
|
|
68
|
+
params.push(ref.value);
|
|
69
|
+
}
|
|
70
|
+
let sql;
|
|
71
|
+
const node = ast;
|
|
72
|
+
switch (node.kind) {
|
|
73
|
+
case "select":
|
|
74
|
+
sql = renderSelect(node, context.contract, paramIndexMap);
|
|
75
|
+
break;
|
|
76
|
+
case "insert":
|
|
77
|
+
sql = renderInsert(node, context.contract, paramIndexMap);
|
|
78
|
+
break;
|
|
79
|
+
case "update":
|
|
80
|
+
sql = renderUpdate(node, context.contract, paramIndexMap);
|
|
81
|
+
break;
|
|
82
|
+
case "delete":
|
|
83
|
+
sql = renderDelete(node, context.contract, paramIndexMap);
|
|
84
|
+
break;
|
|
85
|
+
default: throw new Error(`Unsupported AST node kind: ${node.kind}`);
|
|
86
|
+
}
|
|
87
|
+
return Object.freeze({
|
|
88
|
+
profileId: this.profile.id,
|
|
89
|
+
body: Object.freeze({
|
|
90
|
+
sql,
|
|
91
|
+
params
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
function renderSelect(ast, contract, pim) {
|
|
97
|
+
return [
|
|
98
|
+
`SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(ast.projection, contract, pim)}`,
|
|
99
|
+
`FROM ${renderSource(ast.from, contract, pim)}`,
|
|
100
|
+
ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "",
|
|
101
|
+
ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "",
|
|
102
|
+
ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "",
|
|
103
|
+
ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "",
|
|
104
|
+
ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => {
|
|
105
|
+
return `${renderExpr(order.expr, contract, pim)} ${order.dir.toUpperCase()}`;
|
|
106
|
+
}).join(", ")}` : "",
|
|
107
|
+
typeof ast.limit === "number" ? `LIMIT ${ast.limit}` : "",
|
|
108
|
+
typeof ast.offset === "number" ? `OFFSET ${ast.offset}` : ""
|
|
109
|
+
].filter((part) => part.length > 0).join(" ").trim();
|
|
110
|
+
}
|
|
111
|
+
function renderProjection(projection, contract, pim) {
|
|
112
|
+
return projection.map((item) => {
|
|
113
|
+
const alias = quoteIdentifier(item.alias);
|
|
114
|
+
if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${alias}`;
|
|
115
|
+
return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;
|
|
116
|
+
}).join(", ");
|
|
117
|
+
}
|
|
118
|
+
function renderDistinctPrefix(distinct, distinctOn, contract, pim) {
|
|
119
|
+
if (distinctOn && distinctOn.length > 0) return `DISTINCT ON (${distinctOn.map((expr) => renderExpr(expr, contract, pim)).join(", ")}) `;
|
|
120
|
+
if (distinct) return "DISTINCT ";
|
|
121
|
+
return "";
|
|
122
|
+
}
|
|
123
|
+
function renderSource(source, contract, pim) {
|
|
124
|
+
const node = source;
|
|
125
|
+
switch (node.kind) {
|
|
126
|
+
case "table-source": {
|
|
127
|
+
const table = quoteIdentifier(node.name);
|
|
128
|
+
if (!node.alias) return table;
|
|
129
|
+
return `${table} AS ${quoteIdentifier(node.alias)}`;
|
|
130
|
+
}
|
|
131
|
+
case "derived-table-source": return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;
|
|
132
|
+
default: throw new Error(`Unsupported source node kind: ${node.kind}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function assertScalarSubquery(query) {
|
|
136
|
+
if (query.projection.length !== 1) throw new Error("Subquery expressions must project exactly one column");
|
|
137
|
+
}
|
|
138
|
+
function renderSubqueryExpr(expr, contract, pim) {
|
|
139
|
+
assertScalarSubquery(expr.query);
|
|
140
|
+
return `(${renderSelect(expr.query, contract, pim)})`;
|
|
141
|
+
}
|
|
142
|
+
function renderWhere(expr, contract, pim) {
|
|
143
|
+
return renderExpr(expr, contract, pim);
|
|
144
|
+
}
|
|
145
|
+
function renderNullCheck(expr, contract, pim) {
|
|
146
|
+
const rendered = renderExpr(expr.expr, contract, pim);
|
|
147
|
+
const renderedExpr = expr.expr.kind === "operation" || expr.expr.kind === "subquery" ? `(${rendered})` : rendered;
|
|
148
|
+
return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;
|
|
149
|
+
}
|
|
150
|
+
function renderBinary(expr, contract, pim) {
|
|
151
|
+
if (expr.right.kind === "list" && expr.right.values.length === 0) {
|
|
152
|
+
if (expr.op === "in") return "FALSE";
|
|
153
|
+
if (expr.op === "notIn") return "TRUE";
|
|
154
|
+
}
|
|
155
|
+
const leftExpr = expr.left;
|
|
156
|
+
const left = renderExpr(leftExpr, contract, pim);
|
|
157
|
+
const leftRendered = leftExpr.kind === "operation" || leftExpr.kind === "subquery" ? `(${left})` : left;
|
|
158
|
+
const rightNode = expr.right;
|
|
159
|
+
let right;
|
|
160
|
+
switch (rightNode.kind) {
|
|
161
|
+
case "list":
|
|
162
|
+
right = renderListLiteral(rightNode, pim);
|
|
163
|
+
break;
|
|
164
|
+
case "literal":
|
|
165
|
+
right = renderLiteral(rightNode);
|
|
166
|
+
break;
|
|
167
|
+
case "column-ref":
|
|
168
|
+
right = renderColumn(rightNode);
|
|
169
|
+
break;
|
|
170
|
+
case "param-ref":
|
|
171
|
+
right = renderParamRef(rightNode, pim);
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
right = renderExpr(rightNode, contract, pim);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
return `${leftRendered} ${{
|
|
178
|
+
eq: "=",
|
|
179
|
+
neq: "!=",
|
|
180
|
+
gt: ">",
|
|
181
|
+
lt: "<",
|
|
182
|
+
gte: ">=",
|
|
183
|
+
lte: "<=",
|
|
184
|
+
like: "LIKE",
|
|
185
|
+
in: "IN",
|
|
186
|
+
notIn: "NOT IN"
|
|
187
|
+
}[expr.op]} ${right}`;
|
|
188
|
+
}
|
|
189
|
+
function renderListLiteral(expr, pim) {
|
|
190
|
+
if (expr.values.length === 0) return "(NULL)";
|
|
191
|
+
return `(${expr.values.map((v) => {
|
|
192
|
+
if (v.kind === "param-ref") return renderParamRef(v, pim);
|
|
193
|
+
if (v.kind === "literal") return renderLiteral(v);
|
|
194
|
+
return renderExpr(v, void 0, pim);
|
|
195
|
+
}).join(", ")})`;
|
|
196
|
+
}
|
|
197
|
+
function renderColumn(ref) {
|
|
198
|
+
if (ref.table === "excluded") return `excluded.${quoteIdentifier(ref.column)}`;
|
|
199
|
+
return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;
|
|
200
|
+
}
|
|
201
|
+
function renderAggregateExpr(expr, contract, pim) {
|
|
202
|
+
const fn = expr.fn.toUpperCase();
|
|
203
|
+
if (!expr.expr) return `${fn}(*)`;
|
|
204
|
+
return `${fn}(${renderExpr(expr.expr, contract, pim)})`;
|
|
205
|
+
}
|
|
206
|
+
function renderJsonObjectExpr(expr, contract, pim) {
|
|
207
|
+
return `json_build_object(${expr.entries.flatMap((entry) => {
|
|
208
|
+
const key = `'${escapeLiteral(entry.key)}'`;
|
|
209
|
+
if (entry.value.kind === "literal") return [key, renderLiteral(entry.value)];
|
|
210
|
+
return [key, renderExpr(entry.value, contract, pim)];
|
|
211
|
+
}).join(", ")})`;
|
|
212
|
+
}
|
|
213
|
+
function renderOrderByItems(items, contract, pim) {
|
|
214
|
+
return items.map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`).join(", ");
|
|
215
|
+
}
|
|
216
|
+
function renderJsonArrayAggExpr(expr, contract, pim) {
|
|
217
|
+
const aggregateOrderBy = expr.orderBy && expr.orderBy.length > 0 ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : "";
|
|
218
|
+
const aggregated = `json_agg(${renderExpr(expr.expr, contract, pim)}${aggregateOrderBy})`;
|
|
219
|
+
if (expr.onEmpty === "emptyArray") return `coalesce(${aggregated}, json_build_array())`;
|
|
220
|
+
return aggregated;
|
|
221
|
+
}
|
|
222
|
+
function renderExpr(expr, contract, pim) {
|
|
223
|
+
const node = expr;
|
|
224
|
+
switch (node.kind) {
|
|
225
|
+
case "column-ref": return renderColumn(node);
|
|
226
|
+
case "identifier-ref": return quoteIdentifier(node.name);
|
|
227
|
+
case "operation": return renderOperation(node, contract, pim);
|
|
228
|
+
case "subquery": return renderSubqueryExpr(node, contract, pim);
|
|
229
|
+
case "aggregate": return renderAggregateExpr(node, contract, pim);
|
|
230
|
+
case "json-object": return renderJsonObjectExpr(node, contract, pim);
|
|
231
|
+
case "json-array-agg": return renderJsonArrayAggExpr(node, contract, pim);
|
|
232
|
+
case "binary": return renderBinary(node, contract, pim);
|
|
233
|
+
case "and":
|
|
234
|
+
if (node.exprs.length === 0) return "TRUE";
|
|
235
|
+
return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" AND ")})`;
|
|
236
|
+
case "or":
|
|
237
|
+
if (node.exprs.length === 0) return "FALSE";
|
|
238
|
+
return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" OR ")})`;
|
|
239
|
+
case "exists": return `${node.notExists ? "NOT " : ""}EXISTS (${renderSelect(node.subquery, contract, pim)})`;
|
|
240
|
+
case "null-check": return renderNullCheck(node, contract, pim);
|
|
241
|
+
case "not": return `NOT (${renderExpr(node.expr, contract, pim)})`;
|
|
242
|
+
case "param-ref": return renderParamRef(node, pim);
|
|
243
|
+
case "literal": return renderLiteral(node);
|
|
244
|
+
case "list": return renderListLiteral(node, pim);
|
|
245
|
+
default: throw new Error(`Unsupported expression node kind: ${node.kind}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function renderParamRef(ref, pim) {
|
|
249
|
+
const index = pim?.get(ref);
|
|
250
|
+
if (index === void 0) throw new Error("ParamRef not found in index map");
|
|
251
|
+
return renderTypedParam(index, ref.codecId);
|
|
252
|
+
}
|
|
253
|
+
function renderLiteral(expr) {
|
|
254
|
+
if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
|
|
255
|
+
if (typeof expr.value === "number" || typeof expr.value === "boolean") return String(expr.value);
|
|
256
|
+
if (typeof expr.value === "bigint") return String(expr.value);
|
|
257
|
+
if (expr.value === null) return "NULL";
|
|
258
|
+
if (expr.value === void 0) return "NULL";
|
|
259
|
+
if (expr.value instanceof Date) return `'${escapeLiteral(expr.value.toISOString())}'`;
|
|
260
|
+
if (Array.isArray(expr.value)) return `ARRAY[${expr.value.map((v) => renderLiteral(new LiteralExpr(v))).join(", ")}]`;
|
|
261
|
+
const json = JSON.stringify(expr.value);
|
|
262
|
+
if (json === void 0) return "NULL";
|
|
263
|
+
return `'${escapeLiteral(json)}'`;
|
|
264
|
+
}
|
|
265
|
+
function renderOperation(expr, contract, pim) {
|
|
266
|
+
const self = renderExpr(expr.self, contract, pim);
|
|
267
|
+
const args = expr.args.map((arg) => {
|
|
268
|
+
return renderExpr(arg, contract, pim);
|
|
269
|
+
});
|
|
270
|
+
let result = expr.lowering.template;
|
|
271
|
+
result = result.replace(/\{\{self\}\}/g, self);
|
|
272
|
+
for (let i = 0; i < args.length; i++) result = result.replace(new RegExp(`\\{\\{arg${i}\\}\\}`, "g"), args[i] ?? "");
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
function renderJoin(join, contract, pim) {
|
|
276
|
+
return `${join.joinType.toUpperCase()} JOIN ${join.lateral ? "LATERAL " : ""}${renderSource(join.source, contract, pim)} ON ${renderJoinOn(join.on, contract, pim)}`;
|
|
277
|
+
}
|
|
278
|
+
function renderJoinOn(on, contract, pim) {
|
|
279
|
+
if (on.kind === "eq-col-join-on") return `${renderColumn(on.left)} = ${renderColumn(on.right)}`;
|
|
280
|
+
return renderWhere(on, contract, pim);
|
|
281
|
+
}
|
|
282
|
+
function getInsertColumnOrder(rows, contract, tableName) {
|
|
283
|
+
const orderedColumns = [];
|
|
284
|
+
const seenColumns = /* @__PURE__ */ new Set();
|
|
285
|
+
for (const row of rows) for (const column of Object.keys(row)) {
|
|
286
|
+
if (seenColumns.has(column)) continue;
|
|
287
|
+
seenColumns.add(column);
|
|
288
|
+
orderedColumns.push(column);
|
|
289
|
+
}
|
|
290
|
+
if (orderedColumns.length > 0) return orderedColumns;
|
|
291
|
+
return Object.keys(contract.storage.tables[tableName]?.columns ?? {});
|
|
292
|
+
}
|
|
293
|
+
function renderInsertValue(value, pim) {
|
|
294
|
+
if (!value || value.kind === "default-value") return "DEFAULT";
|
|
295
|
+
switch (value.kind) {
|
|
296
|
+
case "param-ref": return renderParamRef(value, pim);
|
|
297
|
+
case "column-ref": return renderColumn(value);
|
|
298
|
+
default: throw new Error(`Unsupported value node in INSERT: ${value.kind}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function renderInsert(ast, contract, pim) {
|
|
302
|
+
const table = quoteIdentifier(ast.table.name);
|
|
303
|
+
const rows = ast.rows;
|
|
304
|
+
if (rows.length === 0) throw new Error("INSERT requires at least one row");
|
|
305
|
+
const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
|
|
306
|
+
return `${(() => {
|
|
307
|
+
if (!hasExplicitValues) {
|
|
308
|
+
if (rows.length === 1) return `INSERT INTO ${table} DEFAULT VALUES`;
|
|
309
|
+
const defaultColumns = getInsertColumnOrder(rows, contract, ast.table.name);
|
|
310
|
+
if (defaultColumns.length === 0) return `INSERT INTO ${table} VALUES ${rows.map(() => "()").join(", ")}`;
|
|
311
|
+
const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));
|
|
312
|
+
const defaultRow = `(${defaultColumns.map(() => "DEFAULT").join(", ")})`;
|
|
313
|
+
return `INSERT INTO ${table} (${quotedColumns.join(", ")}) VALUES ${rows.map(() => defaultRow).join(", ")}`;
|
|
314
|
+
}
|
|
315
|
+
const columnOrder = getInsertColumnOrder(rows, contract, ast.table.name);
|
|
316
|
+
const columns = columnOrder.map((column) => quoteIdentifier(column));
|
|
317
|
+
const values = rows.map((row) => {
|
|
318
|
+
return `(${columnOrder.map((column) => renderInsertValue(row[column], pim)).join(", ")})`;
|
|
319
|
+
}).join(", ");
|
|
320
|
+
return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
|
|
321
|
+
})()}${ast.onConflict ? (() => {
|
|
322
|
+
const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
|
|
323
|
+
if (conflictColumns.length === 0) throw new Error("INSERT onConflict requires at least one conflict column");
|
|
324
|
+
const action = ast.onConflict.action;
|
|
325
|
+
switch (action.kind) {
|
|
326
|
+
case "do-nothing": return ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
|
|
327
|
+
case "do-update-set": {
|
|
328
|
+
const updates = Object.entries(action.set).map(([colName, value]) => {
|
|
329
|
+
const target = quoteIdentifier(colName);
|
|
330
|
+
if (value.kind === "param-ref") return `${target} = ${renderParamRef(value, pim)}`;
|
|
331
|
+
return `${target} = ${renderColumn(value)}`;
|
|
332
|
+
});
|
|
333
|
+
return ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
|
|
334
|
+
}
|
|
335
|
+
default: throw new Error(`Unsupported onConflict action: ${action.kind}`);
|
|
336
|
+
}
|
|
337
|
+
})() : ""}${ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : ""}`;
|
|
338
|
+
}
|
|
339
|
+
function renderUpdate(ast, contract, pim) {
|
|
340
|
+
const table = quoteIdentifier(ast.table.name);
|
|
341
|
+
const setClauses = Object.entries(ast.set).map(([col, val]) => {
|
|
342
|
+
const column = quoteIdentifier(col);
|
|
343
|
+
let value;
|
|
344
|
+
switch (val.kind) {
|
|
345
|
+
case "param-ref":
|
|
346
|
+
value = renderParamRef(val, pim);
|
|
347
|
+
break;
|
|
348
|
+
case "column-ref":
|
|
349
|
+
value = renderColumn(val);
|
|
350
|
+
break;
|
|
351
|
+
default: throw new Error(`Unsupported value node in UPDATE: ${val.kind}`);
|
|
352
|
+
}
|
|
353
|
+
return `${column} = ${value}`;
|
|
354
|
+
});
|
|
355
|
+
const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : "";
|
|
356
|
+
const returningClause = ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : "";
|
|
357
|
+
return `UPDATE ${table} SET ${setClauses.join(", ")}${whereClause}${returningClause}`;
|
|
358
|
+
}
|
|
359
|
+
function renderDelete(ast, contract, pim) {
|
|
360
|
+
return `DELETE FROM ${quoteIdentifier(ast.table.name)}${ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : ""}${ast.returning?.length ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(", ")}` : ""}`;
|
|
361
|
+
}
|
|
362
|
+
function createPostgresAdapter(options) {
|
|
363
|
+
return Object.freeze(new PostgresAdapterImpl(options));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region src/core/migrations/operations/data-transform.ts
|
|
368
|
+
/**
|
|
369
|
+
* User-facing `dataTransform` factory for the Postgres migration authoring
|
|
370
|
+
* surface. Invoked directly inside a `migration.ts` file:
|
|
371
|
+
*
|
|
372
|
+
* ```ts
|
|
373
|
+
* import endContract from './end-contract.json' with { type: 'json' };
|
|
374
|
+
* import { dataTransform } from '@prisma-next/target-postgres/migration';
|
|
375
|
+
*
|
|
376
|
+
* dataTransform(endContract, 'backfill emails', {
|
|
377
|
+
* check: () => db.users.count().where(({ email }) => email.isNull()),
|
|
378
|
+
* run: () => db.users.update({ email: '' }).where(({ email }) => email.isNull()),
|
|
379
|
+
* });
|
|
380
|
+
* ```
|
|
381
|
+
*
|
|
382
|
+
* The factory accepts lazy closures (`() => SqlQueryPlan | Buildable`),
|
|
383
|
+
* invokes each one, asserts that its `meta.storageHash` matches the
|
|
384
|
+
* `contract` it was handed (→ `PN-MIG-2005` on mismatch), and lowers the
|
|
385
|
+
* plan via the Postgres adapter to a serialized `{sql, params}` payload
|
|
386
|
+
* for `ops.json`.
|
|
387
|
+
*/
|
|
388
|
+
/** Single shared adapter for apply/CLI; sufficient for single-threaded migration execution. */
|
|
389
|
+
let adapterSingleton = null;
|
|
390
|
+
function getAdapter() {
|
|
391
|
+
if (adapterSingleton === null) adapterSingleton = createPostgresAdapter();
|
|
392
|
+
return adapterSingleton;
|
|
393
|
+
}
|
|
394
|
+
function dataTransform(contract, name, options) {
|
|
395
|
+
const adapter = getAdapter();
|
|
396
|
+
const runClosures = Array.isArray(options.run) ? options.run : [options.run];
|
|
397
|
+
return {
|
|
398
|
+
id: `data_migration.${name}`,
|
|
399
|
+
label: `Data transform: ${name}`,
|
|
400
|
+
operationClass: "data",
|
|
401
|
+
name,
|
|
402
|
+
source: "migration.ts",
|
|
403
|
+
check: options.check ? invokeAndLower(options.check, contract, adapter, name) : null,
|
|
404
|
+
run: runClosures.map((closure) => invokeAndLower(closure, contract, adapter, name))
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function invokeAndLower(closure, contract, adapter, name) {
|
|
408
|
+
const result = closure();
|
|
409
|
+
const plan = isBuildable(result) ? result.build() : result;
|
|
410
|
+
assertContractMatches(plan, contract, name);
|
|
411
|
+
const lowered = lowerSqlPlan(adapter, contract, plan);
|
|
412
|
+
return {
|
|
413
|
+
sql: lowered.sql,
|
|
414
|
+
params: lowered.params
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function isBuildable(value) {
|
|
418
|
+
return typeof value === "object" && value !== null && "build" in value && typeof value.build === "function";
|
|
419
|
+
}
|
|
420
|
+
function assertContractMatches(plan, contract, name) {
|
|
421
|
+
if (plan.meta.storageHash !== contract.storage.storageHash) throw errorDataTransformContractMismatch({
|
|
422
|
+
dataTransformName: name,
|
|
423
|
+
expected: contract.storage.storageHash,
|
|
424
|
+
actual: plan.meta.storageHash
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/core/migrations/operations/raw.ts
|
|
430
|
+
/**
|
|
431
|
+
* Identity factory for an already-materialized `SqlMigrationPlanOperation`.
|
|
432
|
+
*
|
|
433
|
+
* The planner uses this via `liftOpToCall` to carry ops produced by SQL
|
|
434
|
+
* family methods, codec control hooks, and component database dependencies
|
|
435
|
+
* alongside migration IR without reverse-engineering them. Users writing
|
|
436
|
+
* raw migrations can pass a full op shape directly — typically built by
|
|
437
|
+
* composing SQL family helpers — to author a migration that bypasses the
|
|
438
|
+
* structured call classes.
|
|
439
|
+
*/
|
|
440
|
+
function rawSql(op) {
|
|
441
|
+
return op;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
//#endregion
|
|
445
|
+
export { PostgresMigration as Migration, addColumn, addEnumValues, addForeignKey, addPrimaryKey, addUnique, alterColumnType, createEnumType, createExtension, createIndex, createSchema, createTable, dataTransform, dropColumn, dropConstraint, dropDefault, dropEnumType, dropIndex, dropNotNull, dropTable, placeholder, rawSql, renameType, setDefault, setNotNull };
|
|
446
|
+
//# sourceMappingURL=migration.mjs.map
|