@prisma/orm-target-mysql 0.0.0-stage → 8.0.0-rc.21
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/LICENSE +201 -0
- package/README.md +20 -2
- package/dist/adapter-_WBomuTw.d.mts +27 -0
- package/dist/adapter-_WBomuTw.d.mts.map +1 -0
- package/dist/adapter.d.mts +6 -0
- package/dist/adapter.mjs +3 -0
- package/dist/adapter__adapter.d.mts +2 -0
- package/dist/adapter__adapter.mjs +2 -0
- package/dist/adapter__codec-types.d.mts +3 -0
- package/dist/adapter__codec-types.mjs +1 -0
- package/dist/adapter__control.d.mts +2 -0
- package/dist/adapter__control.mjs +2 -0
- package/dist/adapter__runtime.d.mts +2 -0
- package/dist/adapter__runtime.mjs +417 -0
- package/dist/adapter__runtime.mjs.map +1 -0
- package/dist/codec-descriptor-DXyubAS6-siA0R8Ow.d.mts +43 -0
- package/dist/codec-descriptor-DXyubAS6-siA0R8Ow.d.mts.map +1 -0
- package/dist/codec-descriptor-Du6DSz-3-ytBCu_mq.mjs +93 -0
- package/dist/codec-descriptor-Du6DSz-3-ytBCu_mq.mjs.map +1 -0
- package/dist/codec-descriptor-J3TP08l8-ekLvUVxW.d.mts +1 -0
- package/dist/codec-descriptor-oLRh9E29.d.mts +2 -0
- package/dist/codec-ids-BHUwoNOM.d.mts +2 -0
- package/dist/codec-ids-C00hAFkc.mjs +2 -0
- package/dist/codec-ids-cjxtOcLM-vFeQhgPm.mjs +10 -0
- package/dist/codec-ids-cjxtOcLM-vFeQhgPm.mjs.map +1 -0
- package/dist/codec-ids-sMOU8F-B-BQbCq2dr.d.mts +10 -0
- package/dist/codec-ids-sMOU8F-B-BQbCq2dr.d.mts.map +1 -0
- package/dist/codec-types-Bd7DL1Mr-CZWNfnp9.d.mts +21 -0
- package/dist/codec-types-Bd7DL1Mr-CZWNfnp9.d.mts.map +1 -0
- package/dist/codec-types-Bo3Jfilx.d.mts +1 -0
- package/dist/codec-types-Ja2kLzLS.d.mts +1 -0
- package/dist/codecs-C00kjHgh.mjs +282 -0
- package/dist/codecs-C00kjHgh.mjs.map +1 -0
- package/dist/codecs-CO_VNEYU-CwAnKzRs.d.mts +102 -0
- package/dist/codecs-CO_VNEYU-CwAnKzRs.d.mts.map +1 -0
- package/dist/codecs-DM61agRr.d.mts +21 -0
- package/dist/codecs-DM61agRr.d.mts.map +1 -0
- package/dist/contract-contributions-B9njRJbt-ClEtrK2L.mjs +14 -0
- package/dist/contract-contributions-B9njRJbt-ClEtrK2L.mjs.map +1 -0
- package/dist/contract-free-BvCdx_Ee.mjs +71 -0
- package/dist/contract-free-BvCdx_Ee.mjs.map +1 -0
- package/dist/contract-free-Cw9Mjcro.d.mts +22 -0
- package/dist/contract-free-Cw9Mjcro.d.mts.map +1 -0
- package/dist/control-C9zxRXNN.mjs +74 -0
- package/dist/control-C9zxRXNN.mjs.map +1 -0
- package/dist/control-DHkZbo58.d.mts +25 -0
- package/dist/control-DHkZbo58.d.mts.map +1 -0
- package/dist/control-Ez_PtlFI.d.mts +121 -0
- package/dist/control-Ez_PtlFI.d.mts.map +1 -0
- package/dist/control-WTY7Jpxk.mjs +577 -0
- package/dist/control-WTY7Jpxk.mjs.map +1 -0
- package/dist/control-_4epnrIW.d.mts +27 -0
- package/dist/control-_4epnrIW.d.mts.map +1 -0
- package/dist/control-tables-CHw2F-rg.d.mts +9 -0
- package/dist/control-tables-CHw2F-rg.d.mts.map +1 -0
- package/dist/control-tables-CcQ77JE7-CxTQYoQJ.mjs +9 -0
- package/dist/control-tables-CcQ77JE7-CxTQYoQJ.mjs.map +1 -0
- package/dist/data-type-entries-B0AoBozh-f9AEUIUQ.mjs +42 -0
- package/dist/data-type-entries-B0AoBozh-f9AEUIUQ.mjs.map +1 -0
- package/dist/data-types-BpihGKoK-BMW-m4EN.d.mts +52 -0
- package/dist/data-types-BpihGKoK-BMW-m4EN.d.mts.map +1 -0
- package/dist/data-types-Dv9gwVRV-BZPzCWZk.mjs +181 -0
- package/dist/data-types-Dv9gwVRV-BZPzCWZk.mjs.map +1 -0
- package/dist/data-types-SXrh0Lou.d.mts +8 -0
- package/dist/data-types-SXrh0Lou.d.mts.map +1 -0
- package/dist/ddl-CT6DPEqg.d.mts +1 -0
- package/dist/ddl-DDmMHyA_-Bb8sXoS0.mjs +12 -0
- package/dist/ddl-DDmMHyA_-Bb8sXoS0.mjs.map +1 -0
- package/dist/default-normalizer-BBhGpw7r.d.mts +27 -0
- package/dist/default-normalizer-BBhGpw7r.d.mts.map +1 -0
- package/dist/default-normalizer-BDUgHXUn-Xk7HQJuI.mjs +90 -0
- package/dist/default-normalizer-BDUgHXUn-Xk7HQJuI.mjs.map +1 -0
- package/dist/descriptor-meta-BurjcSiU-Cbk2L1jf.mjs +82 -0
- package/dist/descriptor-meta-BurjcSiU-Cbk2L1jf.mjs.map +1 -0
- package/dist/descriptor-meta-runtime-Bk_00UrX-BLN4Ahpj.mjs +17 -0
- package/dist/descriptor-meta-runtime-Bk_00UrX-BLN4Ahpj.mjs.map +1 -0
- package/dist/driver.d.mts +3 -0
- package/dist/driver.mjs +2 -0
- package/dist/driver__control.d.mts +2 -0
- package/dist/driver__control.mjs +2 -0
- package/dist/driver__runtime.d.mts +2 -0
- package/dist/driver__runtime.mjs +325 -0
- package/dist/driver__runtime.mjs.map +1 -0
- package/dist/errors-BYhjQT7y.d.mts +10 -0
- package/dist/errors-BYhjQT7y.d.mts.map +1 -0
- package/dist/errors-rvH_F2Yj-BQrO_--u.mjs +20 -0
- package/dist/errors-rvH_F2Yj-BQrO_--u.mjs.map +1 -0
- package/dist/marker-lock-CmGvN4hw-Com29AtQ.mjs +51 -0
- package/dist/marker-lock-CmGvN4hw-Com29AtQ.mjs.map +1 -0
- package/dist/marker-lock-su6IxinO.d.mts +18 -0
- package/dist/marker-lock-su6IxinO.d.mts.map +1 -0
- package/dist/marker-read-aEaHihYj-Cyg16yn1.mjs +78 -0
- package/dist/marker-read-aEaHihYj-Cyg16yn1.mjs.map +1 -0
- package/dist/migration-DmlblTTw.d.mts +284 -0
- package/dist/migration-DmlblTTw.d.mts.map +1 -0
- package/dist/migration-tFuoN9GB.mjs +5 -0
- package/dist/mysql-contract-serializer-DLv0uW_f-Cg4A43Ry.mjs +160 -0
- package/dist/mysql-contract-serializer-DLv0uW_f-Cg4A43Ry.mjs.map +1 -0
- package/dist/nodes-CvcX47ot-B-ZaUYRj.mjs +25 -0
- package/dist/nodes-CvcX47ot-B-ZaUYRj.mjs.map +1 -0
- package/dist/nodes-xc0cR0_c-2YbhgEjb.d.mts +27 -0
- package/dist/nodes-xc0cR0_c-2YbhgEjb.d.mts.map +1 -0
- package/dist/pack-YVG-iBMQ.d.mts +1073 -0
- package/dist/pack-YVG-iBMQ.d.mts.map +1 -0
- package/dist/planner-target-details-D6g2uSp--C5NKHmCc.d.mts +12 -0
- package/dist/planner-target-details-D6g2uSp--C5NKHmCc.d.mts.map +1 -0
- package/dist/runner-C4r6yEd1-BWQrxW9q.mjs +1644 -0
- package/dist/runner-C4r6yEd1-BWQrxW9q.mjs.map +1 -0
- package/dist/runtime-BGyTXcQH.d.mts +36 -0
- package/dist/runtime-BGyTXcQH.d.mts.map +1 -0
- package/dist/runtime-CeuRr9nE.d.mts +29 -0
- package/dist/runtime-CeuRr9nE.d.mts.map +1 -0
- package/dist/runtime-Cl0BbTZq.d.mts +22 -0
- package/dist/runtime-Cl0BbTZq.d.mts.map +1 -0
- package/dist/sql-utils-BOS1c2QT.d.mts +30 -0
- package/dist/sql-utils-BOS1c2QT.d.mts.map +1 -0
- package/dist/sql-utils-Db0IQO_B-PaULnfrE.mjs +30 -0
- package/dist/sql-utils-Db0IQO_B-PaULnfrE.mjs.map +1 -0
- package/dist/sql-utils-RW0vJvDl.mjs +94 -0
- package/dist/sql-utils-RW0vJvDl.mjs.map +1 -0
- package/dist/statement-A6bbPBf1-q61iHQLb.mjs +483 -0
- package/dist/statement-A6bbPBf1-q61iHQLb.mjs.map +1 -0
- package/dist/target.d.mts +24 -0
- package/dist/target.mjs +19 -0
- package/dist/target__codec-descriptor.d.mts +3 -0
- package/dist/target__codec-descriptor.mjs +2 -0
- package/dist/target__codec-ids.d.mts +3 -0
- package/dist/target__codec-ids.mjs +3 -0
- package/dist/target__codec-types.d.mts +3 -0
- package/dist/target__codec-types.mjs +1 -0
- package/dist/target__codecs.d.mts +3 -0
- package/dist/target__codecs.mjs +2 -0
- package/dist/target__contract-free.d.mts +2 -0
- package/dist/target__contract-free.mjs +3 -0
- package/dist/target__control-tables.d.mts +2 -0
- package/dist/target__control-tables.mjs +2 -0
- package/dist/target__control.d.mts +3 -0
- package/dist/target__control.mjs +58 -0
- package/dist/target__control.mjs.map +1 -0
- package/dist/target__data-types.d.mts +3 -0
- package/dist/target__data-types.mjs +3 -0
- package/dist/target__ddl.d.mts +3 -0
- package/dist/target__ddl.mjs +2 -0
- package/dist/target__default-normalizer.d.mts +2 -0
- package/dist/target__default-normalizer.mjs +2 -0
- package/dist/target__errors.d.mts +2 -0
- package/dist/target__errors.mjs +2 -0
- package/dist/target__marker-lock.d.mts +2 -0
- package/dist/target__marker-lock.mjs +2 -0
- package/dist/target__migration.d.mts +2 -0
- package/dist/target__migration.mjs +3 -0
- package/dist/target__pack.d.mts +2 -0
- package/dist/target__pack.mjs +2 -0
- package/dist/target__runtime.d.mts +2 -0
- package/dist/target__runtime.mjs +17 -0
- package/dist/target__runtime.mjs.map +1 -0
- package/dist/target__sql-utils.d.mts +2 -0
- package/dist/target__sql-utils.mjs +3 -0
- package/package.json +71 -3
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { n as mysqlQueryNotYetSupported } from "./errors-rvH_F2Yj-BQrO_--u.mjs";
|
|
2
|
+
import { n as quoteIdentifier, r as quoteLiteral } from "./sql-utils-Db0IQO_B-PaULnfrE.mjs";
|
|
3
|
+
import { i as encodeMysqlDatetime, r as decodeMysqlDatetime, t as assembleMysqlCodecRegistry } from "./codecs-C00kjHgh.mjs";
|
|
4
|
+
import { n as LEDGER_TABLE_NAME, r as MARKER_TABLE_NAME, t as CONTROL_TABLE_NAMES } from "./control-tables-CcQ77JE7-CxTQYoQJ.mjs";
|
|
5
|
+
import { n as buildSignMarkerBootstrapQueries, t as buildControlTableBootstrapQueries } from "./contract-free-BvCdx_Ee.mjs";
|
|
6
|
+
import { n as readMysqlDefault } from "./default-normalizer-BDUgHXUn-Xk7HQJuI.mjs";
|
|
7
|
+
import { i as withMarkerLock } from "./marker-lock-CmGvN4hw-Com29AtQ.mjs";
|
|
8
|
+
import { a as readMarkerRows, i as readMarkerResult, n as mysqlAdapterDescriptorMeta, o as tableExists, r as parseJsonColumn, t as decodeMysqlMarkerRow } from "./marker-read-aEaHihYj-Cyg16yn1.mjs";
|
|
9
|
+
import { codecForRef } from "@prisma/orm-framework/components/codec";
|
|
10
|
+
import { structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
11
|
+
import { encodeLiteralDefault, isDdlNode, renderOpaqueSql } from "@prisma/orm-family-sql/relational-core/ast";
|
|
12
|
+
import { APP_SPACE_ID } from "@prisma/orm-framework/components/control";
|
|
13
|
+
import { checkSqlDefaultText, contractColumns, readColumnDefault, sqlDefaultFunctions } from "@prisma/orm-family-sql/family/control";
|
|
14
|
+
import { RelationalSchemaNodeKind, SqlSchemaIR, SqlTableIR } from "@prisma/orm-family-sql/schema-ir/types";
|
|
15
|
+
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
16
|
+
import { REFERENTIAL_ACTION_SQL } from "@prisma/orm-family-sql/contract/referential-action-sql";
|
|
17
|
+
import { parseMarkerRowSafely, withMarkerReadErrorHandling } from "@prisma/orm-framework/errors/execution";
|
|
18
|
+
import { resolveIntrospectedColumnType } from "@prisma/orm-family-sql/family/control-adapter";
|
|
19
|
+
import { ledgerOriginFromStored } from "@prisma/orm-toolchain/migration-tools/ledger-origin";
|
|
20
|
+
//#region ../../../3-targets/mysql/2-adapter/dist/control.mjs
|
|
21
|
+
/** Column types MySQL gives a default only when it is written as an expression in parentheses. */
|
|
22
|
+
const EXPRESSION_DEFAULT_ONLY = /^(?:(?:tiny|medium|long)?(?:text|blob)|json|geometry)\b/i;
|
|
23
|
+
const FRACTIONAL_SECONDS = /^(?:datetime|timestamp)\((\d)\)$/i;
|
|
24
|
+
function refusedDefault(where, why) {
|
|
25
|
+
throw structuredError("CONTRACT.DEFAULT_INVALID", `Column "${where.table}"."${where.column}" has a default MySQL cannot store: ${why}`, { meta: {
|
|
26
|
+
table: where.table,
|
|
27
|
+
column: where.column
|
|
28
|
+
} });
|
|
29
|
+
}
|
|
30
|
+
/** A wire value as the SQL literal MySQL reads for it. */
|
|
31
|
+
function mysqlInlineLiteral(wire, where) {
|
|
32
|
+
if (wire === null) return "NULL";
|
|
33
|
+
if (typeof wire === "boolean") return wire ? "1" : "0";
|
|
34
|
+
if (typeof wire === "number") {
|
|
35
|
+
if (!Number.isFinite(wire)) return refusedDefault(where, `${wire} is not a finite number`);
|
|
36
|
+
return String(wire);
|
|
37
|
+
}
|
|
38
|
+
if (typeof wire === "bigint") return String(wire);
|
|
39
|
+
if (typeof wire === "string") return quoteLiteral(wire);
|
|
40
|
+
if (wire instanceof Date) return quoteLiteral(encodeMysqlDatetime(wire));
|
|
41
|
+
if (wire instanceof Uint8Array) return `X'${Buffer.from(wire).toString("hex")}'`;
|
|
42
|
+
if (typeof wire === "object") return quoteLiteral(JSON.stringify(wire));
|
|
43
|
+
return refusedDefault(where, `a ${typeof wire} has no SQL literal`);
|
|
44
|
+
}
|
|
45
|
+
function withinParentheses(columnType, literal) {
|
|
46
|
+
return EXPRESSION_DEFAULT_ONLY.test(columnType.trim()) ? `(${literal})` : literal;
|
|
47
|
+
}
|
|
48
|
+
/** `CURRENT_TIMESTAMP` with the column's fractional-second precision, which MySQL requires to match. */
|
|
49
|
+
function currentTimestampFor(columnType) {
|
|
50
|
+
const precision = FRACTIONAL_SECONDS.exec(columnType.trim())?.[1];
|
|
51
|
+
return precision === void 0 ? "CURRENT_TIMESTAMP" : `CURRENT_TIMESTAMP(${precision})`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The `DEFAULT …` clause of a column, or `''` for an `autoincrement()` default, which a column writes as `AUTO_INCREMENT` instead. A literal is read by the column's codec, and a text or blob column's literal is written as an expression, as MySQL requires.
|
|
55
|
+
*/
|
|
56
|
+
async function renderMysqlColumnDefault(def, columnType, codecLookup, codecRef, where) {
|
|
57
|
+
if (def.kind === "function") {
|
|
58
|
+
const text = def.expression.text;
|
|
59
|
+
if (text === "autoincrement()") return "";
|
|
60
|
+
if (text === "now()") return `DEFAULT (${currentTimestampFor(columnType)})`;
|
|
61
|
+
if (checkSqlDefaultText(text) !== void 0) throw structuredError("CONTRACT.DEFAULT_INVALID", `Unsafe default expression in contract: "${text}". Default expressions must not contain semicolons, SQL comment tokens, dollar-quoting, or subqueries.`, { meta: { expression: text } });
|
|
62
|
+
return `DEFAULT (${renderOpaqueSql(def.expression)})`;
|
|
63
|
+
}
|
|
64
|
+
const encoded = codecRef === void 0 ? void 0 : await encodeLiteralDefault(codecLookup, codecRef, def.value, where);
|
|
65
|
+
if (encoded?.kind === "sql-null") return "DEFAULT NULL";
|
|
66
|
+
return `DEFAULT ${withinParentheses(columnType, mysqlInlineLiteral(encoded === void 0 ? def.value : encoded.wire, where))}`;
|
|
67
|
+
}
|
|
68
|
+
function isAutoincrement(column) {
|
|
69
|
+
return column.default?.kind === "function" && column.default.expression.text === "autoincrement()";
|
|
70
|
+
}
|
|
71
|
+
async function renderColumn(column, codecLookup, table) {
|
|
72
|
+
const parts = [quoteIdentifier(column.name), column.type];
|
|
73
|
+
if (column.notNull) parts.push("NOT NULL");
|
|
74
|
+
if (column.default !== void 0) {
|
|
75
|
+
const clause = await renderMysqlColumnDefault(column.default, column.type, codecLookup, column.codecRef, {
|
|
76
|
+
table,
|
|
77
|
+
column: column.name
|
|
78
|
+
});
|
|
79
|
+
if (clause.length > 0) parts.push(clause);
|
|
80
|
+
}
|
|
81
|
+
if (isAutoincrement(column)) parts.push("AUTO_INCREMENT");
|
|
82
|
+
if (column.primaryKey) parts.push("PRIMARY KEY");
|
|
83
|
+
return parts.join(" ");
|
|
84
|
+
}
|
|
85
|
+
function columnList(columns) {
|
|
86
|
+
return columns.map(quoteIdentifier).join(", ");
|
|
87
|
+
}
|
|
88
|
+
function named(name, body) {
|
|
89
|
+
return name === void 0 ? body : `CONSTRAINT ${quoteIdentifier(name)} ${body}`;
|
|
90
|
+
}
|
|
91
|
+
function renderConstraint(constraint) {
|
|
92
|
+
switch (constraint.kind) {
|
|
93
|
+
case "primary-key": return named(constraint.name, `PRIMARY KEY (${columnList(constraint.columns)})`);
|
|
94
|
+
case "unique": return named(constraint.name, `UNIQUE (${columnList(constraint.columns)})`);
|
|
95
|
+
case "foreign-key": {
|
|
96
|
+
const actions = [constraint.onDelete === void 0 ? void 0 : `ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`, constraint.onUpdate === void 0 ? void 0 : `ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`].filter((action) => action !== void 0);
|
|
97
|
+
return named(constraint.name, [`FOREIGN KEY (${columnList(constraint.columns)}) REFERENCES ${quoteIdentifier(constraint.refTable)} (${columnList(constraint.refColumns)})`, ...actions].join(" "));
|
|
98
|
+
}
|
|
99
|
+
case "check-expression": throw structuredError("CONTRACT.CONSTRAINT_INVALID", `The MySQL target does not write CHECK constraints yet (constraint "${constraint.name}").`, { meta: { constraintName: constraint.name } });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** The `CREATE TABLE` statement of a MySQL DDL node. */
|
|
103
|
+
async function renderMysqlCreateTable(node, codecLookup) {
|
|
104
|
+
const definitions = [...await Promise.all(node.columns.map((column) => renderColumn(column, codecLookup, node.table))), ...(node.constraints ?? []).map(renderConstraint)];
|
|
105
|
+
return {
|
|
106
|
+
sql: `CREATE TABLE ${node.ifNotExists === true ? "IF NOT EXISTS " : ""}${quoteIdentifier(node.table)} (\n ${definitions.join(",\n ")}\n)`,
|
|
107
|
+
params: []
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function isLoose(value) {
|
|
111
|
+
return typeof value === "object" && value !== null;
|
|
112
|
+
}
|
|
113
|
+
function child(value, key) {
|
|
114
|
+
const found = isLoose(value) ? value[key] : void 0;
|
|
115
|
+
return isLoose(found) ? found : void 0;
|
|
116
|
+
}
|
|
117
|
+
function tableIndexKey(tableName, indexName) {
|
|
118
|
+
return JSON.stringify([tableName, indexName]);
|
|
119
|
+
}
|
|
120
|
+
/** The indexes the contract handed to introspection declares, read from every contract space it holds. */
|
|
121
|
+
function declaredIndexes(contract) {
|
|
122
|
+
const contracts = isLoose(contract) && Array.isArray(contract["contracts"]) ? contract["contracts"] : [contract];
|
|
123
|
+
const declared = /* @__PURE__ */ new Set();
|
|
124
|
+
const declaredUnique = /* @__PURE__ */ new Set();
|
|
125
|
+
for (const space of contracts) for (const namespace of Object.values(child(child(space, "storage"), "namespaces") ?? {})) for (const [tableName, table] of Object.entries(child(child(namespace, "entries"), "table") ?? {})) {
|
|
126
|
+
const indexes = isLoose(table) ? table["indexes"] : void 0;
|
|
127
|
+
for (const index of Array.isArray(indexes) ? indexes : []) {
|
|
128
|
+
if (!isLoose(index) || typeof index["name"] !== "string") continue;
|
|
129
|
+
const key = tableIndexKey(tableName, index["name"]);
|
|
130
|
+
declared.add(key);
|
|
131
|
+
if (index["unique"] === true) declaredUnique.add(key);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
declaresIndex: (tableName, indexName) => declared.has(tableIndexKey(tableName, indexName)),
|
|
136
|
+
declaresUniqueIndex: (tableName, indexName) => declaredUnique.has(tableIndexKey(tableName, indexName))
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const NOTHING_DECLARED = {
|
|
140
|
+
declaresIndex: () => false,
|
|
141
|
+
declaresUniqueIndex: () => false
|
|
142
|
+
};
|
|
143
|
+
const PRIMARY_INDEX = "PRIMARY";
|
|
144
|
+
const REFERENTIAL_ACTIONS = {
|
|
145
|
+
RESTRICT: "restrict",
|
|
146
|
+
CASCADE: "cascade",
|
|
147
|
+
"SET NULL": "setNull",
|
|
148
|
+
"SET DEFAULT": "setDefault"
|
|
149
|
+
};
|
|
150
|
+
/** A rule `REFERENTIAL_CONSTRAINTS` reports, with `NO ACTION`, MySQL's default, as no action at all. */
|
|
151
|
+
function referentialAction(rule) {
|
|
152
|
+
const normalized = rule.toUpperCase();
|
|
153
|
+
if (normalized === "NO ACTION") return void 0;
|
|
154
|
+
const action = REFERENTIAL_ACTIONS[normalized];
|
|
155
|
+
if (action === void 0) throw structuredError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Unknown MySQL referential action rule: "${rule}". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`, { meta: { rule } });
|
|
156
|
+
return action;
|
|
157
|
+
}
|
|
158
|
+
function tableDependsOn(tableName) {
|
|
159
|
+
return [{
|
|
160
|
+
nodeKind: RelationalSchemaNodeKind.schema,
|
|
161
|
+
id: "database"
|
|
162
|
+
}, {
|
|
163
|
+
nodeKind: RelationalSchemaNodeKind.table,
|
|
164
|
+
id: tableName
|
|
165
|
+
}];
|
|
166
|
+
}
|
|
167
|
+
function columnDependsOn(tableName, columns) {
|
|
168
|
+
return columns.map((column) => [...tableDependsOn(tableName), {
|
|
169
|
+
nodeKind: RelationalSchemaNodeKind.column,
|
|
170
|
+
id: `column:${column}`
|
|
171
|
+
}]);
|
|
172
|
+
}
|
|
173
|
+
function groupBy(rows, key) {
|
|
174
|
+
const groups = /* @__PURE__ */ new Map();
|
|
175
|
+
for (const row of rows) {
|
|
176
|
+
const group = groups.get(key(row));
|
|
177
|
+
if (group === void 0) groups.set(key(row), [row]);
|
|
178
|
+
else group.push(row);
|
|
179
|
+
}
|
|
180
|
+
return groups;
|
|
181
|
+
}
|
|
182
|
+
function byPosition(position) {
|
|
183
|
+
return (a, b) => Number(position(a)) - Number(position(b));
|
|
184
|
+
}
|
|
185
|
+
async function columnOf(row, dataTypes, readLiteralDefault) {
|
|
186
|
+
const reported = readMysqlDefault(row.column_default, row.extra);
|
|
187
|
+
const readDefault = reported === void 0 ? {} : reported.kind === "function" ? { resolvedDefault: reported } : await readLiteralDefault(row.table_name, row.column_name, reported.literal.body);
|
|
188
|
+
const reportedType = {
|
|
189
|
+
text: row.column_type,
|
|
190
|
+
kind: void 0,
|
|
191
|
+
schema: void 0,
|
|
192
|
+
name: void 0
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
name: row.column_name,
|
|
196
|
+
typeText: row.column_type,
|
|
197
|
+
nullable: row.is_nullable === "YES",
|
|
198
|
+
...ifDefined("default", row.column_default ?? void 0),
|
|
199
|
+
...readDefault,
|
|
200
|
+
reportedType,
|
|
201
|
+
...resolveIntrospectedColumnType(reportedType, dataTypes)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function indexesOf(rows) {
|
|
205
|
+
return [...groupBy(rows, (row) => row.index_name).entries()].map(([name, parts]) => {
|
|
206
|
+
const ordered = [...parts].sort(byPosition((part) => part.seq_in_index));
|
|
207
|
+
const expressions = ordered.flatMap((part) => part.expression === null ? [] : [part.expression]);
|
|
208
|
+
return {
|
|
209
|
+
name,
|
|
210
|
+
unique: ordered[0]?.non_unique === "0",
|
|
211
|
+
columns: ordered.flatMap((part) => part.column_name === null ? [] : [part.column_name]),
|
|
212
|
+
expression: expressions.length === 0 ? void 0 : expressions.join(", ")
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function sameColumns(a, b) {
|
|
217
|
+
return a.length === b.length && a.every((column, index) => column === b[index]);
|
|
218
|
+
}
|
|
219
|
+
function foreignKeysOf(tableName, rows) {
|
|
220
|
+
return [...groupBy(rows, (row) => row.constraint_name).entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, parts]) => {
|
|
221
|
+
const ordered = [...parts].sort(byPosition((part) => part.ordinal_position));
|
|
222
|
+
const [first] = ordered;
|
|
223
|
+
const columns = ordered.map((part) => part.column_name);
|
|
224
|
+
const referencedTable = first?.referenced_table_name ?? "";
|
|
225
|
+
const referencedSchema = first?.referenced_table_schema ?? void 0;
|
|
226
|
+
return {
|
|
227
|
+
columns,
|
|
228
|
+
referencedTable,
|
|
229
|
+
referencedColumns: ordered.map((part) => part.referenced_column_name),
|
|
230
|
+
...ifDefined("referencedSchema", referencedSchema),
|
|
231
|
+
name,
|
|
232
|
+
...ifDefined("onDelete", first === void 0 ? void 0 : referentialAction(first.delete_rule)),
|
|
233
|
+
...ifDefined("onUpdate", first === void 0 ? void 0 : referentialAction(first.update_rule)),
|
|
234
|
+
dependsOn: [...referencedSchema === void 0 ? [tableDependsOn(referencedTable)] : [], ...columnDependsOn(tableName, columns)]
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The index InnoDB creates for a foreign key that no index already serves: it carries the key's name and exactly the key's columns. Introspection leaves it out, because the contract describes the key, not that index. An explicit index can look the same, so one the contract declares is kept.
|
|
240
|
+
*/
|
|
241
|
+
function isForeignKeyIndex(tableName, index, foreignKeys, declared) {
|
|
242
|
+
if (declared.declaresIndex(tableName, index.name)) return false;
|
|
243
|
+
return foreignKeys.some((fk) => fk.name === index.name && index.expression === void 0 && sameColumns(fk.columns, index.columns));
|
|
244
|
+
}
|
|
245
|
+
async function tableOf(tableName, rows, dataTypes, readLiteralDefault, declared) {
|
|
246
|
+
const columns = {};
|
|
247
|
+
for (const row of [...rows.columns].sort(byPosition((column) => column.ordinal_position))) columns[row.column_name] = await columnOf(row, dataTypes, readLiteralDefault);
|
|
248
|
+
const foreignKeys = foreignKeysOf(tableName, rows.foreignKeys);
|
|
249
|
+
const indexes = indexesOf(rows.indexes);
|
|
250
|
+
const expressionIndexNames = new Set(indexes.filter((index) => index.expression !== void 0).map((index) => index.name));
|
|
251
|
+
const uniqueConstraintNames = new Set(rows.constraints.filter((constraint) => constraint.constraint_type === "UNIQUE" && !expressionIndexNames.has(constraint.constraint_name) && !declared.declaresUniqueIndex(tableName, constraint.constraint_name)).map((constraint) => constraint.constraint_name));
|
|
252
|
+
const primary = indexes.find((index) => index.name === PRIMARY_INDEX);
|
|
253
|
+
const primaryKey = primary === void 0 ? void 0 : {
|
|
254
|
+
columns: primary.columns,
|
|
255
|
+
dependsOn: columnDependsOn(tableName, primary.columns)
|
|
256
|
+
};
|
|
257
|
+
const uniques = indexes.filter((index) => uniqueConstraintNames.has(index.name)).map((index) => ({
|
|
258
|
+
columns: index.columns,
|
|
259
|
+
name: index.name,
|
|
260
|
+
dependsOn: columnDependsOn(tableName, index.columns)
|
|
261
|
+
}));
|
|
262
|
+
const plainIndexes = indexes.filter((index) => index.name !== PRIMARY_INDEX && !uniqueConstraintNames.has(index.name) && !isForeignKeyIndex(tableName, index, foreignKeys, declared)).map((index) => {
|
|
263
|
+
const base = {
|
|
264
|
+
naming: {
|
|
265
|
+
kind: "exact",
|
|
266
|
+
name: index.name
|
|
267
|
+
},
|
|
268
|
+
where: void 0,
|
|
269
|
+
unique: index.unique,
|
|
270
|
+
partial: false,
|
|
271
|
+
type: void 0,
|
|
272
|
+
options: void 0,
|
|
273
|
+
annotations: void 0,
|
|
274
|
+
dependsOn: columnDependsOn(tableName, index.columns)
|
|
275
|
+
};
|
|
276
|
+
return index.expression === void 0 ? {
|
|
277
|
+
...base,
|
|
278
|
+
columns: index.columns
|
|
279
|
+
} : {
|
|
280
|
+
...base,
|
|
281
|
+
expression: index.expression
|
|
282
|
+
};
|
|
283
|
+
});
|
|
284
|
+
return new SqlTableIR({
|
|
285
|
+
name: tableName,
|
|
286
|
+
columns,
|
|
287
|
+
...ifDefined("primaryKey", primaryKey),
|
|
288
|
+
foreignKeys,
|
|
289
|
+
uniques,
|
|
290
|
+
indexes: plainIndexes
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* The schema IR of the database the rows describe: one flat tree of its tables. MySQL lists every unique index as a UNIQUE constraint, so one is reported as a unique constraint unless the contract declares a unique index of that name on the table, or it indexes an expression. The index InnoDB creates for a foreign key is left out, unless the contract declares an index of that name on the table.
|
|
295
|
+
*/
|
|
296
|
+
async function buildMysqlSchemaIR(rows, dataTypes, readLiteralDefault, declared = NOTHING_DECLARED) {
|
|
297
|
+
const columnsByTable = groupBy(rows.columns, (row) => row.table_name);
|
|
298
|
+
const indexesByTable = groupBy(rows.indexes, (row) => row.table_name);
|
|
299
|
+
const constraintsByTable = groupBy(rows.constraints, (row) => row.table_name);
|
|
300
|
+
const foreignKeysByTable = groupBy(rows.foreignKeys, (row) => row.table_name);
|
|
301
|
+
const tables = {};
|
|
302
|
+
for (const tableName of rows.tables) tables[tableName] = await tableOf(tableName, {
|
|
303
|
+
columns: columnsByTable.get(tableName) ?? [],
|
|
304
|
+
indexes: indexesByTable.get(tableName) ?? [],
|
|
305
|
+
constraints: constraintsByTable.get(tableName) ?? [],
|
|
306
|
+
foreignKeys: foreignKeysByTable.get(tableName) ?? []
|
|
307
|
+
}, dataTypes, readLiteralDefault, declared);
|
|
308
|
+
return new SqlSchemaIR({ tables });
|
|
309
|
+
}
|
|
310
|
+
const TABLES = `SELECT TABLE_NAME AS table_name
|
|
311
|
+
FROM information_schema.TABLES
|
|
312
|
+
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE'
|
|
313
|
+
ORDER BY TABLE_NAME`;
|
|
314
|
+
const COLUMNS = `SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name,
|
|
315
|
+
ORDINAL_POSITION AS ordinal_position, COLUMN_DEFAULT AS column_default,
|
|
316
|
+
IS_NULLABLE AS is_nullable, COLUMN_TYPE AS column_type, EXTRA AS extra
|
|
317
|
+
FROM information_schema.COLUMNS
|
|
318
|
+
WHERE TABLE_SCHEMA = DATABASE()
|
|
319
|
+
ORDER BY TABLE_NAME, ORDINAL_POSITION`;
|
|
320
|
+
const INDEXES = `SELECT TABLE_NAME AS table_name, INDEX_NAME AS index_name,
|
|
321
|
+
NON_UNIQUE AS non_unique, SEQ_IN_INDEX AS seq_in_index,
|
|
322
|
+
COLUMN_NAME AS column_name, EXPRESSION AS expression
|
|
323
|
+
FROM information_schema.STATISTICS
|
|
324
|
+
WHERE TABLE_SCHEMA = DATABASE()
|
|
325
|
+
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX`;
|
|
326
|
+
const CONSTRAINTS = `SELECT TABLE_NAME AS table_name, CONSTRAINT_NAME AS constraint_name,
|
|
327
|
+
CONSTRAINT_TYPE AS constraint_type
|
|
328
|
+
FROM information_schema.TABLE_CONSTRAINTS
|
|
329
|
+
WHERE TABLE_SCHEMA = DATABASE()`;
|
|
330
|
+
const FOREIGN_KEYS = `SELECT k.TABLE_NAME AS table_name, k.CONSTRAINT_NAME AS constraint_name,
|
|
331
|
+
k.COLUMN_NAME AS column_name, k.ORDINAL_POSITION AS ordinal_position,
|
|
332
|
+
NULLIF(k.REFERENCED_TABLE_SCHEMA, k.TABLE_SCHEMA) AS referenced_table_schema,
|
|
333
|
+
k.REFERENCED_TABLE_NAME AS referenced_table_name,
|
|
334
|
+
k.REFERENCED_COLUMN_NAME AS referenced_column_name,
|
|
335
|
+
r.UPDATE_RULE AS update_rule, r.DELETE_RULE AS delete_rule
|
|
336
|
+
FROM information_schema.KEY_COLUMN_USAGE k
|
|
337
|
+
JOIN information_schema.REFERENTIAL_CONSTRAINTS r
|
|
338
|
+
ON r.CONSTRAINT_SCHEMA = k.CONSTRAINT_SCHEMA
|
|
339
|
+
AND r.TABLE_NAME = k.TABLE_NAME
|
|
340
|
+
AND r.CONSTRAINT_NAME = k.CONSTRAINT_NAME
|
|
341
|
+
WHERE k.TABLE_SCHEMA = DATABASE() AND k.REFERENCED_TABLE_NAME IS NOT NULL
|
|
342
|
+
ORDER BY k.TABLE_NAME, k.CONSTRAINT_NAME, k.ORDINAL_POSITION`;
|
|
343
|
+
/** Reads the catalog rows of the connection's database, leaving out the runner's control tables. */
|
|
344
|
+
async function readMysqlCatalog(driver) {
|
|
345
|
+
const keep = (rows) => rows.filter((row) => !CONTROL_TABLE_NAMES.has(row.table_name));
|
|
346
|
+
const tables = await driver.query(TABLES);
|
|
347
|
+
const columns = await driver.query(COLUMNS);
|
|
348
|
+
const indexes = await driver.query(INDEXES);
|
|
349
|
+
const constraints = await driver.query(CONSTRAINTS);
|
|
350
|
+
const foreignKeys = await driver.query(FOREIGN_KEYS);
|
|
351
|
+
return {
|
|
352
|
+
tables: keep(tables.rows).map((row) => row.table_name),
|
|
353
|
+
columns: keep(columns.rows),
|
|
354
|
+
indexes: keep(indexes.rows),
|
|
355
|
+
constraints: keep(constraints.rows),
|
|
356
|
+
foreignKeys: keep(foreignKeys.rows)
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
const LEDGER_COLUMNS = "space, migration_name, migration_hash, origin_core_hash, destination_core_hash, operations, created_at";
|
|
360
|
+
function operationCount(operations) {
|
|
361
|
+
const parsed = typeof operations === "string" ? parseOperations(operations) : operations;
|
|
362
|
+
return Array.isArray(parsed) ? parsed.length : 0;
|
|
363
|
+
}
|
|
364
|
+
function parseOperations(text) {
|
|
365
|
+
try {
|
|
366
|
+
return JSON.parse(text);
|
|
367
|
+
} catch {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function text(row, column) {
|
|
372
|
+
const value = row[column];
|
|
373
|
+
return typeof value === "string" ? value : String(value);
|
|
374
|
+
}
|
|
375
|
+
/** The ledger's entries for `space`, or for every space, in the order they were applied. */
|
|
376
|
+
async function readLedgerEntries(driver, space) {
|
|
377
|
+
if (!await tableExists(driver, "_prisma_ledger")) return [];
|
|
378
|
+
const select = `SELECT ${LEDGER_COLUMNS} FROM ${quoteIdentifier(LEDGER_TABLE_NAME)}`;
|
|
379
|
+
const { rows } = space === void 0 ? await driver.query(`${select} ORDER BY id`) : await driver.query(`${select} WHERE space = ? ORDER BY id`, [space]);
|
|
380
|
+
return rows.map((row) => {
|
|
381
|
+
const origin = row["origin_core_hash"];
|
|
382
|
+
return {
|
|
383
|
+
space: text(row, "space"),
|
|
384
|
+
migrationName: text(row, "migration_name"),
|
|
385
|
+
migrationHash: text(row, "migration_hash"),
|
|
386
|
+
from: ledgerOriginFromStored(typeof origin === "string" ? origin : null),
|
|
387
|
+
to: text(row, "destination_core_hash"),
|
|
388
|
+
appliedAt: decodeMysqlDatetime(text(row, "created_at")),
|
|
389
|
+
operationCount: operationCount(row["operations"])
|
|
390
|
+
};
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
const MARKER_INSERT = `INSERT INTO ${quoteIdentifier(MARKER_TABLE_NAME)} (space, core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants) VALUES (?, ?, ?, NULL, NULL, CURRENT_TIMESTAMP(3), NULL, '{}', ?)`;
|
|
394
|
+
function markerInsertParams(space, destination) {
|
|
395
|
+
return [
|
|
396
|
+
space,
|
|
397
|
+
destination.storageHash,
|
|
398
|
+
destination.profileHash,
|
|
399
|
+
JSON.stringify(destination.invariants ?? [])
|
|
400
|
+
];
|
|
401
|
+
}
|
|
402
|
+
/** Inserts the marker row of `space`; fails when the space already has one. */
|
|
403
|
+
async function insertMarkerRow(driver, space, destination) {
|
|
404
|
+
await driver.query(MARKER_INSERT, markerInsertParams(space, destination));
|
|
405
|
+
}
|
|
406
|
+
/** Writes the marker row of `space`, replacing the row the space already has. */
|
|
407
|
+
async function upsertMarkerRow(driver, space, destination) {
|
|
408
|
+
await driver.query(`${MARKER_INSERT} AS incoming ON DUPLICATE KEY UPDATE core_hash = incoming.core_hash, profile_hash = incoming.profile_hash, contract_json = incoming.contract_json, canonical_version = incoming.canonical_version, updated_at = CURRENT_TIMESTAMP(3), app_tag = incoming.app_tag, meta = incoming.meta, invariants = incoming.invariants`, markerInsertParams(space, destination));
|
|
409
|
+
}
|
|
410
|
+
function invariantsOf(text) {
|
|
411
|
+
const parsed = parseJsonColumn("invariants", text);
|
|
412
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Advances the marker row of `space` from `expectedFrom` to `destination`, and says whether it did. MySQL has no `RETURNING`, so the row is read and locked with `FOR UPDATE` first, inside the transaction the caller holds, and written only when it still holds `expectedFrom`. Supplied invariants are merged with the stored ones.
|
|
416
|
+
*/
|
|
417
|
+
async function compareAndSwapMarkerRow(driver, space, expectedFrom, destination) {
|
|
418
|
+
const { rows } = await driver.query(`SELECT core_hash, invariants FROM ${quoteIdentifier(MARKER_TABLE_NAME)} WHERE space = ? FOR UPDATE`, [space]);
|
|
419
|
+
const [row] = rows;
|
|
420
|
+
if (row === void 0 || row["core_hash"] !== expectedFrom) return false;
|
|
421
|
+
const invariants = destination.invariants === void 0 ? void 0 : [.../* @__PURE__ */ new Set([...invariantsOf(row["invariants"]), ...destination.invariants])].sort();
|
|
422
|
+
await driver.query(`UPDATE ${quoteIdentifier(MARKER_TABLE_NAME)} SET core_hash = ?, profile_hash = ?, updated_at = CURRENT_TIMESTAMP(3)${invariants === void 0 ? "" : ", invariants = ?"} WHERE space = ? AND core_hash = ?`, [
|
|
423
|
+
destination.storageHash,
|
|
424
|
+
destination.profileHash,
|
|
425
|
+
...invariants === void 0 ? [] : [JSON.stringify(invariants)],
|
|
426
|
+
space,
|
|
427
|
+
expectedFrom
|
|
428
|
+
]);
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
/** Appends a ledger entry for `space`. */
|
|
432
|
+
async function insertLedgerRow(driver, space, entry) {
|
|
433
|
+
await driver.query(`INSERT INTO ${quoteIdentifier(LEDGER_TABLE_NAME)} (space, migration_name, migration_hash, origin_core_hash, destination_core_hash, operations) VALUES (?, ?, ?, ?, ?, ?)`, [
|
|
434
|
+
space,
|
|
435
|
+
entry.migrationName,
|
|
436
|
+
entry.migrationHash,
|
|
437
|
+
entry.from,
|
|
438
|
+
entry.to,
|
|
439
|
+
JSON.stringify(entry.operations)
|
|
440
|
+
]);
|
|
441
|
+
}
|
|
442
|
+
/** A DDL node MySQL does not build, such as one another target's visitor accepts. */
|
|
443
|
+
function unsupportedDdl(ast) {
|
|
444
|
+
return structuredError("RUNTIME.DDL_UNSUPPORTED", `The MySQL control adapter cannot lower the DDL node "${ast.kind}".`, { meta: {
|
|
445
|
+
surface: "control-adapter",
|
|
446
|
+
kind: ast.kind
|
|
447
|
+
} });
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* The MySQL control adapter. It introspects the connection's database from `information_schema`, creates, reads and writes the marker and ledger tables, takes the marker lock, and runs work in a transaction. Query lowering refuses with `RUNTIME.AST_UNSUPPORTED`.
|
|
451
|
+
*/
|
|
452
|
+
var MysqlControlAdapter = class {
|
|
453
|
+
codecRegistry;
|
|
454
|
+
declaredDataTypes;
|
|
455
|
+
familyId = "sql";
|
|
456
|
+
targetId = "mysql";
|
|
457
|
+
markerLocation = MARKER_TABLE_NAME;
|
|
458
|
+
/** `declaredDataTypes` are the stack's data types, which introspection resolves each column's reported type over. */
|
|
459
|
+
constructor(codecRegistry, declaredDataTypes) {
|
|
460
|
+
this.codecRegistry = codecRegistry;
|
|
461
|
+
this.declaredDataTypes = declaredDataTypes;
|
|
462
|
+
}
|
|
463
|
+
bootstrapControlTableQueries() {
|
|
464
|
+
return buildControlTableBootstrapQueries();
|
|
465
|
+
}
|
|
466
|
+
bootstrapSignMarkerQueries() {
|
|
467
|
+
return buildSignMarkerBootstrapQueries();
|
|
468
|
+
}
|
|
469
|
+
lower(ast) {
|
|
470
|
+
if (isDdlNode(ast)) throw structuredError("RUNTIME.DDL_UNSUPPORTED", "lower() cannot lower DDL: DDL default literals require inline codec encoding, which is async. Use lowerToExecuteRequest().", { meta: { surface: "control-adapter" } });
|
|
471
|
+
throw mysqlQueryNotYetSupported("Lowering queries");
|
|
472
|
+
}
|
|
473
|
+
async lowerToExecuteRequest(ast) {
|
|
474
|
+
if (!isDdlNode(ast)) throw mysqlQueryNotYetSupported("Lowering queries");
|
|
475
|
+
if (typeof ast.accept !== "function") throw unsupportedDdl(ast);
|
|
476
|
+
return ast.accept(new Proxy({ createTable: (node) => renderMysqlCreateTable(node, this.codecRegistry) }, { get: (target, method) => Reflect.get(target, method) ?? (() => Promise.reject(unsupportedDdl(ast))) }));
|
|
477
|
+
}
|
|
478
|
+
async renderColumnDefault(column, table) {
|
|
479
|
+
if (column.default === void 0) return "";
|
|
480
|
+
return renderMysqlColumnDefault(column.default, column.type, this.codecRegistry, column.codecRef, {
|
|
481
|
+
table,
|
|
482
|
+
column: column.name
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
async readMarker(driver, space) {
|
|
486
|
+
const result = await readMarkerResult(driver, space);
|
|
487
|
+
return result.kind === "present" ? result.record : null;
|
|
488
|
+
}
|
|
489
|
+
async readAllMarkers(driver) {
|
|
490
|
+
return withMarkerReadErrorHandling(async () => {
|
|
491
|
+
const markers = /* @__PURE__ */ new Map();
|
|
492
|
+
for (const row of await readMarkerRows(driver, void 0) ?? []) {
|
|
493
|
+
const space = String(row["space"]);
|
|
494
|
+
markers.set(space, parseMarkerRowSafely(row, () => decodeMysqlMarkerRow(row), {
|
|
495
|
+
space,
|
|
496
|
+
markerLocation: MARKER_TABLE_NAME
|
|
497
|
+
}));
|
|
498
|
+
}
|
|
499
|
+
return markers;
|
|
500
|
+
}, {
|
|
501
|
+
space: APP_SPACE_ID,
|
|
502
|
+
markerLocation: MARKER_TABLE_NAME
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
async readLedger(driver, space) {
|
|
506
|
+
return withMarkerReadErrorHandling(() => readLedgerEntries(driver, space), {
|
|
507
|
+
space: space ?? "*",
|
|
508
|
+
markerLocation: LEDGER_TABLE_NAME
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
async insertMarker(driver, space, destination) {
|
|
512
|
+
await insertMarkerRow(driver, space, destination);
|
|
513
|
+
}
|
|
514
|
+
async initMarker(driver, space, destination) {
|
|
515
|
+
await upsertMarkerRow(driver, space, destination);
|
|
516
|
+
}
|
|
517
|
+
async updateMarker(driver, space, expectedFrom, destination) {
|
|
518
|
+
return compareAndSwapMarkerRow(driver, space, expectedFrom, destination);
|
|
519
|
+
}
|
|
520
|
+
async writeLedgerEntry(driver, space, entry) {
|
|
521
|
+
await insertLedgerRow(driver, space, entry);
|
|
522
|
+
}
|
|
523
|
+
/** Takes no lock: MySQL's `GET_LOCK` lives for the session, not the transaction, so {@link holdMarkerLock} takes it around the transaction instead. */
|
|
524
|
+
async lockMarker(_driver) {}
|
|
525
|
+
/** Takes `GET_LOCK` before `work` runs and releases it when `work` ends, so `db sign` creates the marker table, whose DDL would end a transaction, under the lock. */
|
|
526
|
+
async holdMarkerLock(driver, work) {
|
|
527
|
+
return withMarkerLock(driver, work);
|
|
528
|
+
}
|
|
529
|
+
async withTransaction(driver, fn) {
|
|
530
|
+
return this.#inTransaction(driver, fn);
|
|
531
|
+
}
|
|
532
|
+
async #inTransaction(driver, fn) {
|
|
533
|
+
await driver.query("START TRANSACTION");
|
|
534
|
+
let result;
|
|
535
|
+
try {
|
|
536
|
+
result = await fn();
|
|
537
|
+
} catch (error) {
|
|
538
|
+
try {
|
|
539
|
+
await driver.query("ROLLBACK");
|
|
540
|
+
} catch (rollbackError) {
|
|
541
|
+
if (error instanceof Error && error.cause === void 0) error.cause = rollbackError;
|
|
542
|
+
}
|
|
543
|
+
throw error;
|
|
544
|
+
}
|
|
545
|
+
await driver.query("COMMIT");
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
async introspect(driver, contract) {
|
|
549
|
+
const columns = contractColumns(contract);
|
|
550
|
+
return buildMysqlSchemaIR(await readMysqlCatalog(driver), this.declaredDataTypes, async (tableName, columnName, rawDefault) => {
|
|
551
|
+
const column = columns.columnOf(void 0, tableName, columnName);
|
|
552
|
+
const codec = column === void 0 ? void 0 : codecForRef(this.codecRegistry, column.codecRef);
|
|
553
|
+
if (codec === void 0) return {};
|
|
554
|
+
return readColumnDefault(codec, {
|
|
555
|
+
literal: {
|
|
556
|
+
kind: "value",
|
|
557
|
+
body: rawDefault
|
|
558
|
+
},
|
|
559
|
+
raw: rawDefault
|
|
560
|
+
}, void 0);
|
|
561
|
+
}, declaredIndexes(contract));
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
const mysqlAdapterDescriptor = {
|
|
565
|
+
...mysqlAdapterDescriptorMeta,
|
|
566
|
+
controlMutationDefaults: {
|
|
567
|
+
defaultFunctionRegistry: new Map(Object.entries(sqlDefaultFunctions())),
|
|
568
|
+
generatorDescriptors: []
|
|
569
|
+
},
|
|
570
|
+
create(stack) {
|
|
571
|
+
return new MysqlControlAdapter(assembleMysqlCodecRegistry(stack.target, stack.extensions), stack.declaredDataTypes.map(({ type }) => type));
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
//#endregion
|
|
575
|
+
export { buildMysqlSchemaIR as n, mysqlAdapterDescriptor as r, MysqlControlAdapter as t };
|
|
576
|
+
|
|
577
|
+
//# sourceMappingURL=control-WTY7Jpxk.mjs.map
|