litedbmodel 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scp/authoring-sql.d.ts +78 -0
- package/dist/scp/authoring-sql.d.ts.map +1 -1
- package/dist/scp/authoring-sql.js +110 -2
- package/dist/scp/authoring-sql.js.map +1 -1
- package/dist/scp/catalog.d.ts +5 -2
- package/dist/scp/catalog.d.ts.map +1 -1
- package/dist/scp/catalog.js +32 -1
- package/dist/scp/catalog.js.map +1 -1
- package/dist/scp/codegen.d.ts +143 -85
- package/dist/scp/codegen.d.ts.map +1 -1
- package/dist/scp/codegen.js +374 -90
- package/dist/scp/codegen.js.map +1 -1
- package/dist/scp/coltype.d.ts +41 -0
- package/dist/scp/coltype.d.ts.map +1 -0
- package/dist/scp/coltype.js +188 -0
- package/dist/scp/coltype.js.map +1 -0
- package/dist/scp/dialect.d.ts +12 -3
- package/dist/scp/dialect.d.ts.map +1 -1
- package/dist/scp/dialect.js +12 -3
- package/dist/scp/dialect.js.map +1 -1
- package/dist/scp/find-filter-guard.d.ts +68 -0
- package/dist/scp/find-filter-guard.d.ts.map +1 -0
- package/dist/scp/find-filter-guard.js +88 -0
- package/dist/scp/find-filter-guard.js.map +1 -0
- package/dist/scp/fragment/assemble.d.ts +61 -0
- package/dist/scp/fragment/assemble.d.ts.map +1 -0
- package/dist/scp/fragment/assemble.js +156 -0
- package/dist/scp/fragment/assemble.js.map +1 -0
- package/dist/scp/fragment/compile-pg.d.ts +107 -0
- package/dist/scp/fragment/compile-pg.d.ts.map +1 -0
- package/dist/scp/fragment/compile-pg.js +142 -0
- package/dist/scp/fragment/compile-pg.js.map +1 -0
- package/dist/scp/fragment/index.d.ts +16 -0
- package/dist/scp/fragment/index.d.ts.map +1 -0
- package/dist/scp/fragment/index.js +34 -0
- package/dist/scp/fragment/index.js.map +1 -0
- package/dist/scp/fragment/model.d.ts +119 -0
- package/dist/scp/fragment/model.d.ts.map +1 -0
- package/dist/scp/fragment/model.js +66 -0
- package/dist/scp/fragment/model.js.map +1 -0
- package/dist/scp/fragment/pg-array-type.d.ts +13 -0
- package/dist/scp/fragment/pg-array-type.d.ts.map +1 -0
- package/dist/scp/fragment/pg-array-type.js +34 -0
- package/dist/scp/fragment/pg-array-type.js.map +1 -0
- package/dist/scp/guard.d.ts +2 -6
- package/dist/scp/guard.d.ts.map +1 -1
- package/dist/scp/guard.js +19 -22
- package/dist/scp/guard.js.map +1 -1
- package/dist/scp/index.cjs +18695 -3921
- package/dist/scp/index.d.ts +41 -24
- package/dist/scp/index.d.ts.map +1 -1
- package/dist/scp/index.js +134 -49
- package/dist/scp/index.js.map +1 -1
- package/dist/scp/index.mjs +4830 -1432
- package/dist/scp/makesql/authoring-compile.d.ts +90 -0
- package/dist/scp/makesql/authoring-compile.d.ts.map +1 -0
- package/dist/scp/makesql/authoring-compile.js +494 -0
- package/dist/scp/makesql/authoring-compile.js.map +1 -0
- package/dist/scp/makesql/compile-crud.d.ts +133 -0
- package/dist/scp/makesql/compile-crud.d.ts.map +1 -0
- package/dist/scp/makesql/compile-crud.js +288 -0
- package/dist/scp/makesql/compile-crud.js.map +1 -0
- package/dist/scp/makesql/compile-relation.d.ts +157 -0
- package/dist/scp/makesql/compile-relation.d.ts.map +1 -0
- package/dist/scp/makesql/compile-relation.js +425 -0
- package/dist/scp/makesql/compile-relation.js.map +1 -0
- package/dist/scp/makesql/compile-select.d.ts +52 -0
- package/dist/scp/makesql/compile-select.d.ts.map +1 -0
- package/dist/scp/makesql/compile-select.js +58 -0
- package/dist/scp/makesql/compile-select.js.map +1 -0
- package/dist/scp/makesql/compile.d.ts +63 -0
- package/dist/scp/makesql/compile.d.ts.map +1 -0
- package/dist/scp/makesql/compile.js +99 -0
- package/dist/scp/makesql/compile.js.map +1 -0
- package/dist/scp/makesql/handler.d.ts +58 -0
- package/dist/scp/makesql/handler.d.ts.map +1 -0
- package/dist/scp/makesql/handler.js +113 -0
- package/dist/scp/makesql/handler.js.map +1 -0
- package/dist/scp/makesql/index.d.ts +33 -0
- package/dist/scp/makesql/index.d.ts.map +1 -0
- package/dist/scp/makesql/index.js +114 -0
- package/dist/scp/makesql/index.js.map +1 -0
- package/dist/scp/makesql/ir.d.ts +42 -0
- package/dist/scp/makesql/ir.d.ts.map +1 -0
- package/dist/scp/makesql/ir.js +66 -0
- package/dist/scp/makesql/ir.js.map +1 -0
- package/dist/scp/makesql/json-array.d.ts +84 -0
- package/dist/scp/makesql/json-array.d.ts.map +1 -0
- package/dist/scp/makesql/json-array.js +118 -0
- package/dist/scp/makesql/json-array.js.map +1 -0
- package/dist/scp/makesql/json-batch.d.ts +102 -0
- package/dist/scp/makesql/json-batch.d.ts.map +1 -0
- package/dist/scp/makesql/json-batch.js +269 -0
- package/dist/scp/makesql/json-batch.js.map +1 -0
- package/dist/scp/makesql/makesql.d.ts +99 -0
- package/dist/scp/makesql/makesql.d.ts.map +1 -0
- package/dist/scp/makesql/makesql.js +122 -0
- package/dist/scp/makesql/makesql.js.map +1 -0
- package/dist/scp/makesql/outtype.d.ts +44 -0
- package/dist/scp/makesql/outtype.d.ts.map +1 -0
- package/dist/scp/makesql/outtype.js +197 -0
- package/dist/scp/makesql/outtype.js.map +1 -0
- package/dist/scp/makesql/pool-executor.d.ts +47 -0
- package/dist/scp/makesql/pool-executor.d.ts.map +1 -0
- package/dist/scp/makesql/pool-executor.js +50 -0
- package/dist/scp/makesql/pool-executor.js.map +1 -0
- package/dist/scp/makesql/static-bundle.d.ts +187 -0
- package/dist/scp/makesql/static-bundle.d.ts.map +1 -0
- package/dist/scp/makesql/static-bundle.js +1113 -0
- package/dist/scp/makesql/static-bundle.js.map +1 -0
- package/dist/scp/makesql/tx.d.ts +216 -0
- package/dist/scp/makesql/tx.d.ts.map +1 -0
- package/dist/scp/makesql/tx.js +788 -0
- package/dist/scp/makesql/tx.js.map +1 -0
- package/dist/scp/makesql/writeouttype.d.ts +66 -0
- package/dist/scp/makesql/writeouttype.d.ts.map +1 -0
- package/dist/scp/makesql/writeouttype.js +195 -0
- package/dist/scp/makesql/writeouttype.js.map +1 -0
- package/dist/scp/relation.d.ts +86 -74
- package/dist/scp/relation.d.ts.map +1 -1
- package/dist/scp/relation.js +186 -120
- package/dist/scp/relation.js.map +1 -1
- package/dist/scp/runtime.d.ts +158 -211
- package/dist/scp/runtime.d.ts.map +1 -1
- package/dist/scp/runtime.js +250 -515
- package/dist/scp/runtime.js.map +1 -1
- package/dist/scp/typed-object.d.ts +12 -1
- package/dist/scp/typed-object.d.ts.map +1 -1
- package/dist/scp/typed-object.js +25 -4
- package/dist/scp/typed-object.js.map +1 -1
- package/docs/proposal/litedbmodel-v2-scp-architecture.md +51 -0
- package/docs/proposal/v0-coverage-matrix.md +157 -0
- package/docs/proposal/v2-completeness-plan.md +90 -0
- package/docs/proposal/v2-sql-parity-checklist.md +162 -0
- package/package.json +3 -3
- package/dist/scp/bridge.d.ts +0 -64
- package/dist/scp/bridge.d.ts.map +0 -1
- package/dist/scp/bridge.js +0 -329
- package/dist/scp/bridge.js.map +0 -1
- package/dist/scp/compile-dialect.d.ts +0 -39
- package/dist/scp/compile-dialect.d.ts.map +0 -1
- package/dist/scp/compile-dialect.js +0 -62
- package/dist/scp/compile-dialect.js.map +0 -1
- package/dist/scp/compile-sqlite.d.ts +0 -114
- package/dist/scp/compile-sqlite.d.ts.map +0 -1
- package/dist/scp/compile-sqlite.js +0 -149
- package/dist/scp/compile-sqlite.js.map +0 -1
- package/dist/scp/ir.d.ts +0 -92
- package/dist/scp/ir.d.ts.map +0 -1
- package/dist/scp/ir.js +0 -28
- package/dist/scp/ir.js.map +0 -1
- package/dist/scp/render.d.ts +0 -40
- package/dist/scp/render.d.ts.map +0 -1
- package/dist/scp/render.js +0 -170
- package/dist/scp/render.js.map +0 -1
- package/dist/scp/write-plan.d.ts +0 -161
- package/dist/scp/write-plan.d.ts.map +0 -1
- package/dist/scp/write-plan.js +0 -528
- package/dist/scp/write-plan.js.map +0 -1
- package/dist/scp/write-runtime.d.ts +0 -80
- package/dist/scp/write-runtime.d.ts.map +0 -1
- package/dist/scp/write-runtime.js +0 -167
- package/dist/scp/write-runtime.js.map +0 -1
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* litedbmodel v2 SCP — dialect-parameterized Backend Compile (WS6, #26; spec §4/§5/§8/§10).
|
|
3
|
-
*
|
|
4
|
-
* The SAME Component-graph IR compiles to SQLite, Postgres and MySQL SQL. The IR→structure
|
|
5
|
-
* lowering (SELECT/INSERT/UPDATE/DELETE skeletons, the WHERE fragment tree, `col = ?`, IN-list
|
|
6
|
-
* `(?)` expansion, param slots) is SHARED across dialects; only the genuine dialect divergences
|
|
7
|
-
* (INSERT conflict clause + INSERT verb) are delegated to the {@link Dialect} strategy (the SSoT
|
|
8
|
-
* — no scattered `?:`). Placeholders stay `?` through compilation; the PG `?`→`$N` conversion is
|
|
9
|
-
* a final render-time one-pass ({@link import('./dialect').Dialect.finalizePlaceholders}), NOT a
|
|
10
|
-
* compile-time concern — so the compiled `CompiledOperation.sql` is dialect-tagged but still
|
|
11
|
-
* `?`-placeheld, keeping the bundle uniform.
|
|
12
|
-
*
|
|
13
|
-
* `compile-sqlite.ts` delegates its INSERT compile here with the SQLite dialect, so the pinned
|
|
14
|
-
* SQLite golden (WS1) is preserved byte-for-byte and the PG/MySQL variants diverge ONLY where the
|
|
15
|
-
* v1 SqlBuilders diverge (proven byte-identical in the WS6 dialect-golden test).
|
|
16
|
-
*/
|
|
17
|
-
import type { CompiledOperation, ExprNode } from './ir';
|
|
18
|
-
import type { Dialect } from './dialect';
|
|
19
|
-
/** Column → value Expression IR (insertion order = SQL column order). */
|
|
20
|
-
export interface InsertShape {
|
|
21
|
-
readonly table: string;
|
|
22
|
-
readonly values: Record<string, ExprNode>;
|
|
23
|
-
readonly returning?: readonly string[];
|
|
24
|
-
readonly onConflict?: readonly string[];
|
|
25
|
-
readonly onConflictAction?: 'ignore' | {
|
|
26
|
-
readonly updateColumns: 'all' | readonly string[];
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Compile an INSERT for a given dialect. Byte-identical to the corresponding v1 SqlBuilder's
|
|
31
|
-
* single-record `buildInsert` output (the golden bar):
|
|
32
|
-
* - SQLite: `INSERT [OR IGNORE] INTO t (c) VALUES (?)[ ON CONFLICT (k) DO UPDATE SET c = excluded.c][ RETURNING r]`
|
|
33
|
-
* - Postgres: `INSERT INTO t (c) VALUES (?)[ ON CONFLICT (k) DO NOTHING | DO UPDATE SET c = EXCLUDED.c][ RETURNING r]`
|
|
34
|
-
* - MySQL: `INSERT [IGNORE] INTO t (c) VALUES (?)[ ON DUPLICATE KEY UPDATE c = VALUES(c)]`
|
|
35
|
-
*
|
|
36
|
-
* Placeholders remain `?`; PG's `?`→`$N` is applied at render time.
|
|
37
|
-
*/
|
|
38
|
-
export declare function compileInsertFor(dialect: Dialect, desc: InsertShape): CompiledOperation;
|
|
39
|
-
//# sourceMappingURL=compile-dialect.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compile-dialect.d.ts","sourceRoot":"","sources":["../../src/scp/compile-dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AAKzD,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,aAAa,EAAE,KAAK,GAAG,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;CAC9F;AAKD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAiBvF"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* litedbmodel v2 SCP — dialect-parameterized Backend Compile (WS6, #26; spec §4/§5/§8/§10).
|
|
4
|
-
*
|
|
5
|
-
* The SAME Component-graph IR compiles to SQLite, Postgres and MySQL SQL. The IR→structure
|
|
6
|
-
* lowering (SELECT/INSERT/UPDATE/DELETE skeletons, the WHERE fragment tree, `col = ?`, IN-list
|
|
7
|
-
* `(?)` expansion, param slots) is SHARED across dialects; only the genuine dialect divergences
|
|
8
|
-
* (INSERT conflict clause + INSERT verb) are delegated to the {@link Dialect} strategy (the SSoT
|
|
9
|
-
* — no scattered `?:`). Placeholders stay `?` through compilation; the PG `?`→`$N` conversion is
|
|
10
|
-
* a final render-time one-pass ({@link import('./dialect').Dialect.finalizePlaceholders}), NOT a
|
|
11
|
-
* compile-time concern — so the compiled `CompiledOperation.sql` is dialect-tagged but still
|
|
12
|
-
* `?`-placeheld, keeping the bundle uniform.
|
|
13
|
-
*
|
|
14
|
-
* `compile-sqlite.ts` delegates its INSERT compile here with the SQLite dialect, so the pinned
|
|
15
|
-
* SQLite golden (WS1) is preserved byte-for-byte and the PG/MySQL variants diverge ONLY where the
|
|
16
|
-
* v1 SqlBuilders diverge (proven byte-identical in the WS6 dialect-golden test).
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.compileInsertFor = compileInsertFor;
|
|
20
|
-
/** Row → logical model assembly (shape only). */
|
|
21
|
-
const assembly = (shape) => ({ shape });
|
|
22
|
-
/**
|
|
23
|
-
* Compile an INSERT for a given dialect. Byte-identical to the corresponding v1 SqlBuilder's
|
|
24
|
-
* single-record `buildInsert` output (the golden bar):
|
|
25
|
-
* - SQLite: `INSERT [OR IGNORE] INTO t (c) VALUES (?)[ ON CONFLICT (k) DO UPDATE SET c = excluded.c][ RETURNING r]`
|
|
26
|
-
* - Postgres: `INSERT INTO t (c) VALUES (?)[ ON CONFLICT (k) DO NOTHING | DO UPDATE SET c = EXCLUDED.c][ RETURNING r]`
|
|
27
|
-
* - MySQL: `INSERT [IGNORE] INTO t (c) VALUES (?)[ ON DUPLICATE KEY UPDATE c = VALUES(c)]`
|
|
28
|
-
*
|
|
29
|
-
* Placeholders remain `?`; PG's `?`→`$N` is applied at render time.
|
|
30
|
-
*/
|
|
31
|
-
function compileInsertFor(dialect, desc) {
|
|
32
|
-
const columns = Object.keys(desc.values);
|
|
33
|
-
if (columns.length === 0)
|
|
34
|
-
throw new Error('INSERT requires at least one value column');
|
|
35
|
-
const placeholders = columns.map(() => '?').join(', ');
|
|
36
|
-
const params = columns.map((c) => desc.values[c]);
|
|
37
|
-
const conflictAction = resolveConflictAction(desc, columns);
|
|
38
|
-
const verb = dialect.insertVerb(conflictAction);
|
|
39
|
-
let sql = `${verb} ${desc.table} (${columns.join(', ')}) VALUES (${placeholders})`;
|
|
40
|
-
if (conflictAction !== undefined) {
|
|
41
|
-
sql += dialect.insertConflictClause(desc.onConflict ?? [], conflictAction);
|
|
42
|
-
}
|
|
43
|
-
if (desc.returning !== undefined)
|
|
44
|
-
sql += ` RETURNING ${desc.returning.join(', ')}`;
|
|
45
|
-
return { component: 'Insert', sql, where: null, params, assembly: assembly('items') };
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Resolve the dialect-neutral {@link ConflictAction} from the INSERT description. An `'all'`
|
|
49
|
-
* update-column list is expanded to the concrete inserted columns EXCEPT the conflict keys
|
|
50
|
-
* (matching the v1 SqlBuilders' `onConflictUpdate === 'all' ? columns : …`, which include all
|
|
51
|
-
* columns; the v1 builders use the full `columns` list for `'all'`, so we mirror that exactly).
|
|
52
|
-
* Returns undefined when the INSERT declares no conflict handling.
|
|
53
|
-
*/
|
|
54
|
-
function resolveConflictAction(desc, columns) {
|
|
55
|
-
if (desc.onConflict === undefined || desc.onConflictAction === undefined)
|
|
56
|
-
return undefined;
|
|
57
|
-
if (desc.onConflictAction === 'ignore')
|
|
58
|
-
return 'ignore';
|
|
59
|
-
const cols = desc.onConflictAction.updateColumns === 'all' ? columns : desc.onConflictAction.updateColumns;
|
|
60
|
-
return { updateColumns: cols };
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=compile-dialect.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compile-dialect.js","sourceRoot":"","sources":["../../src/scp/compile-dialect.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;AA6BH,4CAiBC;AA7BD,iDAAiD;AACjD,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAEhD;;;;;;;;GAQG;AACH,SAAgB,gBAAgB,CAAC,OAAgB,EAAE,IAAiB;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACvF,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,MAAM,GAAe,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9D,MAAM,cAAc,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IAChD,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,YAAY,GAAG,CAAC;IAEnF,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,GAAG,IAAI,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAEnF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;AACxF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,IAAiB,EAAE,OAA0B;IAC1E,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3F,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;IAC3G,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* litedbmodel v2 SCP — SQLite Backend Compile (WS1, #21).
|
|
3
|
-
*
|
|
4
|
-
* Lowers a structured CRUD operation description (a Component-graph Select/Insert/Update/
|
|
5
|
-
* Delete node with ports) into a {@link CompiledOperation}: SQLite dialect SQL text,
|
|
6
|
-
* a fragment tree (dynamic WHERE/SET with existence rules), and static param slots — the
|
|
7
|
-
* IR shape of spec §8. Placeholders are unified as `?` (the `?`→`$N` pass is PG-only and
|
|
8
|
-
* OUT OF SCOPE for WS1).
|
|
9
|
-
*
|
|
10
|
-
* The generated SQLite SQL is byte-identical to what litedbmodel v1's SqliteSqlBuilder /
|
|
11
|
-
* `DBModel._buildSelectSQL` produce for equivalent queries (the golden bar). In
|
|
12
|
-
* particular:
|
|
13
|
-
* - SELECT: `SELECT <cols> FROM <t>[ WHERE <c>][ GROUP BY <g>][ ORDER BY <o>][ LIMIT ?][ OFFSET ?]`
|
|
14
|
-
* - INSERT: `INSERT INTO <t> (<cols>) VALUES (<vals>)[ RETURNING <r>]`
|
|
15
|
-
* - UPDATE: `UPDATE <t> SET <a = ?, …> WHERE <c>[ RETURNING <r>]`
|
|
16
|
-
* - DELETE: `DELETE FROM <t> WHERE <c>[ RETURNING <r>]`
|
|
17
|
-
* - WHERE parts joined by ` AND ` (or ` OR ` for an OR group), equality `col = ?`,
|
|
18
|
-
* IN-list `col IN (?, …)`, empty array → `1 = 0`, NULL → `col IS NULL`.
|
|
19
|
-
*
|
|
20
|
-
* ## Hard rule: closed Expression IR only
|
|
21
|
-
*
|
|
22
|
-
* Every param slot this compiler emits is an Expression IR node from bc's closed set
|
|
23
|
-
* (`PORTABLE_EXPR_OPERATORS`). NO litedbmodel-local opcode is ever invented. An
|
|
24
|
-
* un-lowerable predicate is the Raw SQL escape hatch's concern (spec §13), not a fake
|
|
25
|
-
* opcode. {@link compileSelect} et al. only construct `ref` / `coalesce` / etc.
|
|
26
|
-
*/
|
|
27
|
-
import type { CompiledOperation, ExprNode } from './ir';
|
|
28
|
-
/** A reference into the input scope or a sibling wire result (Expression IR `ref`). */
|
|
29
|
-
export type Ref = {
|
|
30
|
-
ref: string[];
|
|
31
|
-
};
|
|
32
|
-
/** A single WHERE condition. `skipWhen` (absent → always present) drives SKIP (§8). */
|
|
33
|
-
export type Condition = {
|
|
34
|
-
kind: 'eq';
|
|
35
|
-
column: string;
|
|
36
|
-
value: ExprNode;
|
|
37
|
-
skipWhen?: ExprNode;
|
|
38
|
-
} | {
|
|
39
|
-
kind: 'cmp';
|
|
40
|
-
column: string;
|
|
41
|
-
op: '<' | '<=' | '>' | '>=' | '<>';
|
|
42
|
-
value: ExprNode;
|
|
43
|
-
skipWhen?: ExprNode;
|
|
44
|
-
} | {
|
|
45
|
-
kind: 'isNull';
|
|
46
|
-
column: string;
|
|
47
|
-
skipWhen?: ExprNode;
|
|
48
|
-
} | {
|
|
49
|
-
kind: 'in';
|
|
50
|
-
column: string;
|
|
51
|
-
value: ExprNode;
|
|
52
|
-
skipWhen?: ExprNode;
|
|
53
|
-
}
|
|
54
|
-
/** A nested AND/OR group (parenthesized, dynamic-expansion spec §4). */
|
|
55
|
-
| {
|
|
56
|
-
kind: 'group';
|
|
57
|
-
connector: 'AND' | 'OR';
|
|
58
|
-
conditions: Condition[];
|
|
59
|
-
skipWhen?: ExprNode;
|
|
60
|
-
};
|
|
61
|
-
export interface SelectDesc {
|
|
62
|
-
table: string;
|
|
63
|
-
/** Projection columns; `['*']` renders `*`. */
|
|
64
|
-
select: string[];
|
|
65
|
-
where?: Condition[];
|
|
66
|
-
/** Raw ORDER BY body (dialect-neutral text, e.g. `"created_at DESC"`). */
|
|
67
|
-
order?: string;
|
|
68
|
-
/** GROUP BY body. */
|
|
69
|
-
group?: string;
|
|
70
|
-
/** LIMIT value as an Expression IR node (e.g. a `coalesce` default). */
|
|
71
|
-
limit?: ExprNode;
|
|
72
|
-
/** OFFSET value as an Expression IR node. */
|
|
73
|
-
offset?: ExprNode;
|
|
74
|
-
}
|
|
75
|
-
export interface InsertDesc {
|
|
76
|
-
table: string;
|
|
77
|
-
/** Column → value Expression IR (insertion order = SQL column order). */
|
|
78
|
-
values: Record<string, ExprNode>;
|
|
79
|
-
returning?: string[];
|
|
80
|
-
onConflict?: string[];
|
|
81
|
-
onConflictAction?: 'ignore' | {
|
|
82
|
-
updateColumns: 'all' | string[];
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
export interface UpdateDesc {
|
|
86
|
-
table: string;
|
|
87
|
-
/** Column → value Expression IR (insertion order = SET clause order). */
|
|
88
|
-
set: Record<string, ExprNode>;
|
|
89
|
-
where: Condition[];
|
|
90
|
-
returning?: string[];
|
|
91
|
-
}
|
|
92
|
-
export interface DeleteDesc {
|
|
93
|
-
table: string;
|
|
94
|
-
where: Condition[];
|
|
95
|
-
returning?: string[];
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Compile a SELECT. Static params (LIMIT / OFFSET) sit AFTER the `{where}` splice, so
|
|
99
|
-
* they are emitted after the fragment params (dynamic-expansion spec §6).
|
|
100
|
-
*/
|
|
101
|
-
export declare function compileSelect(desc: SelectDesc): CompiledOperation;
|
|
102
|
-
/**
|
|
103
|
-
* Compile an INSERT (SQLite). All params are static (no WHERE); order = column order. The
|
|
104
|
-
* dialect-specific conflict/verb rendering is delegated to the SQLite {@link SQLITE} strategy
|
|
105
|
-
* ({@link compileInsertFor}) — the SAME dialect-parameterized compile the PG/MySQL Backend
|
|
106
|
-
* Compile uses (WS6), so SQLite is byte-for-byte unchanged and the other dialects diverge only
|
|
107
|
-
* where the v1 SqlBuilders diverge.
|
|
108
|
-
*/
|
|
109
|
-
export declare function compileInsert(desc: InsertDesc): CompiledOperation;
|
|
110
|
-
/** Compile an UPDATE. SET params (static) precede the `{where}` splice (spec §6). */
|
|
111
|
-
export declare function compileUpdate(desc: UpdateDesc): CompiledOperation;
|
|
112
|
-
/** Compile a DELETE. No static params before the WHERE (all params are conditions). */
|
|
113
|
-
export declare function compileDelete(desc: DeleteDesc): CompiledOperation;
|
|
114
|
-
//# sourceMappingURL=compile-sqlite.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compile-sqlite.d.ts","sourceRoot":"","sources":["../../src/scp/compile-sqlite.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* litedbmodel v2 SCP — SQLite Backend Compile (WS1, #21).
|
|
4
|
-
*
|
|
5
|
-
* Lowers a structured CRUD operation description (a Component-graph Select/Insert/Update/
|
|
6
|
-
* Delete node with ports) into a {@link CompiledOperation}: SQLite dialect SQL text,
|
|
7
|
-
* a fragment tree (dynamic WHERE/SET with existence rules), and static param slots — the
|
|
8
|
-
* IR shape of spec §8. Placeholders are unified as `?` (the `?`→`$N` pass is PG-only and
|
|
9
|
-
* OUT OF SCOPE for WS1).
|
|
10
|
-
*
|
|
11
|
-
* The generated SQLite SQL is byte-identical to what litedbmodel v1's SqliteSqlBuilder /
|
|
12
|
-
* `DBModel._buildSelectSQL` produce for equivalent queries (the golden bar). In
|
|
13
|
-
* particular:
|
|
14
|
-
* - SELECT: `SELECT <cols> FROM <t>[ WHERE <c>][ GROUP BY <g>][ ORDER BY <o>][ LIMIT ?][ OFFSET ?]`
|
|
15
|
-
* - INSERT: `INSERT INTO <t> (<cols>) VALUES (<vals>)[ RETURNING <r>]`
|
|
16
|
-
* - UPDATE: `UPDATE <t> SET <a = ?, …> WHERE <c>[ RETURNING <r>]`
|
|
17
|
-
* - DELETE: `DELETE FROM <t> WHERE <c>[ RETURNING <r>]`
|
|
18
|
-
* - WHERE parts joined by ` AND ` (or ` OR ` for an OR group), equality `col = ?`,
|
|
19
|
-
* IN-list `col IN (?, …)`, empty array → `1 = 0`, NULL → `col IS NULL`.
|
|
20
|
-
*
|
|
21
|
-
* ## Hard rule: closed Expression IR only
|
|
22
|
-
*
|
|
23
|
-
* Every param slot this compiler emits is an Expression IR node from bc's closed set
|
|
24
|
-
* (`PORTABLE_EXPR_OPERATORS`). NO litedbmodel-local opcode is ever invented. An
|
|
25
|
-
* un-lowerable predicate is the Raw SQL escape hatch's concern (spec §13), not a fake
|
|
26
|
-
* opcode. {@link compileSelect} et al. only construct `ref` / `coalesce` / etc.
|
|
27
|
-
*/
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.compileSelect = compileSelect;
|
|
30
|
-
exports.compileInsert = compileInsert;
|
|
31
|
-
exports.compileUpdate = compileUpdate;
|
|
32
|
-
exports.compileDelete = compileDelete;
|
|
33
|
-
const ir_1 = require("./ir");
|
|
34
|
-
const dialect_1 = require("./dialect");
|
|
35
|
-
const compile_dialect_1 = require("./compile-dialect");
|
|
36
|
-
// ── WHERE fragment-tree lowering (spec §8) ────────────────────────────────────
|
|
37
|
-
/** Lower one condition to a fragment (leaf) or nested tree, without a leading connector. */
|
|
38
|
-
function lowerCondition(c) {
|
|
39
|
-
if (c.kind === 'group') {
|
|
40
|
-
const tree = {
|
|
41
|
-
connector: c.connector,
|
|
42
|
-
fragments: c.conditions.map(lowerCondition),
|
|
43
|
-
};
|
|
44
|
-
// A group's own SKIP guard is carried by wrapping it — but a FragmentTree has no
|
|
45
|
-
// `when`; represent a conditional group as a single-fragment tree is not expressible,
|
|
46
|
-
// so a guarded group is lowered as a leaf-less tree whose presence is the OR/AND of
|
|
47
|
-
// its members' presence (renderTree already drops it when empty). A group with its
|
|
48
|
-
// own skipWhen is not part of WS1's representative surface; reject loudly if used.
|
|
49
|
-
if (c.skipWhen !== undefined) {
|
|
50
|
-
throw new Error('a conditional (SKIP) group is not supported in WS1; guard the member conditions individually');
|
|
51
|
-
}
|
|
52
|
-
return tree;
|
|
53
|
-
}
|
|
54
|
-
let f;
|
|
55
|
-
switch (c.kind) {
|
|
56
|
-
case 'eq':
|
|
57
|
-
f = { always: true, sql: `${c.column} = ?`, params: [c.value] };
|
|
58
|
-
break;
|
|
59
|
-
case 'cmp':
|
|
60
|
-
f = { always: true, sql: `${c.column} ${c.op} ?`, params: [c.value] };
|
|
61
|
-
break;
|
|
62
|
-
case 'isNull':
|
|
63
|
-
f = { always: true, sql: `${c.column} IS NULL`, params: [] };
|
|
64
|
-
break;
|
|
65
|
-
case 'in':
|
|
66
|
-
// IN-list: single `(?)` slot expands at render time (spec §5). golden text:
|
|
67
|
-
// `col IN (?, ?, …)` with `, ` separators; empty array degenerates to `(NULL)`.
|
|
68
|
-
f = { always: true, sql: `${c.column} IN (?)`, params: [c.value], expand: 0 };
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
if (c.skipWhen !== undefined) {
|
|
72
|
-
delete f.always;
|
|
73
|
-
f.when = c.skipWhen;
|
|
74
|
-
}
|
|
75
|
-
return f;
|
|
76
|
-
}
|
|
77
|
-
/** Build a top-level AND fragment tree from a condition list (null when empty). */
|
|
78
|
-
function lowerWhere(conditions) {
|
|
79
|
-
if (conditions === undefined || conditions.length === 0)
|
|
80
|
-
return null;
|
|
81
|
-
return { connector: 'AND', fragments: conditions.map(lowerCondition) };
|
|
82
|
-
}
|
|
83
|
-
// ── CRUD compilers ────────────────────────────────────────────────────────────
|
|
84
|
-
const assembly = (shape) => ({ shape });
|
|
85
|
-
/**
|
|
86
|
-
* Compile a SELECT. Static params (LIMIT / OFFSET) sit AFTER the `{where}` splice, so
|
|
87
|
-
* they are emitted after the fragment params (dynamic-expansion spec §6).
|
|
88
|
-
*/
|
|
89
|
-
function compileSelect(desc) {
|
|
90
|
-
const cols = desc.select.length === 1 && desc.select[0] === '*' ? '*' : desc.select.join(', ');
|
|
91
|
-
let sql = `SELECT ${cols} FROM ${desc.table}`;
|
|
92
|
-
const where = lowerWhere(desc.where);
|
|
93
|
-
// The WHERE splice marker is emitted whenever a fragment tree exists (even if all
|
|
94
|
-
// fragments may skip — degeneration is a render-time decision, spec §3).
|
|
95
|
-
if (where !== null)
|
|
96
|
-
sql += ir_1.WHERE_SLOT;
|
|
97
|
-
if (desc.group !== undefined)
|
|
98
|
-
sql += ` GROUP BY ${desc.group}`;
|
|
99
|
-
if (desc.order !== undefined)
|
|
100
|
-
sql += ` ORDER BY ${desc.order}`;
|
|
101
|
-
const params = [];
|
|
102
|
-
if (desc.limit !== undefined) {
|
|
103
|
-
sql += ` LIMIT ?`;
|
|
104
|
-
params.push(desc.limit);
|
|
105
|
-
}
|
|
106
|
-
if (desc.offset !== undefined) {
|
|
107
|
-
sql += ` OFFSET ?`;
|
|
108
|
-
params.push(desc.offset);
|
|
109
|
-
}
|
|
110
|
-
return { component: 'Select', sql, where, params, assembly: assembly('items') };
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Compile an INSERT (SQLite). All params are static (no WHERE); order = column order. The
|
|
114
|
-
* dialect-specific conflict/verb rendering is delegated to the SQLite {@link SQLITE} strategy
|
|
115
|
-
* ({@link compileInsertFor}) — the SAME dialect-parameterized compile the PG/MySQL Backend
|
|
116
|
-
* Compile uses (WS6), so SQLite is byte-for-byte unchanged and the other dialects diverge only
|
|
117
|
-
* where the v1 SqlBuilders diverge.
|
|
118
|
-
*/
|
|
119
|
-
function compileInsert(desc) {
|
|
120
|
-
return (0, compile_dialect_1.compileInsertFor)(dialect_1.SQLITE, desc);
|
|
121
|
-
}
|
|
122
|
-
/** Compile an UPDATE. SET params (static) precede the `{where}` splice (spec §6). */
|
|
123
|
-
function compileUpdate(desc) {
|
|
124
|
-
const setCols = Object.keys(desc.set);
|
|
125
|
-
if (setCols.length === 0)
|
|
126
|
-
throw new Error('UPDATE requires at least one SET column');
|
|
127
|
-
const setClauses = setCols.map((c) => `${c} = ?`);
|
|
128
|
-
const params = setCols.map((c) => desc.set[c]);
|
|
129
|
-
const where = lowerWhere(desc.where);
|
|
130
|
-
if (where === null)
|
|
131
|
-
throw new Error('UPDATE requires conditions');
|
|
132
|
-
// The ` WHERE ` keyword is emitted by render() (it prepends ` WHERE ` when the fragment
|
|
133
|
-
// tree renders non-empty). Splice the marker directly after the SET clause.
|
|
134
|
-
let sql = `UPDATE ${desc.table} SET ${setClauses.join(', ')}${ir_1.WHERE_SLOT}`;
|
|
135
|
-
if (desc.returning !== undefined)
|
|
136
|
-
sql += ` RETURNING ${desc.returning.join(', ')}`;
|
|
137
|
-
return { component: 'Update', sql, where, params, assembly: assembly('items') };
|
|
138
|
-
}
|
|
139
|
-
/** Compile a DELETE. No static params before the WHERE (all params are conditions). */
|
|
140
|
-
function compileDelete(desc) {
|
|
141
|
-
const where = lowerWhere(desc.where);
|
|
142
|
-
if (where === null)
|
|
143
|
-
throw new Error('DELETE requires conditions');
|
|
144
|
-
let sql = `DELETE FROM ${desc.table}${ir_1.WHERE_SLOT}`;
|
|
145
|
-
if (desc.returning !== undefined)
|
|
146
|
-
sql += ` RETURNING ${desc.returning.join(', ')}`;
|
|
147
|
-
return { component: 'Delete', sql, where, params: [], assembly: assembly('items') };
|
|
148
|
-
}
|
|
149
|
-
//# sourceMappingURL=compile-sqlite.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compile-sqlite.js","sourceRoot":"","sources":["../../src/scp/compile-sqlite.ts"],"names":[],"mappings":"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"}
|
package/dist/scp/ir.d.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* litedbmodel v2 SCP — Backend Compile IR shapes (WS1, #21).
|
|
3
|
-
*
|
|
4
|
-
* These are the litedbmodel-specific SQL IR structures a Component-graph CRUD node
|
|
5
|
-
* carries AFTER Backend Compile (spec §8). They are the input a thin multi-language
|
|
6
|
-
* runtime reads (WS3) to produce byte-identical SQL. The normative rules for how a
|
|
7
|
-
* runtime expands them are `docs/proposal/sql-dynamic-expansion-spec.md`.
|
|
8
|
-
*
|
|
9
|
-
* ## Param slots (spec §8) — the closed Expression IR set only
|
|
10
|
-
*
|
|
11
|
-
* Every element of a `params` array is 1:1 with a `?` placeholder and is one of (using
|
|
12
|
-
* bc's FLAT scope — input ports and node results are top-level scope roots, matching
|
|
13
|
-
* `runBehavior`'s `{...input, ...results}`):
|
|
14
|
-
* - an **input reference** `{ ref: ["authorId"] }`
|
|
15
|
-
* - a **wire reference** `{ ref: ["<nodeId>", "field"] }`
|
|
16
|
-
* - an **Expression IR operator node** `{ coalesce: [{ refOpt: ["limit"] }, 20] }`
|
|
17
|
-
*
|
|
18
|
-
* All three are Expression IR nodes from bc's CLOSED operator set (`PORTABLE_EXPR_OPERATORS`
|
|
19
|
-
* — `ref`/`refOpt`/`coalesce`/`add`/`eq`/… ~23 ops). NO litedbmodel-local opcodes are ever
|
|
20
|
-
* emitted; an un-lowerable SQL construct is the Raw SQL escape hatch's concern (spec §13),
|
|
21
|
-
* not a fake opcode. This is enforced by {@link assertParamsPortable}.
|
|
22
|
-
*/
|
|
23
|
-
/** An Expression IR node (bc closed set). Opaque here; validated by the guard. */
|
|
24
|
-
export type ExprNode = unknown;
|
|
25
|
-
/**
|
|
26
|
-
* A dynamic WHERE/SET fragment with an existence rule (spec §8).
|
|
27
|
-
*
|
|
28
|
-
* - `always: true` — the fragment is unconditionally present.
|
|
29
|
-
* - `when: <ExprNode>` — the fragment is present iff the Expression evaluates to a
|
|
30
|
-
* truthy (present) binding. A `cond ? [...] : SKIP` in authoring lowers to a fragment
|
|
31
|
-
* whose `when` tests the presence of the driving input (§8 / feasibility §4). SKIP is
|
|
32
|
-
* NOT an Expression opcode — it is the ABSENCE of the fragment when `when` is false.
|
|
33
|
-
*
|
|
34
|
-
* `sql` is the fragment's literal SQL text (leading connector included, e.g. `" AND "`),
|
|
35
|
-
* with `?` placeholders. `params` are the fragment's param slots (1:1 with its `?`),
|
|
36
|
-
* appended to the assembled params array in fragment order only when the fragment is
|
|
37
|
-
* present. `expand` marks an IN-list slot whose single `?` expands to `(?, ?, …)` per the
|
|
38
|
-
* bound array's length (dynamic-expansion spec §5).
|
|
39
|
-
*/
|
|
40
|
-
export interface Fragment {
|
|
41
|
-
/** Unconditionally present. Exactly one of `always` / `when` is set. */
|
|
42
|
-
always?: true;
|
|
43
|
-
/** Presence guard (Expression IR). Present iff it evaluates truthy. */
|
|
44
|
-
when?: ExprNode;
|
|
45
|
-
/** Literal SQL text (includes the leading connector, e.g. `" AND status = ?"`). */
|
|
46
|
-
sql: string;
|
|
47
|
-
/** Param slots (Expression IR nodes), 1:1 with this fragment's `?`. */
|
|
48
|
-
params: ExprNode[];
|
|
49
|
-
/**
|
|
50
|
-
* IN-list expansion: index into `params` whose bound value is an array; its single `?`
|
|
51
|
-
* in `sql` (written `(?)`) expands to `(?, ?, …)` (dynamic-expansion spec §5).
|
|
52
|
-
*/
|
|
53
|
-
expand?: number;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* A compiled fragment tree (spec §8): ordered fragments combined by a single connector
|
|
57
|
-
* (`AND` / `OR`). Nested groups parenthesize (dynamic-expansion spec §4). A `null` tree
|
|
58
|
-
* means "no WHERE" (empty-WHERE degeneration, §3 of the spec).
|
|
59
|
-
*/
|
|
60
|
-
export interface FragmentTree {
|
|
61
|
-
connector: 'AND' | 'OR';
|
|
62
|
-
fragments: (Fragment | FragmentTree)[];
|
|
63
|
-
}
|
|
64
|
-
/** The assembly spec (row → logical model). WS1 emits the shape only. */
|
|
65
|
-
export interface AssemblySpec {
|
|
66
|
-
shape: string;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* The Backend Compile output of one CRUD node (spec §8). `sql` is the fully flattened
|
|
70
|
-
* static SQL with a single `{where}` splice point where the fragment tree renders (or no
|
|
71
|
-
* splice point at all for writes whose WHERE is static). `params` are the STATIC param
|
|
72
|
-
* slots (those outside the fragment tree — e.g. Insert values, LIMIT); fragment params
|
|
73
|
-
* are interleaved at render time per the dynamic-expansion spec.
|
|
74
|
-
*/
|
|
75
|
-
export interface CompiledOperation {
|
|
76
|
-
/** Catalog component name (`Select` / `Insert` / `Update` / `Delete`). */
|
|
77
|
-
component: string;
|
|
78
|
-
/** SQLite dialect SQL text with a `{where}` splice marker if a fragment tree applies. */
|
|
79
|
-
sql: string;
|
|
80
|
-
/** The dynamic WHERE/SET fragment tree, or null when the WHERE is fully static/absent. */
|
|
81
|
-
where: FragmentTree | null;
|
|
82
|
-
/**
|
|
83
|
-
* Static param slots outside the fragment tree, in SQL position order. Each is an
|
|
84
|
-
* Expression IR node (input-ref / wire-ref / operator) from the closed set.
|
|
85
|
-
*/
|
|
86
|
-
params: ExprNode[];
|
|
87
|
-
/** Row → logical model assembly (shape only in WS1). */
|
|
88
|
-
assembly: AssemblySpec;
|
|
89
|
-
}
|
|
90
|
-
/** The literal `{where}` splice marker inside `CompiledOperation.sql`. */
|
|
91
|
-
export declare const WHERE_SLOT = "{where}";
|
|
92
|
-
//# sourceMappingURL=ir.d.ts.map
|
package/dist/scp/ir.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../src/scp/ir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,kFAAkF;AAClF,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC;AAE/B;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,uEAAuE;IACvE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,CAAC,QAAQ,GAAG,YAAY,CAAC,EAAE,CAAC;CACxC;AAED,yEAAyE;AACzE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,GAAG,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,wDAAwD;IACxD,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,0EAA0E;AAC1E,eAAO,MAAM,UAAU,YAAY,CAAC"}
|
package/dist/scp/ir.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* litedbmodel v2 SCP — Backend Compile IR shapes (WS1, #21).
|
|
4
|
-
*
|
|
5
|
-
* These are the litedbmodel-specific SQL IR structures a Component-graph CRUD node
|
|
6
|
-
* carries AFTER Backend Compile (spec §8). They are the input a thin multi-language
|
|
7
|
-
* runtime reads (WS3) to produce byte-identical SQL. The normative rules for how a
|
|
8
|
-
* runtime expands them are `docs/proposal/sql-dynamic-expansion-spec.md`.
|
|
9
|
-
*
|
|
10
|
-
* ## Param slots (spec §8) — the closed Expression IR set only
|
|
11
|
-
*
|
|
12
|
-
* Every element of a `params` array is 1:1 with a `?` placeholder and is one of (using
|
|
13
|
-
* bc's FLAT scope — input ports and node results are top-level scope roots, matching
|
|
14
|
-
* `runBehavior`'s `{...input, ...results}`):
|
|
15
|
-
* - an **input reference** `{ ref: ["authorId"] }`
|
|
16
|
-
* - a **wire reference** `{ ref: ["<nodeId>", "field"] }`
|
|
17
|
-
* - an **Expression IR operator node** `{ coalesce: [{ refOpt: ["limit"] }, 20] }`
|
|
18
|
-
*
|
|
19
|
-
* All three are Expression IR nodes from bc's CLOSED operator set (`PORTABLE_EXPR_OPERATORS`
|
|
20
|
-
* — `ref`/`refOpt`/`coalesce`/`add`/`eq`/… ~23 ops). NO litedbmodel-local opcodes are ever
|
|
21
|
-
* emitted; an un-lowerable SQL construct is the Raw SQL escape hatch's concern (spec §13),
|
|
22
|
-
* not a fake opcode. This is enforced by {@link assertParamsPortable}.
|
|
23
|
-
*/
|
|
24
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.WHERE_SLOT = void 0;
|
|
26
|
-
/** The literal `{where}` splice marker inside `CompiledOperation.sql`. */
|
|
27
|
-
exports.WHERE_SLOT = '{where}';
|
|
28
|
-
//# sourceMappingURL=ir.js.map
|
package/dist/scp/ir.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ir.js","sourceRoot":"","sources":["../../src/scp/ir.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AA0EH,0EAA0E;AAC7D,QAAA,UAAU,GAAG,SAAS,CAAC"}
|
package/dist/scp/render.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* litedbmodel v2 SCP — fragment-tree render + param assembly (WS1, #21).
|
|
3
|
-
*
|
|
4
|
-
* The NORMATIVE reference implementation of `docs/proposal/sql-dynamic-expansion-spec.md`.
|
|
5
|
-
* Given a compiled operation and a bound input scope, it deterministically produces the
|
|
6
|
-
* final SQLite SQL text (`?` placeholders) and the flat params array. Every multi-language
|
|
7
|
-
* runtime (WS3) must reproduce this byte-for-byte; this TS implementation is the golden
|
|
8
|
-
* reference the conformance harness pins.
|
|
9
|
-
*
|
|
10
|
-
* The three moving parts (dynamic-expansion spec):
|
|
11
|
-
* §2 SKIP → fragment existence: a fragment with `when` is present iff `when` evaluates
|
|
12
|
-
* to a present (non-null / true) binding; an absent fragment contributes NO SQL and
|
|
13
|
-
* NO params.
|
|
14
|
-
* §3 empty-WHERE degeneration: if no fragment is present the whole `{where}` splice
|
|
15
|
-
* (including the ` WHERE ` keyword) collapses to the empty string.
|
|
16
|
-
* §4 AND/OR structure + parenthesization: a nested tree renders `(… <connector> …)`.
|
|
17
|
-
* §5 IN-list array expansion: a fragment slot marked `expand` turns its `(?)` into
|
|
18
|
-
* `(?, ?, …)` for each element of the bound array (0 elements → the `1 = 0`
|
|
19
|
-
* always-false degeneration, byte-identical to litedbmodel v1's empty-IN handling).
|
|
20
|
-
*/
|
|
21
|
-
import { type Scope, type Value } from 'behavior-contracts';
|
|
22
|
-
import type { CompiledOperation } from './ir';
|
|
23
|
-
import { type Dialect } from './dialect';
|
|
24
|
-
/** The result of rendering: final SQL text + flat params (1:1 with `?`). */
|
|
25
|
-
export interface RenderedSql {
|
|
26
|
-
sql: string;
|
|
27
|
-
params: Value[];
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Render a compiled operation to final SQLite SQL + params for a bound input scope.
|
|
31
|
-
*
|
|
32
|
-
* Param order (matches SQL text order, dynamic-expansion spec §6): the compiled `sql`
|
|
33
|
-
* splices the WHERE tree at `{where}`; static params before the marker are emitted first,
|
|
34
|
-
* then the fragment params in tree order, then static params after the marker. WS1's CRUD
|
|
35
|
-
* shapes place all pre-WHERE statics (Insert values, Update SET) before `{where}` and all
|
|
36
|
-
* post-WHERE statics (LIMIT / OFFSET) after — so a single left-to-right walk of the
|
|
37
|
-
* spliced SQL yields the canonical `?` order.
|
|
38
|
-
*/
|
|
39
|
-
export declare function renderOperation(op: CompiledOperation, input: Scope, dialect?: Dialect): RenderedSql;
|
|
40
|
-
//# sourceMappingURL=render.d.ts.map
|
package/dist/scp/render.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/scp/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAsB,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAA0B,MAAM,MAAM,CAAC;AAEtE,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAqFD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,OAAgB,GAAG,WAAW,CA6B3G"}
|