@prisma/orm-target-sqlite 8.0.0-rc.19 → 8.0.0-rc.19-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.
- package/dist/{adapter-DtwSwFvA.d.mts → adapter-rNrGhNM6.d.mts} +6 -6
- package/dist/{adapter-DtwSwFvA.d.mts.map → adapter-rNrGhNM6.d.mts.map} +1 -1
- package/dist/adapter.d.mts +1 -1
- package/dist/adapter__adapter.d.mts +1 -1
- package/dist/adapter__control.mjs +1 -5
- package/dist/adapter__control.mjs.map +1 -1
- package/dist/{aggregates-DD6XxtyA.d.mts → aggregates-C91ltL9M.d.mts} +6 -6
- package/dist/{aggregates-DD6XxtyA.d.mts.map → aggregates-C91ltL9M.d.mts.map} +1 -1
- package/dist/{control-BY0lE0MI.d.mts → control-CqSlwRpm.d.mts} +4 -4
- package/dist/{control-BY0lE0MI.d.mts.map → control-CqSlwRpm.d.mts.map} +1 -1
- package/dist/descriptor-meta-BWlR2rDN-Y8Y4_jie.mjs +109 -0
- package/dist/descriptor-meta-BWlR2rDN-Y8Y4_jie.mjs.map +1 -0
- package/dist/{migration-DLJQnUxF.d.mts → migration-p83G5mtQ.d.mts} +3 -3
- package/dist/{migration-DLJQnUxF.d.mts.map → migration-p83G5mtQ.d.mts.map} +1 -1
- package/dist/{op-factory-call-DAI1NqNz.d.mts → op-factory-call-CnufFdpE.d.mts} +2 -2
- package/dist/{op-factory-call-DAI1NqNz.d.mts.map → op-factory-call-CnufFdpE.d.mts.map} +1 -1
- package/dist/{pack-DVMuQib7.d.mts → pack-D09sgwDC.d.mts} +92 -4
- package/dist/{pack-DVMuQib7.d.mts.map → pack-D09sgwDC.d.mts.map} +1 -1
- package/dist/{planner-D65FzuZZ.d.mts → planner-ChwhExQU.d.mts} +2 -2
- package/dist/{planner-D65FzuZZ.d.mts.map → planner-ChwhExQU.d.mts.map} +1 -1
- package/dist/planner-produced-sqlite-migration-D0aHh8Z9.d.mts +1 -0
- package/dist/{planner-produced-sqlite-migration-CkHb8T4n-DD8b29qz.d.mts → planner-produced-sqlite-migration-DuM9c3YI-COeeqS8N.d.mts} +3 -3
- package/dist/planner-produced-sqlite-migration-DuM9c3YI-COeeqS8N.d.mts.map +1 -0
- package/dist/{sqlite-migration-BqbQmUY1-CdxaTXni.d.mts → sqlite-migration-CLIMaHLy-BQ6vv7gq.d.mts} +3 -3
- package/dist/{sqlite-migration-BqbQmUY1-CdxaTXni.d.mts.map → sqlite-migration-CLIMaHLy-BQ6vv7gq.d.mts.map} +1 -1
- package/dist/{tables-DD_EmImp-B8ZaVBMr.d.mts → tables-C6oejIsc-BgxW5wBn.d.mts} +3 -3
- package/dist/{tables-DD_EmImp-B8ZaVBMr.d.mts.map → tables-C6oejIsc-BgxW5wBn.d.mts.map} +1 -1
- package/dist/target.d.mts +10 -10
- package/dist/target.mjs +2 -2
- package/dist/target__aggregates.d.mts +1 -1
- package/dist/target__control.d.mts +2 -2
- package/dist/target__control.mjs +522 -3
- package/dist/target__control.mjs.map +1 -0
- package/dist/target__migration.d.mts +2 -2
- package/dist/target__op-factory-call.d.mts +1 -1
- package/dist/target__pack.d.mts +1 -1
- package/dist/target__pack.mjs +1 -1
- package/dist/target__planner-produced-sqlite-migration.d.mts +2 -2
- package/dist/target__planner.d.mts +1 -1
- package/package.json +9 -9
- package/dist/control-Oq9sp9Tq.mjs +0 -574
- package/dist/control-Oq9sp9Tq.mjs.map +0 -1
- package/dist/descriptor-meta-B9drv0U6-DoV55ut2.mjs +0 -54
- package/dist/descriptor-meta-B9drv0U6-DoV55ut2.mjs.map +0 -1
- package/dist/planner-produced-sqlite-migration-AnV25lXu.d.mts +0 -1
- package/dist/planner-produced-sqlite-migration-CkHb8T4n-DD8b29qz.d.mts.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/orm-target-sqlite",
|
|
3
|
-
"version": "8.0.0-rc.19",
|
|
3
|
+
"version": "8.0.0-rc.19-dev.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -9,19 +9,19 @@
|
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@prisma/orm-family-sql": "8.0.0-rc.19",
|
|
13
|
-
"@prisma/orm-framework": "8.0.0-rc.19",
|
|
14
|
-
"@prisma/orm-toolchain": "8.0.0-rc.19",
|
|
12
|
+
"@prisma/orm-family-sql": "8.0.0-rc.19-dev.2",
|
|
13
|
+
"@prisma/orm-framework": "8.0.0-rc.19-dev.2",
|
|
14
|
+
"@prisma/orm-toolchain": "8.0.0-rc.19-dev.2",
|
|
15
15
|
"@standard-schema/spec": "1.1.0",
|
|
16
16
|
"arktype": "^2.2.2",
|
|
17
17
|
"pathe": "^2.0.3"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@internal/adapter-sqlite": "8.0.0-rc.19",
|
|
21
|
-
"@internal/driver-sqlite": "8.0.0-rc.19",
|
|
22
|
-
"@internal/target-sqlite": "8.0.0-rc.19",
|
|
23
|
-
"@repo/tsconfig": "8.0.0-rc.19",
|
|
24
|
-
"@repo/tsdown": "8.0.0-rc.19",
|
|
20
|
+
"@internal/adapter-sqlite": "8.0.0-rc.19-dev.2",
|
|
21
|
+
"@internal/driver-sqlite": "8.0.0-rc.19-dev.2",
|
|
22
|
+
"@internal/target-sqlite": "8.0.0-rc.19-dev.2",
|
|
23
|
+
"@repo/tsconfig": "8.0.0-rc.19-dev.2",
|
|
24
|
+
"@repo/tsdown": "8.0.0-rc.19-dev.2",
|
|
25
25
|
"tsdown": "0.22.14",
|
|
26
26
|
"typescript": "5.9.3"
|
|
27
27
|
},
|
|
@@ -1,574 +0,0 @@
|
|
|
1
|
-
import { a as SQLITE_INTEGER_CODEC_ID, c as SQLITE_TEXT_CODEC_ID, i as SQLITE_DATETIME_CODEC_ID, o as SQLITE_JSON_CODEC_ID, r as SQLITE_BLOB_CODEC_ID, s as SQLITE_REAL_CODEC_ID, t as SQLITE_BIGINT_CODEC_ID } from "./codec-ids-wgEvkCkg-8bxcCujY.mjs";
|
|
2
|
-
import { n as sqliteError } from "./errors-DnR-sMHS-KkMLIP2U.mjs";
|
|
3
|
-
import { t as sqliteTargetDescriptorMeta } from "./descriptor-meta-B9drv0U6-DoV55ut2.mjs";
|
|
4
|
-
import { r as quoteIdentifier } from "./sql-utils-XGT5Esi2-5k9pvJeF.mjs";
|
|
5
|
-
import { g as conversionCopyOf, p as affinityStorageClasses, y as rebuiltTableName } from "./op-factory-call-Dzsgcf3B-B7IaqEjE.mjs";
|
|
6
|
-
import { t as SqliteContractSerializer } from "./sqlite-contract-view-CJ895eER-n57Mabt2.mjs";
|
|
7
|
-
import { b as verifySqliteDatabaseSchema, h as sqliteContractToSchema, o as diffSqliteSchema } from "./sqlite-migration-B7LD9iDG-BTpw_zNF.mjs";
|
|
8
|
-
import { n as createSqliteMigrationPlanner } from "./planner-DD8nGrZ_-BcGCsYVP.mjs";
|
|
9
|
-
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
10
|
-
import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
11
|
-
import { InternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
12
|
-
import { APP_SPACE_ID, failedPrecheckWhy, schemaCheckWhy, withFailingSpace } from "@prisma/orm-framework/components/control";
|
|
13
|
-
import { convertedColumnOf, fieldOfColumn, requiredColumnsOfMigration, rowsWithoutValueFailure, runnerFailure, runnerSuccess, sqlTypeLookupsOf, unconvertedFieldOf } from "@prisma/orm-family-sql/family/control";
|
|
14
|
-
import { relationalNodeEntityKind, relationalNodeGranularity } from "@prisma/orm-family-sql/schema-ir/types";
|
|
15
|
-
import { SqlStorage } from "@prisma/orm-family-sql/contract/types";
|
|
16
|
-
import { SqlSchemaVerifierBase } from "@prisma/orm-family-sql/family/ir";
|
|
17
|
-
import { notOk, ok, okVoid } from "@prisma/orm-framework/utils/result";
|
|
18
|
-
import { SqlQueryError } from "@prisma/orm-family-sql/errors";
|
|
19
|
-
//#region ../../../3-targets/3-targets/sqlite/dist/control.mjs
|
|
20
|
-
const NOT_NULL_VIOLATION_SQLSTATE = "23502";
|
|
21
|
-
function createSqliteMigrationRunner(family) {
|
|
22
|
-
return new SqliteMigrationRunner(family);
|
|
23
|
-
}
|
|
24
|
-
var SqliteMigrationRunner = class {
|
|
25
|
-
family;
|
|
26
|
-
constructor(family) {
|
|
27
|
-
this.family = family;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Apply the plan against an already-open connection without managing
|
|
31
|
-
* the transaction lifecycle. The caller ({@link SqliteMigrationRunner.execute})
|
|
32
|
-
* owns BEGIN/COMMIT/ROLLBACK and any connection-level setup (FK pragma
|
|
33
|
-
* toggle, FK integrity check).
|
|
34
|
-
*/
|
|
35
|
-
async executeOnConnection(options) {
|
|
36
|
-
const driver = options.driver;
|
|
37
|
-
if (options.space !== void 0 && options.space !== options.plan.spaceId) throw sqliteError("MIGRATION.CONTRACT_SPACE_VIOLATION", `SqlMigrationRunner: options.space (${options.space}) does not match plan.spaceId (${options.plan.spaceId})`, { meta: {
|
|
38
|
-
space: options.space,
|
|
39
|
-
planSpaceId: options.plan.spaceId
|
|
40
|
-
} });
|
|
41
|
-
const space = options.plan.spaceId;
|
|
42
|
-
const planOps = blindCast(await Promise.all(options.plan.operations));
|
|
43
|
-
const destinationCheck = this.ensurePlanMatchesDestinationContract(options.plan.destination, options.destinationContract);
|
|
44
|
-
if (!destinationCheck.ok) return destinationCheck;
|
|
45
|
-
const policyCheck = this.enforcePolicyCompatibility(options.policy, planOps);
|
|
46
|
-
if (!policyCheck.ok) return policyCheck;
|
|
47
|
-
const ensureResult = await this.ensureControlTables(driver, options.destinationContract);
|
|
48
|
-
if (!ensureResult.ok) return ensureResult;
|
|
49
|
-
const existingMarker = await this.family.readMarker({
|
|
50
|
-
driver,
|
|
51
|
-
space
|
|
52
|
-
});
|
|
53
|
-
const markerCheck = this.ensureMarkerCompatibility(existingMarker, options.plan);
|
|
54
|
-
if (!markerCheck.ok) return markerCheck;
|
|
55
|
-
const markerAtDestination = this.markerMatchesDestination(existingMarker, options.plan);
|
|
56
|
-
const isSelfEdge = options.plan.origin?.storageHash === options.plan.destination.storageHash;
|
|
57
|
-
const skipOperations = markerAtDestination && options.plan.origin != null && !isSelfEdge;
|
|
58
|
-
let operationsExecuted;
|
|
59
|
-
let executedOperations;
|
|
60
|
-
if (skipOperations) {
|
|
61
|
-
operationsExecuted = 0;
|
|
62
|
-
executedOperations = [];
|
|
63
|
-
} else {
|
|
64
|
-
const applyResult = await this.applyPlan(driver, options, planOps);
|
|
65
|
-
if (!applyResult.ok) return applyResult;
|
|
66
|
-
operationsExecuted = applyResult.value.operationsExecuted;
|
|
67
|
-
executedOperations = applyResult.value.executedOperations;
|
|
68
|
-
}
|
|
69
|
-
if (space === APP_SPACE_ID) {
|
|
70
|
-
const schemaNode = await this.family.introspect({
|
|
71
|
-
driver,
|
|
72
|
-
contract: options.destinationContract
|
|
73
|
-
});
|
|
74
|
-
const schemaVerifyResult = verifySqliteDatabaseSchema({
|
|
75
|
-
contract: options.destinationContract,
|
|
76
|
-
actualSchema: schemaNode,
|
|
77
|
-
strict: options.strictVerification ?? true,
|
|
78
|
-
frameworkComponents: options.frameworkComponents
|
|
79
|
-
});
|
|
80
|
-
if (!schemaVerifyResult.ok) return runnerFailure("MIGRATION.SCHEMA_VERIFY_FAILED", schemaVerifyResult.summary, {
|
|
81
|
-
why: schemaCheckWhy(schemaVerifyResult.schema.issues),
|
|
82
|
-
meta: { schemaIssues: schemaVerifyResult.schema.issues }
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
const incomingInvariants = options.plan.providedInvariants;
|
|
86
|
-
const existingInvariants = new Set(existingMarker?.invariants ?? []);
|
|
87
|
-
const incomingIsSubsetOfExisting = incomingInvariants.every((id) => existingInvariants.has(id));
|
|
88
|
-
if (!(isSelfEdge && operationsExecuted === 0 && incomingIsSubsetOfExisting)) {
|
|
89
|
-
const markerResult = await this.upsertMarker(driver, options, existingMarker, space);
|
|
90
|
-
if (!markerResult.ok) return markerResult;
|
|
91
|
-
await this.recordLedgerEntries(driver, options, executedOperations);
|
|
92
|
-
}
|
|
93
|
-
return runnerSuccess({
|
|
94
|
-
operationsPlanned: planOps.length,
|
|
95
|
-
operationsExecuted
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
async execute(options) {
|
|
99
|
-
const driver = options.driver;
|
|
100
|
-
const perSpaceOptions = options.perSpaceOptions;
|
|
101
|
-
if (perSpaceOptions.length === 0) return ok({ perSpaceResults: [] });
|
|
102
|
-
const fkWasEnabled = await this.readForeignKeysEnabled(driver);
|
|
103
|
-
if (fkWasEnabled) await driver.query("PRAGMA foreign_keys = OFF");
|
|
104
|
-
try {
|
|
105
|
-
await this.beginExclusiveTransaction(driver);
|
|
106
|
-
let committed = false;
|
|
107
|
-
try {
|
|
108
|
-
const perSpaceResults = [];
|
|
109
|
-
let lastProcessedSpace;
|
|
110
|
-
for (const spaceOptions of perSpaceOptions) {
|
|
111
|
-
const space = spaceOptions.space ?? spaceOptions.plan.spaceId;
|
|
112
|
-
const result = await this.executeOnConnection({
|
|
113
|
-
...spaceOptions,
|
|
114
|
-
driver,
|
|
115
|
-
space
|
|
116
|
-
});
|
|
117
|
-
if (!result.ok) return notOk(withFailingSpace(result.failure, space));
|
|
118
|
-
perSpaceResults.push({
|
|
119
|
-
space,
|
|
120
|
-
value: result.value
|
|
121
|
-
});
|
|
122
|
-
lastProcessedSpace = space;
|
|
123
|
-
}
|
|
124
|
-
if (fkWasEnabled) {
|
|
125
|
-
const fkIntegrityCheck = await this.verifyForeignKeyIntegrity(driver);
|
|
126
|
-
if (!fkIntegrityCheck.ok) return notOk(withFailingSpace(fkIntegrityCheck.failure, lastProcessedSpace ?? APP_SPACE_ID));
|
|
127
|
-
}
|
|
128
|
-
await this.commitTransaction(driver);
|
|
129
|
-
committed = true;
|
|
130
|
-
return ok({ perSpaceResults });
|
|
131
|
-
} finally {
|
|
132
|
-
if (!committed) await this.rollbackTransaction(driver);
|
|
133
|
-
}
|
|
134
|
-
} finally {
|
|
135
|
-
if (fkWasEnabled) await driver.query("PRAGMA foreign_keys = ON");
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
async readForeignKeysEnabled(driver) {
|
|
139
|
-
return (await driver.query("PRAGMA foreign_keys")).rows[0]?.foreign_keys === 1;
|
|
140
|
-
}
|
|
141
|
-
async verifyForeignKeyIntegrity(driver) {
|
|
142
|
-
const result = await driver.query("PRAGMA foreign_key_check");
|
|
143
|
-
if (result.rows.length === 0) return okVoid();
|
|
144
|
-
return runnerFailure("MIGRATION.FOREIGN_KEY_VIOLATION", `Foreign key integrity check failed after migration: ${result.rows.length} violation(s).`, {
|
|
145
|
-
why: "PRAGMA foreign_key_check reported violations after applying recreate-table operations.",
|
|
146
|
-
meta: { violations: result.rows }
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
async applyPlan(driver, options, ops) {
|
|
150
|
-
const checks = options.executionChecks;
|
|
151
|
-
const runPrechecks = checks?.prechecks !== false;
|
|
152
|
-
const runPostchecks = checks?.postchecks !== false;
|
|
153
|
-
const runIdempotency = checks?.idempotencyChecks !== false;
|
|
154
|
-
let operationsExecuted = 0;
|
|
155
|
-
const executedOperations = [];
|
|
156
|
-
for (const operation of ops) {
|
|
157
|
-
options.callbacks?.onOperationStart?.(operation);
|
|
158
|
-
try {
|
|
159
|
-
if (runPostchecks && runIdempotency) {
|
|
160
|
-
if (await this.expectationsAreSatisfied(driver, operation.postcheck)) {
|
|
161
|
-
executedOperations.push(this.createSkipRecord(operation));
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (runPrechecks) {
|
|
166
|
-
const precheckResult = await this.runExpectationSteps(driver, operation.precheck, operation, "precheck");
|
|
167
|
-
if (!precheckResult.ok) return precheckResult;
|
|
168
|
-
}
|
|
169
|
-
const executeResult = await this.runExecuteSteps(driver, operation.execute, operation, {
|
|
170
|
-
contract: options.destinationContract,
|
|
171
|
-
operationIndex: ops.indexOf(operation),
|
|
172
|
-
operations: ops,
|
|
173
|
-
edges: options.migrationEdges
|
|
174
|
-
});
|
|
175
|
-
if (!executeResult.ok) return executeResult;
|
|
176
|
-
if (runPostchecks) {
|
|
177
|
-
const postcheckResult = await this.runExpectationSteps(driver, operation.postcheck, operation, "postcheck", {
|
|
178
|
-
contract: options.destinationContract,
|
|
179
|
-
operationIndex: ops.indexOf(operation)
|
|
180
|
-
});
|
|
181
|
-
if (!postcheckResult.ok) return postcheckResult;
|
|
182
|
-
}
|
|
183
|
-
executedOperations.push(operation);
|
|
184
|
-
operationsExecuted += 1;
|
|
185
|
-
} finally {
|
|
186
|
-
options.callbacks?.onOperationComplete?.(operation);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return ok({
|
|
190
|
-
operationsExecuted,
|
|
191
|
-
executedOperations
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
async ensureControlTables(driver, contract) {
|
|
195
|
-
const lowererContext = { contract };
|
|
196
|
-
for (const query of this.family.bootstrapControlTableQueries()) await this.executeStatement(driver, await this.family.lowerAst(query, lowererContext));
|
|
197
|
-
return okVoid();
|
|
198
|
-
}
|
|
199
|
-
async runExpectationSteps(driver, steps, operation, phase, plan) {
|
|
200
|
-
for (const step of steps) {
|
|
201
|
-
const result = await driver.query(step.sql, step.params ?? []);
|
|
202
|
-
if (!this.stepResultIsTrue(result.rows)) {
|
|
203
|
-
const code = phase === "precheck" ? "MIGRATION.PRECHECK_FAILED" : "MIGRATION.POSTCHECK_FAILED";
|
|
204
|
-
const field = plan === void 0 ? void 0 : unconvertedFieldOf(step, plan.contract);
|
|
205
|
-
const converted = convertedColumnOf(step);
|
|
206
|
-
const failedCheck = {
|
|
207
|
-
operationId: operation.id,
|
|
208
|
-
phase,
|
|
209
|
-
description: step.description
|
|
210
|
-
};
|
|
211
|
-
const unconverted = converted === void 0 ? void 0 : await this.unconvertedValueText(driver, converted);
|
|
212
|
-
return runnerFailure(code, `Operation ${operation.id} failed during ${phase}: ${step.description}`, {
|
|
213
|
-
...ifDefined("why", unconverted ?? (phase === "precheck" ? failedPrecheckWhy(failedCheck) : void 0)),
|
|
214
|
-
meta: {
|
|
215
|
-
failedCheck,
|
|
216
|
-
...ifDefined("failedTypeChange", field === void 0 || plan === void 0 || converted === void 0 ? void 0 : converted.by === "conversion" ? {
|
|
217
|
-
field,
|
|
218
|
-
by: "conversion",
|
|
219
|
-
reason: "invalidResult",
|
|
220
|
-
operationIndex: plan.operationIndex
|
|
221
|
-
} : {
|
|
222
|
-
field,
|
|
223
|
-
by: "cast",
|
|
224
|
-
reason: "value",
|
|
225
|
-
operationIndex: plan.operationIndex
|
|
226
|
-
})
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return okVoid();
|
|
232
|
-
}
|
|
233
|
-
/** Names the first value of a retyped column that kept a storage class its new type does not hold. */
|
|
234
|
-
async unconvertedValueText(driver, cast) {
|
|
235
|
-
const typeSql = (await driver.query("SELECT type FROM pragma_table_info(?) WHERE name = ?", [cast.table, cast.column])).rows[0]?.type;
|
|
236
|
-
if (typeSql === void 0) return void 0;
|
|
237
|
-
const column = quoteIdentifier(cast.column);
|
|
238
|
-
const classes = ["null", ...affinityStorageClasses(typeSql)];
|
|
239
|
-
const row = (await driver.query(`SELECT quote(${column}) AS value, typeof(${column}) AS storageClass FROM ${quoteIdentifier(cast.table)} WHERE typeof(${column}) NOT IN (${classes.map(() => "?").join(", ")}) LIMIT 1`, classes)).rows[0];
|
|
240
|
-
if (row === void 0) return void 0;
|
|
241
|
-
return `The value ${row.value.length > 40 ? `${row.value.slice(0, 40)}…` : row.value} of column "${cast.column}" on "${cast.table}" is still stored as ${row.storageClass}, which ${typeSql} cannot hold.`;
|
|
242
|
-
}
|
|
243
|
-
async runExecuteSteps(driver, steps, operation, plan) {
|
|
244
|
-
for (const step of steps) try {
|
|
245
|
-
await driver.query(step.sql, step.params ?? []);
|
|
246
|
-
} catch (error) {
|
|
247
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
248
|
-
const failed = `Operation ${operation.id} failed during execution: ${step.description}`;
|
|
249
|
-
const rowsWithoutValue = await this.rowsWithoutValue(driver, error, plan);
|
|
250
|
-
const failedConversion = rowsWithoutValue === void 0 ? await this.failedConversion(driver, step, error, plan) : void 0;
|
|
251
|
-
return runnerFailure("MIGRATION.EXECUTION_FAILED", rowsWithoutValue?.summary ?? failed, {
|
|
252
|
-
why: rowsWithoutValue === void 0 ? message : `${failed}: ${message}`,
|
|
253
|
-
meta: {
|
|
254
|
-
operationId: operation.id,
|
|
255
|
-
stepDescription: step.description,
|
|
256
|
-
sql: step.sql,
|
|
257
|
-
...ifDefined("rowsWithoutValue", rowsWithoutValue?.reports),
|
|
258
|
-
...ifDefined("failedTypeChange", failedConversion)
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
return okVoid();
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* The conversion that failed, when the failed step is the copy of a rebuild that converts columns
|
|
266
|
-
* and there is evidence for it: a copy expression that fails on its own has an error in its
|
|
267
|
-
* expression, and a constraint of the new table that names a converted column was broken by a
|
|
268
|
-
* value the conversion produced. Any other failure of the copy is not the conversion's.
|
|
269
|
-
*/
|
|
270
|
-
async failedConversion(driver, step, error, plan) {
|
|
271
|
-
const copy = conversionCopyOf(step);
|
|
272
|
-
if (copy === void 0) return void 0;
|
|
273
|
-
const columns = Object.keys(copy.expressions);
|
|
274
|
-
const failed = async (column) => {
|
|
275
|
-
try {
|
|
276
|
-
await driver.query(`SELECT ${copy.expressions[column]} FROM ${quoteIdentifier(copy.table)}`);
|
|
277
|
-
return false;
|
|
278
|
-
} catch {
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
for (const column of columns) if (await failed(column)) return this.conversionOf(plan, copy.table, column, "expressionError");
|
|
283
|
-
const constrainedList = SqlQueryError.is(error) ? error.constraint : void 0;
|
|
284
|
-
if (constrainedList === void 0) return void 0;
|
|
285
|
-
const constrained = new Set(constrainedList.split(", "));
|
|
286
|
-
const column = columns.find((name) => constrained.has(`${rebuiltTableName(copy.table)}.${name}`));
|
|
287
|
-
return column === void 0 ? void 0 : this.conversionOf(plan, copy.table, column, "invalidResult");
|
|
288
|
-
}
|
|
289
|
-
conversionOf(plan, table, column, reason) {
|
|
290
|
-
const field = fieldOfColumn(plan.contract, table, column);
|
|
291
|
-
return field === void 0 ? void 0 : {
|
|
292
|
-
field,
|
|
293
|
-
by: "conversion",
|
|
294
|
-
reason,
|
|
295
|
-
operationIndex: plan.operationIndex
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* The rows a table rebuild found no value for, when its copy failed on a NOT NULL column of the
|
|
300
|
-
* new table: the columns the rebuild's postchecks mark as becoming required are counted, the
|
|
301
|
-
* rebuild's own first, then those of every other operation of its migration.
|
|
302
|
-
*/
|
|
303
|
-
rowsWithoutValue(driver, error, plan) {
|
|
304
|
-
if (!(SqlQueryError.is(error) && error.sqlState === NOT_NULL_VIOLATION_SQLSTATE)) return Promise.resolve(void 0);
|
|
305
|
-
const marks = requiredColumnsOfMigration(plan.operations, plan.edges, plan.operationIndex);
|
|
306
|
-
return rowsWithoutValueFailure({
|
|
307
|
-
failed: marks.filter((mark) => mark.operationIndex === plan.operationIndex),
|
|
308
|
-
others: marks,
|
|
309
|
-
count: async ({ required }) => {
|
|
310
|
-
const where = required.reason !== "newField" ? ` WHERE ${quoteIdentifier(required.column)} IS NULL` : "";
|
|
311
|
-
return (await driver.query(`SELECT COUNT(*) AS rows FROM ${quoteIdentifier(required.table)}${where}`)).rows[0]?.rows ?? 0;
|
|
312
|
-
},
|
|
313
|
-
contract: plan.contract
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
stepResultIsTrue(rows) {
|
|
317
|
-
if (!rows || rows.length === 0) return false;
|
|
318
|
-
const firstRow = rows[0];
|
|
319
|
-
const firstValue = firstRow ? Object.values(firstRow)[0] : void 0;
|
|
320
|
-
if (typeof firstValue === "number") return firstValue !== 0;
|
|
321
|
-
if (typeof firstValue === "boolean") return firstValue;
|
|
322
|
-
if (typeof firstValue === "string") {
|
|
323
|
-
const lower = firstValue.toLowerCase();
|
|
324
|
-
if (lower === "true" || lower === "1") return true;
|
|
325
|
-
if (lower === "false" || lower === "0") return false;
|
|
326
|
-
return firstValue.length > 0;
|
|
327
|
-
}
|
|
328
|
-
return Boolean(firstValue);
|
|
329
|
-
}
|
|
330
|
-
async expectationsAreSatisfied(driver, steps) {
|
|
331
|
-
if (steps.length === 0) return false;
|
|
332
|
-
for (const step of steps) {
|
|
333
|
-
const result = await driver.query(step.sql, step.params ?? []);
|
|
334
|
-
if (!this.stepResultIsTrue(result.rows)) return false;
|
|
335
|
-
}
|
|
336
|
-
return true;
|
|
337
|
-
}
|
|
338
|
-
createSkipRecord(operation) {
|
|
339
|
-
return Object.freeze({
|
|
340
|
-
id: operation.id,
|
|
341
|
-
label: operation.label,
|
|
342
|
-
...ifDefined("summary", operation.summary),
|
|
343
|
-
operationClass: operation.operationClass,
|
|
344
|
-
target: operation.target,
|
|
345
|
-
precheck: Object.freeze([]),
|
|
346
|
-
execute: Object.freeze([]),
|
|
347
|
-
postcheck: Object.freeze([...operation.postcheck]),
|
|
348
|
-
meta: Object.freeze({
|
|
349
|
-
...operation.meta ?? {},
|
|
350
|
-
runner: Object.freeze({
|
|
351
|
-
skipped: true,
|
|
352
|
-
reason: "postcheck_pre_satisfied"
|
|
353
|
-
})
|
|
354
|
-
})
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
markerMatchesDestination(marker, plan) {
|
|
358
|
-
if (!marker) return false;
|
|
359
|
-
if (marker.storageHash !== plan.destination.storageHash) return false;
|
|
360
|
-
if (plan.destination.profileHash && marker.profileHash !== plan.destination.profileHash) return false;
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
enforcePolicyCompatibility(policy, operations) {
|
|
364
|
-
const allowedClasses = new Set(policy.allowedOperationClasses);
|
|
365
|
-
for (const operation of operations) if (!allowedClasses.has(operation.operationClass)) return runnerFailure("MIGRATION.POLICY_VIOLATION", `Operation ${operation.id} has class "${operation.operationClass}" which is not allowed by policy.`, {
|
|
366
|
-
why: `Policy only allows: ${policy.allowedOperationClasses.join(", ")}.`,
|
|
367
|
-
meta: {
|
|
368
|
-
operationId: operation.id,
|
|
369
|
-
operationClass: operation.operationClass,
|
|
370
|
-
allowedClasses: policy.allowedOperationClasses
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
return okVoid();
|
|
374
|
-
}
|
|
375
|
-
ensureMarkerCompatibility(marker, plan) {
|
|
376
|
-
const origin = plan.origin ?? null;
|
|
377
|
-
if (!origin) return okVoid();
|
|
378
|
-
if (!marker) return runnerFailure("MIGRATION.MARKER_ORIGIN_MISMATCH", `Missing contract marker: expected origin storage hash ${origin.storageHash}.`, { meta: { expectedOriginStorageHash: origin.storageHash } });
|
|
379
|
-
if (marker.storageHash !== origin.storageHash) return runnerFailure("MIGRATION.MARKER_ORIGIN_MISMATCH", `Existing contract marker (${marker.storageHash}) does not match plan origin (${origin.storageHash}).`, { meta: {
|
|
380
|
-
markerStorageHash: marker.storageHash,
|
|
381
|
-
expectedOriginStorageHash: origin.storageHash
|
|
382
|
-
} });
|
|
383
|
-
if (origin.profileHash && marker.profileHash !== origin.profileHash) return runnerFailure("MIGRATION.MARKER_ORIGIN_MISMATCH", `Existing contract marker profile hash (${marker.profileHash}) does not match plan origin profile hash (${origin.profileHash}).`, { meta: {
|
|
384
|
-
markerProfileHash: marker.profileHash,
|
|
385
|
-
expectedOriginProfileHash: origin.profileHash
|
|
386
|
-
} });
|
|
387
|
-
return okVoid();
|
|
388
|
-
}
|
|
389
|
-
ensurePlanMatchesDestinationContract(destination, contract) {
|
|
390
|
-
if (destination.storageHash !== contract.storage.storageHash) return runnerFailure("MIGRATION.DESTINATION_CONTRACT_MISMATCH", `Plan destination storage hash (${destination.storageHash}) does not match provided contract storage hash (${contract.storage.storageHash}).`, { meta: {
|
|
391
|
-
planStorageHash: destination.storageHash,
|
|
392
|
-
contractStorageHash: contract.storage.storageHash
|
|
393
|
-
} });
|
|
394
|
-
if (destination.profileHash && contract.profileHash && destination.profileHash !== contract.profileHash) return runnerFailure("MIGRATION.DESTINATION_CONTRACT_MISMATCH", `Plan destination profile hash (${destination.profileHash}) does not match provided contract profile hash (${contract.profileHash}).`, { meta: {
|
|
395
|
-
planProfileHash: destination.profileHash,
|
|
396
|
-
contractProfileHash: contract.profileHash
|
|
397
|
-
} });
|
|
398
|
-
return okVoid();
|
|
399
|
-
}
|
|
400
|
-
async upsertMarker(driver, options, existingMarker, space) {
|
|
401
|
-
const destination = {
|
|
402
|
-
storageHash: options.plan.destination.storageHash,
|
|
403
|
-
profileHash: options.plan.destination.profileHash ?? options.destinationContract.profileHash ?? options.plan.destination.storageHash,
|
|
404
|
-
invariants: options.plan.providedInvariants ?? []
|
|
405
|
-
};
|
|
406
|
-
if (!existingMarker) {
|
|
407
|
-
await this.family.initMarker({
|
|
408
|
-
driver,
|
|
409
|
-
space,
|
|
410
|
-
destination
|
|
411
|
-
});
|
|
412
|
-
return okVoid();
|
|
413
|
-
}
|
|
414
|
-
if (!await this.family.updateMarker({
|
|
415
|
-
driver,
|
|
416
|
-
space,
|
|
417
|
-
expectedFrom: existingMarker.storageHash,
|
|
418
|
-
destination
|
|
419
|
-
})) {
|
|
420
|
-
const found = await this.family.readMarker({
|
|
421
|
-
driver,
|
|
422
|
-
space
|
|
423
|
-
});
|
|
424
|
-
return runnerFailure("MIGRATION.MARKER_CAS_FAILURE", "Marker was modified by another process during migration execution.", { meta: {
|
|
425
|
-
space,
|
|
426
|
-
expectedStorageHash: existingMarker.storageHash,
|
|
427
|
-
foundStorageHash: found?.storageHash ?? null,
|
|
428
|
-
destinationStorageHash: options.plan.destination.storageHash
|
|
429
|
-
} });
|
|
430
|
-
}
|
|
431
|
-
return okVoid();
|
|
432
|
-
}
|
|
433
|
-
async recordLedgerEntries(driver, options, executedOperations) {
|
|
434
|
-
const plan = options.plan;
|
|
435
|
-
const space = plan.spaceId;
|
|
436
|
-
const edges = options.migrationEdges;
|
|
437
|
-
const totalEdgeOps = edges.reduce((sum, edge) => sum + edge.operationCount, 0);
|
|
438
|
-
if (totalEdgeOps !== plan.operations.length) throw new InternalError(`Ledger write: plan.operations length (${plan.operations.length}) does not match sum of migrationEdges operationCount (${totalEdgeOps})`);
|
|
439
|
-
let offset = 0;
|
|
440
|
-
for (const edge of edges) {
|
|
441
|
-
const edgeOps = executedOperations.slice(offset, offset + edge.operationCount);
|
|
442
|
-
offset += edge.operationCount;
|
|
443
|
-
await this.family.writeLedgerEntry({
|
|
444
|
-
driver,
|
|
445
|
-
space,
|
|
446
|
-
entry: {
|
|
447
|
-
edgeId: `${edge.from}->${edge.to}`,
|
|
448
|
-
from: edge.from,
|
|
449
|
-
to: edge.to,
|
|
450
|
-
migrationName: edge.dirName,
|
|
451
|
-
migrationHash: edge.migrationHash,
|
|
452
|
-
operations: edgeOps
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
async beginExclusiveTransaction(driver) {
|
|
458
|
-
await driver.query("BEGIN EXCLUSIVE");
|
|
459
|
-
}
|
|
460
|
-
async commitTransaction(driver) {
|
|
461
|
-
await driver.query("COMMIT");
|
|
462
|
-
}
|
|
463
|
-
async rollbackTransaction(driver) {
|
|
464
|
-
await driver.query("ROLLBACK");
|
|
465
|
-
}
|
|
466
|
-
async executeStatement(driver, statement) {
|
|
467
|
-
await driver.query(statement.sql, statement.params);
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
/**
|
|
471
|
-
* SQLite target `SchemaVerifier` concretion. Mirrors the Postgres
|
|
472
|
-
* shape: hooks return the empty list pending the call-site migration
|
|
473
|
-
* that routes the existing verifier behaviour through the SPI.
|
|
474
|
-
*/
|
|
475
|
-
var SqliteSchemaVerifier = class extends SqlSchemaVerifierBase {
|
|
476
|
-
verifyCommonSqlSchema(_options) {
|
|
477
|
-
return [];
|
|
478
|
-
}
|
|
479
|
-
verifyTargetExtensions(_options) {
|
|
480
|
-
return [];
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
function isSqlContract(contract) {
|
|
484
|
-
return contract === null || contract.storage instanceof SqlStorage;
|
|
485
|
-
}
|
|
486
|
-
const sqliteControlTargetDescriptor = {
|
|
487
|
-
...sqliteTargetDescriptorMeta,
|
|
488
|
-
contractSerializer: new SqliteContractSerializer(),
|
|
489
|
-
schemaVerifier: new SqliteSchemaVerifier(),
|
|
490
|
-
diffSchema(input) {
|
|
491
|
-
return diffSqliteSchema(input);
|
|
492
|
-
},
|
|
493
|
-
classifySubjectGranularity: relationalNodeGranularity,
|
|
494
|
-
classifyEntityKind: relationalNodeEntityKind,
|
|
495
|
-
migrations: {
|
|
496
|
-
createPlanner(adapter) {
|
|
497
|
-
return createSqliteMigrationPlanner(adapter);
|
|
498
|
-
},
|
|
499
|
-
createRunner(family) {
|
|
500
|
-
return createSqliteMigrationRunner(family);
|
|
501
|
-
},
|
|
502
|
-
contractToSchema(contract, frameworkComponents) {
|
|
503
|
-
if (!isSqlContract(contract)) throw sqliteError("CONTRACT.TARGET_MISMATCH", "sqliteControlTargetDescriptor.contractToSchema received a non-SQL contract; expected Contract<SqlStorage>");
|
|
504
|
-
return sqliteContractToSchema(contract, sqlTypeLookupsOf(frameworkComponents));
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
create() {
|
|
508
|
-
return {
|
|
509
|
-
familyId: "sql",
|
|
510
|
-
targetId: "sqlite"
|
|
511
|
-
};
|
|
512
|
-
},
|
|
513
|
-
createPlanner(adapter) {
|
|
514
|
-
return createSqliteMigrationPlanner(adapter);
|
|
515
|
-
},
|
|
516
|
-
createRunner(family) {
|
|
517
|
-
return createSqliteMigrationRunner(family);
|
|
518
|
-
}
|
|
519
|
-
};
|
|
520
|
-
/**
|
|
521
|
-
* The base PSL scalars as zero-arg type constructors in the unified authoring
|
|
522
|
-
* channel. Each names a codec; the column's database type is its data type's.
|
|
523
|
-
*
|
|
524
|
-
* The type position is the only storage decider: a mutation-default generator
|
|
525
|
-
* (`@onCreate(uuid())`) never re-picks a column's storage.
|
|
526
|
-
*
|
|
527
|
-
* These are the constructors only PSL offers. They are defined here, next to the codecs they name, but the adapter contributes them: the TypeScript contract builder builds its `type.*` helpers from the target, so a target contribution would add `type.String()` and the like there. The constructors that should also be `type.*` helpers are the target's own (`sqliteAuthoringTypes`).
|
|
528
|
-
*/
|
|
529
|
-
const sqlitePslTypeConstructors = {
|
|
530
|
-
String: {
|
|
531
|
-
kind: "typeConstructor",
|
|
532
|
-
documentation: "Variable-length text stored as SQLite text.",
|
|
533
|
-
output: { codecId: SQLITE_TEXT_CODEC_ID }
|
|
534
|
-
},
|
|
535
|
-
Int: {
|
|
536
|
-
kind: "typeConstructor",
|
|
537
|
-
documentation: "An integer stored as SQLite integer and represented as a JavaScript number.",
|
|
538
|
-
output: { codecId: SQLITE_INTEGER_CODEC_ID }
|
|
539
|
-
},
|
|
540
|
-
BigInt: {
|
|
541
|
-
kind: "typeConstructor",
|
|
542
|
-
documentation: "An integer stored as SQLite integer and represented as a JavaScript bigint.",
|
|
543
|
-
output: { codecId: SQLITE_BIGINT_CODEC_ID }
|
|
544
|
-
},
|
|
545
|
-
Float: {
|
|
546
|
-
kind: "typeConstructor",
|
|
547
|
-
documentation: "A floating-point number stored as SQLite real.",
|
|
548
|
-
output: { codecId: SQLITE_REAL_CODEC_ID }
|
|
549
|
-
},
|
|
550
|
-
Decimal: {
|
|
551
|
-
kind: "typeConstructor",
|
|
552
|
-
documentation: "A decimal value stored and represented as text to preserve precision.",
|
|
553
|
-
output: { codecId: SQLITE_TEXT_CODEC_ID }
|
|
554
|
-
},
|
|
555
|
-
DateTime: {
|
|
556
|
-
kind: "typeConstructor",
|
|
557
|
-
documentation: "A date and time stored as SQLite text.",
|
|
558
|
-
output: { codecId: SQLITE_DATETIME_CODEC_ID }
|
|
559
|
-
},
|
|
560
|
-
Json: {
|
|
561
|
-
kind: "typeConstructor",
|
|
562
|
-
documentation: "A JSON value serialized to SQLite text.",
|
|
563
|
-
output: { codecId: SQLITE_JSON_CODEC_ID }
|
|
564
|
-
},
|
|
565
|
-
Bytes: {
|
|
566
|
-
kind: "typeConstructor",
|
|
567
|
-
documentation: "Binary data stored as a SQLite blob.",
|
|
568
|
-
output: { codecId: SQLITE_BLOB_CODEC_ID }
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
//#endregion
|
|
572
|
-
export { sqlitePslTypeConstructors as n, sqliteControlTargetDescriptor as t };
|
|
573
|
-
|
|
574
|
-
//# sourceMappingURL=control-Oq9sp9Tq.mjs.map
|