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
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* litedbmodel v2 SCP — RELATION batch-load compile → `makeSQL`, reproducing the
|
|
4
|
+
* ORIGINAL `LazyRelation` SQL text byte-for-byte across all shapes and dialects:
|
|
5
|
+
*
|
|
6
|
+
* single-key, unlimited:
|
|
7
|
+
* PG `SELECT … FROM t WHERE t.key = ANY(?::type[])[ AND <filters>][ ORDER BY …]`
|
|
8
|
+
* MySQL/SQLite `SELECT … FROM t WHERE t.key IN (?, …)[ AND <filters>][ ORDER BY …]`
|
|
9
|
+
* single-key, per-parent limit:
|
|
10
|
+
* PG `SELECT t.* FROM unnest(?::type[]) AS _keys(key) CROSS JOIN LATERAL
|
|
11
|
+
* (SELECT * FROM t WHERE t.key = _keys.key[ AND <filters>] ORDER BY … LIMIT n) t`
|
|
12
|
+
* MySQL/SQLite `WITH ranked AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY key ORDER BY …) AS _rn
|
|
13
|
+
* FROM t WHERE key IN (?, …)[ AND <filters>]) SELECT * FROM ranked WHERE _rn <= n`
|
|
14
|
+
* composite-key, unlimited:
|
|
15
|
+
* PG `SELECT … FROM t JOIN unnest(?::t1[], ?::t2[]) AS _u(a1, a2) ON t.k1=_u.a1 AND …`
|
|
16
|
+
* MySQL/SQLite `SELECT … FROM t WHERE (k1, k2) IN ((?, ?), …)`
|
|
17
|
+
* composite-key, per-parent limit: PG LATERAL composite / others ROW_NUMBER composite.
|
|
18
|
+
*
|
|
19
|
+
* The PG type text (`?::type[]`) comes from the ORIGINAL `inferPgArrayType` (sqlCast
|
|
20
|
+
* wins, else element-type inference). The .rs regressions are NOT reproduced: PG
|
|
21
|
+
* per-parent-limit is LATERAL (not ROW_NUMBER), and PG types are sqlCast-driven (not
|
|
22
|
+
* text-folded).
|
|
23
|
+
*
|
|
24
|
+
* Inner SELECTs reuse {@link compileSelect} — the same text `buildSelectSQL` yields —
|
|
25
|
+
* so the whole shape is byte-faithful to the original relation builder.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.PG_ARRAY_CAST_TOKEN = void 0;
|
|
29
|
+
exports.inferPgArrayType = inferPgArrayType;
|
|
30
|
+
exports.resolvePgArrayCast = resolvePgArrayCast;
|
|
31
|
+
exports.compileCompositeKeyStaticUnlimited = compileCompositeKeyStaticUnlimited;
|
|
32
|
+
exports.compileSingleKeyUnlimited = compileSingleKeyUnlimited;
|
|
33
|
+
exports.compileSingleKeyLimited = compileSingleKeyLimited;
|
|
34
|
+
exports.compileCompositeKeyUnlimited = compileCompositeKeyUnlimited;
|
|
35
|
+
exports.compileCompositeKeyLimited = compileCompositeKeyLimited;
|
|
36
|
+
exports.compileCompositeKeyStaticLimited = compileCompositeKeyStaticLimited;
|
|
37
|
+
const DBConditions_1 = require("../../DBConditions");
|
|
38
|
+
const compile_select_1 = require("./compile-select");
|
|
39
|
+
/**
|
|
40
|
+
* Reproduce the ORIGINAL `LazyRelation.inferPgArrayType`: sqlCast wins (`<cast>[]`);
|
|
41
|
+
* otherwise infer the element type from the sample values. Byte-identical to the
|
|
42
|
+
* original (which is the PG anchor — NOT the .rs coarse text-folding).
|
|
43
|
+
*/
|
|
44
|
+
function inferPgArrayType(values, sqlCast) {
|
|
45
|
+
if (sqlCast)
|
|
46
|
+
return `${sqlCast}[]`;
|
|
47
|
+
if (values.length === 0)
|
|
48
|
+
return 'text[]';
|
|
49
|
+
const sample = values[0];
|
|
50
|
+
if (typeof sample === 'number') {
|
|
51
|
+
if (values.every((v) => Number.isInteger(v)))
|
|
52
|
+
return 'int[]';
|
|
53
|
+
return 'numeric[]';
|
|
54
|
+
}
|
|
55
|
+
if (typeof sample === 'bigint')
|
|
56
|
+
return 'bigint[]';
|
|
57
|
+
if (typeof sample === 'boolean')
|
|
58
|
+
return 'boolean[]';
|
|
59
|
+
if (sample instanceof Date)
|
|
60
|
+
return 'timestamp[]';
|
|
61
|
+
return 'text[]';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The DEFERRED PG array-cast token (#46): a placeholder emitted in the STATIC SQL text where
|
|
65
|
+
* the `= ANY(?::<T>[])` / `UNNEST(?::<T>[])` element type `<T>` cannot be known at symbolic
|
|
66
|
+
* compile time (a schema-less `whereIn`, or a relation batch compiled without concrete keys).
|
|
67
|
+
* The render/handler layer resolves it from the BOUND values via {@link inferPgArrayType} — a
|
|
68
|
+
* mechanical dialect-render step, the same category as the `?`→`$N` placeholder render. This
|
|
69
|
+
* reproduces v1's live-PG-correct cast (`::int[]` for int keys, etc.), which v1 got because
|
|
70
|
+
* `inferPgArrayType` saw the real values at runtime.
|
|
71
|
+
*
|
|
72
|
+
* A byte sequence no legitimate SQL identifier/type text contains, so the resolve is a safe
|
|
73
|
+
* literal substring replace (never a regex over user text).
|
|
74
|
+
*/
|
|
75
|
+
exports.PG_ARRAY_CAST_TOKEN = '@@PG_ARRAY_CAST@@';
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the FIRST unresolved {@link PG_ARRAY_CAST_TOKEN} in a PG SQL fragment to the element
|
|
78
|
+
* type inferred from the bound `values` (v1 `inferPgArrayType`). Called at render time, once per
|
|
79
|
+
* array param, left-to-right — so each deferred array cast binds the type of its own value set.
|
|
80
|
+
* SQL with no token is returned unchanged (every non-deferred cast is already concrete).
|
|
81
|
+
*/
|
|
82
|
+
function resolvePgArrayCast(sql, values) {
|
|
83
|
+
const at = sql.indexOf(exports.PG_ARRAY_CAST_TOKEN);
|
|
84
|
+
if (at < 0)
|
|
85
|
+
return sql;
|
|
86
|
+
return sql.slice(0, at) + inferPgArrayType(values) + sql.slice(at + exports.PG_ARRAY_CAST_TOKEN.length);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The PG array-cast element type for a batch cast, honoring `sqlCast` (concrete column type) →
|
|
90
|
+
* the deferred {@link PG_ARRAY_CAST_TOKEN} (resolve at render from bound values) → inference from
|
|
91
|
+
* the compile-time sample `values`. Centralizes the #43/#46 precedence for every relation shape.
|
|
92
|
+
*/
|
|
93
|
+
function pgArrayCastType(values, sqlCast, defer) {
|
|
94
|
+
if (sqlCast)
|
|
95
|
+
return `${sqlCast}[]`;
|
|
96
|
+
if (defer)
|
|
97
|
+
return exports.PG_ARRAY_CAST_TOKEN;
|
|
98
|
+
return inferPgArrayType(values);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The STATIC composite-key batch forms (#47 item 1) — length-INDEPENDENT so the compiled `op.sql`
|
|
102
|
+
* is fixed (one param per column on PG; ONE JSON param on MySQL/SQLite), the SAME static-op
|
|
103
|
+
* property the single-key relation forms have. PG stays byte-identical to v1's `unnest`-JOIN
|
|
104
|
+
* (`batchLoadWithUnnestJoin`), with the element-type cast DEFERRED (#46) to render from the real
|
|
105
|
+
* keys. MySQL/SQLite use the single-JSON tuple form (the owner-approved deviation the single-key
|
|
106
|
+
* IN-list and the batch UPDATE composite already use — RESULT parity, NOT byte-identity): a
|
|
107
|
+
* `JSON_TABLE`/`json_each` subquery over one JSON array-of-tuples param. The v1 literal
|
|
108
|
+
* `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden `compileCompositeKeyUnlimited`.
|
|
109
|
+
*
|
|
110
|
+
* The JSON tuple param is `[[k1a,k2a],[k1b,k2b],…]` (positional element arrays), read back by
|
|
111
|
+
* ordinal path (`$[0]`, `$[1]`, …) so no per-column JSON key names are needed.
|
|
112
|
+
*/
|
|
113
|
+
function compileCompositeKeyStaticUnlimited(opts) {
|
|
114
|
+
const { tableName, targetKeys } = opts;
|
|
115
|
+
if (opts.dialect === 'postgres') {
|
|
116
|
+
// PG unnest-JOIN — ONE array param per key column (length-independent). Deferred cast (#46):
|
|
117
|
+
// the element type is resolved at render from the real per-column key arrays.
|
|
118
|
+
const unnestParams = targetKeys
|
|
119
|
+
.map((k) => `?::${pgArrayCastType([], opts.sqlCastMap?.get(k), opts.deferPgArrayCast)}`)
|
|
120
|
+
.join(', ');
|
|
121
|
+
const unnestAlias = `_unnest_${tableName}`;
|
|
122
|
+
const columnAliases = targetKeys.map((k) => `_unnest_${tableName}_${k}`).join(', ');
|
|
123
|
+
const joinConditions = targetKeys
|
|
124
|
+
.map((key) => `${tableName}.${key} = ${unnestAlias}._unnest_${tableName}_${key}`)
|
|
125
|
+
.join(' AND ');
|
|
126
|
+
const joinClause = `JOIN unnest(${unnestParams}) AS ${unnestAlias}(${columnAliases}) ON ${joinConditions}`;
|
|
127
|
+
// One placeholder array PER column fixes the arity of the JOIN params (each binds one array).
|
|
128
|
+
return (0, compile_select_1.compileSelect)({
|
|
129
|
+
dialect: opts.dialect,
|
|
130
|
+
tableName,
|
|
131
|
+
select: opts.select,
|
|
132
|
+
join: joinClause,
|
|
133
|
+
joinParams: targetKeys.map(() => [null]),
|
|
134
|
+
conditions: opts.conditions,
|
|
135
|
+
order: opts.order,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// MySQL/SQLite: composite membership via ONE JSON array-of-tuples param, read by ORDINAL path.
|
|
139
|
+
const jsonSubquery = compositeJsonMembership(opts.dialect, tableName, targetKeys);
|
|
140
|
+
const conditions = { ...opts.conditions, __raw__: [jsonSubquery, [[null]]] };
|
|
141
|
+
return (0, compile_select_1.compileSelect)({
|
|
142
|
+
dialect: opts.dialect,
|
|
143
|
+
tableName,
|
|
144
|
+
select: opts.select,
|
|
145
|
+
conditions,
|
|
146
|
+
order: opts.order,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The MySQL/SQLite composite-membership predicate over ONE JSON array-of-tuples param (ordinal
|
|
151
|
+
* paths). MySQL: `(k1,k2) IN (SELECT c0, c1 FROM JSON_TABLE(?, '$[*]' COLUMNS(c0 JSON PATH '$[0]',
|
|
152
|
+
* …)))` — an IN-subquery so it inherits the SAME per-column type coercion `(k1,k2) IN ((?,?),…)`
|
|
153
|
+
* would (the single-key rationale). SQLite: `EXISTS (SELECT 1 FROM json_each(?) je WHERE
|
|
154
|
+
* json_extract(je.value,'$[0]') = t.k1 AND …)` — the composite json_each form the batch UPDATE uses.
|
|
155
|
+
*/
|
|
156
|
+
function compositeJsonMembership(dialect, tableName, targetKeys) {
|
|
157
|
+
if (dialect === 'mysql') {
|
|
158
|
+
const cols = targetKeys.map((_, i) => `c${i}`);
|
|
159
|
+
const jtCols = cols.map((c, i) => `${c} JSON PATH '$[${i}]'`).join(', ');
|
|
160
|
+
const selectCols = cols.map((c) => `JSON_UNQUOTE(${c})`).join(', ');
|
|
161
|
+
const keyTuple = targetKeys.map((k) => `${tableName}.${k}`).join(', ');
|
|
162
|
+
return `(${keyTuple}) IN (SELECT ${selectCols} FROM JSON_TABLE(?, '$[*]' COLUMNS(${jtCols})) jt)`;
|
|
163
|
+
}
|
|
164
|
+
// SQLite: EXISTS over json_each, matching every key column by ordinal element.
|
|
165
|
+
const match = targetKeys
|
|
166
|
+
.map((k, i) => `json_extract(je.value, '$[${i}]') = ${tableName}.${k}`)
|
|
167
|
+
.join(' AND ');
|
|
168
|
+
return `EXISTS (SELECT 1 FROM json_each(?) je WHERE ${match})`;
|
|
169
|
+
}
|
|
170
|
+
// ============================================================================
|
|
171
|
+
// Single-key, unlimited.
|
|
172
|
+
// ============================================================================
|
|
173
|
+
/**
|
|
174
|
+
* `= ANY(?::type[])` (PG) / `IN (?, …)` (MySQL/SQLite) single-key unlimited batch load.
|
|
175
|
+
* Reproduces `batchLoadWithAnyArray` (PG) and `batchLoadWithIn` (others).
|
|
176
|
+
*
|
|
177
|
+
* The key array binds as ONE param on PG (`values` is a single array param); on
|
|
178
|
+
* MySQL/SQLite the original passes the array to `DBConditions` which expands it to
|
|
179
|
+
* `IN (?, ?, …)` with one param per element — reproduced here verbatim.
|
|
180
|
+
*/
|
|
181
|
+
function compileSingleKeyUnlimited(opts) {
|
|
182
|
+
if (opts.dialect === 'postgres') {
|
|
183
|
+
const sqlCast = opts.sqlCastMap?.get(opts.targetKey);
|
|
184
|
+
const pgType = pgArrayCastType(opts.values, sqlCast, opts.deferPgArrayCast);
|
|
185
|
+
const conditions = {
|
|
186
|
+
__raw__: [`${opts.tableName}.${opts.targetKey} = ANY(?::${pgType})`, [opts.values]],
|
|
187
|
+
...opts.conditions,
|
|
188
|
+
};
|
|
189
|
+
return (0, compile_select_1.compileSelect)({
|
|
190
|
+
dialect: opts.dialect,
|
|
191
|
+
tableName: opts.tableName,
|
|
192
|
+
select: opts.select,
|
|
193
|
+
conditions,
|
|
194
|
+
order: opts.order,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// MySQL/SQLite: `{ ...conditions, [targetKey]: values }` → `IN (?, …)` (array expand).
|
|
198
|
+
const conditions = { ...opts.conditions, [opts.targetKey]: opts.values };
|
|
199
|
+
return (0, compile_select_1.compileSelect)({
|
|
200
|
+
dialect: opts.dialect,
|
|
201
|
+
tableName: opts.tableName,
|
|
202
|
+
select: opts.select,
|
|
203
|
+
conditions,
|
|
204
|
+
order: opts.order,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
// ============================================================================
|
|
208
|
+
// Single-key, per-parent limit.
|
|
209
|
+
// ============================================================================
|
|
210
|
+
/**
|
|
211
|
+
* Per-parent-limit single-key batch load: PG `CROSS JOIN LATERAL` (the v1 anchor —
|
|
212
|
+
* NOT the .rs ROW_NUMBER regression); MySQL/SQLite `ROW_NUMBER() OVER (PARTITION BY …)`.
|
|
213
|
+
* Reproduces `batchLoadWithLateral` / `batchLoadWithRowNumber`.
|
|
214
|
+
*/
|
|
215
|
+
function compileSingleKeyLimited(opts) {
|
|
216
|
+
if (opts.dialect === 'postgres') {
|
|
217
|
+
const sqlCast = opts.sqlCastMap?.get(opts.targetKey);
|
|
218
|
+
const pgType = pgArrayCastType(opts.values, sqlCast, opts.deferPgArrayCast);
|
|
219
|
+
const lateralConditions = {
|
|
220
|
+
__raw__: `${opts.tableName}.${opts.targetKey} = _keys.key`,
|
|
221
|
+
...opts.conditions,
|
|
222
|
+
};
|
|
223
|
+
const inner = (0, compile_select_1.compileSelect)({
|
|
224
|
+
dialect: opts.dialect,
|
|
225
|
+
tableName: opts.tableName,
|
|
226
|
+
conditions: lateralConditions,
|
|
227
|
+
order: opts.order,
|
|
228
|
+
limit: opts.limit,
|
|
229
|
+
});
|
|
230
|
+
const sql = `SELECT ${opts.tableName}.* FROM unnest(?::${pgType}) AS _keys(key) ` +
|
|
231
|
+
`CROSS JOIN LATERAL (${inner.sql}) ${opts.tableName}`;
|
|
232
|
+
return { sql, params: [opts.values, ...inner.params] };
|
|
233
|
+
}
|
|
234
|
+
// MySQL/SQLite: ROW_NUMBER() CTE.
|
|
235
|
+
const orderBy = opts.order || opts.targetKey;
|
|
236
|
+
const cteConditions = { [opts.targetKey]: opts.values, ...opts.conditions };
|
|
237
|
+
const cte = (0, compile_select_1.compileSelect)({
|
|
238
|
+
dialect: opts.dialect,
|
|
239
|
+
tableName: opts.tableName,
|
|
240
|
+
select: `*, ROW_NUMBER() OVER (PARTITION BY ${opts.targetKey} ORDER BY ${orderBy}) AS _rn`,
|
|
241
|
+
conditions: cteConditions,
|
|
242
|
+
});
|
|
243
|
+
return (0, compile_select_1.compileSelect)({
|
|
244
|
+
dialect: opts.dialect,
|
|
245
|
+
tableName: 'ranked',
|
|
246
|
+
conditions: { __raw__: `_rn <= ${opts.limit}` },
|
|
247
|
+
cte: { name: 'ranked', sql: cte.sql, params: cte.params },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
// ============================================================================
|
|
251
|
+
// Composite-key, unlimited.
|
|
252
|
+
// ============================================================================
|
|
253
|
+
/** Transpose tuples to per-column arrays: `[[1,a],[2,b]] → [[1,2],[a,b]]`. */
|
|
254
|
+
function transpose(targetKeys, tuples) {
|
|
255
|
+
return targetKeys.map((_, colIndex) => tuples.map((t) => t[colIndex]));
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Composite-key unlimited batch load: PG `JOIN unnest(?::t1[], ?::t2[]) AS _u(a,b) ON …`
|
|
259
|
+
* (reproduces `batchLoadWithUnnestJoin`); MySQL/SQLite `(k1, k2) IN ((?, ?), …)`
|
|
260
|
+
* (reproduces `batchLoadWithCompositeIn` via `DBTupleIn`).
|
|
261
|
+
*/
|
|
262
|
+
function compileCompositeKeyUnlimited(opts) {
|
|
263
|
+
const { tableName, targetKeys, tuples } = opts;
|
|
264
|
+
if (opts.dialect === 'postgres') {
|
|
265
|
+
const columnArrays = transpose(targetKeys, tuples);
|
|
266
|
+
const unnestParams = columnArrays
|
|
267
|
+
.map((arr, i) => `?::${inferPgArrayType(arr, opts.sqlCastMap?.get(targetKeys[i]))}`)
|
|
268
|
+
.join(', ');
|
|
269
|
+
const unnestAlias = `_unnest_${tableName}`;
|
|
270
|
+
const columnAliases = targetKeys.map((k) => `_unnest_${tableName}_${k}`).join(', ');
|
|
271
|
+
const joinConditions = targetKeys
|
|
272
|
+
.map((key) => `${tableName}.${key} = ${unnestAlias}._unnest_${tableName}_${key}`)
|
|
273
|
+
.join(' AND ');
|
|
274
|
+
const joinClause = `JOIN unnest(${unnestParams}) AS ${unnestAlias}(${columnAliases}) ON ${joinConditions}`;
|
|
275
|
+
return (0, compile_select_1.compileSelect)({
|
|
276
|
+
dialect: opts.dialect,
|
|
277
|
+
tableName,
|
|
278
|
+
select: opts.select,
|
|
279
|
+
join: joinClause,
|
|
280
|
+
joinParams: columnArrays,
|
|
281
|
+
conditions: opts.conditions,
|
|
282
|
+
order: opts.order,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// MySQL/SQLite: (k1, k2) IN ((?, ?), …) built exactly as `batchLoadWithCompositeIn`.
|
|
286
|
+
const tuplePlaceholders = tuples
|
|
287
|
+
.map(() => `(${targetKeys.map(() => '?').join(', ')})`)
|
|
288
|
+
.join(', ');
|
|
289
|
+
const inClause = `(${targetKeys.join(', ')}) IN (${tuplePlaceholders})`;
|
|
290
|
+
// The original builds base conditions FIRST then the composite IN last; DBConditions
|
|
291
|
+
// preserves object key insertion order, so replicate that order.
|
|
292
|
+
const conditions = { ...opts.conditions, __raw__: [inClause, tuples.flat()] };
|
|
293
|
+
return (0, compile_select_1.compileSelect)({
|
|
294
|
+
dialect: opts.dialect,
|
|
295
|
+
tableName,
|
|
296
|
+
select: opts.select,
|
|
297
|
+
conditions,
|
|
298
|
+
order: opts.order,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Composite-key, per-parent limit.
|
|
303
|
+
// ============================================================================
|
|
304
|
+
/**
|
|
305
|
+
* Composite-key per-parent-limit: PG LATERAL composite (reproduces
|
|
306
|
+
* `batchLoadWithLateralComposite`); MySQL/SQLite ROW_NUMBER composite (reproduces
|
|
307
|
+
* `batchLoadWithRowNumberComposite`).
|
|
308
|
+
*/
|
|
309
|
+
function compileCompositeKeyLimited(opts) {
|
|
310
|
+
const { tableName, targetKeys, tuples, limit } = opts;
|
|
311
|
+
if (opts.dialect === 'postgres') {
|
|
312
|
+
const columnArrays = transpose(targetKeys, tuples);
|
|
313
|
+
const unnestParams = columnArrays
|
|
314
|
+
.map((arr, i) => `?::${inferPgArrayType(arr, opts.sqlCastMap?.get(targetKeys[i]))}`)
|
|
315
|
+
.join(', ');
|
|
316
|
+
const keyAliases = targetKeys.map((_, i) => `key${i}`).join(', ');
|
|
317
|
+
const keyConditions = targetKeys
|
|
318
|
+
.map((key, i) => `${tableName}.${key} = _keys.key${i}`)
|
|
319
|
+
.join(' AND ');
|
|
320
|
+
const lateralConditions = { __raw__: keyConditions, ...opts.conditions };
|
|
321
|
+
const inner = (0, compile_select_1.compileSelect)({
|
|
322
|
+
dialect: opts.dialect,
|
|
323
|
+
tableName,
|
|
324
|
+
conditions: lateralConditions,
|
|
325
|
+
order: opts.order,
|
|
326
|
+
limit,
|
|
327
|
+
});
|
|
328
|
+
const sql = `SELECT ${tableName}.* FROM unnest(${unnestParams}) AS _keys(${keyAliases}) ` +
|
|
329
|
+
`CROSS JOIN LATERAL (${inner.sql}) ${tableName}`;
|
|
330
|
+
return { sql, params: [...columnArrays, ...inner.params] };
|
|
331
|
+
}
|
|
332
|
+
// MySQL/SQLite ROW_NUMBER composite.
|
|
333
|
+
const orderBy = opts.order || targetKeys.join(', ');
|
|
334
|
+
const partitionBy = targetKeys.join(', ');
|
|
335
|
+
const tuplePlaceholders = tuples
|
|
336
|
+
.map(() => `(${targetKeys.map(() => '?').join(', ')})`)
|
|
337
|
+
.join(', ');
|
|
338
|
+
const inClause = `(${targetKeys.join(', ')}) IN (${tuplePlaceholders})`;
|
|
339
|
+
const cteParams = tuples.flat();
|
|
340
|
+
const cteConditions = { __raw__: [inClause, cteParams], ...opts.conditions };
|
|
341
|
+
const cte = (0, compile_select_1.compileSelect)({
|
|
342
|
+
dialect: opts.dialect,
|
|
343
|
+
tableName,
|
|
344
|
+
select: `*, ROW_NUMBER() OVER (PARTITION BY ${partitionBy} ORDER BY ${orderBy}) AS _rn`,
|
|
345
|
+
conditions: cteConditions,
|
|
346
|
+
});
|
|
347
|
+
return (0, compile_select_1.compileSelect)({
|
|
348
|
+
dialect: opts.dialect,
|
|
349
|
+
tableName: 'ranked',
|
|
350
|
+
conditions: { __raw__: `_rn <= ${limit}` },
|
|
351
|
+
cte: { name: 'ranked', sql: cte.sql, params: cte.params },
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
// ============================================================================
|
|
355
|
+
// Composite-key, per-parent limit — STATIC (length-independent) form (#47 last gap).
|
|
356
|
+
// ============================================================================
|
|
357
|
+
/**
|
|
358
|
+
* The STATIC composite-key per-parent-LIMIT batch form (#47 last completeness gap) — the
|
|
359
|
+
* length-INDEPENDENT sibling of {@link compileCompositeKeyLimited}, so the compiled `op.sql` is
|
|
360
|
+
* FIXED (one array param per key column on PG; ONE JSON array-of-tuples param on MySQL/SQLite) and
|
|
361
|
+
* can be a STATIC bundle op — exactly the property {@link compileSingleKeyLimited} and
|
|
362
|
+
* {@link compileCompositeKeyStaticUnlimited} already have.
|
|
363
|
+
*
|
|
364
|
+
* The per-parent window is IDENTICAL to the single-key-limited path:
|
|
365
|
+
* - **PG**: `CROSS JOIN LATERAL` over `unnest(?::t1[], ?::t2[])` — BYTE-identical to v1's
|
|
366
|
+
* `batchLoadWithLateralComposite` (the composite LATERAL is already structurally
|
|
367
|
+
* length-independent; only the element-type cast was value-derived, and that is DEFERRED (#46)
|
|
368
|
+
* to render from the real keys via {@link PG_ARRAY_CAST_TOKEN}). No deviation on PG.
|
|
369
|
+
* - **MySQL/SQLite**: the SAME `ROW_NUMBER() OVER (PARTITION BY <keys> ORDER BY <order>)` CTE +
|
|
370
|
+
* `_rn <= limit` filter v1's `batchLoadWithRowNumberComposite` emits — but the CTE membership
|
|
371
|
+
* WHERE is the STATIC JSON-tuple predicate ({@link compositeJsonMembership}) instead of v1's
|
|
372
|
+
* value-dependent `(k1,k2) IN ((?,?),…)`. This is the owner-sanctioned static deviation the
|
|
373
|
+
* composite UNLIMITED form ({@link compileCompositeKeyStaticUnlimited}) and the single-key
|
|
374
|
+
* IN-list already use: the JSON subquery selects the SAME child rows the tuple-IN would, the
|
|
375
|
+
* window partitions/orders identically, so it is RESULT-parity to v1 (proven live). The v1
|
|
376
|
+
* literal `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden
|
|
377
|
+
* {@link compileCompositeKeyLimited}.
|
|
378
|
+
*/
|
|
379
|
+
function compileCompositeKeyStaticLimited(opts) {
|
|
380
|
+
const { tableName, targetKeys, limit } = opts;
|
|
381
|
+
if (opts.dialect === 'postgres') {
|
|
382
|
+
// PG LATERAL composite — ONE array param per key column (length-independent). Deferred cast
|
|
383
|
+
// (#46): each element type resolved at render from that column's real key array.
|
|
384
|
+
const unnestParams = targetKeys
|
|
385
|
+
.map((k) => `?::${pgArrayCastType([], opts.sqlCastMap?.get(k), opts.deferPgArrayCast)}`)
|
|
386
|
+
.join(', ');
|
|
387
|
+
const keyAliases = targetKeys.map((_, i) => `key${i}`).join(', ');
|
|
388
|
+
const keyConditions = targetKeys
|
|
389
|
+
.map((key, i) => `${tableName}.${key} = _keys.key${i}`)
|
|
390
|
+
.join(' AND ');
|
|
391
|
+
const lateralConditions = { __raw__: keyConditions, ...opts.conditions };
|
|
392
|
+
const inner = (0, compile_select_1.compileSelect)({
|
|
393
|
+
dialect: opts.dialect,
|
|
394
|
+
tableName,
|
|
395
|
+
conditions: lateralConditions,
|
|
396
|
+
order: opts.order,
|
|
397
|
+
limit,
|
|
398
|
+
});
|
|
399
|
+
const sql = `SELECT ${tableName}.* FROM unnest(${unnestParams}) AS _keys(${keyAliases}) ` +
|
|
400
|
+
`CROSS JOIN LATERAL (${inner.sql}) ${tableName}`;
|
|
401
|
+
// One placeholder array PER column fixes the arity (each binds one array param at execute time).
|
|
402
|
+
return { sql, params: [...targetKeys.map(() => [null]), ...inner.params] };
|
|
403
|
+
}
|
|
404
|
+
// MySQL/SQLite: the SAME ROW_NUMBER composite CTE + `_rn <= limit` as v1, but with the STATIC
|
|
405
|
+
// JSON-membership WHERE (one JSON array-of-tuples param) in place of v1's `(k1,k2) IN ((?,?),…)`.
|
|
406
|
+
const orderBy = opts.order || targetKeys.join(', ');
|
|
407
|
+
const partitionBy = targetKeys.join(', ');
|
|
408
|
+
const jsonSubquery = compositeJsonMembership(opts.dialect, tableName, targetKeys);
|
|
409
|
+
const cteConditions = { __raw__: [jsonSubquery, [[null]]], ...opts.conditions };
|
|
410
|
+
const cte = (0, compile_select_1.compileSelect)({
|
|
411
|
+
dialect: opts.dialect,
|
|
412
|
+
tableName,
|
|
413
|
+
select: `*, ROW_NUMBER() OVER (PARTITION BY ${partitionBy} ORDER BY ${orderBy}) AS _rn`,
|
|
414
|
+
conditions: cteConditions,
|
|
415
|
+
});
|
|
416
|
+
return (0, compile_select_1.compileSelect)({
|
|
417
|
+
dialect: opts.dialect,
|
|
418
|
+
tableName: 'ranked',
|
|
419
|
+
conditions: { __raw__: `_rn <= ${limit}` },
|
|
420
|
+
cte: { name: 'ranked', sql: cte.sql, params: cte.params },
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
// Silence unused import in builds where DBConditions is only referenced via ConditionObject.
|
|
424
|
+
void DBConditions_1.DBConditions;
|
|
425
|
+
//# sourceMappingURL=compile-relation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-relation.js","sourceRoot":"","sources":["../../../src/scp/makesql/compile-relation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* litedbmodel v2 SCP — SELECT compile → `makeSQL`, reproducing the ORIGINAL
|
|
3
|
+
* `DBModel._buildSelectSQL` text byte-for-byte (the internal builder `find()` uses):
|
|
4
|
+
*
|
|
5
|
+
* [WITH <cte> AS (…) ]SELECT <cols> FROM <t>[ <join>][ WHERE <cond>]
|
|
6
|
+
* [ GROUP BY <group>][ ORDER BY <order>][ LIMIT <n>][ OFFSET <n>][ FOR UPDATE][ <append>]
|
|
7
|
+
*
|
|
8
|
+
* LIMIT/OFFSET are INLINE literals (`LIMIT 10`), NOT parameters — the original inlines
|
|
9
|
+
* them (`sql += \` LIMIT ${options.limit}\``); reproduced here. FOR UPDATE / GROUP BY /
|
|
10
|
+
* raw `append` tail are the original's exact text. HAVING is carried through `append`
|
|
11
|
+
* (v1 core has no dedicated HAVING; the .rs-only HAVING is not the PG anchor).
|
|
12
|
+
*
|
|
13
|
+
* Param order matches the original exactly: CTE params → JOIN params → WHERE params.
|
|
14
|
+
*/
|
|
15
|
+
import type { ConditionObject } from '../../DBConditions';
|
|
16
|
+
import type { OrderSpec } from '../../Column';
|
|
17
|
+
import type { MakeSQL } from './makesql';
|
|
18
|
+
import type { Dialect } from './handler';
|
|
19
|
+
/** SELECT descriptor — mirrors the fields `_buildSelectSQL` reads from `SelectOptions`. */
|
|
20
|
+
export interface SelectDesc {
|
|
21
|
+
dialect: Dialect;
|
|
22
|
+
tableName: string;
|
|
23
|
+
/** SELECT column list (an explicit `options.select`). Empty/absent → falls back to {@link selectColumn}. */
|
|
24
|
+
select?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The model's `SELECT_COLUMN` (v1 `DBModel.SELECT_COLUMN`) — the fallback projection when no explicit
|
|
27
|
+
* `select` is given. v1 derives the SELECT list as `options.select || this.SELECT_COLUMN`
|
|
28
|
+
* (`DBModel._buildSelectSQL`:572), so a subclass that overrides `SELECT_COLUMN` must flow through here
|
|
29
|
+
* rather than being hardcoded to `'*'`. Absent → the base-class default `'*'` (`DBModel.SELECT_COLUMN`).
|
|
30
|
+
*/
|
|
31
|
+
selectColumn?: string;
|
|
32
|
+
conditions?: ConditionObject;
|
|
33
|
+
join?: string;
|
|
34
|
+
joinParams?: unknown[];
|
|
35
|
+
cte?: {
|
|
36
|
+
name: string;
|
|
37
|
+
sql: string;
|
|
38
|
+
params: unknown[];
|
|
39
|
+
};
|
|
40
|
+
group?: string;
|
|
41
|
+
order?: OrderSpec | string;
|
|
42
|
+
limit?: number;
|
|
43
|
+
offset?: number;
|
|
44
|
+
forUpdate?: boolean;
|
|
45
|
+
append?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compile a SELECT to a `makeSQL` bundle, byte-identical to `_buildSelectSQL`.
|
|
49
|
+
* Empty WHERE ⇒ no ` WHERE` (matches the original's `if (whereClause)` guard).
|
|
50
|
+
*/
|
|
51
|
+
export declare function compileSelect(desc: SelectDesc): MakeSQL;
|
|
52
|
+
//# sourceMappingURL=compile-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-select.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile-select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,4GAA4G;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CA6BvD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* litedbmodel v2 SCP — SELECT compile → `makeSQL`, reproducing the ORIGINAL
|
|
4
|
+
* `DBModel._buildSelectSQL` text byte-for-byte (the internal builder `find()` uses):
|
|
5
|
+
*
|
|
6
|
+
* [WITH <cte> AS (…) ]SELECT <cols> FROM <t>[ <join>][ WHERE <cond>]
|
|
7
|
+
* [ GROUP BY <group>][ ORDER BY <order>][ LIMIT <n>][ OFFSET <n>][ FOR UPDATE][ <append>]
|
|
8
|
+
*
|
|
9
|
+
* LIMIT/OFFSET are INLINE literals (`LIMIT 10`), NOT parameters — the original inlines
|
|
10
|
+
* them (`sql += \` LIMIT ${options.limit}\``); reproduced here. FOR UPDATE / GROUP BY /
|
|
11
|
+
* raw `append` tail are the original's exact text. HAVING is carried through `append`
|
|
12
|
+
* (v1 core has no dedicated HAVING; the .rs-only HAVING is not the PG anchor).
|
|
13
|
+
*
|
|
14
|
+
* Param order matches the original exactly: CTE params → JOIN params → WHERE params.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.compileSelect = compileSelect;
|
|
18
|
+
const Column_1 = require("../../Column");
|
|
19
|
+
const compile_1 = require("./compile");
|
|
20
|
+
const json_array_1 = require("./json-array");
|
|
21
|
+
/**
|
|
22
|
+
* Compile a SELECT to a `makeSQL` bundle, byte-identical to `_buildSelectSQL`.
|
|
23
|
+
* Empty WHERE ⇒ no ` WHERE` (matches the original's `if (whereClause)` guard).
|
|
24
|
+
*/
|
|
25
|
+
function compileSelect(desc) {
|
|
26
|
+
const params = [];
|
|
27
|
+
const selectCols = desc.select || (desc.selectColumn ?? '*');
|
|
28
|
+
const formatter = (0, compile_1.formatterFor)(desc.dialect);
|
|
29
|
+
// Param order (matches SQL order): CTE params → JOIN params → WHERE params.
|
|
30
|
+
if (desc.cte?.params && desc.cte.params.length > 0)
|
|
31
|
+
params.push(...desc.cte.params);
|
|
32
|
+
if (desc.joinParams && desc.joinParams.length > 0)
|
|
33
|
+
params.push(...desc.joinParams);
|
|
34
|
+
const whereClause = (0, json_array_1.conditionsFor)(desc.conditions ?? {}, desc.dialect).compile(params, formatter);
|
|
35
|
+
let sql = '';
|
|
36
|
+
if (desc.cte)
|
|
37
|
+
sql = `WITH ${desc.cte.name} AS (${desc.cte.sql}) `;
|
|
38
|
+
sql += `SELECT ${selectCols} FROM ${desc.tableName}`;
|
|
39
|
+
if (desc.join)
|
|
40
|
+
sql += ` ${desc.join}`;
|
|
41
|
+
if (whereClause)
|
|
42
|
+
sql += ` WHERE ${whereClause}`;
|
|
43
|
+
if (desc.group)
|
|
44
|
+
sql += ` GROUP BY ${desc.group}`;
|
|
45
|
+
const orderClause = typeof desc.order === 'string' ? desc.order : (0, Column_1.orderToString)(desc.order);
|
|
46
|
+
if (orderClause)
|
|
47
|
+
sql += ` ORDER BY ${orderClause}`;
|
|
48
|
+
if (desc.limit !== undefined)
|
|
49
|
+
sql += ` LIMIT ${desc.limit}`;
|
|
50
|
+
if (desc.offset !== undefined)
|
|
51
|
+
sql += ` OFFSET ${desc.offset}`;
|
|
52
|
+
if (desc.forUpdate)
|
|
53
|
+
sql += ' FOR UPDATE';
|
|
54
|
+
if (desc.append)
|
|
55
|
+
sql += ` ${desc.append}`;
|
|
56
|
+
return { sql, params };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=compile-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-select.js","sourceRoot":"","sources":["../../../src/scp/makesql/compile-select.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AAuCH,sCA6BC;AAjED,yCAA6C;AAG7C,uCAAyC;AACzC,6CAA6C;AA4B7C;;;GAGG;AACH,SAAgB,aAAa,CAAC,IAAgB;IAC5C,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE7C,4EAA4E;IAC5E,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpF,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAEnF,MAAM,WAAW,GAAG,IAAA,0BAAa,EAAC,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAElG,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,IAAI,CAAC,GAAG;QAAE,GAAG,GAAG,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAElE,GAAG,IAAI,UAAU,UAAU,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;IACrD,IAAI,IAAI,CAAC,IAAI;QAAE,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,WAAW;QAAE,GAAG,IAAI,UAAU,WAAW,EAAE,CAAC;IAChD,IAAI,IAAI,CAAC,KAAK;QAAE,GAAG,IAAI,aAAa,IAAI,CAAC,KAAK,EAAE,CAAC;IAEjD,MAAM,WAAW,GACf,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1E,IAAI,WAAW;QAAE,GAAG,IAAI,aAAa,WAAW,EAAE,CAAC;IAEnD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,IAAI,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC;IAC5D,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,SAAS;QAAE,GAAG,IAAI,aAAa,CAAC;IACzC,IAAI,IAAI,CAAC,MAAM;QAAE,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IAE1C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* litedbmodel v2 SCP — the COMPILE step (build time, TS). Emits the tuned dialect SQL
|
|
3
|
+
* TEXT for every surface as `makeSQL` port bundles, by REUSING the ORIGINAL tuned
|
|
4
|
+
* builders (`DBConditions`/`DBValues`, `LazyRelationContext`, `Postgres/Mysql/Sqlite
|
|
5
|
+
* SqlBuilder`, `DBModel.buildSelectSQL` + single INSERT/UPDATE/DELETE). Because each
|
|
6
|
+
* bundle's `sql`/`params` come from driving the original, the assembled + rendered
|
|
7
|
+
* output is byte-identical to what the original library sends over the wire.
|
|
8
|
+
*
|
|
9
|
+
* There is NO abstract IR here and NO reduced form. The produced artifact is ONLY
|
|
10
|
+
* `makeSQL` port bundles (`{ sql, params, skip? }`) — SQL structure (`= ANY`,
|
|
11
|
+
* `CROSS JOIN LATERAL`, `UNNEST`, cast, subquery, batch shapes) is TEXT inside `sql`.
|
|
12
|
+
*
|
|
13
|
+
* The three dialects share this compile: PG compiled text is the anchor and stays
|
|
14
|
+
* byte-identical to v1 (`= ANY(?::t[])` / `UNNEST` / LATERAL). MySQL/SQLite array &
|
|
15
|
+
* batch surfaces INTENTIONALLY DEVIATE from v1 (epic #43/#45): instead of v1's
|
|
16
|
+
* N-placeholder `IN (?, …)` / multi-VALUES / `VALUES ROW` / `CASE WHEN`, they now emit a
|
|
17
|
+
* SINGLE JSON param expanded server-side (`MEMBER OF` / `JSON_TABLE` / `json_each`; see
|
|
18
|
+
* `json-array.ts` / `json-batch.ts`). Result parity with v1 is proven on real MySQL 8 +
|
|
19
|
+
* SQLite (`test/scp/json-array-parity.test.ts`). Everything else stays v1 byte-match.
|
|
20
|
+
*/
|
|
21
|
+
import { type ConditionObject } from '../../DBConditions';
|
|
22
|
+
import type { SqlCastFormatter } from '../../DBValues';
|
|
23
|
+
import type { MakeSQL } from './makesql';
|
|
24
|
+
import type { Dialect } from './handler';
|
|
25
|
+
/** PostgreSQL cast formatter: `?` → `?::type` (matches `DBValues` default formatter). */
|
|
26
|
+
export declare const pgCastFormatter: SqlCastFormatter;
|
|
27
|
+
/** MySQL/SQLite cast formatter: no cast (placeholder unchanged). */
|
|
28
|
+
export declare const noCastFormatter: SqlCastFormatter;
|
|
29
|
+
/** The cast formatter the original builders use for a given dialect. */
|
|
30
|
+
export declare function formatterFor(dialect: Dialect): SqlCastFormatter;
|
|
31
|
+
/**
|
|
32
|
+
* Compile a WHERE clause (bare, without the `WHERE` keyword) from a condition object
|
|
33
|
+
* to a `makeSQL` bundle. The text + params come STRAIGHT from the original
|
|
34
|
+
* `DBConditions.compile(params, formatter)`, so every construct it supports —
|
|
35
|
+
* eq/ne/cmp (custom-op key), IN-list, empty-IN (`1 = 0`), IS NULL, IS NOT NULL
|
|
36
|
+
* (`dbNotNull`), boolean literal (`= TRUE`), LIKE/ILIKE/BETWEEN (custom-op/raw),
|
|
37
|
+
* IN/NOT IN subquery (`DBSubquery`), EXISTS/NOT EXISTS (`DBExists`), correlated
|
|
38
|
+
* parentRef, raw (`__raw__`), AND/OR grouping with parens (`__or__` / nested
|
|
39
|
+
* DBConditions), cast (`dbCast`/`dbCastIn`, dialect-gated), immediate inline
|
|
40
|
+
* (`dbImmediate`/`dbRaw`), dynamic (`dbDynamic`), tuple/composite IN (`dbTupleIn`) —
|
|
41
|
+
* is reproduced byte-for-byte.
|
|
42
|
+
*
|
|
43
|
+
* Empty clause → `{ sql: '', params: [] }` (the original returns `''` when no part is
|
|
44
|
+
* present; folded here into an empty bundle so composition drops it).
|
|
45
|
+
*/
|
|
46
|
+
export declare function compileWhere(conditions: ConditionObject, dialect: Dialect): MakeSQL;
|
|
47
|
+
/**
|
|
48
|
+
* Wrap a bare WHERE core (from {@link compileWhere}) as the ` WHERE <core>` clause a
|
|
49
|
+
* SELECT/UPDATE/DELETE appends — byte-identical to the originals which do
|
|
50
|
+
* `sql += \` WHERE ${whereClause}\`` only when `whereClause` is non-empty. An empty
|
|
51
|
+
* core yields an empty bundle (no ` WHERE`).
|
|
52
|
+
*/
|
|
53
|
+
export declare function whereClause(where: MakeSQL): MakeSQL;
|
|
54
|
+
/**
|
|
55
|
+
* Compose a leading condition with an ordered list of optional (SKIP-guarded) trailing
|
|
56
|
+
* conditions joined by ` AND `, exactly as the original relation/select path appends
|
|
57
|
+
* `config.conditions` after a mandatory key predicate. Each optional member carries
|
|
58
|
+
* its own connector (` AND <core>`), so a skipped member drops its connector too.
|
|
59
|
+
*
|
|
60
|
+
* Returns the list of `makeSQL` components (head + guarded tails); the caller composes.
|
|
61
|
+
*/
|
|
62
|
+
export declare function andTrailing(head: MakeSQL, tails: MakeSQL[]): MakeSQL[];
|
|
63
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,yFAAyF;AACzF,eAAO,MAAM,eAAe,EAAE,gBAAyE,CAAC;AACxG,oEAAoE;AACpE,eAAO,MAAM,eAAe,EAAE,gBAA+C,CAAC;AAE9E,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAE/D;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAKnF;AAMD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGnD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAOtE"}
|