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.
Files changed (163) hide show
  1. package/dist/scp/authoring-sql.d.ts +78 -0
  2. package/dist/scp/authoring-sql.d.ts.map +1 -1
  3. package/dist/scp/authoring-sql.js +110 -2
  4. package/dist/scp/authoring-sql.js.map +1 -1
  5. package/dist/scp/catalog.d.ts +5 -2
  6. package/dist/scp/catalog.d.ts.map +1 -1
  7. package/dist/scp/catalog.js +32 -1
  8. package/dist/scp/catalog.js.map +1 -1
  9. package/dist/scp/codegen.d.ts +143 -85
  10. package/dist/scp/codegen.d.ts.map +1 -1
  11. package/dist/scp/codegen.js +374 -90
  12. package/dist/scp/codegen.js.map +1 -1
  13. package/dist/scp/coltype.d.ts +41 -0
  14. package/dist/scp/coltype.d.ts.map +1 -0
  15. package/dist/scp/coltype.js +188 -0
  16. package/dist/scp/coltype.js.map +1 -0
  17. package/dist/scp/dialect.d.ts +12 -3
  18. package/dist/scp/dialect.d.ts.map +1 -1
  19. package/dist/scp/dialect.js +12 -3
  20. package/dist/scp/dialect.js.map +1 -1
  21. package/dist/scp/find-filter-guard.d.ts +68 -0
  22. package/dist/scp/find-filter-guard.d.ts.map +1 -0
  23. package/dist/scp/find-filter-guard.js +88 -0
  24. package/dist/scp/find-filter-guard.js.map +1 -0
  25. package/dist/scp/fragment/assemble.d.ts +61 -0
  26. package/dist/scp/fragment/assemble.d.ts.map +1 -0
  27. package/dist/scp/fragment/assemble.js +156 -0
  28. package/dist/scp/fragment/assemble.js.map +1 -0
  29. package/dist/scp/fragment/compile-pg.d.ts +107 -0
  30. package/dist/scp/fragment/compile-pg.d.ts.map +1 -0
  31. package/dist/scp/fragment/compile-pg.js +142 -0
  32. package/dist/scp/fragment/compile-pg.js.map +1 -0
  33. package/dist/scp/fragment/index.d.ts +16 -0
  34. package/dist/scp/fragment/index.d.ts.map +1 -0
  35. package/dist/scp/fragment/index.js +34 -0
  36. package/dist/scp/fragment/index.js.map +1 -0
  37. package/dist/scp/fragment/model.d.ts +119 -0
  38. package/dist/scp/fragment/model.d.ts.map +1 -0
  39. package/dist/scp/fragment/model.js +66 -0
  40. package/dist/scp/fragment/model.js.map +1 -0
  41. package/dist/scp/fragment/pg-array-type.d.ts +13 -0
  42. package/dist/scp/fragment/pg-array-type.d.ts.map +1 -0
  43. package/dist/scp/fragment/pg-array-type.js +34 -0
  44. package/dist/scp/fragment/pg-array-type.js.map +1 -0
  45. package/dist/scp/guard.d.ts +2 -6
  46. package/dist/scp/guard.d.ts.map +1 -1
  47. package/dist/scp/guard.js +19 -22
  48. package/dist/scp/guard.js.map +1 -1
  49. package/dist/scp/index.cjs +18695 -3921
  50. package/dist/scp/index.d.ts +41 -24
  51. package/dist/scp/index.d.ts.map +1 -1
  52. package/dist/scp/index.js +134 -49
  53. package/dist/scp/index.js.map +1 -1
  54. package/dist/scp/index.mjs +4830 -1432
  55. package/dist/scp/makesql/authoring-compile.d.ts +90 -0
  56. package/dist/scp/makesql/authoring-compile.d.ts.map +1 -0
  57. package/dist/scp/makesql/authoring-compile.js +494 -0
  58. package/dist/scp/makesql/authoring-compile.js.map +1 -0
  59. package/dist/scp/makesql/compile-crud.d.ts +133 -0
  60. package/dist/scp/makesql/compile-crud.d.ts.map +1 -0
  61. package/dist/scp/makesql/compile-crud.js +288 -0
  62. package/dist/scp/makesql/compile-crud.js.map +1 -0
  63. package/dist/scp/makesql/compile-relation.d.ts +157 -0
  64. package/dist/scp/makesql/compile-relation.d.ts.map +1 -0
  65. package/dist/scp/makesql/compile-relation.js +425 -0
  66. package/dist/scp/makesql/compile-relation.js.map +1 -0
  67. package/dist/scp/makesql/compile-select.d.ts +52 -0
  68. package/dist/scp/makesql/compile-select.d.ts.map +1 -0
  69. package/dist/scp/makesql/compile-select.js +58 -0
  70. package/dist/scp/makesql/compile-select.js.map +1 -0
  71. package/dist/scp/makesql/compile.d.ts +63 -0
  72. package/dist/scp/makesql/compile.d.ts.map +1 -0
  73. package/dist/scp/makesql/compile.js +99 -0
  74. package/dist/scp/makesql/compile.js.map +1 -0
  75. package/dist/scp/makesql/handler.d.ts +58 -0
  76. package/dist/scp/makesql/handler.d.ts.map +1 -0
  77. package/dist/scp/makesql/handler.js +113 -0
  78. package/dist/scp/makesql/handler.js.map +1 -0
  79. package/dist/scp/makesql/index.d.ts +33 -0
  80. package/dist/scp/makesql/index.d.ts.map +1 -0
  81. package/dist/scp/makesql/index.js +114 -0
  82. package/dist/scp/makesql/index.js.map +1 -0
  83. package/dist/scp/makesql/ir.d.ts +42 -0
  84. package/dist/scp/makesql/ir.d.ts.map +1 -0
  85. package/dist/scp/makesql/ir.js +66 -0
  86. package/dist/scp/makesql/ir.js.map +1 -0
  87. package/dist/scp/makesql/json-array.d.ts +84 -0
  88. package/dist/scp/makesql/json-array.d.ts.map +1 -0
  89. package/dist/scp/makesql/json-array.js +118 -0
  90. package/dist/scp/makesql/json-array.js.map +1 -0
  91. package/dist/scp/makesql/json-batch.d.ts +102 -0
  92. package/dist/scp/makesql/json-batch.d.ts.map +1 -0
  93. package/dist/scp/makesql/json-batch.js +269 -0
  94. package/dist/scp/makesql/json-batch.js.map +1 -0
  95. package/dist/scp/makesql/makesql.d.ts +99 -0
  96. package/dist/scp/makesql/makesql.d.ts.map +1 -0
  97. package/dist/scp/makesql/makesql.js +122 -0
  98. package/dist/scp/makesql/makesql.js.map +1 -0
  99. package/dist/scp/makesql/outtype.d.ts +44 -0
  100. package/dist/scp/makesql/outtype.d.ts.map +1 -0
  101. package/dist/scp/makesql/outtype.js +197 -0
  102. package/dist/scp/makesql/outtype.js.map +1 -0
  103. package/dist/scp/makesql/pool-executor.d.ts +47 -0
  104. package/dist/scp/makesql/pool-executor.d.ts.map +1 -0
  105. package/dist/scp/makesql/pool-executor.js +50 -0
  106. package/dist/scp/makesql/pool-executor.js.map +1 -0
  107. package/dist/scp/makesql/static-bundle.d.ts +187 -0
  108. package/dist/scp/makesql/static-bundle.d.ts.map +1 -0
  109. package/dist/scp/makesql/static-bundle.js +1113 -0
  110. package/dist/scp/makesql/static-bundle.js.map +1 -0
  111. package/dist/scp/makesql/tx.d.ts +216 -0
  112. package/dist/scp/makesql/tx.d.ts.map +1 -0
  113. package/dist/scp/makesql/tx.js +788 -0
  114. package/dist/scp/makesql/tx.js.map +1 -0
  115. package/dist/scp/makesql/writeouttype.d.ts +66 -0
  116. package/dist/scp/makesql/writeouttype.d.ts.map +1 -0
  117. package/dist/scp/makesql/writeouttype.js +195 -0
  118. package/dist/scp/makesql/writeouttype.js.map +1 -0
  119. package/dist/scp/relation.d.ts +86 -74
  120. package/dist/scp/relation.d.ts.map +1 -1
  121. package/dist/scp/relation.js +186 -120
  122. package/dist/scp/relation.js.map +1 -1
  123. package/dist/scp/runtime.d.ts +158 -211
  124. package/dist/scp/runtime.d.ts.map +1 -1
  125. package/dist/scp/runtime.js +250 -515
  126. package/dist/scp/runtime.js.map +1 -1
  127. package/dist/scp/typed-object.d.ts +12 -1
  128. package/dist/scp/typed-object.d.ts.map +1 -1
  129. package/dist/scp/typed-object.js +25 -4
  130. package/dist/scp/typed-object.js.map +1 -1
  131. package/docs/proposal/litedbmodel-v2-scp-architecture.md +51 -0
  132. package/docs/proposal/v0-coverage-matrix.md +157 -0
  133. package/docs/proposal/v2-completeness-plan.md +90 -0
  134. package/docs/proposal/v2-sql-parity-checklist.md +162 -0
  135. package/package.json +3 -3
  136. package/dist/scp/bridge.d.ts +0 -64
  137. package/dist/scp/bridge.d.ts.map +0 -1
  138. package/dist/scp/bridge.js +0 -329
  139. package/dist/scp/bridge.js.map +0 -1
  140. package/dist/scp/compile-dialect.d.ts +0 -39
  141. package/dist/scp/compile-dialect.d.ts.map +0 -1
  142. package/dist/scp/compile-dialect.js +0 -62
  143. package/dist/scp/compile-dialect.js.map +0 -1
  144. package/dist/scp/compile-sqlite.d.ts +0 -114
  145. package/dist/scp/compile-sqlite.d.ts.map +0 -1
  146. package/dist/scp/compile-sqlite.js +0 -149
  147. package/dist/scp/compile-sqlite.js.map +0 -1
  148. package/dist/scp/ir.d.ts +0 -92
  149. package/dist/scp/ir.d.ts.map +0 -1
  150. package/dist/scp/ir.js +0 -28
  151. package/dist/scp/ir.js.map +0 -1
  152. package/dist/scp/render.d.ts +0 -40
  153. package/dist/scp/render.d.ts.map +0 -1
  154. package/dist/scp/render.js +0 -170
  155. package/dist/scp/render.js.map +0 -1
  156. package/dist/scp/write-plan.d.ts +0 -161
  157. package/dist/scp/write-plan.d.ts.map +0 -1
  158. package/dist/scp/write-plan.js +0 -528
  159. package/dist/scp/write-plan.js.map +0 -1
  160. package/dist/scp/write-runtime.d.ts +0 -80
  161. package/dist/scp/write-runtime.d.ts.map +0 -1
  162. package/dist/scp/write-runtime.js +0 -167
  163. package/dist/scp/write-runtime.js.map +0 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * litedbmodel v2 SCP — CRUD compile → `makeSQL` bundles, by driving the ORIGINAL
3
+ * dialect SQL builders (`postgresSqlBuilder` / `mysqlSqlBuilder` / `sqliteSqlBuilder`)
4
+ * and the original single-row UPDATE/DELETE text. The produced `{ sql, params }` is
5
+ * byte-identical to what the original library sends, for every dialect and every
6
+ * shape:
7
+ *
8
+ * INSERT single (+per-col `?::sqlCast` on PG) & batch (PG UNNEST + type inference /
9
+ * MySQL·SQLite multi-VALUES) + ON CONFLICT (DO NOTHING / DO UPDATE incl. `= 'all'`
10
+ * → all columns) + RETURNING (bare / `t.col` alias / `table.col` / MySQL simulate);
11
+ * UPDATE single (`SET c = ?::sqlCast`) & batch (PG UNNEST / MySQL JOIN-VALUES /
12
+ * SQLite CASE-WHEN) + SKIP-column; DELETE; and the SELECT tail (LIMIT/OFFSET inline,
13
+ * FOR UPDATE, GROUP BY/HAVING) via `buildSelectSQL`.
14
+ *
15
+ * These delegate to the SAME builders the runtime uses, so parity is by construction.
16
+ */
17
+ import type { SqlBuilder, InsertBuildOptions, UpdateManyBuildOptions } from '../../drivers/types';
18
+ import type { ConditionObject } from '../../DBConditions';
19
+ import type { MakeSQL } from './makesql';
20
+ import type { Dialect } from './handler';
21
+ /** The original dialect builder for a dialect (the exact object the runtime uses). */
22
+ export declare function builderFor(dialect: Dialect): SqlBuilder;
23
+ /**
24
+ * Compile INSERT (single or batch) to a `makeSQL` bundle via the original
25
+ * `buildInsert`. Single-row on PG carries per-col `?::sqlCast`; batch on PG uses UNNEST
26
+ * with type inference; MySQL/SQLite use multi-VALUES. ON CONFLICT / RETURNING are the
27
+ * original's exact verbs. `onConflictUpdate: 'all'` expands to every column (the
28
+ * builder's fallback), so an empty DO-UPDATE never breaks.
29
+ */
30
+ export declare function compileInsert(dialect: Dialect, options: InsertBuildOptions): MakeSQL;
31
+ /**
32
+ * Options for a heterogeneous `createMany`, mirroring the inputs `DBModel._insert` has
33
+ * AFTER serialization: the serialized `records`, their paired `rawRecords`, the shared
34
+ * `sqlCastMap` / ON CONFLICT / RETURNING. The per-group `columns` are DERIVED here (not
35
+ * supplied) — this is the whole point of the grouping.
36
+ */
37
+ export interface InsertManyBuildOptions {
38
+ tableName: string;
39
+ /** Serialized records (as `DBModel._insert` holds them after `serializeRecord`). */
40
+ records: Record<string, unknown>[];
41
+ /** Raw records before serialization, paired 1:1 with `records` (PG UNNEST path). */
42
+ rawRecords?: Record<string, unknown>[];
43
+ sqlCastMap?: Map<string, string>;
44
+ onConflict?: string[];
45
+ onConflictIgnore?: boolean;
46
+ onConflictUpdate?: 'all' | string[];
47
+ returning?: string;
48
+ }
49
+ /**
50
+ * Compile a (possibly heterogeneous) `createMany` into a COMPOSITION of `makeSQL`
51
+ * INSERT components — one per column-set group, exactly as `DBModel._insert`
52
+ * (`src/DBModel.ts:928-1020`) groups records and emits one `buildInsert` per group.
53
+ *
54
+ * A `createMany` whose rows carry DIFFERENT column subsets is not one INSERT: the
55
+ * production write path groups rows by their sorted-column-set pattern
56
+ * (`patternKey = recordColumns.sort().join(',')`) so each batch INSERT is homogeneous
57
+ * (no DEFAULT keyword), and emits ONE statement per group. In the `makeSQL` model that
58
+ * is precisely a composition of several INSERT components — no new vocabulary. This
59
+ * function reproduces that grouping byte-for-byte:
60
+ *
61
+ * - column detection per row drops `undefined` and DEFAULT immediates, exactly as
62
+ * `_insert:940-946 / 958-964`;
63
+ * - columns are CANONICAL sorted (`recordColumns.sort()`), the pattern key is the
64
+ * joined sorted columns, group order is first-seen insertion order (`Map`), and each
65
+ * group carries its serialized + raw records paired — mirroring `_insert:955-975`;
66
+ * - each group's SQL text comes from the SAME original `buildInsert` (`compileInsert`),
67
+ * so every component is byte-identical to the statement `_insert` sends for that
68
+ * group.
69
+ *
70
+ * The composition of the returned components (via `composeMakeSQL`) is the full
71
+ * multi-statement `createMany` the production path executes.
72
+ */
73
+ export declare function compileInsertMany(dialect: Dialect, options: InsertManyBuildOptions): MakeSQL[];
74
+ /**
75
+ * Compile batch UPDATE to a `makeSQL` bundle via the original `buildUpdateMany`: PG
76
+ * UNNEST (`SET c = v.c FROM UNNEST(?::t[],…) AS v(cols) WHERE t.k = v.k`), MySQL
77
+ * JOIN-VALUES (`JOIN (VALUES ROW(…)) AS v(…) ON … SET …`), SQLite CASE-WHEN
78
+ * (`SET c = CASE WHEN k = ? THEN ? … END … WHERE k IN (…)`), with SKIP-column handling
79
+ * (PG `CASE WHEN v._skip_c` / MySQL `IF(v._skip_c,…)` / SQLite `WHEN … THEN t.col`).
80
+ */
81
+ export declare function compileUpdateMany(dialect: Dialect, options: UpdateManyBuildOptions): MakeSQL;
82
+ /**
83
+ * Compile a single-row UPDATE to a `makeSQL` bundle, reproducing the original
84
+ * `DBModel._update` text byte-for-byte: `UPDATE <t> SET <c = ?[::cast] | token>, … WHERE
85
+ * <cond>[ RETURNING …]`. `serializedValues` is the already-serialized value map
86
+ * (DBToken values compile via their own `.compile`, matching the original), and
87
+ * `sqlCastMap` drives the per-column `?::sqlCast` on PG (skipping timestamp/date, as
88
+ * the original does). Throws `UPDATE requires conditions` when the WHERE is empty
89
+ * (v1 anchor: WHERE mandatory).
90
+ */
91
+ export declare function compileUpdateSingle(opts: {
92
+ dialect: Dialect;
93
+ tableName: string;
94
+ serializedValues: Record<string, unknown>;
95
+ conditions: ConditionObject;
96
+ sqlCastMap?: Map<string, string>;
97
+ returning?: string;
98
+ }): MakeSQL;
99
+ /**
100
+ * Compile DELETE to a `makeSQL` bundle, reproducing the original `DBModel._delete`
101
+ * text: `DELETE FROM <t> WHERE <cond>[ RETURNING …]`. Throws `DELETE requires
102
+ * conditions` when the WHERE is empty (v1 anchor: WHERE mandatory — the .rs "delete
103
+ * everything" behavior is NOT reproduced).
104
+ */
105
+ export declare function compileDelete(opts: {
106
+ dialect: Dialect;
107
+ tableName: string;
108
+ conditions: ConditionObject;
109
+ returning?: string;
110
+ }): MakeSQL;
111
+ /**
112
+ * Compile a `deleteMany` — delete the rows whose primary key is in a given SET of key values — as a
113
+ * COMPOSITION of `makeSQL` DELETE components (one per PK column-set group, mirroring the createMany
114
+ * grouping contract). A single-column PK reduces to ONE DELETE with the v1 IN-list condition
115
+ * (`{ pk: [values] }` → PG `= ANY` / MySQL·SQLite JSON-subquery via `conditionsFor`); a COMPOSITE PK
116
+ * groups the key-tuples by their present key set and emits ONE DELETE per group whose WHERE is the
117
+ * v1 conjunction of per-column IN-lists (each group homogeneous). Every group's WHERE text comes
118
+ * from the SAME original `DBConditions`/`conditionsFor` builder ({@link compileDelete}) — NEVER a
119
+ * hand-roll — so the deleteMany SQL is byte-identical to what the v1 condition path emits.
120
+ *
121
+ * The returned components compose (via the batch tx plan) into the full multi-statement `deleteMany`
122
+ * the production path would execute. An empty key set yields NO components (nothing to delete).
123
+ */
124
+ export declare function compileDeleteMany(opts: {
125
+ dialect: Dialect;
126
+ tableName: string;
127
+ /** The PK column names (single or composite). */
128
+ keyColumns: string[];
129
+ /** The key-tuples to delete: each row maps every PK column → its value. */
130
+ keys: Record<string, unknown>[];
131
+ returning?: string;
132
+ }): MakeSQL[];
133
+ //# sourceMappingURL=compile-crud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-crud.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile-crud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CASvD;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAGpF;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACvC,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,EAAE,CAwE9F;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAoB5F;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CA2BV;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,eAAe,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CASV;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,EAAE,CA8BZ"}
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — CRUD compile → `makeSQL` bundles, by driving the ORIGINAL
4
+ * dialect SQL builders (`postgresSqlBuilder` / `mysqlSqlBuilder` / `sqliteSqlBuilder`)
5
+ * and the original single-row UPDATE/DELETE text. The produced `{ sql, params }` is
6
+ * byte-identical to what the original library sends, for every dialect and every
7
+ * shape:
8
+ *
9
+ * INSERT single (+per-col `?::sqlCast` on PG) & batch (PG UNNEST + type inference /
10
+ * MySQL·SQLite multi-VALUES) + ON CONFLICT (DO NOTHING / DO UPDATE incl. `= 'all'`
11
+ * → all columns) + RETURNING (bare / `t.col` alias / `table.col` / MySQL simulate);
12
+ * UPDATE single (`SET c = ?::sqlCast`) & batch (PG UNNEST / MySQL JOIN-VALUES /
13
+ * SQLite CASE-WHEN) + SKIP-column; DELETE; and the SELECT tail (LIMIT/OFFSET inline,
14
+ * FOR UPDATE, GROUP BY/HAVING) via `buildSelectSQL`.
15
+ *
16
+ * These delegate to the SAME builders the runtime uses, so parity is by construction.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.builderFor = builderFor;
20
+ exports.compileInsert = compileInsert;
21
+ exports.compileInsertMany = compileInsertMany;
22
+ exports.compileUpdateMany = compileUpdateMany;
23
+ exports.compileUpdateSingle = compileUpdateSingle;
24
+ exports.compileDelete = compileDelete;
25
+ exports.compileDeleteMany = compileDeleteMany;
26
+ const PostgresSqlBuilder_1 = require("../../drivers/PostgresSqlBuilder");
27
+ const MysqlSqlBuilder_1 = require("../../drivers/MysqlSqlBuilder");
28
+ const SqliteSqlBuilder_1 = require("../../drivers/SqliteSqlBuilder");
29
+ const DBValues_1 = require("../../DBValues");
30
+ const compile_1 = require("./compile");
31
+ const json_array_1 = require("./json-array");
32
+ const json_batch_1 = require("./json-batch");
33
+ /** The original dialect builder for a dialect (the exact object the runtime uses). */
34
+ function builderFor(dialect) {
35
+ switch (dialect) {
36
+ case 'postgres':
37
+ return PostgresSqlBuilder_1.postgresSqlBuilder;
38
+ case 'mysql':
39
+ return MysqlSqlBuilder_1.mysqlSqlBuilder;
40
+ case 'sqlite':
41
+ return SqliteSqlBuilder_1.sqliteSqlBuilder;
42
+ }
43
+ }
44
+ // ============================================================================
45
+ // INSERT (single & batch) — driven by the original `buildInsert`.
46
+ // ============================================================================
47
+ /**
48
+ * Compile INSERT (single or batch) to a `makeSQL` bundle via the original
49
+ * `buildInsert`. Single-row on PG carries per-col `?::sqlCast`; batch on PG uses UNNEST
50
+ * with type inference; MySQL/SQLite use multi-VALUES. ON CONFLICT / RETURNING are the
51
+ * original's exact verbs. `onConflictUpdate: 'all'` expands to every column (the
52
+ * builder's fallback), so an empty DO-UPDATE never breaks.
53
+ */
54
+ function compileInsert(dialect, options) {
55
+ const { sql, params } = builderFor(dialect).buildInsert(options);
56
+ return { sql, params };
57
+ }
58
+ /**
59
+ * Compile a (possibly heterogeneous) `createMany` into a COMPOSITION of `makeSQL`
60
+ * INSERT components — one per column-set group, exactly as `DBModel._insert`
61
+ * (`src/DBModel.ts:928-1020`) groups records and emits one `buildInsert` per group.
62
+ *
63
+ * A `createMany` whose rows carry DIFFERENT column subsets is not one INSERT: the
64
+ * production write path groups rows by their sorted-column-set pattern
65
+ * (`patternKey = recordColumns.sort().join(',')`) so each batch INSERT is homogeneous
66
+ * (no DEFAULT keyword), and emits ONE statement per group. In the `makeSQL` model that
67
+ * is precisely a composition of several INSERT components — no new vocabulary. This
68
+ * function reproduces that grouping byte-for-byte:
69
+ *
70
+ * - column detection per row drops `undefined` and DEFAULT immediates, exactly as
71
+ * `_insert:940-946 / 958-964`;
72
+ * - columns are CANONICAL sorted (`recordColumns.sort()`), the pattern key is the
73
+ * joined sorted columns, group order is first-seen insertion order (`Map`), and each
74
+ * group carries its serialized + raw records paired — mirroring `_insert:955-975`;
75
+ * - each group's SQL text comes from the SAME original `buildInsert` (`compileInsert`),
76
+ * so every component is byte-identical to the statement `_insert` sends for that
77
+ * group.
78
+ *
79
+ * The composition of the returned components (via `composeMakeSQL`) is the full
80
+ * multi-statement `createMany` the production path executes.
81
+ */
82
+ function compileInsertMany(dialect, options) {
83
+ const { records, rawRecords, tableName, sqlCastMap, onConflict, onConflictIgnore, onConflictUpdate, returning } = options;
84
+ // Group records by their sorted-column-set pattern — mirrors DBModel._insert:928-975
85
+ // exactly (fast single-record path + multi-record Map grouping, same DEFAULT/undefined
86
+ // filtering, same canonical sort, same first-seen group order, same raw/serialized pair).
87
+ const grouped = new Map();
88
+ if (records.length === 1) {
89
+ const record = records[0];
90
+ const recordColumns = [];
91
+ for (const key of Object.keys(record)) {
92
+ const val = record[key];
93
+ if (val !== undefined && !(val instanceof DBValues_1.DBImmediateValue && val.value === 'DEFAULT')) {
94
+ recordColumns.push(key);
95
+ }
96
+ }
97
+ recordColumns.sort();
98
+ grouped.set('_', { columns: recordColumns, records: [record], rawRecords: [rawRecords ? rawRecords[0] : record] });
99
+ }
100
+ else {
101
+ for (let i = 0; i < records.length; i++) {
102
+ const record = records[i];
103
+ const recordColumns = [];
104
+ for (const key of Object.keys(record)) {
105
+ const val = record[key];
106
+ if (val !== undefined && !(val instanceof DBValues_1.DBImmediateValue && val.value === 'DEFAULT')) {
107
+ recordColumns.push(key);
108
+ }
109
+ }
110
+ recordColumns.sort();
111
+ const patternKey = recordColumns.join(',');
112
+ if (!grouped.has(patternKey)) {
113
+ grouped.set(patternKey, { columns: recordColumns, records: [], rawRecords: [] });
114
+ }
115
+ const group = grouped.get(patternKey);
116
+ group.records.push(record);
117
+ group.rawRecords.push(rawRecords ? rawRecords[i] : record);
118
+ }
119
+ }
120
+ // One makeSQL INSERT component per group.
121
+ //
122
+ // - PostgreSQL: UNCHANGED — the original `buildInsert` (UNNEST batch, byte-identical).
123
+ // - MySQL/SQLite: the single-JSON-param form (JSON_TABLE / json_each), UNLESS the
124
+ // group carries a DBToken value (e.g. `NOW()`) which can't be JSON-encoded — then it
125
+ // falls back to the original `buildInsert` multi-VALUES for that group (correctness).
126
+ const components = [];
127
+ for (const { columns, records: groupRecords, rawRecords: groupRawRecords } of grouped.values()) {
128
+ if (dialect !== 'postgres' && !(0, json_batch_1.rowsHaveDbToken)(groupRecords, columns)) {
129
+ const jsonOpts = { tableName, columns, records: groupRecords, onConflict, onConflictIgnore, onConflictUpdate, returning };
130
+ components.push(dialect === 'mysql' ? (0, json_batch_1.mysqlInsertJson)(jsonOpts) : (0, json_batch_1.sqliteInsertJson)(jsonOpts));
131
+ continue;
132
+ }
133
+ components.push(compileInsert(dialect, {
134
+ tableName,
135
+ columns,
136
+ records: groupRecords,
137
+ rawRecords: groupRawRecords,
138
+ sqlCastMap,
139
+ onConflict,
140
+ onConflictIgnore,
141
+ onConflictUpdate,
142
+ returning,
143
+ }));
144
+ }
145
+ return components;
146
+ }
147
+ // ============================================================================
148
+ // UPDATE batch — driven by the original `buildUpdateMany`.
149
+ // ============================================================================
150
+ /**
151
+ * Compile batch UPDATE to a `makeSQL` bundle via the original `buildUpdateMany`: PG
152
+ * UNNEST (`SET c = v.c FROM UNNEST(?::t[],…) AS v(cols) WHERE t.k = v.k`), MySQL
153
+ * JOIN-VALUES (`JOIN (VALUES ROW(…)) AS v(…) ON … SET …`), SQLite CASE-WHEN
154
+ * (`SET c = CASE WHEN k = ? THEN ? … END … WHERE k IN (…)`), with SKIP-column handling
155
+ * (PG `CASE WHEN v._skip_c` / MySQL `IF(v._skip_c,…)` / SQLite `WHEN … THEN t.col`).
156
+ */
157
+ function compileUpdateMany(dialect, options) {
158
+ // PostgreSQL: UNCHANGED (UNNEST). MySQL/SQLite: single-JSON-param form (JSON_TABLE
159
+ // join / CASE-over-json_each) with SKIP preserved — unless a DBToken value is present
160
+ // (can't be JSON-encoded), in which case fall back to the original builder.
161
+ if (dialect !== 'postgres') {
162
+ const allCols = [...options.keyColumns, ...options.updateColumns];
163
+ if (!(0, json_batch_1.rowsHaveDbToken)(options.records, allCols)) {
164
+ const jsonOpts = {
165
+ tableName: options.tableName,
166
+ keyColumns: options.keyColumns,
167
+ updateColumns: options.updateColumns,
168
+ records: options.records,
169
+ skipMap: options.skipMap,
170
+ returning: options.returning,
171
+ };
172
+ return dialect === 'mysql' ? (0, json_batch_1.mysqlUpdateManyJson)(jsonOpts) : (0, json_batch_1.sqliteUpdateManyJson)(jsonOpts);
173
+ }
174
+ }
175
+ const { sql, params } = builderFor(dialect).buildUpdateMany(options);
176
+ return { sql, params };
177
+ }
178
+ // ============================================================================
179
+ // UPDATE single — reproduces the ORIGINAL `_update` SET-clause + WHERE text exactly.
180
+ // ============================================================================
181
+ /**
182
+ * Compile a single-row UPDATE to a `makeSQL` bundle, reproducing the original
183
+ * `DBModel._update` text byte-for-byte: `UPDATE <t> SET <c = ?[::cast] | token>, … WHERE
184
+ * <cond>[ RETURNING …]`. `serializedValues` is the already-serialized value map
185
+ * (DBToken values compile via their own `.compile`, matching the original), and
186
+ * `sqlCastMap` drives the per-column `?::sqlCast` on PG (skipping timestamp/date, as
187
+ * the original does). Throws `UPDATE requires conditions` when the WHERE is empty
188
+ * (v1 anchor: WHERE mandatory).
189
+ */
190
+ function compileUpdateSingle(opts) {
191
+ const params = [];
192
+ const formatter = opts.dialect === 'postgres' ? (0, compile_1.formatterFor)(opts.dialect) : undefined;
193
+ const sqlCastMap = opts.sqlCastMap ?? new Map();
194
+ const setClauses = [];
195
+ for (const [col, val] of Object.entries(opts.serializedValues)) {
196
+ if (val instanceof DBValues_1.DBToken) {
197
+ setClauses.push(`${col} = ${val.compile(params, undefined, formatter)}`);
198
+ }
199
+ else {
200
+ params.push(val);
201
+ const sqlCast = sqlCastMap.get(col);
202
+ if (sqlCast && formatter && sqlCast !== 'timestamp' && sqlCast !== 'date') {
203
+ setClauses.push(`${col} = ${formatter('?', sqlCast)}`);
204
+ }
205
+ else {
206
+ setClauses.push(`${col} = ?`);
207
+ }
208
+ }
209
+ }
210
+ const whereClause = (0, json_array_1.conditionsFor)(opts.conditions, opts.dialect).compile(params, formatter);
211
+ if (!whereClause)
212
+ throw new Error('UPDATE requires conditions');
213
+ let sql = `UPDATE ${opts.tableName} SET ${setClauses.join(', ')} WHERE ${whereClause}`;
214
+ if (opts.returning)
215
+ sql += ` RETURNING ${opts.returning}`;
216
+ return { sql, params };
217
+ }
218
+ // ============================================================================
219
+ // DELETE single — reproduces the ORIGINAL `_delete` text exactly.
220
+ // ============================================================================
221
+ /**
222
+ * Compile DELETE to a `makeSQL` bundle, reproducing the original `DBModel._delete`
223
+ * text: `DELETE FROM <t> WHERE <cond>[ RETURNING …]`. Throws `DELETE requires
224
+ * conditions` when the WHERE is empty (v1 anchor: WHERE mandatory — the .rs "delete
225
+ * everything" behavior is NOT reproduced).
226
+ */
227
+ function compileDelete(opts) {
228
+ const params = [];
229
+ const formatter = opts.dialect === 'postgres' ? (0, compile_1.formatterFor)(opts.dialect) : undefined;
230
+ const whereClause = (0, json_array_1.conditionsFor)(opts.conditions, opts.dialect).compile(params, formatter);
231
+ if (!whereClause)
232
+ throw new Error('DELETE requires conditions');
233
+ let sql = `DELETE FROM ${opts.tableName} WHERE ${whereClause}`;
234
+ if (opts.returning)
235
+ sql += ` RETURNING ${opts.returning}`;
236
+ return { sql, params };
237
+ }
238
+ // ============================================================================
239
+ // DELETE batch (deleteMany) — a single DELETE keyed by a PK-set IN-list, driven
240
+ // by the ORIGINAL v1 condition builder (compileDelete → DBConditions/conditionsFor).
241
+ // ============================================================================
242
+ /**
243
+ * Compile a `deleteMany` — delete the rows whose primary key is in a given SET of key values — as a
244
+ * COMPOSITION of `makeSQL` DELETE components (one per PK column-set group, mirroring the createMany
245
+ * grouping contract). A single-column PK reduces to ONE DELETE with the v1 IN-list condition
246
+ * (`{ pk: [values] }` → PG `= ANY` / MySQL·SQLite JSON-subquery via `conditionsFor`); a COMPOSITE PK
247
+ * groups the key-tuples by their present key set and emits ONE DELETE per group whose WHERE is the
248
+ * v1 conjunction of per-column IN-lists (each group homogeneous). Every group's WHERE text comes
249
+ * from the SAME original `DBConditions`/`conditionsFor` builder ({@link compileDelete}) — NEVER a
250
+ * hand-roll — so the deleteMany SQL is byte-identical to what the v1 condition path emits.
251
+ *
252
+ * The returned components compose (via the batch tx plan) into the full multi-statement `deleteMany`
253
+ * the production path would execute. An empty key set yields NO components (nothing to delete).
254
+ */
255
+ function compileDeleteMany(opts) {
256
+ const { dialect, tableName, keyColumns, keys, returning } = opts;
257
+ if (keyColumns.length === 0)
258
+ throw new Error('compileDeleteMany: keyColumns must be non-empty');
259
+ if (keys.length === 0)
260
+ return [];
261
+ if (keyColumns.length === 1) {
262
+ // Single PK → ONE DELETE with a v1 IN-list condition (`{ pk: [values] }`).
263
+ const col = keyColumns[0];
264
+ const values = keys.map((k) => k[col]);
265
+ const conditions = { [col]: values };
266
+ return [compileDelete({ dialect, tableName, conditions, returning })];
267
+ }
268
+ // Composite PK → group key-tuples by their present-column set (mirrors createMany grouping), one
269
+ // DELETE per group whose WHERE is the v1 conjunction of per-column IN-lists (each group homogeneous).
270
+ const grouped = new Map();
271
+ for (const key of keys) {
272
+ const present = keyColumns.filter((c) => key[c] !== undefined).sort();
273
+ const patternKey = present.join(',');
274
+ if (!grouped.has(patternKey))
275
+ grouped.set(patternKey, []);
276
+ grouped.get(patternKey).push(key);
277
+ }
278
+ const components = [];
279
+ for (const group of grouped.values()) {
280
+ const present = keyColumns.filter((c) => group[0][c] !== undefined);
281
+ const conditions = {};
282
+ for (const c of present)
283
+ conditions[c] = group.map((k) => k[c]);
284
+ components.push(compileDelete({ dialect, tableName, conditions, returning }));
285
+ }
286
+ return components;
287
+ }
288
+ //# sourceMappingURL=compile-crud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-crud.js","sourceRoot":"","sources":["../../../src/scp/makesql/compile-crud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * litedbmodel v2 SCP — RELATION batch-load compile → `makeSQL`, reproducing the
3
+ * ORIGINAL `LazyRelation` SQL text byte-for-byte across all shapes and dialects:
4
+ *
5
+ * single-key, unlimited:
6
+ * PG `SELECT … FROM t WHERE t.key = ANY(?::type[])[ AND <filters>][ ORDER BY …]`
7
+ * MySQL/SQLite `SELECT … FROM t WHERE t.key IN (?, …)[ AND <filters>][ ORDER BY …]`
8
+ * single-key, per-parent limit:
9
+ * PG `SELECT t.* FROM unnest(?::type[]) AS _keys(key) CROSS JOIN LATERAL
10
+ * (SELECT * FROM t WHERE t.key = _keys.key[ AND <filters>] ORDER BY … LIMIT n) t`
11
+ * MySQL/SQLite `WITH ranked AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY key ORDER BY …) AS _rn
12
+ * FROM t WHERE key IN (?, …)[ AND <filters>]) SELECT * FROM ranked WHERE _rn <= n`
13
+ * composite-key, unlimited:
14
+ * PG `SELECT … FROM t JOIN unnest(?::t1[], ?::t2[]) AS _u(a1, a2) ON t.k1=_u.a1 AND …`
15
+ * MySQL/SQLite `SELECT … FROM t WHERE (k1, k2) IN ((?, ?), …)`
16
+ * composite-key, per-parent limit: PG LATERAL composite / others ROW_NUMBER composite.
17
+ *
18
+ * The PG type text (`?::type[]`) comes from the ORIGINAL `inferPgArrayType` (sqlCast
19
+ * wins, else element-type inference). The .rs regressions are NOT reproduced: PG
20
+ * per-parent-limit is LATERAL (not ROW_NUMBER), and PG types are sqlCast-driven (not
21
+ * text-folded).
22
+ *
23
+ * Inner SELECTs reuse {@link compileSelect} — the same text `buildSelectSQL` yields —
24
+ * so the whole shape is byte-faithful to the original relation builder.
25
+ */
26
+ import { type ConditionObject } from '../../DBConditions';
27
+ import type { MakeSQL } from './makesql';
28
+ import type { Dialect } from './handler';
29
+ /**
30
+ * Reproduce the ORIGINAL `LazyRelation.inferPgArrayType`: sqlCast wins (`<cast>[]`);
31
+ * otherwise infer the element type from the sample values. Byte-identical to the
32
+ * original (which is the PG anchor — NOT the .rs coarse text-folding).
33
+ */
34
+ export declare function inferPgArrayType(values: unknown[], sqlCast?: string): string;
35
+ /**
36
+ * The DEFERRED PG array-cast token (#46): a placeholder emitted in the STATIC SQL text where
37
+ * the `= ANY(?::<T>[])` / `UNNEST(?::<T>[])` element type `<T>` cannot be known at symbolic
38
+ * compile time (a schema-less `whereIn`, or a relation batch compiled without concrete keys).
39
+ * The render/handler layer resolves it from the BOUND values via {@link inferPgArrayType} — a
40
+ * mechanical dialect-render step, the same category as the `?`→`$N` placeholder render. This
41
+ * reproduces v1's live-PG-correct cast (`::int[]` for int keys, etc.), which v1 got because
42
+ * `inferPgArrayType` saw the real values at runtime.
43
+ *
44
+ * A byte sequence no legitimate SQL identifier/type text contains, so the resolve is a safe
45
+ * literal substring replace (never a regex over user text).
46
+ */
47
+ export declare const PG_ARRAY_CAST_TOKEN = "@@PG_ARRAY_CAST@@";
48
+ /**
49
+ * Resolve the FIRST unresolved {@link PG_ARRAY_CAST_TOKEN} in a PG SQL fragment to the element
50
+ * type inferred from the bound `values` (v1 `inferPgArrayType`). Called at render time, once per
51
+ * array param, left-to-right — so each deferred array cast binds the type of its own value set.
52
+ * SQL with no token is returned unchanged (every non-deferred cast is already concrete).
53
+ */
54
+ export declare function resolvePgArrayCast(sql: string, values: unknown[]): string;
55
+ export interface RelationCompileBase {
56
+ dialect: Dialect;
57
+ tableName: string;
58
+ /** SELECT column list (default `*`). */
59
+ select?: string;
60
+ /** Optional relation `where`-filter conditions (`config.conditions`), merged in. */
61
+ conditions?: ConditionObject;
62
+ /** ORDER BY clause (raw text), or undefined. */
63
+ order?: string;
64
+ /** Per-column sqlCast map (drives PG `?::type[]`). */
65
+ sqlCastMap?: Map<string, string>;
66
+ /**
67
+ * Emit the {@link PG_ARRAY_CAST_TOKEN} for the PG `?::<T>[]` element type instead of inferring
68
+ * it from `values` NOW (#46). Set when the SQL text is compiled SYMBOLICALLY (placeholder keys),
69
+ * so the element type is resolved at render from the REAL bound keys — never baked to `text[]`.
70
+ * A `sqlCast` (concrete column type) still wins over the token.
71
+ */
72
+ deferPgArrayCast?: boolean;
73
+ }
74
+ /**
75
+ * The STATIC composite-key batch forms (#47 item 1) — length-INDEPENDENT so the compiled `op.sql`
76
+ * is fixed (one param per column on PG; ONE JSON param on MySQL/SQLite), the SAME static-op
77
+ * property the single-key relation forms have. PG stays byte-identical to v1's `unnest`-JOIN
78
+ * (`batchLoadWithUnnestJoin`), with the element-type cast DEFERRED (#46) to render from the real
79
+ * keys. MySQL/SQLite use the single-JSON tuple form (the owner-approved deviation the single-key
80
+ * IN-list and the batch UPDATE composite already use — RESULT parity, NOT byte-identity): a
81
+ * `JSON_TABLE`/`json_each` subquery over one JSON array-of-tuples param. The v1 literal
82
+ * `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden `compileCompositeKeyUnlimited`.
83
+ *
84
+ * The JSON tuple param is `[[k1a,k2a],[k1b,k2b],…]` (positional element arrays), read back by
85
+ * ordinal path (`$[0]`, `$[1]`, …) so no per-column JSON key names are needed.
86
+ */
87
+ export declare function compileCompositeKeyStaticUnlimited(opts: RelationCompileBase & {
88
+ targetKeys: string[];
89
+ }): MakeSQL;
90
+ /**
91
+ * `= ANY(?::type[])` (PG) / `IN (?, …)` (MySQL/SQLite) single-key unlimited batch load.
92
+ * Reproduces `batchLoadWithAnyArray` (PG) and `batchLoadWithIn` (others).
93
+ *
94
+ * The key array binds as ONE param on PG (`values` is a single array param); on
95
+ * MySQL/SQLite the original passes the array to `DBConditions` which expands it to
96
+ * `IN (?, ?, …)` with one param per element — reproduced here verbatim.
97
+ */
98
+ export declare function compileSingleKeyUnlimited(opts: RelationCompileBase & {
99
+ targetKey: string;
100
+ values: unknown[];
101
+ }): MakeSQL;
102
+ /**
103
+ * Per-parent-limit single-key batch load: PG `CROSS JOIN LATERAL` (the v1 anchor —
104
+ * NOT the .rs ROW_NUMBER regression); MySQL/SQLite `ROW_NUMBER() OVER (PARTITION BY …)`.
105
+ * Reproduces `batchLoadWithLateral` / `batchLoadWithRowNumber`.
106
+ */
107
+ export declare function compileSingleKeyLimited(opts: RelationCompileBase & {
108
+ targetKey: string;
109
+ values: unknown[];
110
+ limit: number;
111
+ }): MakeSQL;
112
+ /**
113
+ * Composite-key unlimited batch load: PG `JOIN unnest(?::t1[], ?::t2[]) AS _u(a,b) ON …`
114
+ * (reproduces `batchLoadWithUnnestJoin`); MySQL/SQLite `(k1, k2) IN ((?, ?), …)`
115
+ * (reproduces `batchLoadWithCompositeIn` via `DBTupleIn`).
116
+ */
117
+ export declare function compileCompositeKeyUnlimited(opts: RelationCompileBase & {
118
+ targetKeys: string[];
119
+ tuples: unknown[][];
120
+ }): MakeSQL;
121
+ /**
122
+ * Composite-key per-parent-limit: PG LATERAL composite (reproduces
123
+ * `batchLoadWithLateralComposite`); MySQL/SQLite ROW_NUMBER composite (reproduces
124
+ * `batchLoadWithRowNumberComposite`).
125
+ */
126
+ export declare function compileCompositeKeyLimited(opts: RelationCompileBase & {
127
+ targetKeys: string[];
128
+ tuples: unknown[][];
129
+ limit: number;
130
+ }): MakeSQL;
131
+ /**
132
+ * The STATIC composite-key per-parent-LIMIT batch form (#47 last completeness gap) — the
133
+ * length-INDEPENDENT sibling of {@link compileCompositeKeyLimited}, so the compiled `op.sql` is
134
+ * FIXED (one array param per key column on PG; ONE JSON array-of-tuples param on MySQL/SQLite) and
135
+ * can be a STATIC bundle op — exactly the property {@link compileSingleKeyLimited} and
136
+ * {@link compileCompositeKeyStaticUnlimited} already have.
137
+ *
138
+ * The per-parent window is IDENTICAL to the single-key-limited path:
139
+ * - **PG**: `CROSS JOIN LATERAL` over `unnest(?::t1[], ?::t2[])` — BYTE-identical to v1's
140
+ * `batchLoadWithLateralComposite` (the composite LATERAL is already structurally
141
+ * length-independent; only the element-type cast was value-derived, and that is DEFERRED (#46)
142
+ * to render from the real keys via {@link PG_ARRAY_CAST_TOKEN}). No deviation on PG.
143
+ * - **MySQL/SQLite**: the SAME `ROW_NUMBER() OVER (PARTITION BY <keys> ORDER BY <order>)` CTE +
144
+ * `_rn <= limit` filter v1's `batchLoadWithRowNumberComposite` emits — but the CTE membership
145
+ * WHERE is the STATIC JSON-tuple predicate ({@link compositeJsonMembership}) instead of v1's
146
+ * value-dependent `(k1,k2) IN ((?,?),…)`. This is the owner-sanctioned static deviation the
147
+ * composite UNLIMITED form ({@link compileCompositeKeyStaticUnlimited}) and the single-key
148
+ * IN-list already use: the JSON subquery selects the SAME child rows the tuple-IN would, the
149
+ * window partitions/orders identically, so it is RESULT-parity to v1 (proven live). The v1
150
+ * literal `(k1,k2) IN ((?,?),…)` byte-form stays proven by the golden
151
+ * {@link compileCompositeKeyLimited}.
152
+ */
153
+ export declare function compileCompositeKeyStaticLimited(opts: RelationCompileBase & {
154
+ targetKeys: string[];
155
+ limit: number;
156
+ }): MakeSQL;
157
+ //# sourceMappingURL=compile-relation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-relation.d.ts","sourceRoot":"","sources":["../../../src/scp/makesql/compile-relation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5E;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAIzE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAaD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GACnD,OAAO,CAmCT;AA4BD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,GACnE,OAAO,CAyBT;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClF,OAAO,CAoCT;AAWD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAA;CAAE,GACxE,OAAO,CAuCT;AAMD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvF,OAAO,CA+CT;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,mBAAmB,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE,OAAO,CA6CT"}