@harperfast/harper 5.2.0-alpha.6 → 5.2.0-beta.1

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 (173) hide show
  1. package/dataLayer/harperBridge/ResourceBridge.ts +7 -0
  2. package/dist/dataLayer/harperBridge/ResourceBridge.js +8 -0
  3. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  4. package/dist/resources/Resource.js +5 -2
  5. package/dist/resources/Resource.js.map +1 -1
  6. package/dist/resources/Table.d.ts +3 -1
  7. package/dist/resources/Table.js +13 -3
  8. package/dist/resources/Table.js.map +1 -1
  9. package/dist/resources/databases.js +21 -0
  10. package/dist/resources/databases.js.map +1 -1
  11. package/dist/sqlEngine/binder/bind.d.ts +72 -0
  12. package/dist/sqlEngine/binder/bind.js +289 -0
  13. package/dist/sqlEngine/binder/bind.js.map +1 -0
  14. package/dist/sqlEngine/config.d.ts +35 -0
  15. package/dist/sqlEngine/config.js +62 -0
  16. package/dist/sqlEngine/config.js.map +1 -0
  17. package/dist/sqlEngine/diff/differential.d.ts +23 -0
  18. package/dist/sqlEngine/diff/differential.js +90 -0
  19. package/dist/sqlEngine/diff/differential.js.map +1 -0
  20. package/dist/sqlEngine/errors.d.ts +22 -0
  21. package/dist/sqlEngine/errors.js +36 -0
  22. package/dist/sqlEngine/errors.js.map +1 -0
  23. package/dist/sqlEngine/executor/runMutation.d.ts +35 -0
  24. package/dist/sqlEngine/executor/runMutation.js +352 -0
  25. package/dist/sqlEngine/executor/runMutation.js.map +1 -0
  26. package/dist/sqlEngine/executor/runSelect.d.ts +7 -0
  27. package/dist/sqlEngine/executor/runSelect.js +14 -0
  28. package/dist/sqlEngine/executor/runSelect.js.map +1 -0
  29. package/dist/sqlEngine/expressions/compile.d.ts +24 -0
  30. package/dist/sqlEngine/expressions/compile.js +326 -0
  31. package/dist/sqlEngine/expressions/compile.js.map +1 -0
  32. package/dist/sqlEngine/functions/aggregates.d.ts +12 -0
  33. package/dist/sqlEngine/functions/aggregates.js +299 -0
  34. package/dist/sqlEngine/functions/aggregates.js.map +1 -0
  35. package/dist/sqlEngine/functions/registry.d.ts +36 -0
  36. package/dist/sqlEngine/functions/registry.js +33 -0
  37. package/dist/sqlEngine/functions/registry.js.map +1 -0
  38. package/dist/sqlEngine/functions/standard.d.ts +9 -0
  39. package/dist/sqlEngine/functions/standard.js +86 -0
  40. package/dist/sqlEngine/functions/standard.js.map +1 -0
  41. package/dist/sqlEngine/index.d.ts +29 -0
  42. package/dist/sqlEngine/index.js +62 -0
  43. package/dist/sqlEngine/index.js.map +1 -0
  44. package/dist/sqlEngine/logical/build.d.ts +20 -0
  45. package/dist/sqlEngine/logical/build.js +326 -0
  46. package/dist/sqlEngine/logical/build.js.map +1 -0
  47. package/dist/sqlEngine/logical/op.d.ts +105 -0
  48. package/dist/sqlEngine/logical/op.js +10 -0
  49. package/dist/sqlEngine/logical/op.js.map +1 -0
  50. package/dist/sqlEngine/optimizer/joinAnalysis.d.ts +37 -0
  51. package/dist/sqlEngine/optimizer/joinAnalysis.js +144 -0
  52. package/dist/sqlEngine/optimizer/joinAnalysis.js.map +1 -0
  53. package/dist/sqlEngine/optimizer/optimize.d.ts +13 -0
  54. package/dist/sqlEngine/optimizer/optimize.js +53 -0
  55. package/dist/sqlEngine/optimizer/optimize.js.map +1 -0
  56. package/dist/sqlEngine/optimizer/ruleEngine.d.ts +7 -0
  57. package/dist/sqlEngine/optimizer/ruleEngine.js +26 -0
  58. package/dist/sqlEngine/optimizer/ruleEngine.js.map +1 -0
  59. package/dist/sqlEngine/optimizer/rules/limitPushdown.d.ts +19 -0
  60. package/dist/sqlEngine/optimizer/rules/limitPushdown.js +55 -0
  61. package/dist/sqlEngine/optimizer/rules/limitPushdown.js.map +1 -0
  62. package/dist/sqlEngine/optimizer/rules/planJoins.d.ts +19 -0
  63. package/dist/sqlEngine/optimizer/rules/planJoins.js +62 -0
  64. package/dist/sqlEngine/optimizer/rules/planJoins.js.map +1 -0
  65. package/dist/sqlEngine/optimizer/rules/predicateNormalize.d.ts +18 -0
  66. package/dist/sqlEngine/optimizer/rules/predicateNormalize.js +80 -0
  67. package/dist/sqlEngine/optimizer/rules/predicateNormalize.js.map +1 -0
  68. package/dist/sqlEngine/optimizer/rules/predicatePushdown.d.ts +11 -0
  69. package/dist/sqlEngine/optimizer/rules/predicatePushdown.js +48 -0
  70. package/dist/sqlEngine/optimizer/rules/predicatePushdown.js.map +1 -0
  71. package/dist/sqlEngine/optimizer/rules/projectionPushdown.d.ts +23 -0
  72. package/dist/sqlEngine/optimizer/rules/projectionPushdown.js +160 -0
  73. package/dist/sqlEngine/optimizer/rules/projectionPushdown.js.map +1 -0
  74. package/dist/sqlEngine/optimizer/rules/sortFromIndex.d.ts +14 -0
  75. package/dist/sqlEngine/optimizer/rules/sortFromIndex.js +49 -0
  76. package/dist/sqlEngine/optimizer/rules/sortFromIndex.js.map +1 -0
  77. package/dist/sqlEngine/optimizer/rules/validateScannable.d.ts +15 -0
  78. package/dist/sqlEngine/optimizer/rules/validateScannable.js +60 -0
  79. package/dist/sqlEngine/optimizer/rules/validateScannable.js.map +1 -0
  80. package/dist/sqlEngine/optimizer/whereToConditions.d.ts +85 -0
  81. package/dist/sqlEngine/optimizer/whereToConditions.js +484 -0
  82. package/dist/sqlEngine/optimizer/whereToConditions.js.map +1 -0
  83. package/dist/sqlEngine/parser/ast.d.ts +139 -0
  84. package/dist/sqlEngine/parser/ast.js +10 -0
  85. package/dist/sqlEngine/parser/ast.js.map +1 -0
  86. package/dist/sqlEngine/parser/normalizer.d.ts +28 -0
  87. package/dist/sqlEngine/parser/normalizer.js +413 -0
  88. package/dist/sqlEngine/parser/normalizer.js.map +1 -0
  89. package/dist/sqlEngine/parser/parse.d.ts +14 -0
  90. package/dist/sqlEngine/parser/parse.js +20 -0
  91. package/dist/sqlEngine/parser/parse.js.map +1 -0
  92. package/dist/sqlEngine/physical/PhysicalDistinct.d.ts +9 -0
  93. package/dist/sqlEngine/physical/PhysicalDistinct.js +29 -0
  94. package/dist/sqlEngine/physical/PhysicalDistinct.js.map +1 -0
  95. package/dist/sqlEngine/physical/PhysicalFilter.d.ts +10 -0
  96. package/dist/sqlEngine/physical/PhysicalFilter.js +25 -0
  97. package/dist/sqlEngine/physical/PhysicalFilter.js.map +1 -0
  98. package/dist/sqlEngine/physical/PhysicalHashAggregate.d.ts +27 -0
  99. package/dist/sqlEngine/physical/PhysicalHashAggregate.js +100 -0
  100. package/dist/sqlEngine/physical/PhysicalHashAggregate.js.map +1 -0
  101. package/dist/sqlEngine/physical/PhysicalHashJoin.d.ts +29 -0
  102. package/dist/sqlEngine/physical/PhysicalHashJoin.js +93 -0
  103. package/dist/sqlEngine/physical/PhysicalHashJoin.js.map +1 -0
  104. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.d.ts +36 -0
  105. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js +78 -0
  106. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js.map +1 -0
  107. package/dist/sqlEngine/physical/PhysicalIndexScan.d.ts +22 -0
  108. package/dist/sqlEngine/physical/PhysicalIndexScan.js +77 -0
  109. package/dist/sqlEngine/physical/PhysicalIndexScan.js.map +1 -0
  110. package/dist/sqlEngine/physical/PhysicalLimit.d.ts +5 -0
  111. package/dist/sqlEngine/physical/PhysicalLimit.js +28 -0
  112. package/dist/sqlEngine/physical/PhysicalLimit.js.map +1 -0
  113. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.d.ts +20 -0
  114. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js +51 -0
  115. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js.map +1 -0
  116. package/dist/sqlEngine/physical/PhysicalProject.d.ts +18 -0
  117. package/dist/sqlEngine/physical/PhysicalProject.js +117 -0
  118. package/dist/sqlEngine/physical/PhysicalProject.js.map +1 -0
  119. package/dist/sqlEngine/physical/PhysicalQualify.d.ts +13 -0
  120. package/dist/sqlEngine/physical/PhysicalQualify.js +29 -0
  121. package/dist/sqlEngine/physical/PhysicalQualify.js.map +1 -0
  122. package/dist/sqlEngine/physical/PhysicalSort.d.ts +12 -0
  123. package/dist/sqlEngine/physical/PhysicalSort.js +59 -0
  124. package/dist/sqlEngine/physical/PhysicalSort.js.map +1 -0
  125. package/dist/sqlEngine/physical/op.d.ts +11 -0
  126. package/dist/sqlEngine/physical/op.js +9 -0
  127. package/dist/sqlEngine/physical/op.js.map +1 -0
  128. package/dist/sqlEngine/physical/plan.d.ts +23 -0
  129. package/dist/sqlEngine/physical/plan.js +162 -0
  130. package/dist/sqlEngine/physical/plan.js.map +1 -0
  131. package/dist/sqlEngine/router.d.ts +26 -0
  132. package/dist/sqlEngine/router.js +48 -0
  133. package/dist/sqlEngine/router.js.map +1 -0
  134. package/dist/sqlEngine/types.d.ts +37 -0
  135. package/dist/sqlEngine/types.js +13 -0
  136. package/dist/sqlEngine/types.js.map +1 -0
  137. package/dist/sqlTranslator/index.js +7 -1
  138. package/dist/sqlTranslator/index.js.map +1 -1
  139. package/dist/validation/deleteValidator.js +10 -2
  140. package/dist/validation/deleteValidator.js.map +1 -1
  141. package/npm-shrinkwrap.json +2 -2
  142. package/package.json +1 -1
  143. package/resources/DESIGN.md +17 -16
  144. package/resources/Resource.ts +5 -2
  145. package/resources/Table.ts +23 -3
  146. package/resources/databases.ts +24 -0
  147. package/sqlTranslator/index.ts +16 -6
  148. package/studio/web/assets/{Chat-CTjtL8Z4.js → Chat-BZks8dVF.js} +2 -2
  149. package/studio/web/assets/{Chat-CTjtL8Z4.js.map → Chat-BZks8dVF.js.map} +1 -1
  150. package/studio/web/assets/{FloatingChat-CafHR4Ur.js → FloatingChat-Dic8paVO.js} +4 -4
  151. package/studio/web/assets/{FloatingChat-CafHR4Ur.js.map → FloatingChat-Dic8paVO.js.map} +1 -1
  152. package/studio/web/assets/{applications-Buh_q0Vj.js → applications-uOXkeUIN.js} +2 -2
  153. package/studio/web/assets/{applications-Buh_q0Vj.js.map → applications-uOXkeUIN.js.map} +1 -1
  154. package/studio/web/assets/{index-0hXeECkS.js → index-i-2wrKhv.js} +6 -6
  155. package/studio/web/assets/{index-0hXeECkS.js.map → index-i-2wrKhv.js.map} +1 -1
  156. package/studio/web/assets/{index.lazy-B00B7VBT.js → index.lazy-Csk8eCoB.js} +4 -4
  157. package/studio/web/assets/{index.lazy-B00B7VBT.js.map → index.lazy-Csk8eCoB.js.map} +1 -1
  158. package/studio/web/assets/{profile-Cg2wwYPn.js → profile-Sb3mGDl6.js} +2 -2
  159. package/studio/web/assets/{profile-Cg2wwYPn.js.map → profile-Sb3mGDl6.js.map} +1 -1
  160. package/studio/web/assets/{setComponentFile-DCaDIvyB.js → setComponentFile-BgZcaPJ2.js} +2 -2
  161. package/studio/web/assets/{setComponentFile-DCaDIvyB.js.map → setComponentFile-BgZcaPJ2.js.map} +1 -1
  162. package/studio/web/assets/{setup-CAVcAQjK.js → setup-DKtlLgmT.js} +2 -2
  163. package/studio/web/assets/{setup-CAVcAQjK.js.map → setup-DKtlLgmT.js.map} +1 -1
  164. package/studio/web/assets/{status-BRXorNdD.js → status-B45iLeug.js} +2 -2
  165. package/studio/web/assets/{status-BRXorNdD.js.map → status-B45iLeug.js.map} +1 -1
  166. package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js → swagger-ui-react-Csu4026e.js} +2 -2
  167. package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js.map → swagger-ui-react-Csu4026e.js.map} +1 -1
  168. package/studio/web/assets/{tsMode-A8gbL74v.js → tsMode-DVgxUr_l.js} +2 -2
  169. package/studio/web/assets/{tsMode-A8gbL74v.js.map → tsMode-DVgxUr_l.js.map} +1 -1
  170. package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js → useEntityRestURL-yfDQMV1f.js} +2 -2
  171. package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js.map → useEntityRestURL-yfDQMV1f.js.map} +1 -1
  172. package/studio/web/index.html +1 -1
  173. package/validation/deleteValidator.ts +11 -2
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ /**
3
+ * Binder.
4
+ *
5
+ * Resolves the table references in a SelectNode to concrete Table classes via
6
+ * core/resources/databases.ts.
7
+ *
8
+ * Single-table SELECT (phase 1-2): fills `boundTable` with primaryKey +
9
+ * attribute names so downstream rules can validate columns. Column references
10
+ * keep their bare names and rows flow through the pipeline keyed by bare
11
+ * attribute name.
12
+ *
13
+ * Multi-table SELECT (phase 3, joins): additionally binds every joined table
14
+ * into an ordered `scope`, and resolves every column reference to the canonical
15
+ * alias of its owning table (mutating `column.table` in place). Ambiguous or
16
+ * unknown qualified references throw EngineUnsupportedError. Join rows flow
17
+ * through the pipeline keyed by `<alias>.<attribute>` (see expressions/compile
18
+ * `qualified` mode and physical/PhysicalQualify).
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports._internal = void 0;
22
+ exports._setDatabasesLoader = _setDatabasesLoader;
23
+ exports.bind = bind;
24
+ exports.bindSelect = bindSelect;
25
+ const errors_ts_1 = require("../errors.js");
26
+ let _databasesLoader = null;
27
+ /**
28
+ * Override hook for tests. Restored to default by passing null.
29
+ */
30
+ function _setDatabasesLoader(loader) {
31
+ _databasesLoader = loader;
32
+ }
33
+ function loadDatabases() {
34
+ if (_databasesLoader)
35
+ return _databasesLoader();
36
+ const mod = require('../../resources/databases.js');
37
+ return mod.getDatabases();
38
+ }
39
+ function bind(stmt, _ctx) {
40
+ switch (stmt.kind) {
41
+ case 'select':
42
+ return bindSelect(stmt);
43
+ case 'insert':
44
+ return bindInsert(stmt);
45
+ case 'update':
46
+ return bindUpdate(stmt);
47
+ case 'delete':
48
+ return bindDelete(stmt);
49
+ default:
50
+ throw new errors_ts_1.EngineUnsupportedError(`bind: unsupported statement kind`);
51
+ }
52
+ }
53
+ /**
54
+ * Mutations are single-table. We resolve the target table to a BoundTable (the
55
+ * Resource class plus primaryKey/attributes) and leave column refs bare — the
56
+ * write executor evaluates assignment/value expressions against bare-keyed rows,
57
+ * exactly like the single-table SELECT path.
58
+ */
59
+ function bindInsert(stmt) {
60
+ const boundTable = bindTableRef(stmt.table, loadDatabases());
61
+ return { ...stmt, table: { ...stmt.table, database: boundTable.database }, boundTable };
62
+ }
63
+ function bindUpdate(stmt) {
64
+ const boundTable = bindTableRef(stmt.table, loadDatabases());
65
+ // SET on the primary key can't be honored by Table.patch (identity is the call
66
+ // argument, not the payload) — reporting the row as updated would be a false
67
+ // success. Reject so `auto` falls back to legacy, which declines the re-key.
68
+ if (boundTable.primaryKey && stmt.assignments.some((a) => a.column === boundTable.primaryKey)) {
69
+ throw new errors_ts_1.EngineUnsupportedError(`UPDATE cannot change the primary key column "${boundTable.primaryKey}"`);
70
+ }
71
+ return { ...stmt, table: { ...stmt.table, database: boundTable.database }, boundTable };
72
+ }
73
+ function bindDelete(stmt) {
74
+ const boundTable = bindTableRef(stmt.table, loadDatabases());
75
+ return { ...stmt, table: { ...stmt.table, database: boundTable.database }, boundTable };
76
+ }
77
+ function bindSelect(stmt) {
78
+ const databases = loadDatabases();
79
+ const fromTable = bindTableRef(stmt.from, databases);
80
+ const scope = [fromTable];
81
+ for (const join of stmt.joins) {
82
+ scope.push(bindTableRef(join.table, databases));
83
+ }
84
+ const qualified = stmt.joins.length > 0;
85
+ if (qualified) {
86
+ // Distinct effective aliases are required: the join row model keys columns
87
+ // by `<alias>.<attr>`, so two tables sharing an alias would collide and
88
+ // overwrite each other on merge.
89
+ const seen = new Set();
90
+ for (const t of scope) {
91
+ if (seen.has(t.effectiveAlias)) {
92
+ throw new errors_ts_1.EngineUnsupportedError(`duplicate table alias "${t.effectiveAlias}" in join; give each joined table a distinct alias`);
93
+ }
94
+ seen.add(t.effectiveAlias);
95
+ }
96
+ }
97
+ if (qualified) {
98
+ // Resolve every column reference to a canonical alias, in place.
99
+ resolveColumnsInSelect(stmt, scope);
100
+ }
101
+ return {
102
+ ...stmt,
103
+ from: { ...stmt.from, database: fromTable.database },
104
+ boundTable: fromTable,
105
+ scope,
106
+ qualified,
107
+ };
108
+ }
109
+ function bindTableRef(ref, databases) {
110
+ const databaseName = ref.database || pickDefaultDatabase(databases, ref.table);
111
+ const dbEntry = databases[databaseName];
112
+ if (!dbEntry) {
113
+ throw new errors_ts_1.EngineUnsupportedError(`database "${databaseName}" not found`);
114
+ }
115
+ const resource = dbEntry[ref.table];
116
+ if (!resource) {
117
+ throw new errors_ts_1.EngineUnsupportedError(`table "${databaseName}.${ref.table}" not found`);
118
+ }
119
+ const r = resource;
120
+ const primaryKey = r.primaryKey;
121
+ const indices = r.indices ?? {};
122
+ // indexNulls lives on both the attribute descriptor and the index dbi
123
+ // (databases.ts sets each) — honor either.
124
+ const attributes = (r.attributes ?? []).map((a) => ({
125
+ name: a.name,
126
+ indexed: !!a.indexed || !!indices[a.name] || a.name === primaryKey,
127
+ isPrimaryKey: a.name === primaryKey,
128
+ indexNulls: a.name !== primaryKey &&
129
+ (!!a.indexNulls || !!indices[a.name]?.indexNulls),
130
+ }));
131
+ return {
132
+ database: databaseName,
133
+ table: ref.table,
134
+ alias: ref.alias,
135
+ effectiveAlias: ref.alias ?? ref.table,
136
+ primaryKey,
137
+ attributes,
138
+ resource,
139
+ };
140
+ }
141
+ function pickDefaultDatabase(databases, tableName) {
142
+ const matches = [];
143
+ for (const dbName of Object.keys(databases)) {
144
+ if (databases[dbName]?.[tableName])
145
+ matches.push(dbName);
146
+ }
147
+ if (matches.length === 0) {
148
+ throw new errors_ts_1.EngineUnsupportedError(`table "${tableName}" not found in any database`);
149
+ }
150
+ if (matches.length > 1) {
151
+ throw new errors_ts_1.EngineUnsupportedError(`table "${tableName}" exists in multiple databases (${matches.join(', ')}); qualify the schema`);
152
+ }
153
+ return matches[0];
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Column resolution for join queries
157
+ // ---------------------------------------------------------------------------
158
+ function resolveColumnsInSelect(stmt, scope) {
159
+ for (const p of stmt.projections)
160
+ resolveColumns(p.expr, scope);
161
+ // Each join's ON sees only the tables in scope at that point: FROM plus the
162
+ // joins up to and including this one (scope[0..i+1]). Resolving against the
163
+ // full scope would let an ON reference a not-yet-joined table or be falsely
164
+ // flagged ambiguous against one.
165
+ for (let i = 0; i < stmt.joins.length; i++) {
166
+ const j = stmt.joins[i];
167
+ if (j.on)
168
+ resolveColumns(j.on, scope.slice(0, i + 2));
169
+ }
170
+ if (stmt.where)
171
+ resolveColumns(stmt.where, scope);
172
+ if (stmt.groupBy)
173
+ for (const g of stmt.groupBy)
174
+ resolveColumns(g, scope);
175
+ if (stmt.having)
176
+ resolveColumns(stmt.having, scope);
177
+ if (stmt.orderBy)
178
+ for (const o of stmt.orderBy)
179
+ resolveColumns(o.expr, scope);
180
+ }
181
+ /** Resolves a qualifier string (alias or table name) to the canonical alias. */
182
+ function resolveQualifier(qualifier, scope) {
183
+ // Exact effective-alias match always wins (it is unique — duplicates are
184
+ // rejected at bind time).
185
+ const byAlias = scope.find((t) => t.effectiveAlias === qualifier);
186
+ if (byAlias)
187
+ return byAlias;
188
+ // Fall back to base-table-name qualification (e.g. `dev.user.col` where the
189
+ // table is unaliased). In a self-join the same base name appears more than
190
+ // once; matching the first silently mis-binds, so reject as ambiguous.
191
+ const byTable = scope.filter((t) => t.table === qualifier);
192
+ if (byTable.length > 1) {
193
+ throw new errors_ts_1.EngineUnsupportedError(`table qualifier "${qualifier}" is ambiguous across ${byTable
194
+ .map((t) => t.effectiveAlias)
195
+ .join(', ')}; qualify columns by alias`);
196
+ }
197
+ return byTable[0];
198
+ }
199
+ function resolveColumns(expr, scope) {
200
+ switch (expr.kind) {
201
+ case 'column': {
202
+ if (expr.table) {
203
+ const t = resolveQualifier(expr.table, scope);
204
+ if (!t) {
205
+ throw new errors_ts_1.EngineUnsupportedError(`unknown table qualifier "${expr.table}" for column "${expr.name}"`);
206
+ }
207
+ expr.table = t.effectiveAlias;
208
+ return;
209
+ }
210
+ // Unqualified: bind to the unique table that declares this attribute.
211
+ const owners = scope.filter((t) => t.attributes.some((a) => a.name === expr.name));
212
+ if (owners.length === 1) {
213
+ expr.table = owners[0].effectiveAlias;
214
+ }
215
+ else if (owners.length > 1) {
216
+ throw new errors_ts_1.EngineUnsupportedError(`column "${expr.name}" is ambiguous across ${owners.map((o) => o.effectiveAlias).join(', ')}; qualify it`);
217
+ }
218
+ else if (scope.length === 1) {
219
+ // Single-table query: an undeclared attribute (Harper tables are
220
+ // schemaless) binds to the only table.
221
+ expr.table = scope[0].effectiveAlias;
222
+ }
223
+ else {
224
+ // Multi-table query: we cannot know which table an undeclared
225
+ // attribute belongs to. Defaulting to the FROM table would silently
226
+ // yield nulls when it actually lives on a joined table, so reject
227
+ // and let 'auto' mode fall back to legacy.
228
+ throw new errors_ts_1.EngineUnsupportedError(`column "${expr.name}" is not declared on any joined table; qualify it with a table alias`);
229
+ }
230
+ return;
231
+ }
232
+ case 'star':
233
+ // `t.*` qualifier is validated at star-expansion time; bare `*` spans all.
234
+ if (expr.table) {
235
+ const t = resolveQualifier(expr.table, scope);
236
+ if (!t)
237
+ throw new errors_ts_1.EngineUnsupportedError(`unknown table qualifier "${expr.table}" in "${expr.table}.*"`);
238
+ expr.table = t.effectiveAlias;
239
+ }
240
+ return;
241
+ case 'binop':
242
+ resolveColumns(expr.left, scope);
243
+ resolveColumns(expr.right, scope);
244
+ return;
245
+ case 'logical':
246
+ expr.args.forEach((a) => resolveColumns(a, scope));
247
+ return;
248
+ case 'in':
249
+ resolveColumns(expr.expr, scope);
250
+ if (Array.isArray(expr.list))
251
+ expr.list.forEach((e) => resolveColumns(e, scope));
252
+ return;
253
+ case 'between':
254
+ resolveColumns(expr.expr, scope);
255
+ resolveColumns(expr.low, scope);
256
+ resolveColumns(expr.high, scope);
257
+ return;
258
+ case 'like':
259
+ resolveColumns(expr.expr, scope);
260
+ resolveColumns(expr.pattern, scope);
261
+ return;
262
+ case 'isNull':
263
+ resolveColumns(expr.expr, scope);
264
+ return;
265
+ case 'funcCall':
266
+ expr.args.forEach((a) => resolveColumns(a, scope));
267
+ return;
268
+ case 'aggCall':
269
+ if (expr.arg.kind !== 'star')
270
+ resolveColumns(expr.arg, scope);
271
+ return;
272
+ case 'case':
273
+ for (const c of expr.cases) {
274
+ resolveColumns(c.when, scope);
275
+ resolveColumns(c.then, scope);
276
+ }
277
+ if (expr.else)
278
+ resolveColumns(expr.else, scope);
279
+ return;
280
+ case 'cast':
281
+ resolveColumns(expr.expr, scope);
282
+ return;
283
+ default:
284
+ return;
285
+ }
286
+ }
287
+ // Surfaced for unit tests.
288
+ exports._internal = { resolveColumns, resolveQualifier };
289
+ //# sourceMappingURL=bind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind.js","sourceRoot":"","sources":["../../../sqlEngine/binder/bind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Reads the SQL engine feature flag and runtime caps.
3
+ *
4
+ * sql.engine selects which engine handles a SQL request:
5
+ * 'legacy' — existing AlaSQL-based path.
6
+ * 'new' — new Resource-API-based path; throws EngineUnsupportedError for
7
+ * queries it can't plan.
8
+ * 'auto' — try the new path first; fall back to legacy on
9
+ * EngineUnsupportedError (default).
10
+ *
11
+ * The flag is read from the HARPER_SQL_ENGINE environment variable, then
12
+ * harperConfig.sql?.engine, then defaults to 'auto'. We deliberately keep
13
+ * this resolution lazy and lightweight so the router can be invoked without a
14
+ * fully booted Harper config (e.g., in unit tests).
15
+ *
16
+ * Phase 5 cutover: the default is now 'auto' — the new engine handles every SQL
17
+ * request it can plan and silently falls back to legacy on anything it can't, so
18
+ * no query changes behavior unless the new engine produces an identical result.
19
+ * The gate for this flip was full parity of the new engine (run in 'auto') against
20
+ * the existing SQL suite: the cutover-readiness differential (46/46 identical) plus
21
+ * the existing behavioral suites under 'auto' — northwind (575 SQL ops) and
22
+ * delete.test.mjs (76) — at 0 failures. Both trial-flip blockers (IN literal
23
+ * coercion, LIKE-predicate DELETE 403) and the northwind gaps (attribute-name
24
+ * validation, quoted-boolean coercion, != / NULL three-valued logic) are fixed.
25
+ * The remaining cutover work is burn-in (watch `sql-engine v2 fallback:` logs) then
26
+ * flipping to 'new' and deleting the legacy path. See PLAN.md phase-5 notes.
27
+ */
28
+ export type SqlEngineMode = 'legacy' | 'new' | 'auto';
29
+ export interface SqlEngineConfig {
30
+ engine: SqlEngineMode;
31
+ allowFullScan: boolean;
32
+ maxSortRows: number;
33
+ maxHashRows: number;
34
+ }
35
+ export declare function getSqlEngineConfig(): SqlEngineConfig;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ /**
3
+ * Reads the SQL engine feature flag and runtime caps.
4
+ *
5
+ * sql.engine selects which engine handles a SQL request:
6
+ * 'legacy' — existing AlaSQL-based path.
7
+ * 'new' — new Resource-API-based path; throws EngineUnsupportedError for
8
+ * queries it can't plan.
9
+ * 'auto' — try the new path first; fall back to legacy on
10
+ * EngineUnsupportedError (default).
11
+ *
12
+ * The flag is read from the HARPER_SQL_ENGINE environment variable, then
13
+ * harperConfig.sql?.engine, then defaults to 'auto'. We deliberately keep
14
+ * this resolution lazy and lightweight so the router can be invoked without a
15
+ * fully booted Harper config (e.g., in unit tests).
16
+ *
17
+ * Phase 5 cutover: the default is now 'auto' — the new engine handles every SQL
18
+ * request it can plan and silently falls back to legacy on anything it can't, so
19
+ * no query changes behavior unless the new engine produces an identical result.
20
+ * The gate for this flip was full parity of the new engine (run in 'auto') against
21
+ * the existing SQL suite: the cutover-readiness differential (46/46 identical) plus
22
+ * the existing behavioral suites under 'auto' — northwind (575 SQL ops) and
23
+ * delete.test.mjs (76) — at 0 failures. Both trial-flip blockers (IN literal
24
+ * coercion, LIKE-predicate DELETE 403) and the northwind gaps (attribute-name
25
+ * validation, quoted-boolean coercion, != / NULL three-valued logic) are fixed.
26
+ * The remaining cutover work is burn-in (watch `sql-engine v2 fallback:` logs) then
27
+ * flipping to 'new' and deleting the legacy path. See PLAN.md phase-5 notes.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.getSqlEngineConfig = getSqlEngineConfig;
31
+ const DEFAULTS = {
32
+ engine: 'auto',
33
+ allowFullScan: false,
34
+ maxSortRows: 1_000_000,
35
+ maxHashRows: 1_000_000,
36
+ };
37
+ function envEngine() {
38
+ const v = process.env.HARPER_SQL_ENGINE;
39
+ if (v === 'legacy' || v === 'new' || v === 'auto')
40
+ return v;
41
+ return undefined;
42
+ }
43
+ function harperConfigEngine() {
44
+ try {
45
+ const harperConfig = globalThis.harperConfig;
46
+ return harperConfig?.sql ?? {};
47
+ }
48
+ catch {
49
+ return {};
50
+ }
51
+ }
52
+ function getSqlEngineConfig() {
53
+ const fromConfig = harperConfigEngine();
54
+ const fromEnv = envEngine();
55
+ return {
56
+ engine: fromEnv ?? fromConfig.engine ?? DEFAULTS.engine,
57
+ allowFullScan: fromConfig.allowFullScan ?? DEFAULTS.allowFullScan,
58
+ maxSortRows: fromConfig.maxSortRows ?? DEFAULTS.maxSortRows,
59
+ maxHashRows: fromConfig.maxHashRows ?? DEFAULTS.maxHashRows,
60
+ };
61
+ }
62
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../sqlEngine/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;AAiCH,gDASC;AA/BD,MAAM,QAAQ,GAAoB;IACjC,MAAM,EAAE,MAAM;IACd,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,SAAS;IACtB,WAAW,EAAE,SAAS;CACtB,CAAC;AAEF,SAAS,SAAS;IACjB,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACxC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IAC5D,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB;IAC1B,IAAI,CAAC;QACJ,MAAM,YAAY,GAAI,UAAoE,CAAC,YAAY,CAAC;QACxG,OAAO,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED,SAAgB,kBAAkB;IACjC,MAAM,UAAU,GAAG,kBAAkB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,OAAO;QACN,MAAM,EAAE,OAAO,IAAI,UAAU,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM;QACvD,aAAa,EAAE,UAAU,CAAC,aAAa,IAAI,QAAQ,CAAC,aAAa;QACjE,WAAW,EAAE,UAAU,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW;QAC3D,WAAW,EAAE,UAAU,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW;KAC3D,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Differential test harness.
3
+ *
4
+ * Runs a SQL query through both the legacy and new engines and deep-equals the
5
+ * results modulo:
6
+ * - row order when no ORDER BY is present (sorted by JSON serialization),
7
+ * - undefined → null translation (legacy returns both; we normalize),
8
+ * - object key order.
9
+ *
10
+ * Used by the parity test suite under core/unitTests/sqlEngine/.
11
+ */
12
+ export interface DifferentialOptions {
13
+ hdb_user?: unknown;
14
+ preserveOrder?: boolean;
15
+ bypass_auth?: boolean;
16
+ }
17
+ export interface DifferentialResult {
18
+ legacy: unknown;
19
+ v2: unknown;
20
+ equal: boolean;
21
+ v2Unsupported?: string;
22
+ }
23
+ export declare function runDifferential(sql: string, opts?: DifferentialOptions): Promise<DifferentialResult>;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /**
3
+ * Differential test harness.
4
+ *
5
+ * Runs a SQL query through both the legacy and new engines and deep-equals the
6
+ * results modulo:
7
+ * - row order when no ORDER BY is present (sorted by JSON serialization),
8
+ * - undefined → null translation (legacy returns both; we normalize),
9
+ * - object key order.
10
+ *
11
+ * Used by the parity test suite under core/unitTests/sqlEngine/.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.runDifferential = runDifferential;
15
+ const errors_ts_1 = require("../errors.js");
16
+ function loadLegacy() {
17
+ return require('../../sqlTranslator/index.js');
18
+ }
19
+ function runLegacy(sql, opts) {
20
+ const translator = loadLegacy();
21
+ return new Promise((resolve, reject) => {
22
+ translator.evaluateSQL({ sql, hdb_user: opts.hdb_user, bypass_auth: opts.bypass_auth ?? true }, (err, data) => {
23
+ if (err)
24
+ reject(err);
25
+ else
26
+ resolve(data);
27
+ });
28
+ });
29
+ }
30
+ async function runV2(sql, opts) {
31
+ const previous = process.env.HARPER_SQL_ENGINE;
32
+ process.env.HARPER_SQL_ENGINE = 'new';
33
+ try {
34
+ return await runLegacy(sql, opts);
35
+ }
36
+ finally {
37
+ if (previous === undefined)
38
+ delete process.env.HARPER_SQL_ENGINE;
39
+ else
40
+ process.env.HARPER_SQL_ENGINE = previous;
41
+ }
42
+ }
43
+ function normalize(value) {
44
+ if (value === undefined)
45
+ return null;
46
+ if (value === null)
47
+ return null;
48
+ if (Array.isArray(value))
49
+ return value.map(normalize);
50
+ if (typeof value === 'object') {
51
+ const out = {};
52
+ for (const k of Object.keys(value).sort()) {
53
+ out[k] = normalize(value[k]);
54
+ }
55
+ return out;
56
+ }
57
+ return value;
58
+ }
59
+ function sortRows(rows) {
60
+ if (!Array.isArray(rows))
61
+ return rows;
62
+ return [...rows].sort((a, b) => {
63
+ const sa = JSON.stringify(a);
64
+ const sb = JSON.stringify(b);
65
+ return sa < sb ? -1 : sa > sb ? 1 : 0;
66
+ });
67
+ }
68
+ function deepEqual(a, b) {
69
+ return JSON.stringify(a) === JSON.stringify(b);
70
+ }
71
+ async function runDifferential(sql, opts = {}) {
72
+ const legacy = await runLegacy(sql, opts);
73
+ let v2;
74
+ let v2Unsupported;
75
+ try {
76
+ v2 = await runV2(sql, opts);
77
+ }
78
+ catch (err) {
79
+ if (err instanceof errors_ts_1.EngineUnsupportedError) {
80
+ return { legacy, v2: undefined, equal: false, v2Unsupported: err.reason };
81
+ }
82
+ throw err;
83
+ }
84
+ const normalizedLegacy = normalize(legacy);
85
+ const normalizedV2 = normalize(v2);
86
+ const a = opts.preserveOrder ? normalizedLegacy : sortRows(normalizedLegacy);
87
+ const b = opts.preserveOrder ? normalizedV2 : sortRows(normalizedV2);
88
+ return { legacy, v2, equal: deepEqual(a, b), v2Unsupported };
89
+ }
90
+ //# sourceMappingURL=differential.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differential.js","sourceRoot":"","sources":["../../../sqlEngine/diff/differential.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Engine-specific error types for the new SQL engine.
3
+ *
4
+ * EngineUnsupportedError is thrown when a query cannot be handled by the new
5
+ * engine — either at plan time (a shape that can't map to the Resource API) or
6
+ * at execution time (an in-memory operator exceeding its row cap, before any
7
+ * result is emitted). The router catches this in 'auto' mode and falls back to
8
+ * the legacy AlaSQL engine.
9
+ *
10
+ * EngineRuntimeError is thrown for genuine runtime failures that are NOT
11
+ * recoverable by falling back (e.g., a mutation target with no primary key).
12
+ * The router does not fall back on it — it surfaces to the caller.
13
+ */
14
+ import { ClientError } from '../utility/errors/hdbError.js';
15
+ export declare class EngineUnsupportedError extends ClientError {
16
+ reason: string;
17
+ astSnippet?: unknown;
18
+ constructor(reason: string, astSnippet?: unknown);
19
+ }
20
+ export declare class EngineRuntimeError extends ClientError {
21
+ constructor(message: string);
22
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * Engine-specific error types for the new SQL engine.
4
+ *
5
+ * EngineUnsupportedError is thrown when a query cannot be handled by the new
6
+ * engine — either at plan time (a shape that can't map to the Resource API) or
7
+ * at execution time (an in-memory operator exceeding its row cap, before any
8
+ * result is emitted). The router catches this in 'auto' mode and falls back to
9
+ * the legacy AlaSQL engine.
10
+ *
11
+ * EngineRuntimeError is thrown for genuine runtime failures that are NOT
12
+ * recoverable by falling back (e.g., a mutation target with no primary key).
13
+ * The router does not fall back on it — it surfaces to the caller.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.EngineRuntimeError = exports.EngineUnsupportedError = void 0;
17
+ const hdbError_js_1 = require("../utility/errors/hdbError.js");
18
+ class EngineUnsupportedError extends hdbError_js_1.ClientError {
19
+ reason;
20
+ astSnippet;
21
+ constructor(reason, astSnippet) {
22
+ super(`SQL engine v2: unsupported query — ${reason}`);
23
+ this.name = 'EngineUnsupportedError';
24
+ this.reason = reason;
25
+ this.astSnippet = astSnippet;
26
+ }
27
+ }
28
+ exports.EngineUnsupportedError = EngineUnsupportedError;
29
+ class EngineRuntimeError extends hdbError_js_1.ClientError {
30
+ constructor(message) {
31
+ super(`SQL engine v2: ${message}`);
32
+ this.name = 'EngineRuntimeError';
33
+ }
34
+ }
35
+ exports.EngineRuntimeError = EngineRuntimeError;
36
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../sqlEngine/errors.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAEH,+DAA4D;AAE5D,MAAa,sBAAuB,SAAQ,yBAAW;IACtD,MAAM,CAAS;IACf,UAAU,CAAW;IAErB,YAAY,MAAc,EAAE,UAAoB;QAC/C,KAAK,CAAC,sCAAsC,MAAM,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;CACD;AAVD,wDAUC;AAED,MAAa,kBAAmB,SAAQ,yBAAW;IAClD,YAAY,OAAe;QAC1B,KAAK,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IAClC,CAAC;CACD;AALD,gDAKC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Phase 4 mutation executors: INSERT / UPDATE / DELETE.
3
+ *
4
+ * Writes go through the Resource API exactly as production code does: the
5
+ * `databases`-resolved entry is the Table class, whose static
6
+ * `create`/`put`/`patch`/`delete`/`get` methods each call `transaction(context,
7
+ * …)` internally and *join* an already-open transaction on the context
8
+ * (resources/Resource.ts). So the whole mutation runs inside a single
9
+ * `transaction(context, …)`; every per-row write joins it and the batch commits
10
+ * (or aborts) atomically.
11
+ *
12
+ * UPDATE/DELETE find their target rows by running the ordinary SELECT pipeline
13
+ * (a synthetic `SELECT … FROM target WHERE …`) inside the same transaction, so
14
+ * the read sees a consistent snapshot with the writes.
15
+ *
16
+ * Response shapes match the legacy SQL path (dataLayer/insert.ts,
17
+ * dataLayer/delete.ts) so callers see no difference:
18
+ * INSERT → { message: "inserted N of M records", inserted_hashes, skipped_hashes }
19
+ * UPDATE → { message: "updated N of M records", update_hashes, skipped_hashes }
20
+ * DELETE → { message: "N of M records successfully deleted", deleted_hashes, skipped_hashes }
21
+ */
22
+ import type { BoundInsert, BoundUpdate, BoundDelete } from '../binder/bind.ts';
23
+ import type { SqlEngineContext } from '../types.ts';
24
+ /** A minimal context carrying the user; `transaction()` attaches `.transaction`. */
25
+ interface WriteContext {
26
+ user?: unknown;
27
+ transaction?: unknown;
28
+ }
29
+ type TransactionRunner = <T>(context: WriteContext, callback: () => Promise<T>) => Promise<T>;
30
+ /** Test hook: override the transaction runner. Pass null to restore the default. */
31
+ export declare function _setTransactionRunner(runner: TransactionRunner | null): void;
32
+ export declare function runInsert(bound: BoundInsert, ctx: SqlEngineContext): Promise<unknown>;
33
+ export declare function runUpdate(bound: BoundUpdate, ctx: SqlEngineContext): Promise<unknown>;
34
+ export declare function runDelete(bound: BoundDelete, ctx: SqlEngineContext): Promise<unknown>;
35
+ export {};