@prisma/orm-target-sqlite 0.16.0-dev.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +23 -0
- package/dist/adapter-DizMsGCb-n4h4w8ms.d.mts +22 -0
- package/dist/adapter-DizMsGCb-n4h4w8ms.d.mts.map +1 -0
- package/dist/adapter-m_BtnNSn.d.mts +2 -0
- package/dist/adapter-wc9p_v2Z-y8pzqMfG.mjs +997 -0
- package/dist/adapter-wc9p_v2Z-y8pzqMfG.mjs.map +1 -0
- package/dist/adapter.d.mts +14 -0
- package/dist/adapter.mjs +6 -0
- package/dist/adapter__adapter.d.mts +4 -0
- package/dist/adapter__adapter.mjs +2 -0
- package/dist/adapter__codec-types.d.mts +4 -0
- package/dist/adapter__codec-types.mjs +1 -0
- package/dist/adapter__column-types.d.mts +2 -0
- package/dist/adapter__column-types.mjs +2 -0
- package/dist/adapter__control.d.mts +5 -0
- package/dist/adapter__control.mjs +261 -0
- package/dist/adapter__control.mjs.map +1 -0
- package/dist/adapter__runtime.d.mts +2 -0
- package/dist/adapter__runtime.mjs +32 -0
- package/dist/adapter__runtime.mjs.map +1 -0
- package/dist/adapter__types.d.mts +3 -0
- package/dist/adapter__types.mjs +1 -0
- package/dist/codec-descriptor-BcgD9f3L-BjEkn9Ob.d.mts +31 -0
- package/dist/codec-descriptor-BcgD9f3L-BjEkn9Ob.d.mts.map +1 -0
- package/dist/codec-descriptor-CyCQXvSl.d.mts +2 -0
- package/dist/codec-descriptor-kVCSW1OR-CPatZUPM.mjs +104 -0
- package/dist/codec-descriptor-kVCSW1OR-CPatZUPM.mjs.map +1 -0
- package/dist/codec-descriptor-rFuZ9DzY-DO0k8l6N.d.mts +1 -0
- package/dist/codec-ids-ChRBs2aB.d.mts +1 -0
- package/dist/codec-ids-DocGjhs--CHhP1jNZ.d.mts +13 -0
- package/dist/codec-ids-DocGjhs--CHhP1jNZ.d.mts.map +1 -0
- package/dist/codec-ids-xicqpuAa-DHnKqnIs.mjs +13 -0
- package/dist/codec-ids-xicqpuAa-DHnKqnIs.mjs.map +1 -0
- package/dist/codec-types-DKB--ltR-CIuvX0zx.d.mts +24 -0
- package/dist/codec-types-DKB--ltR-CIuvX0zx.d.mts.map +1 -0
- package/dist/codec-types-Tw3EFTjf.d.mts +1 -0
- package/dist/codec-types-wPDlPoD7.d.mts +2 -0
- package/dist/codecs-1-oOsTPG-Bv518Lbm.d.mts +155 -0
- package/dist/codecs-1-oOsTPG-Bv518Lbm.d.mts.map +1 -0
- package/dist/codecs-CM_2W3uA.mjs +345 -0
- package/dist/codecs-CM_2W3uA.mjs.map +1 -0
- package/dist/codecs-j-8RDkOt.d.mts +1 -0
- package/dist/column-types-StKUDF6A.mjs +34 -0
- package/dist/column-types-StKUDF6A.mjs.map +1 -0
- package/dist/column-types-iWGuW-0W.d.mts +33 -0
- package/dist/column-types-iWGuW-0W.d.mts.map +1 -0
- package/dist/contract-free-CCLAXZV2.d.mts +88 -0
- package/dist/contract-free-CCLAXZV2.d.mts.map +1 -0
- package/dist/contract-free-DElSXD0q.mjs +90 -0
- package/dist/contract-free-DElSXD0q.mjs.map +1 -0
- package/dist/control--wMueaTg.d.mts +61 -0
- package/dist/control--wMueaTg.d.mts.map +1 -0
- package/dist/control-8G9x72lw.mjs +42 -0
- package/dist/control-8G9x72lw.mjs.map +1 -0
- package/dist/control-DLO163u8.d.mts +19 -0
- package/dist/control-DLO163u8.d.mts.map +1 -0
- package/dist/control-cahq7u71.d.mts +117 -0
- package/dist/control-cahq7u71.d.mts.map +1 -0
- package/dist/control-tables-D_o8dKRB-BXi43noL.mjs +12 -0
- package/dist/control-tables-D_o8dKRB-BXi43noL.mjs.map +1 -0
- package/dist/control-tables-Dua-YcJL.d.mts +12 -0
- package/dist/control-tables-Dua-YcJL.d.mts.map +1 -0
- package/dist/ddl-CW34JvfE-rd1ZIxOn.mjs +66 -0
- package/dist/ddl-CW34JvfE-rd1ZIxOn.mjs.map +1 -0
- package/dist/ddl-CfSqNT0M.d.mts +1 -0
- package/dist/default-normalizer-B9V7TY5u.d.mts +7 -0
- package/dist/default-normalizer-B9V7TY5u.d.mts.map +1 -0
- package/dist/default-normalizer-DuoHj9-O-DsK7lJZn.mjs +69 -0
- package/dist/default-normalizer-DuoHj9-O-DsK7lJZn.mjs.map +1 -0
- package/dist/descriptor-meta-CbYkqTkO-DEJNrICG.mjs +30 -0
- package/dist/descriptor-meta-CbYkqTkO-DEJNrICG.mjs.map +1 -0
- package/dist/descriptor-meta-DnwDwnGg-D3f936hn.mjs +23 -0
- package/dist/descriptor-meta-DnwDwnGg-D3f936hn.mjs.map +1 -0
- package/dist/descriptor-meta-runtime-BkXK3OjD-CxZdKHCw.mjs +13 -0
- package/dist/descriptor-meta-runtime-BkXK3OjD-CxZdKHCw.mjs.map +1 -0
- package/dist/descriptor-meta-vjJkUDsn-Hz3rnAnk.mjs +70 -0
- package/dist/descriptor-meta-vjJkUDsn-Hz3rnAnk.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 +197 -0
- package/dist/driver__runtime.mjs.map +1 -0
- package/dist/errors-CKsaaSnD-BeB4JS8h.mjs +38 -0
- package/dist/errors-CKsaaSnD-BeB4JS8h.mjs.map +1 -0
- package/dist/migration-jsmNRI_8.mjs +47 -0
- package/dist/migration-jsmNRI_8.mjs.map +1 -0
- package/dist/migration-uylRe5MP.d.mts +43 -0
- package/dist/migration-uylRe5MP.d.mts.map +1 -0
- package/dist/native-type-normalizer-CO2wKGL6.d.mts +12 -0
- package/dist/native-type-normalizer-CO2wKGL6.d.mts.map +1 -0
- package/dist/native-type-normalizer-GpQMEyN5.mjs +14 -0
- package/dist/native-type-normalizer-GpQMEyN5.mjs.map +1 -0
- package/dist/nodes-D8EC1yCx-rpfpuJ4T.d.mts +29 -0
- package/dist/nodes-D8EC1yCx-rpfpuJ4T.d.mts.map +1 -0
- package/dist/nodes-DUZSdX86-BBEEaxXY.mjs +33 -0
- package/dist/nodes-DUZSdX86-BBEEaxXY.mjs.map +1 -0
- package/dist/op-factory-call-C_or6163-B_LDzC37.mjs +829 -0
- package/dist/op-factory-call-C_or6163-B_LDzC37.mjs.map +1 -0
- package/dist/op-factory-call-DoHN7Q7L.d.mts +161 -0
- package/dist/op-factory-call-DoHN7Q7L.d.mts.map +1 -0
- package/dist/pack-BfwyQ0b3.d.mts +93 -0
- package/dist/pack-BfwyQ0b3.d.mts.map +1 -0
- package/dist/planner-Bxdi7jZF.d.mts +104 -0
- package/dist/planner-Bxdi7jZF.d.mts.map +1 -0
- package/dist/planner-DiGcIjl1-QnNAhVmX.mjs +811 -0
- package/dist/planner-DiGcIjl1-QnNAhVmX.mjs.map +1 -0
- package/dist/planner-produced-sqlite-migration-BuJysRxx-CaDUbNVx.d.mts +31 -0
- package/dist/planner-produced-sqlite-migration-BuJysRxx-CaDUbNVx.d.mts.map +1 -0
- package/dist/planner-produced-sqlite-migration-C8nxPT0P-DdBqfmAD.mjs +150 -0
- package/dist/planner-produced-sqlite-migration-C8nxPT0P-DdBqfmAD.mjs.map +1 -0
- package/dist/planner-produced-sqlite-migration-uySoqJO-.d.mts +1 -0
- package/dist/planner-target-details-CIQ789Gc-C5U4yVY9.mjs +15 -0
- package/dist/planner-target-details-CIQ789Gc-C5U4yVY9.mjs.map +1 -0
- package/dist/planner-target-details-xR6UfIcz-CMahymzq.d.mts +13 -0
- package/dist/planner-target-details-xR6UfIcz-CMahymzq.d.mts.map +1 -0
- package/dist/render-ops-B10yqmdG.d.mts +11 -0
- package/dist/render-ops-B10yqmdG.d.mts.map +1 -0
- package/dist/render-ops-DIOn_wOx-D33LOy3b.mjs +27 -0
- package/dist/render-ops-DIOn_wOx-D33LOy3b.mjs.map +1 -0
- package/dist/runtime-B1coahKC.d.mts +15 -0
- package/dist/runtime-B1coahKC.d.mts.map +1 -0
- package/dist/runtime-B99c4n56.d.mts +28 -0
- package/dist/runtime-B99c4n56.d.mts.map +1 -0
- package/dist/runtime-tbBYTw7Z.d.mts +10 -0
- package/dist/runtime-tbBYTw7Z.d.mts.map +1 -0
- package/dist/shared-BYAX0FaQ--VvRXVRC.d.mts +68 -0
- package/dist/shared-BYAX0FaQ--VvRXVRC.d.mts.map +1 -0
- package/dist/sql-utils-0SJZOd7Q.d.mts +18 -0
- package/dist/sql-utils-0SJZOd7Q.d.mts.map +1 -0
- package/dist/sql-utils-DqPXZBMA-Mm27NNjs.mjs +35 -0
- package/dist/sql-utils-DqPXZBMA-Mm27NNjs.mjs.map +1 -0
- package/dist/sqlite-contract-view-BpNMaU2m-COMDaGaq.d.mts +31 -0
- package/dist/sqlite-contract-view-BpNMaU2m-COMDaGaq.d.mts.map +1 -0
- package/dist/sqlite-contract-view-CnDITHEE-BvjSbmzL.mjs +151 -0
- package/dist/sqlite-contract-view-CnDITHEE-BvjSbmzL.mjs.map +1 -0
- package/dist/sqlite-migration-CV6LIqhx-D5eMTAbH.mjs +94 -0
- package/dist/sqlite-migration-CV6LIqhx-D5eMTAbH.mjs.map +1 -0
- package/dist/sqlite-migration-o23JHwzY-CwNJcqwl.d.mts +105 -0
- package/dist/sqlite-migration-o23JHwzY-CwNJcqwl.d.mts.map +1 -0
- package/dist/target.d.mts +28 -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 +2 -0
- package/dist/target__codec-types.d.mts +4 -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 +432 -0
- package/dist/target__control.mjs.map +1 -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__migration.d.mts +3 -0
- package/dist/target__migration.mjs +3 -0
- package/dist/target__native-type-normalizer.d.mts +2 -0
- package/dist/target__native-type-normalizer.mjs +2 -0
- package/dist/target__op-factory-call.d.mts +2 -0
- package/dist/target__op-factory-call.mjs +2 -0
- package/dist/target__pack.d.mts +2 -0
- package/dist/target__pack.mjs +2 -0
- package/dist/target__planner-produced-sqlite-migration.d.mts +3 -0
- package/dist/target__planner-produced-sqlite-migration.mjs +2 -0
- package/dist/target__planner-target-details.d.mts +2 -0
- package/dist/target__planner-target-details.mjs +2 -0
- package/dist/target__planner.d.mts +2 -0
- package/dist/target__planner.mjs +2 -0
- package/dist/target__render-ops.d.mts +2 -0
- package/dist/target__render-ops.mjs +2 -0
- package/dist/target__runtime.d.mts +3 -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 +2 -0
- package/dist/types-C5FSREvo-Bm6N5Kog.d.mts +25 -0
- package/dist/types-C5FSREvo-Bm6N5Kog.d.mts.map +1 -0
- package/dist/types-DiH2oWUJ.d.mts +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
import { n as buildSqliteCodecDescriptorRegistry } from "./codec-descriptor-kVCSW1OR-CPatZUPM.mjs";
|
|
2
|
+
import { r as SQLITE_DATETIME_CODEC_ID } from "./codec-ids-xicqpuAa-DHnKqnIs.mjs";
|
|
3
|
+
import { a as sqliteCodecRegistry, i as sqliteCodecDescriptorRegistry, t as jsonDocumentRetag } from "./codecs-CM_2W3uA.mjs";
|
|
4
|
+
import { a as jsonText, i as integer, n as buildSignMarkerBootstrapQueries, o as sqliteTable, r as datetime, s as text, t as buildControlTableBootstrapQueries } from "./contract-free-DElSXD0q.mjs";
|
|
5
|
+
import { n as quoteIdentifier, t as escapeLiteral } from "./sql-utils-DqPXZBMA-Mm27NNjs.mjs";
|
|
6
|
+
import { t as parseSqliteDefault } from "./default-normalizer-DuoHj9-O-DsK7lJZn.mjs";
|
|
7
|
+
import { t as normalizeSqliteNativeType } from "./native-type-normalizer-GpQMEyN5.mjs";
|
|
8
|
+
import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
9
|
+
import { structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
10
|
+
import { RawExpr, isDdlNode } from "@prisma/orm-family-sql/relational-core/ast";
|
|
11
|
+
import { APP_SPACE_ID, extractCodecLookup } from "@prisma/orm-framework/components/control";
|
|
12
|
+
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
13
|
+
import { RelationalSchemaNodeKind, SqlSchemaIR, SqlTableIR } from "@prisma/orm-family-sql/schema-ir/types";
|
|
14
|
+
import { REFERENTIAL_ACTION_SQL } from "@prisma/orm-family-sql/contract/referential-action-sql";
|
|
15
|
+
import { InternalError, assertNever } from "@prisma/orm-framework/utils/internal-error";
|
|
16
|
+
import { parseMarkerRowSafely, withMarkerReadErrorHandling } from "@prisma/orm-framework/errors/execution";
|
|
17
|
+
import { parseContractMarkerRow } from "@prisma/orm-family-sql/family/verify";
|
|
18
|
+
import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma/orm-family-sql/runtime";
|
|
19
|
+
//#region ../../../3-targets/6-adapters/sqlite/dist/adapter-wc9p_v2Z.mjs
|
|
20
|
+
function descriptorsFrom(contributors) {
|
|
21
|
+
return contributors.flatMap((contributor) => contributor.types?.codecTypes?.codecDescriptors ?? []);
|
|
22
|
+
}
|
|
23
|
+
function buildSqliteCodecRegistry(descriptors) {
|
|
24
|
+
const descriptorRegistry = buildSqliteCodecDescriptorRegistry(descriptors);
|
|
25
|
+
const registry = {
|
|
26
|
+
...extractCodecLookup([{
|
|
27
|
+
id: "sqlite-codecs",
|
|
28
|
+
types: { codecTypes: { codecDescriptors: Array.from(descriptorRegistry.values()) } }
|
|
29
|
+
}]),
|
|
30
|
+
descriptorFor: (codecId) => descriptorRegistry.descriptorFor(codecId),
|
|
31
|
+
values: () => descriptorRegistry.values()
|
|
32
|
+
};
|
|
33
|
+
return Object.freeze(registry);
|
|
34
|
+
}
|
|
35
|
+
function assembleSqliteCodecRegistry(target, extensions) {
|
|
36
|
+
return buildSqliteCodecRegistry([
|
|
37
|
+
...descriptorsFrom([target]),
|
|
38
|
+
...sqliteCodecDescriptorRegistry.values(),
|
|
39
|
+
...descriptorsFrom(extensions)
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
function createSqliteCodecRegistryWithBuiltins(codecDescriptors = []) {
|
|
43
|
+
return buildSqliteCodecRegistry([...sqliteCodecDescriptorRegistry.values(), ...codecDescriptors]);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build a coherent SQLite codec registry populated with built-in descriptors only.
|
|
47
|
+
*
|
|
48
|
+
* The returned registry supports both ordinary codec materialization and SQLite target behavior. Stack-composed paths build the same combined registry from target, full adapter, and ordered extension contributions.
|
|
49
|
+
*/
|
|
50
|
+
function createSqliteBuiltinCodecLookup() {
|
|
51
|
+
return createSqliteCodecRegistryWithBuiltins();
|
|
52
|
+
}
|
|
53
|
+
function ledgerOriginFromStored(originCoreHash) {
|
|
54
|
+
if (originCoreHash === null || originCoreHash === "" || originCoreHash === "empty") return null;
|
|
55
|
+
return originCoreHash;
|
|
56
|
+
}
|
|
57
|
+
const CONTROL_CODECS = createAstCodecRegistry(sqliteCodecRegistry);
|
|
58
|
+
async function encodeControlQueryParams(lowered, ast, codecs = CONTROL_CODECS) {
|
|
59
|
+
return encodeParamsWithMetadata(lowered.params.map((slot) => {
|
|
60
|
+
if (slot.kind === "literal") return slot.value;
|
|
61
|
+
throw new InternalError(`control query lowered to a bind slot '${slot.name}', which is unsupported`);
|
|
62
|
+
}), deriveParamMetadata(ast), {}, codecs);
|
|
63
|
+
}
|
|
64
|
+
const DESIGNATOR_LESS_UTC_DATETIME = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?$/;
|
|
65
|
+
function coerceLedgerAppliedAt(value) {
|
|
66
|
+
if (value instanceof Date) return value;
|
|
67
|
+
if (DESIGNATOR_LESS_UTC_DATETIME.test(value)) return /* @__PURE__ */ new Date(`${value.replace(" ", "T")}Z`);
|
|
68
|
+
return new Date(value);
|
|
69
|
+
}
|
|
70
|
+
function operationCountFromStored(operations) {
|
|
71
|
+
if (Array.isArray(operations)) return operations.length;
|
|
72
|
+
if (typeof operations === "string") try {
|
|
73
|
+
const parsed = JSON.parse(operations);
|
|
74
|
+
return Array.isArray(parsed) ? parsed.length : 0;
|
|
75
|
+
} catch {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
const marker = sqliteTable("_prisma_marker", {
|
|
81
|
+
space: text(),
|
|
82
|
+
core_hash: text(),
|
|
83
|
+
profile_hash: text(),
|
|
84
|
+
contract_json: jsonText({ nullable: true }),
|
|
85
|
+
canonical_version: integer({ nullable: true }),
|
|
86
|
+
updated_at: datetime(),
|
|
87
|
+
app_tag: text({ nullable: true }),
|
|
88
|
+
meta: jsonText({ nullable: true }),
|
|
89
|
+
invariants: jsonText()
|
|
90
|
+
});
|
|
91
|
+
/**
|
|
92
|
+
* Writeable subset of `_prisma_ledger`. Omits the DB-generated `id`
|
|
93
|
+
* (`INTEGER PRIMARY KEY AUTOINCREMENT`) and `created_at` (default
|
|
94
|
+
* `strftime(...)`).
|
|
95
|
+
*/
|
|
96
|
+
const ledger = sqliteTable("_prisma_ledger", {
|
|
97
|
+
space: text(),
|
|
98
|
+
migration_name: text(),
|
|
99
|
+
migration_hash: text(),
|
|
100
|
+
origin_core_hash: text({ nullable: true }),
|
|
101
|
+
destination_core_hash: text(),
|
|
102
|
+
operations: jsonText()
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* Read-side handle covering every column of `_prisma_ledger`, including
|
|
106
|
+
* the DB-generated `id` (for ORDER BY) and `created_at`.
|
|
107
|
+
*/
|
|
108
|
+
const ledgerReadShape = sqliteTable("_prisma_ledger", {
|
|
109
|
+
id: integer(),
|
|
110
|
+
space: text(),
|
|
111
|
+
migration_name: text(),
|
|
112
|
+
migration_hash: text(),
|
|
113
|
+
origin_core_hash: text({ nullable: true }),
|
|
114
|
+
destination_core_hash: text(),
|
|
115
|
+
operations: jsonText(),
|
|
116
|
+
created_at: text()
|
|
117
|
+
});
|
|
118
|
+
const sqliteCatalog = sqliteTable("sqlite_master", {
|
|
119
|
+
type: text(),
|
|
120
|
+
name: text()
|
|
121
|
+
});
|
|
122
|
+
const NOW = new RawExpr({
|
|
123
|
+
parts: ["datetime('now')"],
|
|
124
|
+
returns: {
|
|
125
|
+
codecId: SQLITE_DATETIME_CODEC_ID,
|
|
126
|
+
nullable: false
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
function mergeInvariants(current, incoming) {
|
|
130
|
+
return [.../* @__PURE__ */ new Set([...current, ...incoming])].sort();
|
|
131
|
+
}
|
|
132
|
+
async function execute(lower, driver, query) {
|
|
133
|
+
const lowered = lower(query);
|
|
134
|
+
const encoded = await encodeControlQueryParams(lowered, query);
|
|
135
|
+
return (await driver.query(lowered.sql, encoded)).rows;
|
|
136
|
+
}
|
|
137
|
+
function decodeSqliteMarkerRow(row) {
|
|
138
|
+
if (typeof row !== "object" || row === null || !("invariants" in row)) return row;
|
|
139
|
+
const record = row;
|
|
140
|
+
if (typeof record.invariants !== "string") return row;
|
|
141
|
+
let parsed;
|
|
142
|
+
try {
|
|
143
|
+
parsed = JSON.parse(record.invariants);
|
|
144
|
+
} catch (err) {
|
|
145
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
146
|
+
throw structuredError("CONTRACT.MARKER_ROW_CORRUPT", `Invalid contract marker row: invariants is not valid JSON: ${detail}`, {
|
|
147
|
+
meta: { detail },
|
|
148
|
+
cause: err
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
...record,
|
|
153
|
+
invariants: parsed
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const SQLITE_MARKER_TABLE = "_prisma_marker";
|
|
157
|
+
const SQLITE_LEDGER_TABLE = "_prisma_ledger";
|
|
158
|
+
var SqliteControlAdapter = class {
|
|
159
|
+
familyId = "sql";
|
|
160
|
+
targetId = "sqlite";
|
|
161
|
+
codecRegistry;
|
|
162
|
+
constructor(codecRegistry) {
|
|
163
|
+
this.codecRegistry = codecRegistry;
|
|
164
|
+
}
|
|
165
|
+
normalizeDefault = parseSqliteDefault;
|
|
166
|
+
normalizeNativeType = normalizeSqliteNativeType;
|
|
167
|
+
bootstrapControlTableQueries() {
|
|
168
|
+
return buildControlTableBootstrapQueries();
|
|
169
|
+
}
|
|
170
|
+
bootstrapSignMarkerQueries() {
|
|
171
|
+
return buildSignMarkerBootstrapQueries();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Lower a SQL query AST into a SQLite-flavored `{ sql, params }` payload.
|
|
175
|
+
*
|
|
176
|
+
* Delegates to the shared `renderLoweredSql` renderer so the control adapter
|
|
177
|
+
* emits byte-identical SQL to `SqliteAdapterImpl.lower()` for the same AST
|
|
178
|
+
* and contract. Used at migration plan/emit time (e.g. by `dataTransform`)
|
|
179
|
+
* without instantiating the runtime adapter.
|
|
180
|
+
*/
|
|
181
|
+
lower(ast, context) {
|
|
182
|
+
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" } });
|
|
183
|
+
return renderLoweredSql(ast, blindCast(context.contract), this.codecRegistry);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Lower an AST all the way to a driver-ready statement. For DDL nodes,
|
|
187
|
+
* literal column defaults are formatted as inline SQL with SQLite-specific
|
|
188
|
+
* literal syntax (no cast suffix, boolean as 0/1, blob via X'hex'). For
|
|
189
|
+
* query ASTs, params are kept as `?` placeholders; wire values go in
|
|
190
|
+
* `params`. Does NOT call `this.lower()` — independent implementation.
|
|
191
|
+
*/
|
|
192
|
+
async lowerToExecuteRequest(ast, context) {
|
|
193
|
+
if (isDdlNode(ast)) return sqliteRenderDdlExecuteRequest(blindCast(ast), this.codecRegistry);
|
|
194
|
+
const lowered = renderLoweredSql(ast, blindCast(context?.contract), this.codecRegistry);
|
|
195
|
+
const params = await encodeControlQueryParams(lowered, ast, blindCast(this.codecRegistry));
|
|
196
|
+
return {
|
|
197
|
+
sql: lowered.sql,
|
|
198
|
+
params
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Reads the contract marker from `_prisma_marker`. Probes `sqlite_master`
|
|
203
|
+
* first so a fresh database (no marker table) returns `null` instead of a
|
|
204
|
+
* "no such table" error.
|
|
205
|
+
*/
|
|
206
|
+
async readMarker(driver, space) {
|
|
207
|
+
const result = await this.readMarkerDiscriminated(driver, space);
|
|
208
|
+
return result.kind === "present" ? result.record : null;
|
|
209
|
+
}
|
|
210
|
+
async readMarkerDiscriminated(driver, space) {
|
|
211
|
+
return withMarkerReadErrorHandling(() => this.readMarkerResult(driver, space), {
|
|
212
|
+
space,
|
|
213
|
+
markerLocation: SQLITE_MARKER_TABLE
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Reads every row from `_prisma_marker` and returns them keyed by
|
|
218
|
+
* `space`. Mirrors the existence probe in {@link readMarker}: a
|
|
219
|
+
* fresh database without the marker table returns an empty map.
|
|
220
|
+
*/
|
|
221
|
+
async readAllMarkers(driver) {
|
|
222
|
+
return withMarkerReadErrorHandling(() => this.readAllMarkersResult(driver), {
|
|
223
|
+
space: APP_SPACE_ID,
|
|
224
|
+
markerLocation: SQLITE_MARKER_TABLE
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async readAllMarkersResult(driver) {
|
|
228
|
+
const lower = (query) => this.lower(query, { contract: void 0 });
|
|
229
|
+
if ((await execute(lower, driver, sqliteCatalog.select(sqliteCatalog.name).where(sqliteCatalog.type.eq("table").and(sqliteCatalog.name.eq("_prisma_marker"))).build())).length === 0) return /* @__PURE__ */ new Map();
|
|
230
|
+
const rows = blindCast(await execute(lower, driver, marker.select(marker.space, marker.core_hash, marker.profile_hash, marker.contract_json, marker.canonical_version, marker.updated_at, marker.app_tag, marker.meta, marker.invariants).build()));
|
|
231
|
+
const out = /* @__PURE__ */ new Map();
|
|
232
|
+
for (const row of rows) out.set(row.space, parseMarkerRowSafely(row, (raw) => parseContractMarkerRow(decodeSqliteMarkerRow(raw)), {
|
|
233
|
+
space: row.space,
|
|
234
|
+
markerLocation: SQLITE_MARKER_TABLE
|
|
235
|
+
}));
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Reads per-migration ledger rows from `_prisma_ledger` in apply order.
|
|
240
|
+
* Probes `sqlite_master` first so a fresh database without the ledger
|
|
241
|
+
* table returns `[]` instead of raising "no such table".
|
|
242
|
+
*/
|
|
243
|
+
async readLedger(driver, space) {
|
|
244
|
+
return withMarkerReadErrorHandling(() => this.readLedgerResult(driver, space), {
|
|
245
|
+
space: space ?? "*",
|
|
246
|
+
markerLocation: SQLITE_LEDGER_TABLE
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async readLedgerResult(driver, space) {
|
|
250
|
+
const lower = (query) => this.lower(query, { contract: void 0 });
|
|
251
|
+
if ((await execute(lower, driver, sqliteCatalog.select(sqliteCatalog.name).where(sqliteCatalog.type.eq("table").and(sqliteCatalog.name.eq("_prisma_ledger"))).build())).length === 0) return [];
|
|
252
|
+
const base = ledgerReadShape.select(ledgerReadShape.space, ledgerReadShape.migration_name, ledgerReadShape.migration_hash, ledgerReadShape.origin_core_hash, ledgerReadShape.destination_core_hash, ledgerReadShape.operations, ledgerReadShape.created_at);
|
|
253
|
+
return blindCast(await execute(lower, driver, (space !== void 0 ? base.where(ledgerReadShape.space.eq(space)) : base).orderBy(ledgerReadShape.id).build())).map((row) => ({
|
|
254
|
+
space: row.space,
|
|
255
|
+
migrationName: row.migration_name,
|
|
256
|
+
migrationHash: row.migration_hash,
|
|
257
|
+
from: ledgerOriginFromStored(row.origin_core_hash),
|
|
258
|
+
to: row.destination_core_hash,
|
|
259
|
+
appliedAt: coerceLedgerAppliedAt(row.created_at),
|
|
260
|
+
operationCount: operationCountFromStored(row.operations)
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Stamps the initial marker row for `space` via the shared contract-free DML
|
|
265
|
+
* builder, lowered through {@link lower} and executed on the driver. See the
|
|
266
|
+
* `SqlControlAdapter.initMarker` contract.
|
|
267
|
+
*/
|
|
268
|
+
async insertMarker(driver, space, destination) {
|
|
269
|
+
await execute((query) => this.lower(query, { contract: void 0 }), driver, marker.insert({
|
|
270
|
+
space,
|
|
271
|
+
core_hash: destination.storageHash,
|
|
272
|
+
profile_hash: destination.profileHash,
|
|
273
|
+
contract_json: null,
|
|
274
|
+
canonical_version: null,
|
|
275
|
+
updated_at: NOW,
|
|
276
|
+
app_tag: null,
|
|
277
|
+
meta: {},
|
|
278
|
+
invariants: destination.invariants ?? []
|
|
279
|
+
}).build());
|
|
280
|
+
}
|
|
281
|
+
async initMarker(driver, space, destination) {
|
|
282
|
+
await execute((query) => this.lower(query, { contract: void 0 }), driver, marker.upsert({
|
|
283
|
+
space,
|
|
284
|
+
core_hash: destination.storageHash,
|
|
285
|
+
profile_hash: destination.profileHash,
|
|
286
|
+
contract_json: null,
|
|
287
|
+
canonical_version: null,
|
|
288
|
+
updated_at: NOW,
|
|
289
|
+
app_tag: null,
|
|
290
|
+
meta: {},
|
|
291
|
+
invariants: destination.invariants ?? []
|
|
292
|
+
}).onConflict(marker.space).doUpdate((excluded) => ({
|
|
293
|
+
core_hash: excluded.core_hash,
|
|
294
|
+
profile_hash: excluded.profile_hash,
|
|
295
|
+
contract_json: excluded.contract_json,
|
|
296
|
+
canonical_version: excluded.canonical_version,
|
|
297
|
+
updated_at: NOW,
|
|
298
|
+
app_tag: excluded.app_tag,
|
|
299
|
+
meta: excluded.meta,
|
|
300
|
+
invariants: excluded.invariants
|
|
301
|
+
})).build());
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Compare-and-swap advance of the marker row for `space`. See the
|
|
305
|
+
* `SqlControlAdapter.updateMarker` contract.
|
|
306
|
+
*/
|
|
307
|
+
async updateMarker(driver, space, expectedFrom, destination) {
|
|
308
|
+
const currentInvariants = destination.invariants === void 0 ? [] : (await this.readMarker(driver, space))?.invariants ?? [];
|
|
309
|
+
const mergedInvariants = destination.invariants === void 0 ? void 0 : mergeInvariants(currentInvariants, destination.invariants);
|
|
310
|
+
return (await execute((q) => this.lower(q, { contract: void 0 }), driver, marker.update().set({
|
|
311
|
+
core_hash: destination.storageHash,
|
|
312
|
+
profile_hash: destination.profileHash,
|
|
313
|
+
updated_at: NOW,
|
|
314
|
+
...mergedInvariants !== void 0 ? { invariants: mergedInvariants } : {}
|
|
315
|
+
}).where(marker.space.eq(space).and(marker.core_hash.eq(expectedFrom))).returning(marker.space).build())).length > 0;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Appends a ledger entry for `space`. See the
|
|
319
|
+
* `SqlControlAdapter.writeLedgerEntry` contract.
|
|
320
|
+
*/
|
|
321
|
+
async writeLedgerEntry(driver, space, entry) {
|
|
322
|
+
await execute((query) => this.lower(query, { contract: void 0 }), driver, ledger.insert({
|
|
323
|
+
space,
|
|
324
|
+
migration_name: entry.migrationName,
|
|
325
|
+
migration_hash: entry.migrationHash,
|
|
326
|
+
origin_core_hash: entry.from,
|
|
327
|
+
destination_core_hash: entry.to,
|
|
328
|
+
operations: entry.operations
|
|
329
|
+
}).build());
|
|
330
|
+
}
|
|
331
|
+
async readMarkerResult(driver, space) {
|
|
332
|
+
const lower = (query) => this.lower(query, { contract: void 0 });
|
|
333
|
+
if ((await execute(lower, driver, sqliteCatalog.select(sqliteCatalog.name).where(sqliteCatalog.type.eq("table").and(sqliteCatalog.name.eq("_prisma_marker"))).build())).length === 0) return { kind: "no-table" };
|
|
334
|
+
const row = (await execute(lower, driver, marker.select(marker.core_hash, marker.profile_hash, marker.contract_json, marker.canonical_version, marker.updated_at, marker.app_tag, marker.meta, marker.invariants).where(marker.space.eq(space)).build()))[0];
|
|
335
|
+
if (!row) return { kind: "absent" };
|
|
336
|
+
return {
|
|
337
|
+
kind: "present",
|
|
338
|
+
record: parseContractMarkerRow(decodeSqliteMarkerRow(row))
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
async introspect(driver, _contract) {
|
|
342
|
+
const tablesResult = await driver.query(`SELECT name FROM sqlite_master
|
|
343
|
+
WHERE type = 'table'
|
|
344
|
+
AND name NOT LIKE 'sqlite_%'
|
|
345
|
+
AND name NOT IN ('_prisma_marker', '_prisma_ledger')
|
|
346
|
+
ORDER BY name`);
|
|
347
|
+
const tables = {};
|
|
348
|
+
for (const tableRow of tablesResult.rows) {
|
|
349
|
+
const tableName = tableRow.name;
|
|
350
|
+
const columnsResult = await driver.query(`PRAGMA table_info("${escapePragmaArg(tableName)}")`);
|
|
351
|
+
const fkResult = await driver.query(`PRAGMA foreign_key_list("${escapePragmaArg(tableName)}")`);
|
|
352
|
+
const indexListResult = await driver.query(`PRAGMA index_list("${escapePragmaArg(tableName)}")`);
|
|
353
|
+
const columns = {};
|
|
354
|
+
const pkColumns = [];
|
|
355
|
+
for (const col of columnsResult.rows) {
|
|
356
|
+
const resolvedNativeType = normalizeSqliteNativeType(col.type);
|
|
357
|
+
const rawDefault = col.dflt_value ?? void 0;
|
|
358
|
+
columns[col.name] = {
|
|
359
|
+
name: col.name,
|
|
360
|
+
nativeType: col.type.toLowerCase(),
|
|
361
|
+
nullable: col.notnull === 0 && col.pk === 0,
|
|
362
|
+
...ifDefined("default", rawDefault),
|
|
363
|
+
resolvedNativeType,
|
|
364
|
+
...ifDefined("resolvedDefault", rawDefault !== void 0 ? parseSqliteDefault(rawDefault, resolvedNativeType) : void 0)
|
|
365
|
+
};
|
|
366
|
+
if (col.pk > 0) pkColumns.push({
|
|
367
|
+
name: col.name,
|
|
368
|
+
pk: col.pk
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
pkColumns.sort((a, b) => a.pk - b.pk);
|
|
372
|
+
const primaryKey = pkColumns.length > 0 ? {
|
|
373
|
+
columns: pkColumns.map((c) => c.name),
|
|
374
|
+
dependsOn: flatColumnDependsOn(tableName, pkColumns.map((c) => c.name))
|
|
375
|
+
} : void 0;
|
|
376
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
377
|
+
for (const fk of fkResult.rows) {
|
|
378
|
+
const existing = fkMap.get(fk.id);
|
|
379
|
+
if (existing) {
|
|
380
|
+
existing.columns.push(fk.from);
|
|
381
|
+
existing.referencedColumns.push(fk.to);
|
|
382
|
+
} else fkMap.set(fk.id, {
|
|
383
|
+
columns: [fk.from],
|
|
384
|
+
referencedTable: fk.table,
|
|
385
|
+
referencedColumns: [fk.to],
|
|
386
|
+
onDelete: fk.on_delete,
|
|
387
|
+
onUpdate: fk.on_update
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
const foreignKeys = Array.from(fkMap.values()).map((fk) => ({
|
|
391
|
+
columns: Object.freeze([...fk.columns]),
|
|
392
|
+
referencedTable: fk.referencedTable,
|
|
393
|
+
referencedColumns: Object.freeze([...fk.referencedColumns]),
|
|
394
|
+
...ifDefined("onDelete", mapSqliteReferentialAction(fk.onDelete)),
|
|
395
|
+
...ifDefined("onUpdate", mapSqliteReferentialAction(fk.onUpdate)),
|
|
396
|
+
dependsOn: [flatTableDependsOn(fk.referencedTable), ...flatColumnDependsOn(tableName, fk.columns)]
|
|
397
|
+
}));
|
|
398
|
+
const uniques = [];
|
|
399
|
+
const indexes = [];
|
|
400
|
+
for (const idx of indexListResult.rows) {
|
|
401
|
+
const idxColumns = (await driver.query(`PRAGMA index_info("${escapePragmaArg(idx.name)}")`)).rows.sort((a, b) => a.seqno - b.seqno).map((r) => r.name);
|
|
402
|
+
if (idx.origin === "u") uniques.push({
|
|
403
|
+
columns: Object.freeze([...idxColumns]),
|
|
404
|
+
name: idx.name,
|
|
405
|
+
dependsOn: flatColumnDependsOn(tableName, idxColumns)
|
|
406
|
+
});
|
|
407
|
+
else if (idx.origin === "c") indexes.push({
|
|
408
|
+
naming: {
|
|
409
|
+
kind: "exact",
|
|
410
|
+
name: idx.name
|
|
411
|
+
},
|
|
412
|
+
columns: Object.freeze([...idxColumns]),
|
|
413
|
+
where: void 0,
|
|
414
|
+
unique: idx.unique === 1,
|
|
415
|
+
partial: idx.partial === 1,
|
|
416
|
+
type: void 0,
|
|
417
|
+
options: void 0,
|
|
418
|
+
annotations: void 0,
|
|
419
|
+
dependsOn: flatColumnDependsOn(tableName, idxColumns)
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
tables[tableName] = new SqlTableIR({
|
|
423
|
+
name: tableName,
|
|
424
|
+
columns,
|
|
425
|
+
...ifDefined("primaryKey", primaryKey),
|
|
426
|
+
foreignKeys,
|
|
427
|
+
uniques,
|
|
428
|
+
indexes
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return new SqlSchemaIR({ tables });
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
function escapePragmaArg(name) {
|
|
435
|
+
return name.replace(/"/g, "\"\"");
|
|
436
|
+
}
|
|
437
|
+
const SQLITE_REFERENTIAL_ACTION_MAP = {
|
|
438
|
+
"NO ACTION": "noAction",
|
|
439
|
+
RESTRICT: "restrict",
|
|
440
|
+
CASCADE: "cascade",
|
|
441
|
+
"SET NULL": "setNull",
|
|
442
|
+
"SET DEFAULT": "setDefault"
|
|
443
|
+
};
|
|
444
|
+
function mapSqliteReferentialAction(rule) {
|
|
445
|
+
const normalized = rule.toUpperCase();
|
|
446
|
+
const mapped = SQLITE_REFERENTIAL_ACTION_MAP[normalized];
|
|
447
|
+
if (mapped === void 0) throw structuredError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Unknown SQLite referential action rule: "${rule}". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`, { meta: { rule } });
|
|
448
|
+
if (mapped === "noAction") return void 0;
|
|
449
|
+
return mapped;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* The referenced table's chain in the flat (single-schema) tree this
|
|
453
|
+
* introspection builds: the root (`SqlSchemaIR`, fixed `'database'` id)
|
|
454
|
+
* followed by the table's own id. Mirrors the expected-side derivation
|
|
455
|
+
* (`contractToSchemaIR`'s `convertForeignKey`).
|
|
456
|
+
*/
|
|
457
|
+
function flatTableDependsOn(tableName) {
|
|
458
|
+
return [{
|
|
459
|
+
nodeKind: RelationalSchemaNodeKind.schema,
|
|
460
|
+
id: "database"
|
|
461
|
+
}, {
|
|
462
|
+
nodeKind: RelationalSchemaNodeKind.table,
|
|
463
|
+
id: tableName
|
|
464
|
+
}];
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* The chains from a table-child object (foreign key, index, unique, primary
|
|
468
|
+
* key) to each of the own columns it is built on — the introspection-side
|
|
469
|
+
* mirror of `contractToSchemaIR`'s `flatColumnDependsOn`. An object is dropped
|
|
470
|
+
* before the columns it covers.
|
|
471
|
+
*/
|
|
472
|
+
function flatColumnDependsOn(tableName, columns) {
|
|
473
|
+
return columns.map((column) => [...flatTableDependsOn(tableName), {
|
|
474
|
+
nodeKind: RelationalSchemaNodeKind.column,
|
|
475
|
+
id: `column:${column}`
|
|
476
|
+
}]);
|
|
477
|
+
}
|
|
478
|
+
function sqliteInlineLiteral(wire) {
|
|
479
|
+
if (wire === null) return "NULL";
|
|
480
|
+
if (typeof wire === "boolean") return wire ? "1" : "0";
|
|
481
|
+
if (typeof wire === "number") {
|
|
482
|
+
if (!Number.isFinite(wire)) throw structuredError("CONTRACT.DEFAULT_INVALID", `sqliteRenderDdlExecuteRequest: non-finite number wire value ${String(wire)} cannot be emitted as a DEFAULT literal`);
|
|
483
|
+
return String(wire);
|
|
484
|
+
}
|
|
485
|
+
if (typeof wire === "bigint") return String(wire);
|
|
486
|
+
if (wire instanceof Date) {
|
|
487
|
+
if (Number.isNaN(wire.getTime())) throw structuredError("CONTRACT.DEFAULT_INVALID", "sqliteRenderDdlExecuteRequest: invalid Date value cannot be emitted as a DEFAULT literal");
|
|
488
|
+
return `'${escapeLiteral(wire.toISOString())}'`;
|
|
489
|
+
}
|
|
490
|
+
if (typeof wire === "string") return `'${escapeLiteral(wire)}'`;
|
|
491
|
+
if (wire instanceof Uint8Array) return `X'${Array.from(wire).map((b) => b.toString(16).padStart(2, "0")).join("")}'`;
|
|
492
|
+
if (typeof wire === "object") return `'${escapeLiteral(JSON.stringify(wire))}'`;
|
|
493
|
+
throw structuredError("CONTRACT.PACK_CONTRIBUTION_INVALID", `sqliteRenderDdlExecuteRequest: unexpected wire type "${typeof wire}"`, { meta: { wireType: typeof wire } });
|
|
494
|
+
}
|
|
495
|
+
async function sqliteRenderDdlColumnDefault(def, codecLookup, codecRef) {
|
|
496
|
+
if (def.kind === "function") {
|
|
497
|
+
if (def.expression === "autoincrement()") return "";
|
|
498
|
+
if (def.expression === "now()") return "DEFAULT (datetime('now'))";
|
|
499
|
+
return `DEFAULT (${def.expression})`;
|
|
500
|
+
}
|
|
501
|
+
if (codecRef !== void 0) {
|
|
502
|
+
const codec = codecLookup.get(codecRef.codecId);
|
|
503
|
+
if (codec !== void 0) return `DEFAULT ${sqliteInlineLiteral(await codec.encode(def.value, {}))}`;
|
|
504
|
+
}
|
|
505
|
+
return `DEFAULT ${sqliteInlineLiteral(def.value)}`;
|
|
506
|
+
}
|
|
507
|
+
async function sqliteRenderDdlColumn(column, codecLookup) {
|
|
508
|
+
if (column.type.includes("AUTOINCREMENT")) return `${quoteIdentifier(column.name)} ${column.type}`;
|
|
509
|
+
const parts = [quoteIdentifier(column.name), column.type];
|
|
510
|
+
if (column.notNull) parts.push("NOT NULL");
|
|
511
|
+
if (column.primaryKey) parts.push("PRIMARY KEY");
|
|
512
|
+
if (column.default) {
|
|
513
|
+
const clause = await sqliteRenderDdlColumnDefault(column.default, codecLookup, column.codecRef);
|
|
514
|
+
if (clause.length > 0) parts.push(clause);
|
|
515
|
+
}
|
|
516
|
+
return parts.join(" ");
|
|
517
|
+
}
|
|
518
|
+
function sqliteRenderDdlConstraint(constraint) {
|
|
519
|
+
if (constraint.kind === "primary-key") {
|
|
520
|
+
const cols = constraint.columns.map(quoteIdentifier).join(", ");
|
|
521
|
+
if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} PRIMARY KEY (${cols})`;
|
|
522
|
+
return `PRIMARY KEY (${cols})`;
|
|
523
|
+
}
|
|
524
|
+
if (constraint.kind === "foreign-key") {
|
|
525
|
+
let sql = `FOREIGN KEY (${constraint.columns.map(quoteIdentifier).join(", ")}) REFERENCES ${constraint.refTable.split(".").map(quoteIdentifier).join(".")} (${constraint.refColumns.map(quoteIdentifier).join(", ")})`;
|
|
526
|
+
if (constraint.onDelete !== void 0) sql += ` ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`;
|
|
527
|
+
if (constraint.onUpdate !== void 0) sql += ` ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`;
|
|
528
|
+
if (constraint.name !== void 0) sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
|
|
529
|
+
return sql;
|
|
530
|
+
}
|
|
531
|
+
if (constraint.kind === "check-expression") throw structuredError("CONTRACT.CONSTRAINT_INVALID", `SQLite does not support expression CHECK constraints (constraint "${constraint.name}"). Scalar-array columns and their element-non-null checks are Postgres-only.`, { meta: { constraintName: constraint.name } });
|
|
532
|
+
const cols = constraint.columns.map(quoteIdentifier).join(", ");
|
|
533
|
+
if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
|
|
534
|
+
return `UNIQUE (${cols})`;
|
|
535
|
+
}
|
|
536
|
+
async function sqliteRenderDdlExecuteRequest(ast, codecLookup) {
|
|
537
|
+
const node = blindCast(ast);
|
|
538
|
+
const ifNotExists = node.ifNotExists ? "IF NOT EXISTS " : "";
|
|
539
|
+
const tableRef = quoteIdentifier(node.table);
|
|
540
|
+
const columnDefs = await Promise.all(node.columns.map((col) => sqliteRenderDdlColumn(col, codecLookup)));
|
|
541
|
+
const constraintDefs = node.constraints !== void 0 ? node.constraints.map(sqliteRenderDdlConstraint) : [];
|
|
542
|
+
return {
|
|
543
|
+
sql: `CREATE TABLE ${ifNotExists}${tableRef} (\n ${[...columnDefs, ...constraintDefs].join(",\n ")}\n)`,
|
|
544
|
+
params: []
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
function nodeKind(value) {
|
|
548
|
+
if (typeof value === "object" && value !== null && "kind" in value && typeof value.kind === "string") return value.kind;
|
|
549
|
+
return "unknown";
|
|
550
|
+
}
|
|
551
|
+
function unreachableKind(value) {
|
|
552
|
+
return nodeKind(value);
|
|
553
|
+
}
|
|
554
|
+
const defaultCapabilities = Object.freeze({ sql: {
|
|
555
|
+
orderBy: true,
|
|
556
|
+
limit: true,
|
|
557
|
+
lateral: false,
|
|
558
|
+
jsonAgg: true,
|
|
559
|
+
returning: true,
|
|
560
|
+
enums: false
|
|
561
|
+
} });
|
|
562
|
+
var SqliteAdapterImpl = class {
|
|
563
|
+
familyId = "sql";
|
|
564
|
+
targetId = "sqlite";
|
|
565
|
+
profile;
|
|
566
|
+
#codecs;
|
|
567
|
+
constructor(codecRegistry, profileId) {
|
|
568
|
+
this.#codecs = codecRegistry;
|
|
569
|
+
const controlAdapter = new SqliteControlAdapter(codecRegistry);
|
|
570
|
+
this.profile = Object.freeze({
|
|
571
|
+
id: profileId ?? "sqlite/default@1",
|
|
572
|
+
target: "sqlite",
|
|
573
|
+
capabilities: defaultCapabilities,
|
|
574
|
+
readMarker: (queryable) => controlAdapter.readMarkerDiscriminated({
|
|
575
|
+
familyId: "sql",
|
|
576
|
+
targetId: "sqlite",
|
|
577
|
+
query: async (sql, params) => {
|
|
578
|
+
return { rows: [...(await queryable.query(sql, params)).rows] };
|
|
579
|
+
},
|
|
580
|
+
close: async () => {}
|
|
581
|
+
}, APP_SPACE_ID)
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
lower(ast, context) {
|
|
585
|
+
if (isDdlNode(ast)) throw structuredError("RUNTIME.DDL_UNSUPPORTED", "lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.", { meta: { surface: "runtime-adapter" } });
|
|
586
|
+
return renderLoweredSql(ast, context.contract, this.#codecs);
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a sqlite client. Contributed as the descriptor's static `rawCodecInferer` slot. */
|
|
590
|
+
const sqliteRawCodecInferer = { inferCodec(value) {
|
|
591
|
+
switch (typeof value) {
|
|
592
|
+
case "number": return Number.isSafeInteger(value) && value % 1 === 0 ? "sqlite/integer@1" : "sqlite/real@1";
|
|
593
|
+
case "bigint": return "sqlite/bigint@1";
|
|
594
|
+
case "string": return "sqlite/text@1";
|
|
595
|
+
case "boolean": return "sqlite/integer@1";
|
|
596
|
+
case "object": if (value instanceof Uint8Array) return "sqlite/blob@1";
|
|
597
|
+
}
|
|
598
|
+
throw structuredError("RUNTIME.RAW_SQL_UNSUPPORTED_INTERPOLATION", "unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec", { meta: { valueType: typeof value } });
|
|
599
|
+
} };
|
|
600
|
+
/**
|
|
601
|
+
* Lower a SQL query AST into a SQLite-flavored `{ sql, params }` payload.
|
|
602
|
+
*
|
|
603
|
+
* Shared between the runtime adapter (`SqliteAdapterImpl.lower`) and the control adapter (`SqliteControlAdapter.lower`) so both produce byte-identical SQL for the same AST and contract.
|
|
604
|
+
*/
|
|
605
|
+
function renderLoweredSql(ast, contract, codecs) {
|
|
606
|
+
const ctx = {
|
|
607
|
+
contract,
|
|
608
|
+
codecs
|
|
609
|
+
};
|
|
610
|
+
const collectedParamRefs = ast.collectParamRefs();
|
|
611
|
+
const params = [];
|
|
612
|
+
for (const ref of collectedParamRefs) params.push(ref.kind === "prepared-param-ref" ? {
|
|
613
|
+
kind: "bind",
|
|
614
|
+
name: ref.name
|
|
615
|
+
} : {
|
|
616
|
+
kind: "literal",
|
|
617
|
+
value: ref.value
|
|
618
|
+
});
|
|
619
|
+
let sql;
|
|
620
|
+
const node = ast;
|
|
621
|
+
switch (node.kind) {
|
|
622
|
+
case "select":
|
|
623
|
+
sql = renderSelect(node, ctx);
|
|
624
|
+
break;
|
|
625
|
+
case "insert":
|
|
626
|
+
sql = renderInsert(node, ctx);
|
|
627
|
+
break;
|
|
628
|
+
case "update":
|
|
629
|
+
sql = renderUpdate(node, ctx);
|
|
630
|
+
break;
|
|
631
|
+
case "delete":
|
|
632
|
+
sql = renderDelete(node, ctx);
|
|
633
|
+
break;
|
|
634
|
+
default: throw new InternalError(`Unsupported AST node kind: ${nodeKind(node)}`);
|
|
635
|
+
}
|
|
636
|
+
return Object.freeze({
|
|
637
|
+
sql,
|
|
638
|
+
params
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
function renderLimitOffset(keyword, value, ctx) {
|
|
642
|
+
if (value === void 0) return "";
|
|
643
|
+
if (typeof value === "number") return `${keyword} ${value}`;
|
|
644
|
+
return `${keyword} ${renderExpr(value, ctx)}`;
|
|
645
|
+
}
|
|
646
|
+
function renderSelect(ast, ctx) {
|
|
647
|
+
return [
|
|
648
|
+
`SELECT ${ast.distinct ? "DISTINCT " : ""}${renderProjection(ast.projection, ctx)}`,
|
|
649
|
+
ast.from !== void 0 ? `FROM ${renderSource(ast.from, ctx)}` : "",
|
|
650
|
+
ast.joins?.length ? ast.joins.map((join) => renderJoin(join, ctx)).join(" ") : "",
|
|
651
|
+
ast.where ? `WHERE ${renderExpr(ast.where, ctx)}` : "",
|
|
652
|
+
ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, ctx)).join(", ")}` : "",
|
|
653
|
+
ast.having ? `HAVING ${renderExpr(ast.having, ctx)}` : "",
|
|
654
|
+
ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => `${renderExpr(order.expr, ctx)} ${order.dir.toUpperCase()}`).join(", ")}` : "",
|
|
655
|
+
renderLimitOffset("LIMIT", ast.limit, ctx),
|
|
656
|
+
renderLimitOffset("OFFSET", ast.offset, ctx)
|
|
657
|
+
].filter((part) => part.length > 0).join(" ").trim();
|
|
658
|
+
}
|
|
659
|
+
function renderProjection(projection, ctx) {
|
|
660
|
+
return projection.map((item) => {
|
|
661
|
+
const alias = quoteIdentifier(item.alias);
|
|
662
|
+
if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${alias}`;
|
|
663
|
+
return `${renderExpr(item.expr, ctx)} AS ${alias}`;
|
|
664
|
+
}).join(", ");
|
|
665
|
+
}
|
|
666
|
+
function qualifyTableFromNamespaceCoordinate(table, ctx) {
|
|
667
|
+
if (table.namespaceId === void 0) return quoteIdentifier(table.name);
|
|
668
|
+
if (ctx.contract === void 0) throw new InternalError(`Table "${table.name}" carries namespace "${table.namespaceId}" but no contract was supplied to resolve it`);
|
|
669
|
+
const namespace = ctx.contract.storage.namespaces[table.namespaceId];
|
|
670
|
+
if (namespace === void 0) throw structuredError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not present on the contract`, { meta: {
|
|
671
|
+
table: table.name,
|
|
672
|
+
namespaceId: table.namespaceId,
|
|
673
|
+
reason: "not-present"
|
|
674
|
+
} });
|
|
675
|
+
const qualifyTable = namespace.qualifyTable;
|
|
676
|
+
if (qualifyTable === void 0) throw structuredError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not materialised for SQL rendering on the contract`, { meta: {
|
|
677
|
+
table: table.name,
|
|
678
|
+
namespaceId: table.namespaceId,
|
|
679
|
+
reason: "not-materialised"
|
|
680
|
+
} });
|
|
681
|
+
return qualifyTable.call(namespace, table.name);
|
|
682
|
+
}
|
|
683
|
+
function renderTableSource(source, ctx) {
|
|
684
|
+
const qualified = qualifyTableFromNamespaceCoordinate(source, ctx);
|
|
685
|
+
if (!source.alias) return qualified;
|
|
686
|
+
return `${qualified} AS ${quoteIdentifier(source.alias)}`;
|
|
687
|
+
}
|
|
688
|
+
function renderSource(source, ctx) {
|
|
689
|
+
const node = source;
|
|
690
|
+
switch (node.kind) {
|
|
691
|
+
case "table-source": return renderTableSource(node, ctx);
|
|
692
|
+
case "derived-table-source": return `(${renderSelect(node.query, ctx)}) AS ${quoteIdentifier(node.alias)}`;
|
|
693
|
+
case "function-source": {
|
|
694
|
+
if (node.ordinality) throw structuredError("ADAPTER.CAPABILITY_MISSING", "SQLite does not support WITH ORDINALITY on function sources", { meta: {
|
|
695
|
+
target: "sqlite",
|
|
696
|
+
feature: "function-source-with-ordinality"
|
|
697
|
+
} });
|
|
698
|
+
if (node.columnAliases !== void 0) throw structuredError("ADAPTER.CAPABILITY_MISSING", "SQLite does not support returned-column aliases on function sources", { meta: {
|
|
699
|
+
target: "sqlite",
|
|
700
|
+
feature: "function-source-column-aliases"
|
|
701
|
+
} });
|
|
702
|
+
const args = node.args.map((arg) => renderExpr(arg, ctx)).join(", ");
|
|
703
|
+
const call = `${node.fn}(${args})`;
|
|
704
|
+
return node.alias !== void 0 ? `${call} AS ${quoteIdentifier(node.alias)}` : call;
|
|
705
|
+
}
|
|
706
|
+
default: return assertNever(node, `Unsupported source node kind: ${unreachableKind(node)}`);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
function renderExpr(expr, ctx) {
|
|
710
|
+
const node = expr;
|
|
711
|
+
switch (node.kind) {
|
|
712
|
+
case "column-ref": return renderColumn(node);
|
|
713
|
+
case "identifier-ref": return quoteIdentifier(node.name);
|
|
714
|
+
case "operation": return renderOperation(node, ctx);
|
|
715
|
+
case "subquery": return renderSubqueryExpr(node, ctx);
|
|
716
|
+
case "aggregate": return renderAggregateExpr(node, ctx);
|
|
717
|
+
case "window-func": return renderWindowFuncExpr(node, ctx);
|
|
718
|
+
case "function-call": return renderFunctionCallExpr(node, ctx);
|
|
719
|
+
case "cast": return renderCastExpr(node, ctx);
|
|
720
|
+
case "case": return renderCaseExpr(node, ctx);
|
|
721
|
+
case "json-object": return renderJsonObjectExpr(node, ctx);
|
|
722
|
+
case "json-array-agg": return renderJsonArrayAggExpr(node, ctx);
|
|
723
|
+
case "binary": return renderBinary(node, ctx);
|
|
724
|
+
case "and":
|
|
725
|
+
if (node.exprs.length === 0) return "TRUE";
|
|
726
|
+
return `(${node.exprs.map((part) => renderExpr(part, ctx)).join(" AND ")})`;
|
|
727
|
+
case "or":
|
|
728
|
+
if (node.exprs.length === 0) return "FALSE";
|
|
729
|
+
return `(${node.exprs.map((part) => renderExpr(part, ctx)).join(" OR ")})`;
|
|
730
|
+
case "exists":
|
|
731
|
+
if (ctx.contract === void 0) throw new InternalError("EXISTS subquery rendering requires a Sqlite contract");
|
|
732
|
+
return `${node.notExists ? "NOT " : ""}EXISTS (${renderSelect(node.subquery, ctx)})`;
|
|
733
|
+
case "null-check": return renderNullCheck(node, ctx);
|
|
734
|
+
case "not": return `NOT (${renderExpr(node.expr, ctx)})`;
|
|
735
|
+
case "param-ref":
|
|
736
|
+
case "prepared-param-ref": return "?";
|
|
737
|
+
case "literal": return renderLiteral(node);
|
|
738
|
+
case "list": return renderListLiteral(node, ctx);
|
|
739
|
+
case "raw-expr": return renderRawExpr(node, ctx);
|
|
740
|
+
default: return assertNever(node, `Unsupported expression node kind: ${unreachableKind(node)}`);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
function renderRawExpr(node, ctx) {
|
|
744
|
+
return node.parts.map((part) => typeof part === "string" ? part : renderExpr(part, ctx)).join("");
|
|
745
|
+
}
|
|
746
|
+
function renderColumn(ref) {
|
|
747
|
+
if (ref.table === "excluded") return `excluded.${quoteIdentifier(ref.column)}`;
|
|
748
|
+
return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;
|
|
749
|
+
}
|
|
750
|
+
function renderLiteral(expr) {
|
|
751
|
+
if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
|
|
752
|
+
if (typeof expr.value === "number" || typeof expr.value === "boolean") return String(expr.value);
|
|
753
|
+
if (typeof expr.value === "bigint") return String(expr.value);
|
|
754
|
+
if (expr.value === null || expr.value === void 0) return "NULL";
|
|
755
|
+
if (expr.value instanceof Date) return `'${escapeLiteral(expr.value.toISOString())}'`;
|
|
756
|
+
const json = JSON.stringify(expr.value);
|
|
757
|
+
if (json === void 0) return "NULL";
|
|
758
|
+
return `'${escapeLiteral(json)}'`;
|
|
759
|
+
}
|
|
760
|
+
function renderOperation(expr, ctx) {
|
|
761
|
+
const self = renderExpr(expr.self, ctx);
|
|
762
|
+
const args = expr.args.map((arg) => renderExpr(arg, ctx));
|
|
763
|
+
let result = expr.lowering.template;
|
|
764
|
+
result = result.replace(/\{\{self\}\}/g, self);
|
|
765
|
+
for (let i = 0; i < args.length; i++) result = result.replace(new RegExp(`\\{\\{arg${i}\\}\\}`, "g"), args[i] ?? "");
|
|
766
|
+
return result;
|
|
767
|
+
}
|
|
768
|
+
function renderSubqueryExpr(expr, ctx) {
|
|
769
|
+
if (expr.query.projection.length !== 1) throw structuredError("RUNTIME.AST_INVALID", "Subquery expressions must project exactly one column", { meta: { node: "subquery" } });
|
|
770
|
+
if (ctx.contract === void 0) throw new InternalError("Subquery expression rendering requires a Sqlite contract");
|
|
771
|
+
return `(${renderSelect(expr.query, ctx)})`;
|
|
772
|
+
}
|
|
773
|
+
function requiresNullCheckGrouping(kind) {
|
|
774
|
+
switch (kind) {
|
|
775
|
+
case "operation":
|
|
776
|
+
case "subquery": return true;
|
|
777
|
+
case "column-ref":
|
|
778
|
+
case "identifier-ref":
|
|
779
|
+
case "aggregate":
|
|
780
|
+
case "window-func":
|
|
781
|
+
case "function-call":
|
|
782
|
+
case "cast":
|
|
783
|
+
case "case":
|
|
784
|
+
case "json-object":
|
|
785
|
+
case "json-array-agg":
|
|
786
|
+
case "binary":
|
|
787
|
+
case "and":
|
|
788
|
+
case "or":
|
|
789
|
+
case "exists":
|
|
790
|
+
case "null-check":
|
|
791
|
+
case "not":
|
|
792
|
+
case "param-ref":
|
|
793
|
+
case "prepared-param-ref":
|
|
794
|
+
case "literal":
|
|
795
|
+
case "list":
|
|
796
|
+
case "raw-expr": return false;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function renderNullCheck(expr, ctx) {
|
|
800
|
+
const rendered = renderExpr(expr.expr, ctx);
|
|
801
|
+
const renderedExpr = requiresNullCheckGrouping(expr.expr.kind) ? `(${rendered})` : rendered;
|
|
802
|
+
return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;
|
|
803
|
+
}
|
|
804
|
+
function renderBinary(expr, ctx) {
|
|
805
|
+
if (expr.right.kind === "list" && expr.right.values.length === 0) {
|
|
806
|
+
if (expr.op === "in") return "FALSE";
|
|
807
|
+
if (expr.op === "notIn") return "TRUE";
|
|
808
|
+
}
|
|
809
|
+
const leftExpr = expr.left;
|
|
810
|
+
const left = renderExpr(leftExpr, ctx);
|
|
811
|
+
const leftRendered = leftExpr.kind === "operation" || leftExpr.kind === "subquery" ? `(${left})` : left;
|
|
812
|
+
const rightNode = expr.right;
|
|
813
|
+
let right;
|
|
814
|
+
switch (rightNode.kind) {
|
|
815
|
+
case "list":
|
|
816
|
+
right = renderListLiteral(rightNode, ctx);
|
|
817
|
+
break;
|
|
818
|
+
case "literal":
|
|
819
|
+
right = renderLiteral(rightNode);
|
|
820
|
+
break;
|
|
821
|
+
case "column-ref":
|
|
822
|
+
right = renderColumn(rightNode);
|
|
823
|
+
break;
|
|
824
|
+
case "param-ref":
|
|
825
|
+
case "prepared-param-ref":
|
|
826
|
+
right = "?";
|
|
827
|
+
break;
|
|
828
|
+
default:
|
|
829
|
+
right = renderExpr(rightNode, ctx);
|
|
830
|
+
break;
|
|
831
|
+
}
|
|
832
|
+
return `${leftRendered} ${{
|
|
833
|
+
eq: "=",
|
|
834
|
+
neq: "!=",
|
|
835
|
+
gt: ">",
|
|
836
|
+
lt: "<",
|
|
837
|
+
gte: ">=",
|
|
838
|
+
lte: "<=",
|
|
839
|
+
like: "LIKE",
|
|
840
|
+
in: "IN",
|
|
841
|
+
notIn: "NOT IN"
|
|
842
|
+
}[expr.op]} ${right}`;
|
|
843
|
+
}
|
|
844
|
+
function renderListLiteral(expr, ctx) {
|
|
845
|
+
if (expr.values.length === 0) return "(NULL)";
|
|
846
|
+
return `(${expr.values.map((v) => {
|
|
847
|
+
if (v.kind === "param-ref" || v.kind === "prepared-param-ref") return "?";
|
|
848
|
+
if (v.kind === "literal") return renderLiteral(v);
|
|
849
|
+
return renderExpr(v, ctx);
|
|
850
|
+
}).join(", ")})`;
|
|
851
|
+
}
|
|
852
|
+
function renderAggregateExpr(expr, ctx) {
|
|
853
|
+
const fn = expr.fn.toUpperCase();
|
|
854
|
+
if (!expr.expr) return `${fn}(*)`;
|
|
855
|
+
return `${fn}(${renderExpr(expr.expr, ctx)})`;
|
|
856
|
+
}
|
|
857
|
+
function renderWindowFuncExpr(expr, ctx) {
|
|
858
|
+
return `${expr.fn.toUpperCase()}(${expr.args.map((arg) => renderExpr(arg, ctx)).join(", ")}) OVER (${[expr.partitionBy && expr.partitionBy.length > 0 ? `PARTITION BY ${expr.partitionBy.map((e) => renderExpr(e, ctx)).join(", ")}` : "", expr.orderBy && expr.orderBy.length > 0 ? `ORDER BY ${renderOrderByItems(expr.orderBy, ctx)}` : ""].filter((part) => part.length > 0).join(" ")})`;
|
|
859
|
+
}
|
|
860
|
+
function renderFunctionCallExpr(expr, ctx) {
|
|
861
|
+
const args = expr.args.map((arg) => renderExpr(arg, ctx)).join(", ");
|
|
862
|
+
return `${expr.fn}(${args})`;
|
|
863
|
+
}
|
|
864
|
+
function renderCastExpr(expr, ctx) {
|
|
865
|
+
return `CAST(${renderExpr(expr.expr, ctx)} AS ${expr.targetType})`;
|
|
866
|
+
}
|
|
867
|
+
function renderCaseExpr(expr, ctx) {
|
|
868
|
+
return `CASE ${expr.branches.map((branch) => `WHEN ${renderExpr(branch.condition, ctx)} THEN ${renderExpr(branch.value, ctx)}`).join(" ")}${expr.elseExpr === void 0 ? "" : ` ELSE ${renderExpr(expr.elseExpr, ctx)}`} END`;
|
|
869
|
+
}
|
|
870
|
+
function renderJsonValueProjection(projection, ctx) {
|
|
871
|
+
return projection.accept({
|
|
872
|
+
codec: ({ value, codec }) => renderExpr(projectJsonThroughCodec(value, codec, ctx.codecs), ctx),
|
|
873
|
+
native: ({ value }) => renderExpr(value, ctx),
|
|
874
|
+
document: ({ value }) => renderExpr(jsonDocumentRetag(value), ctx)
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
function projectJsonThroughCodec(value, codec, codecs) {
|
|
878
|
+
const descriptor = codecs.descriptorFor(codec.codecId);
|
|
879
|
+
if (descriptor === void 0) throw structuredError("RUNTIME.PARAM_REF_MISSING_CODEC", `SQLite lowering: a JSON projection carries codecId "${codec.codecId}" but the validated SQLite codec registry has no entry for it. This usually indicates a missing extension pack in the runtime stack — register the pack that contributes this codec, or use the codec directly from \`@prisma/orm-target-sqlite/target/codecs\` if it's a builtin.`, { meta: { codecId: codec.codecId } });
|
|
880
|
+
return descriptor.projectJson(value, codec);
|
|
881
|
+
}
|
|
882
|
+
function renderJsonObjectExpr(expr, ctx) {
|
|
883
|
+
return `json_object(${expr.entries.flatMap((entry) => {
|
|
884
|
+
return [`'${escapeLiteral(entry.key)}'`, renderJsonValueProjection(entry.value, ctx)];
|
|
885
|
+
}).join(", ")})`;
|
|
886
|
+
}
|
|
887
|
+
function renderOrderByItems(items, ctx) {
|
|
888
|
+
return items.map((item) => `${renderExpr(item.expr, ctx)} ${item.dir.toUpperCase()}`).join(", ");
|
|
889
|
+
}
|
|
890
|
+
function renderJsonArrayAggExpr(expr, ctx) {
|
|
891
|
+
const aggregateOrderBy = expr.orderBy && expr.orderBy.length > 0 ? ` ORDER BY ${renderOrderByItems(expr.orderBy, ctx)}` : "";
|
|
892
|
+
const aggregated = `json_group_array(${renderJsonValueProjection(expr.expr, ctx)}${aggregateOrderBy})`;
|
|
893
|
+
if (expr.onEmpty === "emptyArray") return `coalesce(${aggregated}, '[]')`;
|
|
894
|
+
return aggregated;
|
|
895
|
+
}
|
|
896
|
+
function renderJoin(join, ctx) {
|
|
897
|
+
if (ctx.contract === void 0) throw new InternalError("JOIN rendering requires a Sqlite contract");
|
|
898
|
+
return `${join.joinType.toUpperCase()} JOIN ${renderSource(join.source, ctx)} ON ${renderJoinOn(join.on, ctx)}`;
|
|
899
|
+
}
|
|
900
|
+
function renderJoinOn(on, ctx) {
|
|
901
|
+
if (on.kind === "eq-col-join-on") return `${renderColumn(on.left)} = ${renderColumn(on.right)}`;
|
|
902
|
+
return renderExpr(on, ctx);
|
|
903
|
+
}
|
|
904
|
+
function renderInsertValue(value, ctx) {
|
|
905
|
+
switch (value.kind) {
|
|
906
|
+
case "param-ref":
|
|
907
|
+
case "prepared-param-ref": return "?";
|
|
908
|
+
case "column-ref": return renderColumn(value);
|
|
909
|
+
case "raw-expr": return renderExpr(value, ctx);
|
|
910
|
+
case "default-value": throw structuredError("RUNTIME.AST_UNSUPPORTED", "SQLite does not support DEFAULT as a value in INSERT ... VALUES", { meta: { node: "default-value" } });
|
|
911
|
+
default: return assertNever(value, `Unsupported value node in INSERT: ${unreachableKind(value)}`);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
function renderInsert(ast, ctx) {
|
|
915
|
+
const table = qualifyTableFromNamespaceCoordinate(ast.table, ctx);
|
|
916
|
+
const rows = ast.rows;
|
|
917
|
+
const firstRow = rows[0];
|
|
918
|
+
if (firstRow === void 0) throw structuredError("RUNTIME.AST_INVALID", "INSERT requires at least one row", { meta: {
|
|
919
|
+
node: "insert",
|
|
920
|
+
table: ast.table.name
|
|
921
|
+
} });
|
|
922
|
+
const columnOrder = Object.keys(firstRow);
|
|
923
|
+
let insertClause;
|
|
924
|
+
if (columnOrder.length === 0) insertClause = `INSERT INTO ${table} DEFAULT VALUES`;
|
|
925
|
+
else {
|
|
926
|
+
const columns = columnOrder.map((column) => quoteIdentifier(column));
|
|
927
|
+
const values = rows.map((row) => {
|
|
928
|
+
return `(${columnOrder.map((column) => {
|
|
929
|
+
const value = row[column];
|
|
930
|
+
if (value === void 0) throw structuredError("RUNTIME.AST_INVALID", `Missing value for column "${column}" in INSERT row`, { meta: {
|
|
931
|
+
node: "insert",
|
|
932
|
+
table: ast.table.name,
|
|
933
|
+
column
|
|
934
|
+
} });
|
|
935
|
+
return renderInsertValue(value, ctx);
|
|
936
|
+
}).join(", ")})`;
|
|
937
|
+
}).join(", ");
|
|
938
|
+
insertClause = `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
|
|
939
|
+
}
|
|
940
|
+
let onConflictClause = "";
|
|
941
|
+
if (ast.onConflict) {
|
|
942
|
+
const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
|
|
943
|
+
if (conflictColumns.length === 0) throw structuredError("RUNTIME.AST_INVALID", "INSERT onConflict requires at least one conflict column", { meta: {
|
|
944
|
+
node: "insert",
|
|
945
|
+
table: ast.table.name
|
|
946
|
+
} });
|
|
947
|
+
const action = ast.onConflict.action;
|
|
948
|
+
switch (action.kind) {
|
|
949
|
+
case "do-nothing":
|
|
950
|
+
onConflictClause = ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
|
|
951
|
+
break;
|
|
952
|
+
case "do-update-set": {
|
|
953
|
+
const updates = Object.entries(action.set).map(([colName, value]) => {
|
|
954
|
+
return `${quoteIdentifier(colName)} = ${renderExpr(value, ctx)}`;
|
|
955
|
+
});
|
|
956
|
+
onConflictClause = ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
|
|
957
|
+
break;
|
|
958
|
+
}
|
|
959
|
+
default: assertNever(action, `Unsupported onConflict action: ${unreachableKind(action)}`);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
const returningClause = renderReturning(ast.returning, ctx);
|
|
963
|
+
return `${insertClause}${onConflictClause}${returningClause}`;
|
|
964
|
+
}
|
|
965
|
+
function renderUpdate(ast, ctx) {
|
|
966
|
+
const table = qualifyTableFromNamespaceCoordinate(ast.table, ctx);
|
|
967
|
+
const setClauses = Object.entries(ast.set).map(([col, val]) => {
|
|
968
|
+
return `${quoteIdentifier(col)} = ${renderExpr(val, ctx)}`;
|
|
969
|
+
});
|
|
970
|
+
const whereClause = ast.where ? ` WHERE ${renderExpr(ast.where, ctx)}` : "";
|
|
971
|
+
const returningClause = renderReturning(ast.returning, ctx);
|
|
972
|
+
return `UPDATE ${table} SET ${setClauses.join(", ")}${whereClause}${returningClause}`;
|
|
973
|
+
}
|
|
974
|
+
function renderDelete(ast, ctx) {
|
|
975
|
+
return `DELETE FROM ${qualifyTableFromNamespaceCoordinate(ast.table, ctx)}${ast.where ? ` WHERE ${renderExpr(ast.where, ctx)}` : ""}${renderReturning(ast.returning, ctx)}`;
|
|
976
|
+
}
|
|
977
|
+
function renderReturning(returning, ctx) {
|
|
978
|
+
if (!returning?.length) return "";
|
|
979
|
+
return ` RETURNING ${returning.map((item) => {
|
|
980
|
+
if (item.expr.kind === "column-ref") {
|
|
981
|
+
const rendered = `${quoteIdentifier(item.expr.table)}.${quoteIdentifier(item.expr.column)}`;
|
|
982
|
+
return item.expr.column === item.alias ? rendered : `${rendered} AS ${quoteIdentifier(item.alias)}`;
|
|
983
|
+
}
|
|
984
|
+
return `${renderExpr(item.expr, ctx)} AS ${quoteIdentifier(item.alias)}`;
|
|
985
|
+
}).join(", ")}`;
|
|
986
|
+
}
|
|
987
|
+
function createSqliteAdapter(options) {
|
|
988
|
+
const codecRegistry = createSqliteCodecRegistryWithBuiltins(options?.codecDescriptors);
|
|
989
|
+
return Object.freeze(new SqliteAdapterImpl(codecRegistry, options?.profileId));
|
|
990
|
+
}
|
|
991
|
+
function createSqliteAdapterWithCodecRegistry(codecRegistry) {
|
|
992
|
+
return Object.freeze(new SqliteAdapterImpl(codecRegistry));
|
|
993
|
+
}
|
|
994
|
+
//#endregion
|
|
995
|
+
export { createSqliteBuiltinCodecLookup as a, createSqliteAdapterWithCodecRegistry as i, assembleSqliteCodecRegistry as n, createSqliteCodecRegistryWithBuiltins as o, createSqliteAdapter as r, sqliteRawCodecInferer as s, SqliteControlAdapter as t };
|
|
996
|
+
|
|
997
|
+
//# sourceMappingURL=adapter-wc9p_v2Z-y8pzqMfG.mjs.map
|