@harperfast/harper 5.2.0-alpha.6 → 5.2.0-beta.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 (276) hide show
  1. package/bin/cliOperations.ts +76 -12
  2. package/bin/run.ts +10 -0
  3. package/bin/status.ts +1 -1
  4. package/components/Application.ts +146 -83
  5. package/components/Scope.ts +4 -0
  6. package/components/componentLoader.ts +7 -0
  7. package/components/operations.js +21 -1
  8. package/config/configUtils.ts +139 -5
  9. package/config-app.schema.json +70 -0
  10. package/dataLayer/harperBridge/ResourceBridge.ts +7 -0
  11. package/dist/bin/cliOperations.js +76 -12
  12. package/dist/bin/cliOperations.js.map +1 -1
  13. package/dist/bin/run.js +9 -0
  14. package/dist/bin/run.js.map +1 -1
  15. package/dist/bin/status.js +1 -1
  16. package/dist/bin/status.js.map +1 -1
  17. package/dist/components/Application.d.ts +12 -5
  18. package/dist/components/Application.js +121 -60
  19. package/dist/components/Application.js.map +1 -1
  20. package/dist/components/Scope.d.ts +1 -0
  21. package/dist/components/Scope.js +4 -0
  22. package/dist/components/Scope.js.map +1 -1
  23. package/dist/components/componentLoader.js +7 -0
  24. package/dist/components/componentLoader.js.map +1 -1
  25. package/dist/components/operations.js +20 -1
  26. package/dist/components/operations.js.map +1 -1
  27. package/dist/config/configUtils.d.ts +31 -0
  28. package/dist/config/configUtils.js +127 -5
  29. package/dist/config/configUtils.js.map +1 -1
  30. package/dist/dataLayer/harperBridge/ResourceBridge.js +8 -0
  31. package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
  32. package/dist/resources/DatabaseTransaction.d.ts +12 -0
  33. package/dist/resources/DatabaseTransaction.js +97 -0
  34. package/dist/resources/DatabaseTransaction.js.map +1 -1
  35. package/dist/resources/RequestTarget.js +13 -3
  36. package/dist/resources/RequestTarget.js.map +1 -1
  37. package/dist/resources/Resource.js +21 -2
  38. package/dist/resources/Resource.js.map +1 -1
  39. package/dist/resources/Table.d.ts +3 -1
  40. package/dist/resources/Table.js +48 -5
  41. package/dist/resources/Table.js.map +1 -1
  42. package/dist/resources/analytics/metadata.d.ts +3 -0
  43. package/dist/resources/analytics/metadata.js +3 -0
  44. package/dist/resources/analytics/metadata.js.map +1 -1
  45. package/dist/resources/analytics/write.js +22 -0
  46. package/dist/resources/analytics/write.js.map +1 -1
  47. package/dist/resources/databases.js +21 -0
  48. package/dist/resources/databases.js.map +1 -1
  49. package/dist/resources/defineResource.js +20 -7
  50. package/dist/resources/defineResource.js.map +1 -1
  51. package/dist/resources/jsResource.d.ts +24 -0
  52. package/dist/resources/jsResource.js +58 -2
  53. package/dist/resources/jsResource.js.map +1 -1
  54. package/dist/resources/openApi.js +45 -20
  55. package/dist/resources/openApi.js.map +1 -1
  56. package/dist/resources/scheduler/CronExpression.d.ts +71 -0
  57. package/dist/resources/scheduler/CronExpression.js +367 -0
  58. package/dist/resources/scheduler/CronExpression.js.map +1 -0
  59. package/dist/resources/scheduler/engine.d.ts +91 -0
  60. package/dist/resources/scheduler/engine.js +767 -0
  61. package/dist/resources/scheduler/engine.js.map +1 -0
  62. package/dist/resources/scheduler/scheduler.d.ts +33 -0
  63. package/dist/resources/scheduler/scheduler.js +200 -0
  64. package/dist/resources/scheduler/scheduler.js.map +1 -0
  65. package/dist/security/auth.js +1 -0
  66. package/dist/security/auth.js.map +1 -1
  67. package/dist/security/jsLoader.js +8 -0
  68. package/dist/security/jsLoader.js.map +1 -1
  69. package/dist/security/keys.d.ts +32 -0
  70. package/dist/security/keys.js +147 -0
  71. package/dist/security/keys.js.map +1 -1
  72. package/dist/server/REST.js +67 -1
  73. package/dist/server/REST.js.map +1 -1
  74. package/dist/server/Server.d.ts +6 -0
  75. package/dist/server/Server.js.map +1 -1
  76. package/dist/server/http.d.ts +2 -0
  77. package/dist/server/http.js +139 -14
  78. package/dist/server/http.js.map +1 -1
  79. package/dist/server/operationsServer.js +3 -3
  80. package/dist/server/operationsServer.js.map +1 -1
  81. package/dist/server/serverHelpers/progressEmitter.js +5 -1
  82. package/dist/server/serverHelpers/progressEmitter.js.map +1 -1
  83. package/dist/server/threads/threadServer.js +9 -5
  84. package/dist/server/threads/threadServer.js.map +1 -1
  85. package/dist/sqlEngine/binder/bind.d.ts +72 -0
  86. package/dist/sqlEngine/binder/bind.js +289 -0
  87. package/dist/sqlEngine/binder/bind.js.map +1 -0
  88. package/dist/sqlEngine/config.d.ts +35 -0
  89. package/dist/sqlEngine/config.js +62 -0
  90. package/dist/sqlEngine/config.js.map +1 -0
  91. package/dist/sqlEngine/diff/differential.d.ts +23 -0
  92. package/dist/sqlEngine/diff/differential.js +90 -0
  93. package/dist/sqlEngine/diff/differential.js.map +1 -0
  94. package/dist/sqlEngine/errors.d.ts +22 -0
  95. package/dist/sqlEngine/errors.js +36 -0
  96. package/dist/sqlEngine/errors.js.map +1 -0
  97. package/dist/sqlEngine/executor/runMutation.d.ts +35 -0
  98. package/dist/sqlEngine/executor/runMutation.js +352 -0
  99. package/dist/sqlEngine/executor/runMutation.js.map +1 -0
  100. package/dist/sqlEngine/executor/runSelect.d.ts +7 -0
  101. package/dist/sqlEngine/executor/runSelect.js +14 -0
  102. package/dist/sqlEngine/executor/runSelect.js.map +1 -0
  103. package/dist/sqlEngine/expressions/compile.d.ts +24 -0
  104. package/dist/sqlEngine/expressions/compile.js +326 -0
  105. package/dist/sqlEngine/expressions/compile.js.map +1 -0
  106. package/dist/sqlEngine/functions/aggregates.d.ts +12 -0
  107. package/dist/sqlEngine/functions/aggregates.js +299 -0
  108. package/dist/sqlEngine/functions/aggregates.js.map +1 -0
  109. package/dist/sqlEngine/functions/registry.d.ts +36 -0
  110. package/dist/sqlEngine/functions/registry.js +33 -0
  111. package/dist/sqlEngine/functions/registry.js.map +1 -0
  112. package/dist/sqlEngine/functions/standard.d.ts +9 -0
  113. package/dist/sqlEngine/functions/standard.js +86 -0
  114. package/dist/sqlEngine/functions/standard.js.map +1 -0
  115. package/dist/sqlEngine/index.d.ts +29 -0
  116. package/dist/sqlEngine/index.js +62 -0
  117. package/dist/sqlEngine/index.js.map +1 -0
  118. package/dist/sqlEngine/logical/build.d.ts +20 -0
  119. package/dist/sqlEngine/logical/build.js +326 -0
  120. package/dist/sqlEngine/logical/build.js.map +1 -0
  121. package/dist/sqlEngine/logical/op.d.ts +105 -0
  122. package/dist/sqlEngine/logical/op.js +10 -0
  123. package/dist/sqlEngine/logical/op.js.map +1 -0
  124. package/dist/sqlEngine/optimizer/joinAnalysis.d.ts +37 -0
  125. package/dist/sqlEngine/optimizer/joinAnalysis.js +144 -0
  126. package/dist/sqlEngine/optimizer/joinAnalysis.js.map +1 -0
  127. package/dist/sqlEngine/optimizer/optimize.d.ts +13 -0
  128. package/dist/sqlEngine/optimizer/optimize.js +53 -0
  129. package/dist/sqlEngine/optimizer/optimize.js.map +1 -0
  130. package/dist/sqlEngine/optimizer/ruleEngine.d.ts +7 -0
  131. package/dist/sqlEngine/optimizer/ruleEngine.js +26 -0
  132. package/dist/sqlEngine/optimizer/ruleEngine.js.map +1 -0
  133. package/dist/sqlEngine/optimizer/rules/limitPushdown.d.ts +19 -0
  134. package/dist/sqlEngine/optimizer/rules/limitPushdown.js +55 -0
  135. package/dist/sqlEngine/optimizer/rules/limitPushdown.js.map +1 -0
  136. package/dist/sqlEngine/optimizer/rules/planJoins.d.ts +19 -0
  137. package/dist/sqlEngine/optimizer/rules/planJoins.js +62 -0
  138. package/dist/sqlEngine/optimizer/rules/planJoins.js.map +1 -0
  139. package/dist/sqlEngine/optimizer/rules/predicateNormalize.d.ts +18 -0
  140. package/dist/sqlEngine/optimizer/rules/predicateNormalize.js +80 -0
  141. package/dist/sqlEngine/optimizer/rules/predicateNormalize.js.map +1 -0
  142. package/dist/sqlEngine/optimizer/rules/predicatePushdown.d.ts +11 -0
  143. package/dist/sqlEngine/optimizer/rules/predicatePushdown.js +48 -0
  144. package/dist/sqlEngine/optimizer/rules/predicatePushdown.js.map +1 -0
  145. package/dist/sqlEngine/optimizer/rules/projectionPushdown.d.ts +23 -0
  146. package/dist/sqlEngine/optimizer/rules/projectionPushdown.js +160 -0
  147. package/dist/sqlEngine/optimizer/rules/projectionPushdown.js.map +1 -0
  148. package/dist/sqlEngine/optimizer/rules/sortFromIndex.d.ts +14 -0
  149. package/dist/sqlEngine/optimizer/rules/sortFromIndex.js +49 -0
  150. package/dist/sqlEngine/optimizer/rules/sortFromIndex.js.map +1 -0
  151. package/dist/sqlEngine/optimizer/rules/validateScannable.d.ts +15 -0
  152. package/dist/sqlEngine/optimizer/rules/validateScannable.js +60 -0
  153. package/dist/sqlEngine/optimizer/rules/validateScannable.js.map +1 -0
  154. package/dist/sqlEngine/optimizer/whereToConditions.d.ts +85 -0
  155. package/dist/sqlEngine/optimizer/whereToConditions.js +484 -0
  156. package/dist/sqlEngine/optimizer/whereToConditions.js.map +1 -0
  157. package/dist/sqlEngine/parser/ast.d.ts +139 -0
  158. package/dist/sqlEngine/parser/ast.js +10 -0
  159. package/dist/sqlEngine/parser/ast.js.map +1 -0
  160. package/dist/sqlEngine/parser/normalizer.d.ts +28 -0
  161. package/dist/sqlEngine/parser/normalizer.js +413 -0
  162. package/dist/sqlEngine/parser/normalizer.js.map +1 -0
  163. package/dist/sqlEngine/parser/parse.d.ts +14 -0
  164. package/dist/sqlEngine/parser/parse.js +20 -0
  165. package/dist/sqlEngine/parser/parse.js.map +1 -0
  166. package/dist/sqlEngine/physical/PhysicalDistinct.d.ts +9 -0
  167. package/dist/sqlEngine/physical/PhysicalDistinct.js +29 -0
  168. package/dist/sqlEngine/physical/PhysicalDistinct.js.map +1 -0
  169. package/dist/sqlEngine/physical/PhysicalFilter.d.ts +10 -0
  170. package/dist/sqlEngine/physical/PhysicalFilter.js +25 -0
  171. package/dist/sqlEngine/physical/PhysicalFilter.js.map +1 -0
  172. package/dist/sqlEngine/physical/PhysicalHashAggregate.d.ts +27 -0
  173. package/dist/sqlEngine/physical/PhysicalHashAggregate.js +100 -0
  174. package/dist/sqlEngine/physical/PhysicalHashAggregate.js.map +1 -0
  175. package/dist/sqlEngine/physical/PhysicalHashJoin.d.ts +29 -0
  176. package/dist/sqlEngine/physical/PhysicalHashJoin.js +93 -0
  177. package/dist/sqlEngine/physical/PhysicalHashJoin.js.map +1 -0
  178. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.d.ts +36 -0
  179. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js +78 -0
  180. package/dist/sqlEngine/physical/PhysicalIndexNestedLoopJoin.js.map +1 -0
  181. package/dist/sqlEngine/physical/PhysicalIndexScan.d.ts +22 -0
  182. package/dist/sqlEngine/physical/PhysicalIndexScan.js +77 -0
  183. package/dist/sqlEngine/physical/PhysicalIndexScan.js.map +1 -0
  184. package/dist/sqlEngine/physical/PhysicalLimit.d.ts +5 -0
  185. package/dist/sqlEngine/physical/PhysicalLimit.js +28 -0
  186. package/dist/sqlEngine/physical/PhysicalLimit.js.map +1 -0
  187. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.d.ts +20 -0
  188. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js +51 -0
  189. package/dist/sqlEngine/physical/PhysicalNestedLoopJoin.js.map +1 -0
  190. package/dist/sqlEngine/physical/PhysicalProject.d.ts +18 -0
  191. package/dist/sqlEngine/physical/PhysicalProject.js +117 -0
  192. package/dist/sqlEngine/physical/PhysicalProject.js.map +1 -0
  193. package/dist/sqlEngine/physical/PhysicalQualify.d.ts +13 -0
  194. package/dist/sqlEngine/physical/PhysicalQualify.js +29 -0
  195. package/dist/sqlEngine/physical/PhysicalQualify.js.map +1 -0
  196. package/dist/sqlEngine/physical/PhysicalSort.d.ts +12 -0
  197. package/dist/sqlEngine/physical/PhysicalSort.js +59 -0
  198. package/dist/sqlEngine/physical/PhysicalSort.js.map +1 -0
  199. package/dist/sqlEngine/physical/op.d.ts +11 -0
  200. package/dist/sqlEngine/physical/op.js +9 -0
  201. package/dist/sqlEngine/physical/op.js.map +1 -0
  202. package/dist/sqlEngine/physical/plan.d.ts +23 -0
  203. package/dist/sqlEngine/physical/plan.js +162 -0
  204. package/dist/sqlEngine/physical/plan.js.map +1 -0
  205. package/dist/sqlEngine/router.d.ts +26 -0
  206. package/dist/sqlEngine/router.js +48 -0
  207. package/dist/sqlEngine/router.js.map +1 -0
  208. package/dist/sqlEngine/types.d.ts +37 -0
  209. package/dist/sqlEngine/types.js +13 -0
  210. package/dist/sqlEngine/types.js.map +1 -0
  211. package/dist/sqlTranslator/index.js +7 -1
  212. package/dist/sqlTranslator/index.js.map +1 -1
  213. package/dist/utility/common_utils.js +25 -0
  214. package/dist/utility/common_utils.js.map +1 -1
  215. package/dist/utility/install/installer.d.ts +9 -1
  216. package/dist/utility/install/installer.js +21 -0
  217. package/dist/utility/install/installer.js.map +1 -1
  218. package/dist/validation/configValidator.js +3 -0
  219. package/dist/validation/configValidator.js.map +1 -1
  220. package/dist/validation/deleteValidator.js +10 -2
  221. package/dist/validation/deleteValidator.js.map +1 -1
  222. package/npm-shrinkwrap.json +272 -230
  223. package/package.json +3 -3
  224. package/resources/DESIGN.md +17 -16
  225. package/resources/DatabaseTransaction.ts +95 -0
  226. package/resources/RequestTarget.ts +12 -3
  227. package/resources/Resource.ts +23 -2
  228. package/resources/Table.ts +57 -6
  229. package/resources/analytics/metadata.ts +3 -0
  230. package/resources/analytics/write.ts +23 -0
  231. package/resources/databases.ts +24 -0
  232. package/resources/defineResource.ts +17 -4
  233. package/resources/jsResource.ts +61 -2
  234. package/resources/openApi.ts +44 -19
  235. package/resources/scheduler/CronExpression.ts +394 -0
  236. package/resources/scheduler/engine.ts +812 -0
  237. package/resources/scheduler/scheduler.ts +236 -0
  238. package/security/auth.ts +1 -0
  239. package/security/jsLoader.ts +8 -0
  240. package/security/keys.ts +152 -0
  241. package/server/REST.ts +70 -1
  242. package/server/Server.ts +6 -0
  243. package/server/http.ts +122 -15
  244. package/server/operationsServer.ts +5 -3
  245. package/server/serverHelpers/progressEmitter.ts +5 -1
  246. package/server/threads/threadServer.js +9 -5
  247. package/sqlTranslator/index.ts +16 -6
  248. package/studio/web/assets/{Chat-CTjtL8Z4.js → Chat-DHP4XpID.js} +2 -2
  249. package/studio/web/assets/{Chat-CTjtL8Z4.js.map → Chat-DHP4XpID.js.map} +1 -1
  250. package/studio/web/assets/{FloatingChat-CafHR4Ur.js → FloatingChat-CJ7PssCv.js} +4 -4
  251. package/studio/web/assets/{FloatingChat-CafHR4Ur.js.map → FloatingChat-CJ7PssCv.js.map} +1 -1
  252. package/studio/web/assets/{applications-Buh_q0Vj.js → applications-DxXiGpsR.js} +2 -2
  253. package/studio/web/assets/{applications-Buh_q0Vj.js.map → applications-DxXiGpsR.js.map} +1 -1
  254. package/studio/web/assets/{index-0hXeECkS.js → index-BdbBanDP.js} +6 -6
  255. package/studio/web/assets/{index-0hXeECkS.js.map → index-BdbBanDP.js.map} +1 -1
  256. package/studio/web/assets/{index.lazy-B00B7VBT.js → index.lazy-B2eH28zD.js} +4 -4
  257. package/studio/web/assets/{index.lazy-B00B7VBT.js.map → index.lazy-B2eH28zD.js.map} +1 -1
  258. package/studio/web/assets/{profile-Cg2wwYPn.js → profile-DK5hgucv.js} +2 -2
  259. package/studio/web/assets/{profile-Cg2wwYPn.js.map → profile-DK5hgucv.js.map} +1 -1
  260. package/studio/web/assets/{setComponentFile-DCaDIvyB.js → setComponentFile-BVDWRYxx.js} +2 -2
  261. package/studio/web/assets/{setComponentFile-DCaDIvyB.js.map → setComponentFile-BVDWRYxx.js.map} +1 -1
  262. package/studio/web/assets/{setup-CAVcAQjK.js → setup-DJ9BInoK.js} +2 -2
  263. package/studio/web/assets/{setup-CAVcAQjK.js.map → setup-DJ9BInoK.js.map} +1 -1
  264. package/studio/web/assets/{status-BRXorNdD.js → status-B_qzmgfD.js} +2 -2
  265. package/studio/web/assets/{status-BRXorNdD.js.map → status-B_qzmgfD.js.map} +1 -1
  266. package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js → swagger-ui-react-DOL5jCqg.js} +2 -2
  267. package/studio/web/assets/{swagger-ui-react-Dy1D62vO.js.map → swagger-ui-react-DOL5jCqg.js.map} +1 -1
  268. package/studio/web/assets/{tsMode-A8gbL74v.js → tsMode-DpxUxfTW.js} +2 -2
  269. package/studio/web/assets/{tsMode-A8gbL74v.js.map → tsMode-DpxUxfTW.js.map} +1 -1
  270. package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js → useEntityRestURL-CU_lY6XW.js} +2 -2
  271. package/studio/web/assets/{useEntityRestURL-cDodrVcQ.js.map → useEntityRestURL-CU_lY6XW.js.map} +1 -1
  272. package/studio/web/index.html +1 -1
  273. package/utility/common_utils.ts +26 -0
  274. package/utility/install/installer.ts +26 -1
  275. package/validation/configValidator.ts +3 -0
  276. package/validation/deleteValidator.ts +11 -2
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalHashAggregate: groups all input rows in a Map keyed on JSON-serialised
4
+ * group-key values, then finalises accumulators and yields one output row per
5
+ * group.
6
+ *
7
+ * Memory is bounded by maxHashRows (total input rows consumed), after which an
8
+ * EngineUnsupportedError is thrown so the router falls back to legacy in 'auto'
9
+ * mode (runSelect fully materializes before returning, so nothing has been
10
+ * emitted when the cap trips).
11
+ *
12
+ * Special cases:
13
+ * - No GROUP BY + no rows → emit one row with default aggregate values
14
+ * (e.g. COUNT(*) = 0).
15
+ * - COUNT(*) arg is a star placeholder; we pass the sentinel value 1 to step()
16
+ * so the accumulator counts every row unconditionally.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.physicalHashAggregate = physicalHashAggregate;
20
+ const compile_ts_1 = require("../expressions/compile.js");
21
+ const registry_ts_1 = require("../functions/registry.js");
22
+ const errors_ts_1 = require("../errors.js");
23
+ function physicalHashAggregate(input, groupKeys, aggs, maxHashRows, qualified = false) {
24
+ // In join (qualified) queries the group-key column lives under its
25
+ // `<alias>.<name>` key, and the aggregate output is keyed the same way so the
26
+ // projection above resolves it consistently.
27
+ const groupKeyNames = groupKeys.map((k) => {
28
+ if (k.kind !== 'column')
29
+ throw new errors_ts_1.EngineUnsupportedError('GROUP BY supports only column refs', k);
30
+ return qualified && k.table ? `${k.table}.${k.name}` : k.name;
31
+ });
32
+ const groupKeyEvals = groupKeyNames.map((key) => (row) => row[key]);
33
+ const compiledAggs = aggs.map((a) => {
34
+ const desc = registry_ts_1.functionRegistry.lookup(a.name);
35
+ if (!desc || desc.kind !== 'aggregate') {
36
+ throw new errors_ts_1.EngineUnsupportedError(`unknown aggregate function: ${a.name}`);
37
+ }
38
+ // DISTINCT-in-aggregate dedup is not implemented; the accumulator would
39
+ // otherwise step every row (silent wrong result, e.g. COUNT(DISTINCT x)
40
+ // counting all rows). Reject so 'auto' falls back to legacy, which dedups.
41
+ if (a.distinct) {
42
+ throw new errors_ts_1.EngineUnsupportedError(`DISTINCT aggregate not supported yet: ${a.name}`);
43
+ }
44
+ const isStarArg = a.arg.kind === 'star';
45
+ const argEval = isStarArg ? null : (0, compile_ts_1.compileExpr)(a.arg, qualified).eval;
46
+ return {
47
+ outputName: a.outputName,
48
+ factory: desc.impl.factory,
49
+ isStarArg,
50
+ argEval,
51
+ };
52
+ });
53
+ return {
54
+ schema: [],
55
+ execute(ctx) {
56
+ return runAggregate(input, ctx, groupKeyEvals, groupKeyNames, compiledAggs, maxHashRows);
57
+ },
58
+ };
59
+ }
60
+ async function* runAggregate(input, ctx, groupKeyEvals, groupKeyNames, compiledAggs, maxHashRows) {
61
+ const groups = new Map();
62
+ let rowCount = 0;
63
+ for await (const row of input.execute(ctx)) {
64
+ if (++rowCount > maxHashRows) {
65
+ throw new errors_ts_1.EngineUnsupportedError(`aggregate exceeded maxHashRows (${maxHashRows})`);
66
+ }
67
+ const keyVals = groupKeyEvals.map((fn) => fn(row));
68
+ const groupKey = JSON.stringify(keyVals);
69
+ let entry = groups.get(groupKey);
70
+ if (!entry) {
71
+ entry = { keys: keyVals, accs: compiledAggs.map((a) => a.factory()) };
72
+ groups.set(groupKey, entry);
73
+ }
74
+ for (let i = 0; i < compiledAggs.length; i++) {
75
+ const agg = compiledAggs[i];
76
+ const val = agg.isStarArg ? 1 : agg.argEval(row);
77
+ entry.accs[i].step(val);
78
+ }
79
+ }
80
+ // No GROUP BY + no rows → emit one row with zero/null aggregate values.
81
+ if (groups.size === 0 && groupKeyNames.length === 0) {
82
+ const outputRow = {};
83
+ for (const agg of compiledAggs) {
84
+ outputRow[agg.outputName] = agg.factory().finalize();
85
+ }
86
+ yield outputRow;
87
+ return;
88
+ }
89
+ for (const { keys, accs } of groups.values()) {
90
+ const outputRow = {};
91
+ for (let i = 0; i < groupKeyNames.length; i++) {
92
+ outputRow[groupKeyNames[i]] = keys[i];
93
+ }
94
+ for (let i = 0; i < compiledAggs.length; i++) {
95
+ outputRow[compiledAggs[i].outputName] = accs[i].finalize();
96
+ }
97
+ yield outputRow;
98
+ }
99
+ }
100
+ //# sourceMappingURL=PhysicalHashAggregate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalHashAggregate.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalHashAggregate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PhysicalHashJoin: equi-join via an in-memory hash table on the right (inner)
3
+ * side.
4
+ *
5
+ * Build phase materializes the right input into a Map keyed on the JSON-encoded
6
+ * join-key tuple (bounded by maxHashRows). Probe phase streams the left
7
+ * (outer) input, looks up each left row's key tuple, and emits the merged row
8
+ * for every matching right row. An optional `residual` predicate (the
9
+ * non-equi remainder of the ON clause) is checked on the merged row.
10
+ *
11
+ * For a LEFT join, a left row with no surviving match emits once with the right
12
+ * side's declared columns null-filled (matching legacy `undefined → null`
13
+ * outer-join semantics in dataLayer/SQLSearch).
14
+ *
15
+ * Rows on both sides are already qualified (`<alias>.<attr>`), so the merge is
16
+ * a plain spread with no key collisions.
17
+ */
18
+ import type { ExprNode } from '../parser/ast.ts';
19
+ import type { PhysicalOp } from './op.ts';
20
+ export interface HashJoinOptions {
21
+ leftKeys: ExprNode[];
22
+ rightKeys: ExprNode[];
23
+ residual?: ExprNode;
24
+ type: 'inner' | 'left';
25
+ /** Right-side qualified keys to null-fill on unmatched LEFT rows. */
26
+ rightNullKeys: string[];
27
+ maxHashRows: number;
28
+ }
29
+ export declare function physicalHashJoin(left: PhysicalOp, right: PhysicalOp, opts: HashJoinOptions): PhysicalOp;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalHashJoin: equi-join via an in-memory hash table on the right (inner)
4
+ * side.
5
+ *
6
+ * Build phase materializes the right input into a Map keyed on the JSON-encoded
7
+ * join-key tuple (bounded by maxHashRows). Probe phase streams the left
8
+ * (outer) input, looks up each left row's key tuple, and emits the merged row
9
+ * for every matching right row. An optional `residual` predicate (the
10
+ * non-equi remainder of the ON clause) is checked on the merged row.
11
+ *
12
+ * For a LEFT join, a left row with no surviving match emits once with the right
13
+ * side's declared columns null-filled (matching legacy `undefined → null`
14
+ * outer-join semantics in dataLayer/SQLSearch).
15
+ *
16
+ * Rows on both sides are already qualified (`<alias>.<attr>`), so the merge is
17
+ * a plain spread with no key collisions.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.physicalHashJoin = physicalHashJoin;
21
+ const compile_ts_1 = require("../expressions/compile.js");
22
+ const errors_ts_1 = require("../errors.js");
23
+ function physicalHashJoin(left, right, opts) {
24
+ const leftKeyEvals = opts.leftKeys.map((e) => (0, compile_ts_1.compileExpr)(e, true).eval);
25
+ const rightKeyEvals = opts.rightKeys.map((e) => (0, compile_ts_1.compileExpr)(e, true).eval);
26
+ const residual = opts.residual ? (0, compile_ts_1.compileExpr)(opts.residual, true) : undefined;
27
+ return {
28
+ schema: [],
29
+ async *execute(ctx) {
30
+ // Build side: right input → Map<keyTuple, Row[]>.
31
+ const buckets = new Map();
32
+ let built = 0;
33
+ for await (const rrow of right.execute(ctx)) {
34
+ if (++built > opts.maxHashRows) {
35
+ throw new errors_ts_1.EngineUnsupportedError(`hash join build side exceeded maxHashRows (${opts.maxHashRows})`);
36
+ }
37
+ const key = keyTuple(rightKeyEvals, rrow);
38
+ if (key === undefined)
39
+ continue; // NULL join key never matches
40
+ const bucket = buckets.get(key);
41
+ if (bucket)
42
+ bucket.push(rrow);
43
+ else
44
+ buckets.set(key, [rrow]);
45
+ }
46
+ for await (const lrow of left.execute(ctx)) {
47
+ const key = keyTuple(leftKeyEvals, lrow);
48
+ let matched = false;
49
+ if (key !== undefined) {
50
+ const bucket = buckets.get(key);
51
+ if (bucket) {
52
+ for (const rrow of bucket) {
53
+ const merged = { ...lrow, ...rrow };
54
+ if (residual) {
55
+ const v = residual.eval(merged);
56
+ if (v == null || v === false)
57
+ continue;
58
+ }
59
+ matched = true;
60
+ yield merged;
61
+ }
62
+ }
63
+ }
64
+ if (!matched && opts.type === 'left') {
65
+ yield nullFill(lrow, opts.rightNullKeys);
66
+ }
67
+ }
68
+ },
69
+ };
70
+ }
71
+ /**
72
+ * Serializes the join key. Returns undefined if any key component is null/
73
+ * undefined or NaN — SQL equi-joins never match on NULL, and NaN is never equal
74
+ * to itself (without this guard JSON.stringify coerces NaN → "null", letting two
75
+ * NaN keys collide and match).
76
+ */
77
+ function keyTuple(evals, row) {
78
+ const vals = [];
79
+ for (const e of evals) {
80
+ const v = e(row);
81
+ if (v == null || (typeof v === 'number' && Number.isNaN(v)))
82
+ return undefined;
83
+ vals.push(v);
84
+ }
85
+ return JSON.stringify(vals);
86
+ }
87
+ function nullFill(lrow, rightNullKeys) {
88
+ const out = { ...lrow };
89
+ for (const k of rightNullKeys)
90
+ out[k] = null;
91
+ return out;
92
+ }
93
+ //# sourceMappingURL=PhysicalHashJoin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalHashJoin.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalHashJoin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * PhysicalIndexNestedLoopJoin: streams the outer (left) input and, for each
3
+ * outer row, probes the inner table via Table.search on its indexed join key.
4
+ *
5
+ * This is the default join strategy when the inner join key is indexed: no full
6
+ * inner scan, bounded memory (one inner result set at a time), and it composes
7
+ * with the inner table's own pushed-down WHERE conditions.
8
+ *
9
+ * The probe equality is ANDed with the inner scan's base conditions. Inner
10
+ * records are filtered by the inner residual (bare names), then qualified with
11
+ * the inner alias and merged with the outer row; an optional join residual (the
12
+ * non-equi remainder of ON) is checked on the merged row. LEFT joins null-fill
13
+ * the inner columns when no inner row matches.
14
+ */
15
+ import type { ExprNode } from '../parser/ast.ts';
16
+ import type { PhysicalOp } from './op.ts';
17
+ import type { ConditionNode } from '../optimizer/whereToConditions.ts';
18
+ export interface IndexNLJoinOptions {
19
+ innerResource: unknown;
20
+ innerAlias: string;
21
+ /** Indexed inner attribute the probe equates against the outer key value. */
22
+ innerAttribute: string;
23
+ /** Outer-side join-key expression (compiled in qualified mode). */
24
+ outerKey: ExprNode;
25
+ /** Inner scan's own pushed-down conditions, ANDed with the probe equality. */
26
+ innerBaseConditions: ConditionNode[];
27
+ innerOperator: 'and' | 'or';
28
+ innerSelect?: string[];
29
+ /** Inner single-table residual (bare names), applied to probe records. */
30
+ innerResidual?: ExprNode;
31
+ /** Non-equi remainder of the ON clause (qualified), applied to merged rows. */
32
+ residualOn?: ExprNode;
33
+ type: 'inner' | 'left';
34
+ rightNullKeys: string[];
35
+ }
36
+ export declare function physicalIndexNestedLoopJoin(left: PhysicalOp, opts: IndexNLJoinOptions): PhysicalOp;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalIndexNestedLoopJoin: streams the outer (left) input and, for each
4
+ * outer row, probes the inner table via Table.search on its indexed join key.
5
+ *
6
+ * This is the default join strategy when the inner join key is indexed: no full
7
+ * inner scan, bounded memory (one inner result set at a time), and it composes
8
+ * with the inner table's own pushed-down WHERE conditions.
9
+ *
10
+ * The probe equality is ANDed with the inner scan's base conditions. Inner
11
+ * records are filtered by the inner residual (bare names), then qualified with
12
+ * the inner alias and merged with the outer row; an optional join residual (the
13
+ * non-equi remainder of ON) is checked on the merged row. LEFT joins null-fill
14
+ * the inner columns when no inner row matches.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.physicalIndexNestedLoopJoin = physicalIndexNestedLoopJoin;
18
+ const compile_ts_1 = require("../expressions/compile.js");
19
+ function physicalIndexNestedLoopJoin(left, opts) {
20
+ const resource = opts.innerResource;
21
+ const outerKeyEval = (0, compile_ts_1.compileExpr)(opts.outerKey, true).eval;
22
+ const innerResidual = opts.innerResidual ? (0, compile_ts_1.compileExpr)(opts.innerResidual, false) : undefined;
23
+ const residualOn = opts.residualOn ? (0, compile_ts_1.compileExpr)(opts.residualOn, true) : undefined;
24
+ const prefix = `${opts.innerAlias}.`;
25
+ return {
26
+ schema: [],
27
+ async *execute(ctx) {
28
+ for await (const outerRow of left.execute(ctx)) {
29
+ const value = outerKeyEval(outerRow);
30
+ let matched = false;
31
+ if (value != null) {
32
+ const target = buildProbeTarget(opts, value);
33
+ for await (const innerRow of resource.search(target)) {
34
+ if (innerResidual) {
35
+ const v = innerResidual.eval(innerRow);
36
+ if (v == null || v === false)
37
+ continue;
38
+ }
39
+ const merged = { ...outerRow };
40
+ for (const k of Object.keys(innerRow))
41
+ merged[prefix + k] = innerRow[k];
42
+ if (residualOn) {
43
+ const v = residualOn.eval(merged);
44
+ if (v == null || v === false)
45
+ continue;
46
+ }
47
+ matched = true;
48
+ yield merged;
49
+ }
50
+ }
51
+ if (!matched && opts.type === 'left') {
52
+ const out = { ...outerRow };
53
+ for (const k of opts.rightNullKeys)
54
+ out[k] = null;
55
+ yield out;
56
+ }
57
+ }
58
+ },
59
+ };
60
+ }
61
+ function buildProbeTarget(opts, value) {
62
+ const probe = { attribute: opts.innerAttribute, value, comparator: 'equals' };
63
+ let conditions;
64
+ if (opts.innerBaseConditions.length === 0) {
65
+ conditions = [probe];
66
+ }
67
+ else if (opts.innerOperator === 'and') {
68
+ conditions = [...opts.innerBaseConditions, probe];
69
+ }
70
+ else {
71
+ conditions = [{ conditions: opts.innerBaseConditions, operator: 'or' }, probe];
72
+ }
73
+ const target = { conditions, operator: 'and', allowFullScan: false };
74
+ if (opts.innerSelect)
75
+ target.select = opts.innerSelect;
76
+ return target;
77
+ }
78
+ //# sourceMappingURL=PhysicalIndexNestedLoopJoin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalIndexNestedLoopJoin.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalIndexNestedLoopJoin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * PhysicalIndexScan: wraps Table.search.
3
+ *
4
+ * Builds the RequestTarget from the LogicalScan's pushed filters/sort/limit
5
+ * and projection, then yields rows from the returned AsyncIterable.
6
+ */
7
+ import type { LogicalScan } from '../logical/op.ts';
8
+ import type { PhysicalOp } from './op.ts';
9
+ import type { ConditionNode } from '../optimizer/whereToConditions.ts';
10
+ export interface PhysicalIndexScanOptions {
11
+ conditions: ConditionNode[];
12
+ operator: 'and' | 'or';
13
+ /**
14
+ * Set for a sort-driven scan (no index-driving predicate; the pushed sort
15
+ * provides index order — D-219). Table.search flags a sort-aligned scan as
16
+ * needFullScan and would reject it under allowFullScan:false, so it must be
17
+ * allowed here. Validated as scannable by validateScannable, so this is not a
18
+ * blanket full-scan escape hatch.
19
+ */
20
+ allowFullScan?: boolean;
21
+ }
22
+ export declare function physicalIndexScan(scan: LogicalScan, opts: PhysicalIndexScanOptions): PhysicalOp;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalIndexScan: wraps Table.search.
4
+ *
5
+ * Builds the RequestTarget from the LogicalScan's pushed filters/sort/limit
6
+ * and projection, then yields rows from the returned AsyncIterable.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.physicalIndexScan = physicalIndexScan;
10
+ const errors_ts_1 = require("../errors.js");
11
+ const hdbError_ts_1 = require("../../utility/errors/hdbError.js");
12
+ function physicalIndexScan(scan, opts) {
13
+ const schema = (scan.boundTable?.attributes ?? []).map((a) => ({
14
+ name: a.name,
15
+ type: 'unknown',
16
+ nullable: true,
17
+ }));
18
+ return {
19
+ schema,
20
+ execute(ctx) {
21
+ return executeScan(scan, opts, ctx);
22
+ },
23
+ };
24
+ }
25
+ async function* executeScan(scan, opts, ctx) {
26
+ const resource = scan.boundTable?.resource;
27
+ if (!resource)
28
+ throw new Error('PhysicalIndexScan: scan has no boundTable.resource');
29
+ const target = { allowFullScan: opts.allowFullScan === true };
30
+ if (ctx.includeExpiredRows)
31
+ target.includeExpired = true;
32
+ // Only attach conditions/operator when there is at least one — Table.search
33
+ // rejects an empty `and`/`or` group ("requires at least one condition"). A
34
+ // scan with no conditions is driven by its pushed sort/limit alone.
35
+ if (opts.conditions.length > 0) {
36
+ target.conditions = opts.conditions;
37
+ target.operator = opts.operator;
38
+ }
39
+ if (scan.projection)
40
+ target.select = scan.projection;
41
+ if (scan.pushedSort && scan.pushedSort.length > 0) {
42
+ const k = scan.pushedSort[0];
43
+ if (k.expr.kind === 'column') {
44
+ target.sort = { attribute: k.expr.name, descending: k.descending };
45
+ }
46
+ }
47
+ if (scan.pushedLimit) {
48
+ if (scan.pushedLimit.limit != null)
49
+ target.limit = scan.pushedLimit.limit;
50
+ if (scan.pushedLimit.offset != null)
51
+ target.offset = scan.pushedLimit.offset;
52
+ }
53
+ // Safety net for the fallback contract: validateScannable predicts what
54
+ // Table.search will accept, but if the prediction is ever wrong (F-145: a
55
+ // pushed `ne null` guard on an index without indexNulls), search throws a
56
+ // capability-shaped ClientError (400/403/404) or IndexRebuildingError at
57
+ // runtime, past the router's EngineUnsupportedError catch — leaking an error
58
+ // where 'auto' should fall back. Convert those here; results are materialized
59
+ // before delivery, so no partial rows have been sent when this fires.
60
+ try {
61
+ for await (const row of resource.search(target)) {
62
+ yield row;
63
+ }
64
+ }
65
+ catch (err) {
66
+ if (err instanceof errors_ts_1.EngineUnsupportedError)
67
+ throw err;
68
+ if (err instanceof hdbError_ts_1.IndexRebuildingError) {
69
+ throw new errors_ts_1.EngineUnsupportedError(`index rebuilding: ${err.message}`);
70
+ }
71
+ if (err instanceof hdbError_ts_1.ClientError) {
72
+ throw new errors_ts_1.EngineUnsupportedError(`search rejected scan: ${err.message}`);
73
+ }
74
+ throw err;
75
+ }
76
+ }
77
+ //# sourceMappingURL=PhysicalIndexScan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalIndexScan.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalIndexScan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * PhysicalLimit: drops `offset` rows then yields up to `limit` rows.
3
+ */
4
+ import type { PhysicalOp } from './op.ts';
5
+ export declare function physicalLimit(child: PhysicalOp, limit: number | undefined, offset: number | undefined): PhysicalOp;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalLimit: drops `offset` rows then yields up to `limit` rows.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.physicalLimit = physicalLimit;
7
+ function physicalLimit(child, limit, offset) {
8
+ return {
9
+ schema: child.schema,
10
+ async *execute(ctx) {
11
+ let skipped = 0;
12
+ let yielded = 0;
13
+ const skip = offset ?? 0;
14
+ const cap = limit ?? Number.POSITIVE_INFINITY;
15
+ for await (const row of child.execute(ctx)) {
16
+ if (skipped < skip) {
17
+ skipped++;
18
+ continue;
19
+ }
20
+ if (yielded >= cap)
21
+ return;
22
+ yield row;
23
+ yielded++;
24
+ }
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=PhysicalLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalLimit.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalLimit.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAKH,sCAmBC;AAnBD,SAAgB,aAAa,CAAC,KAAiB,EAAE,KAAyB,EAAE,MAA0B;IACrG,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,CAAC,CAAC,OAAO,CAAC,GAAqB;YACnC,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC;YACzB,MAAM,GAAG,GAAG,KAAK,IAAI,MAAM,CAAC,iBAAiB,CAAC;YAC9C,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;oBACpB,OAAO,EAAE,CAAC;oBACV,SAAS;gBACV,CAAC;gBACD,IAAI,OAAO,IAAI,GAAG;oBAAE,OAAO;gBAC3B,MAAM,GAAG,CAAC;gBACV,OAAO,EAAE,CAAC;YACX,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * PhysicalNestedLoopJoin: the general join fallback for CROSS joins and
3
+ * non-equi ON predicates that no hash/index strategy can serve.
4
+ *
5
+ * The right (inner) input is materialized once (bounded by maxHashRows); the
6
+ * left (outer) input streams. For each left row every buffered right row is
7
+ * tested against the compiled ON predicate (absent for CROSS) on the merged
8
+ * row. LEFT joins null-fill the right columns when a left row matches nothing.
9
+ *
10
+ * Both inputs are already qualified (`<alias>.<attr>`); merge is a plain spread.
11
+ */
12
+ import type { ExprNode } from '../parser/ast.ts';
13
+ import type { PhysicalOp } from './op.ts';
14
+ export interface NestedLoopJoinOptions {
15
+ on?: ExprNode;
16
+ type: 'inner' | 'left' | 'cross';
17
+ rightNullKeys: string[];
18
+ maxHashRows: number;
19
+ }
20
+ export declare function physicalNestedLoopJoin(left: PhysicalOp, right: PhysicalOp, opts: NestedLoopJoinOptions): PhysicalOp;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * PhysicalNestedLoopJoin: the general join fallback for CROSS joins and
4
+ * non-equi ON predicates that no hash/index strategy can serve.
5
+ *
6
+ * The right (inner) input is materialized once (bounded by maxHashRows); the
7
+ * left (outer) input streams. For each left row every buffered right row is
8
+ * tested against the compiled ON predicate (absent for CROSS) on the merged
9
+ * row. LEFT joins null-fill the right columns when a left row matches nothing.
10
+ *
11
+ * Both inputs are already qualified (`<alias>.<attr>`); merge is a plain spread.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.physicalNestedLoopJoin = physicalNestedLoopJoin;
15
+ const compile_ts_1 = require("../expressions/compile.js");
16
+ const errors_ts_1 = require("../errors.js");
17
+ function physicalNestedLoopJoin(left, right, opts) {
18
+ const on = opts.on ? (0, compile_ts_1.compileExpr)(opts.on, true) : undefined;
19
+ return {
20
+ schema: [],
21
+ async *execute(ctx) {
22
+ const inner = [];
23
+ for await (const rrow of right.execute(ctx)) {
24
+ if (inner.length >= opts.maxHashRows) {
25
+ throw new errors_ts_1.EngineUnsupportedError(`nested-loop join inner side exceeded maxHashRows (${opts.maxHashRows})`);
26
+ }
27
+ inner.push(rrow);
28
+ }
29
+ for await (const lrow of left.execute(ctx)) {
30
+ let matched = false;
31
+ for (const rrow of inner) {
32
+ const merged = { ...lrow, ...rrow };
33
+ if (on) {
34
+ const v = on.eval(merged);
35
+ if (v == null || v === false)
36
+ continue;
37
+ }
38
+ matched = true;
39
+ yield merged;
40
+ }
41
+ if (!matched && opts.type === 'left') {
42
+ const out = { ...lrow };
43
+ for (const k of opts.rightNullKeys)
44
+ out[k] = null;
45
+ yield out;
46
+ }
47
+ }
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=PhysicalNestedLoopJoin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhysicalNestedLoopJoin.js","sourceRoot":"","sources":["../../../sqlEngine/physical/PhysicalNestedLoopJoin.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAeH,wDAiCC;AA3CD,0DAAwD;AACxD,4CAAsD;AAStD,SAAgB,sBAAsB,CAAC,IAAgB,EAAE,KAAiB,EAAE,IAA2B;IACtG,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,wBAAW,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE5D,OAAO;QACN,MAAM,EAAE,EAAE;QACV,KAAK,CAAC,CAAC,OAAO,CAAC,GAAqB;YACnC,MAAM,KAAK,GAAU,EAAE,CAAC;YACxB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7C,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACtC,MAAM,IAAI,kCAAsB,CAAC,qDAAqD,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;gBAC5G,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;YAED,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBAC1B,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;oBACpC,IAAI,EAAE,EAAE,CAAC;wBACR,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAC1B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK;4BAAE,SAAS;oBACxC,CAAC;oBACD,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM,MAAM,CAAC;gBACd,CAAC;gBACD,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACtC,MAAM,GAAG,GAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;oBAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa;wBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;oBAClD,MAAM,GAAG,CAAC;gBACX,CAAC;YACF,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * PhysicalProject: per-row evaluation of the SELECT clause.
3
+ *
4
+ * Single-table (`qualified = false`): star expansion forwards the row's keys
5
+ * intact and layers projected columns on top, matching the Resource API's
6
+ * natural record shape.
7
+ *
8
+ * Join queries (`qualified = true`): rows arrive keyed by `<alias>.<name>`.
9
+ * Output columns are renamed to clean, unqualified names (or the SELECT `AS`
10
+ * alias). When two output columns collide on the same name the later one is
11
+ * suffixed `_2`, `_3`, … in SELECT order (legacy AlaSQL instead emitted
12
+ * `[name]`/`[name1]`; the differential harness normalizes between the two).
13
+ * `SELECT *` expands every column across all joined tables; `SELECT t.*`
14
+ * expands only table `t`'s columns.
15
+ */
16
+ import type { ProjectionNode } from '../parser/ast.ts';
17
+ import type { PhysicalOp } from './op.ts';
18
+ export declare function physicalProject(child: PhysicalOp, projections: ProjectionNode[], qualified?: boolean): PhysicalOp;