@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,80 @@
1
+ "use strict";
2
+ /**
3
+ * Rule R3: predicate normalization.
4
+ *
5
+ * Maps AlaSQL operator forms to a canonical shape ahead of pushdown:
6
+ * - LIKE 'foo%' -> starts_with(foo)
7
+ * - LIKE '%foo' -> ends_with(foo)
8
+ * - LIKE '%foo%' -> contains(foo)
9
+ * - BETWEEN a AND b -> binop chain (col >= a AND col <= b) with semantic
10
+ * hint kept via marker for the pushdown rule
11
+ * - NOT (a > b) -> a <= b (NULL semantics preserved by leaving NOT in
12
+ * place when the operand is anything other than a
13
+ * comparable binop on a single column ref)
14
+ * - IS NULL / IS NOT NULL: left as-is (rule output for downstream).
15
+ *
16
+ * No change-of-meaning rewrites at this stage; the rule is conservative.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.normalizePredicate = normalizePredicate;
20
+ const NOT_OP_INVERSE = {
21
+ '=': '!=',
22
+ '!=': '=',
23
+ '<>': '=',
24
+ '<': '>=',
25
+ '<=': '>',
26
+ '>': '<=',
27
+ '>=': '<',
28
+ };
29
+ function normalizePredicate(expr) {
30
+ switch (expr.kind) {
31
+ case 'logical': {
32
+ if (expr.op === 'not' && expr.args.length === 1) {
33
+ const inner = normalizePredicate(expr.args[0]);
34
+ if (inner.kind === 'binop' && NOT_OP_INVERSE[inner.op]) {
35
+ return {
36
+ kind: 'binop',
37
+ op: NOT_OP_INVERSE[inner.op],
38
+ left: inner.left,
39
+ right: inner.right,
40
+ };
41
+ }
42
+ if (inner.kind === 'isNull') {
43
+ return { ...inner, negated: !inner.negated };
44
+ }
45
+ if (inner.kind === 'between') {
46
+ return { ...inner, negated: !inner.negated };
47
+ }
48
+ if (inner.kind === 'in') {
49
+ return { ...inner, negated: !inner.negated };
50
+ }
51
+ if (inner.kind === 'like') {
52
+ return { ...inner, negated: !inner.negated };
53
+ }
54
+ return { kind: 'logical', op: 'not', args: [inner] };
55
+ }
56
+ return { kind: 'logical', op: expr.op, args: expr.args.map(normalizePredicate) };
57
+ }
58
+ case 'binop':
59
+ return { ...expr, left: normalizeChild(expr.left), right: normalizeChild(expr.right) };
60
+ case 'between':
61
+ return {
62
+ ...expr,
63
+ expr: normalizeChild(expr.expr),
64
+ low: normalizeChild(expr.low),
65
+ high: normalizeChild(expr.high),
66
+ };
67
+ case 'in':
68
+ return { ...expr, expr: normalizeChild(expr.expr) };
69
+ case 'like':
70
+ return { ...expr, expr: normalizeChild(expr.expr), pattern: normalizeChild(expr.pattern) };
71
+ case 'isNull':
72
+ return { ...expr, expr: normalizeChild(expr.expr) };
73
+ default:
74
+ return expr;
75
+ }
76
+ }
77
+ function normalizeChild(expr) {
78
+ return expr;
79
+ }
80
+ //# sourceMappingURL=predicateNormalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicateNormalize.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/predicateNormalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Rule R1: predicate pushdown.
3
+ *
4
+ * Pushes Filter into the Scan immediately below it. The portion that maps to
5
+ * Resource API conditions is stored on Scan.pushedFilter (consumed by the
6
+ * physical planner's whereToConditions). Anything that can't be expressed as
7
+ * a condition is left as Scan.residualFilter and applied by a wrapping
8
+ * PhysicalFilter at execution time.
9
+ */
10
+ import type { LogicalPlan } from '../../logical/op.ts';
11
+ export declare function predicatePushdown(plan: LogicalPlan): LogicalPlan | null;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Rule R1: predicate pushdown.
4
+ *
5
+ * Pushes Filter into the Scan immediately below it. The portion that maps to
6
+ * Resource API conditions is stored on Scan.pushedFilter (consumed by the
7
+ * physical planner's whereToConditions). Anything that can't be expressed as
8
+ * a condition is left as Scan.residualFilter and applied by a wrapping
9
+ * PhysicalFilter at execution time.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.predicatePushdown = predicatePushdown;
13
+ function predicatePushdown(plan) {
14
+ return rewrite(plan);
15
+ }
16
+ function rewrite(plan) {
17
+ switch (plan.kind) {
18
+ case 'Filter': {
19
+ const child = rewrite(plan.input);
20
+ if (child.kind === 'Scan') {
21
+ const merged = child.pushedFilter
22
+ ? { kind: 'logical', op: 'and', args: [child.pushedFilter, plan.predicate] }
23
+ : plan.predicate;
24
+ return { ...child, pushedFilter: merged };
25
+ }
26
+ return { ...plan, input: child };
27
+ }
28
+ case 'Project':
29
+ return { ...plan, input: rewrite(plan.input) };
30
+ case 'Sort':
31
+ return { ...plan, input: rewrite(plan.input) };
32
+ case 'Limit':
33
+ return { ...plan, input: rewrite(plan.input) };
34
+ case 'Distinct':
35
+ return { ...plan, input: rewrite(plan.input) };
36
+ case 'Aggregate':
37
+ // Recurse into input so WHERE filters below get pushed to the scan.
38
+ // HAVING (a Filter above us) must NOT be pushed through the Aggregate.
39
+ return { ...plan, input: rewrite(plan.input) };
40
+ case 'Join':
41
+ // Per-table WHERE conjuncts were attached as Filters directly above each
42
+ // base scan by logical/build; push them in on both sides.
43
+ return { ...plan, left: rewrite(plan.left), right: rewrite(plan.right) };
44
+ default:
45
+ return plan;
46
+ }
47
+ }
48
+ //# sourceMappingURL=predicatePushdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicatePushdown.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/predicatePushdown.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAIH,8CAEC;AAFD,SAAgB,iBAAiB,CAAC,IAAiB;IAClD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,OAAO,CAAC,IAAiB;IACjC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACf,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY;oBAChC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAkB,EAAE,EAAE,EAAE,KAAc,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE;oBAC9F,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;gBAClB,OAAO,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;YAC3C,CAAC;YACD,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QACD,KAAK,SAAS;YACb,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,MAAM;YACV,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,OAAO;YACX,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,UAAU;YACd,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,WAAW;YACf,oEAAoE;YACpE,uEAAuE;YACvE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,MAAM;YACV,yEAAyE;YACzE,0DAA0D;YAC1D,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1E;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Rule R2: projection pushdown.
3
+ *
4
+ * Walks the plan from the root and computes the minimal set of attributes
5
+ * each Scan must produce. The set is stored on Scan.projection and is mapped
6
+ * to Resource API target.select by the physical planner.
7
+ *
8
+ * If any projection includes a `*`, we leave the scan's projection
9
+ * unrestricted (undefined → fetch all attributes). This keeps semantics
10
+ * matching legacy SQL. We can tighten this later by binding `*` to the
11
+ * concrete attribute list at plan time.
12
+ */
13
+ import type { ExprNode, ProjectionNode, SortNode } from '../../parser/ast.ts';
14
+ import type { LogicalPlan } from '../../logical/op.ts';
15
+ export declare function projectionPushdown(plan: LogicalPlan): LogicalPlan | null;
16
+ declare function containsStar(projections: ProjectionNode[]): boolean;
17
+ declare function collectColumns(expr: ExprNode, out: Set<string>): void;
18
+ export declare const _internal: {
19
+ collectColumns: typeof collectColumns;
20
+ containsStar: typeof containsStar;
21
+ };
22
+ export declare function collectRequiredColumnsFromKeys(keys: SortNode[]): Set<string>;
23
+ export {};
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * Rule R2: projection pushdown.
4
+ *
5
+ * Walks the plan from the root and computes the minimal set of attributes
6
+ * each Scan must produce. The set is stored on Scan.projection and is mapped
7
+ * to Resource API target.select by the physical planner.
8
+ *
9
+ * If any projection includes a `*`, we leave the scan's projection
10
+ * unrestricted (undefined → fetch all attributes). This keeps semantics
11
+ * matching legacy SQL. We can tighten this later by binding `*` to the
12
+ * concrete attribute list at plan time.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports._internal = void 0;
16
+ exports.projectionPushdown = projectionPushdown;
17
+ exports.collectRequiredColumnsFromKeys = collectRequiredColumnsFromKeys;
18
+ function projectionPushdown(plan) {
19
+ return rewrite(plan, undefined);
20
+ }
21
+ function rewrite(plan, required) {
22
+ switch (plan.kind) {
23
+ case 'Project': {
24
+ if (containsStar(plan.projections)) {
25
+ return { ...plan, input: rewrite(plan.input, undefined) };
26
+ }
27
+ const need = new Set();
28
+ for (const p of plan.projections)
29
+ collectColumns(p.expr, need);
30
+ return { ...plan, input: rewrite(plan.input, need) };
31
+ }
32
+ case 'Filter': {
33
+ if (required) {
34
+ const merged = new Set(required);
35
+ collectColumns(plan.predicate, merged);
36
+ return { ...plan, input: rewrite(plan.input, merged) };
37
+ }
38
+ return { ...plan, input: rewrite(plan.input, undefined) };
39
+ }
40
+ case 'Sort': {
41
+ if (required) {
42
+ const merged = new Set(required);
43
+ for (const k of plan.keys)
44
+ collectColumns(k.expr, merged);
45
+ return { ...plan, input: rewrite(plan.input, merged) };
46
+ }
47
+ return { ...plan, input: rewrite(plan.input, undefined) };
48
+ }
49
+ case 'Limit':
50
+ return { ...plan, input: rewrite(plan.input, required) };
51
+ case 'Distinct':
52
+ return { ...plan, input: rewrite(plan.input, required) };
53
+ case 'Aggregate': {
54
+ // `required` from above contains synthetic __agg_N__ names that don't
55
+ // exist in the input. Compute the actual columns the input must supply.
56
+ const need = new Set();
57
+ for (const k of plan.groupKeys)
58
+ collectColumns(k, need);
59
+ for (const a of plan.aggs) {
60
+ if (a.arg.kind !== 'star')
61
+ collectColumns(a.arg, need);
62
+ }
63
+ return { ...plan, input: rewrite(plan.input, need.size > 0 ? need : undefined) };
64
+ }
65
+ case 'Scan': {
66
+ if (!required)
67
+ return { ...plan, projection: undefined };
68
+ if (plan.pushedFilter)
69
+ collectColumns(plan.pushedFilter, required);
70
+ if (plan.pushedSort)
71
+ for (const k of plan.pushedSort)
72
+ collectColumns(k.expr, required);
73
+ if (plan.residualFilter)
74
+ collectColumns(plan.residualFilter, required);
75
+ return { ...plan, projection: [...required].sort() };
76
+ }
77
+ default:
78
+ return plan;
79
+ }
80
+ }
81
+ function containsStar(projections) {
82
+ for (const p of projections) {
83
+ if (containsStarExpr(p.expr))
84
+ return true;
85
+ }
86
+ return false;
87
+ }
88
+ function containsStarExpr(expr) {
89
+ if (expr.kind === 'star')
90
+ return true;
91
+ if (expr.kind === 'binop')
92
+ return containsStarExpr(expr.left) || containsStarExpr(expr.right);
93
+ if (expr.kind === 'logical')
94
+ return expr.args.some(containsStarExpr);
95
+ if (expr.kind === 'funcCall')
96
+ return expr.args.some(containsStarExpr);
97
+ return false;
98
+ }
99
+ function collectColumns(expr, out) {
100
+ switch (expr.kind) {
101
+ case 'column':
102
+ out.add(expr.name);
103
+ return;
104
+ case 'binop':
105
+ collectColumns(expr.left, out);
106
+ collectColumns(expr.right, out);
107
+ return;
108
+ case 'logical':
109
+ expr.args.forEach((a) => collectColumns(a, out));
110
+ return;
111
+ case 'in':
112
+ collectColumns(expr.expr, out);
113
+ if (Array.isArray(expr.list)) {
114
+ expr.list.forEach((e) => collectColumns(e, out));
115
+ }
116
+ return;
117
+ case 'between':
118
+ collectColumns(expr.expr, out);
119
+ collectColumns(expr.low, out);
120
+ collectColumns(expr.high, out);
121
+ return;
122
+ case 'like':
123
+ collectColumns(expr.expr, out);
124
+ collectColumns(expr.pattern, out);
125
+ return;
126
+ case 'isNull':
127
+ collectColumns(expr.expr, out);
128
+ return;
129
+ case 'funcCall':
130
+ expr.args.forEach((a) => collectColumns(a, out));
131
+ return;
132
+ case 'aggCall':
133
+ if (expr.arg.kind !== 'star')
134
+ collectColumns(expr.arg, out);
135
+ return;
136
+ case 'case':
137
+ for (const c of expr.cases) {
138
+ collectColumns(c.when, out);
139
+ collectColumns(c.then, out);
140
+ }
141
+ if (expr.else)
142
+ collectColumns(expr.else, out);
143
+ return;
144
+ case 'star':
145
+ case 'literal':
146
+ return;
147
+ default:
148
+ return;
149
+ }
150
+ }
151
+ // Surface a helper for unit tests / external rules.
152
+ exports._internal = { collectColumns, containsStar };
153
+ // Helper that other rules can use without re-walking plans.
154
+ function collectRequiredColumnsFromKeys(keys) {
155
+ const out = new Set();
156
+ for (const k of keys)
157
+ collectColumns(k.expr, out);
158
+ return out;
159
+ }
160
+ //# sourceMappingURL=projectionPushdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectionPushdown.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/projectionPushdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Rule R7: sort-from-index detection.
3
+ *
4
+ * If a Sort's keys all reference indexed attributes on a leaf Scan and the
5
+ * Sort sits directly above the Scan (with no Filter that would change row
6
+ * order), push the sort into Scan.pushedSort so Table.search returns rows in
7
+ * the requested order. The Resource API only supports a single primary sort
8
+ * with an optional `next` chain; phase 1 only handles the single-key case.
9
+ *
10
+ * If pushdown is not possible the Sort stays in place and the executor sorts
11
+ * in memory (capped by config.maxSortRows).
12
+ */
13
+ import type { LogicalPlan } from '../../logical/op.ts';
14
+ export declare function sortFromIndex(plan: LogicalPlan): LogicalPlan | null;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * Rule R7: sort-from-index detection.
4
+ *
5
+ * If a Sort's keys all reference indexed attributes on a leaf Scan and the
6
+ * Sort sits directly above the Scan (with no Filter that would change row
7
+ * order), push the sort into Scan.pushedSort so Table.search returns rows in
8
+ * the requested order. The Resource API only supports a single primary sort
9
+ * with an optional `next` chain; phase 1 only handles the single-key case.
10
+ *
11
+ * If pushdown is not possible the Sort stays in place and the executor sorts
12
+ * in memory (capped by config.maxSortRows).
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.sortFromIndex = sortFromIndex;
16
+ function sortFromIndex(plan) {
17
+ return rewrite(plan);
18
+ }
19
+ function rewrite(plan) {
20
+ switch (plan.kind) {
21
+ case 'Sort': {
22
+ const child = rewrite(plan.input);
23
+ if (child.kind === 'Scan' && !child.pushedSort) {
24
+ if (plan.keys.length !== 1)
25
+ return { ...plan, input: child };
26
+ const key = plan.keys[0];
27
+ if (key.expr.kind !== 'column')
28
+ return { ...plan, input: child };
29
+ const attribute = key.expr.name;
30
+ const indexed = child.boundTable?.attributes.some((a) => a.name === attribute && a.indexed);
31
+ if (!indexed)
32
+ return { ...plan, input: child };
33
+ return { ...child, pushedSort: [key] };
34
+ }
35
+ return { ...plan, input: child };
36
+ }
37
+ case 'Project':
38
+ return { ...plan, input: rewrite(plan.input) };
39
+ case 'Filter':
40
+ return { ...plan, input: rewrite(plan.input) };
41
+ case 'Limit':
42
+ return { ...plan, input: rewrite(plan.input) };
43
+ case 'Distinct':
44
+ return { ...plan, input: rewrite(plan.input) };
45
+ default:
46
+ return plan;
47
+ }
48
+ }
49
+ //# sourceMappingURL=sortFromIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortFromIndex.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/sortFromIndex.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAIH,sCAEC;AAFD,SAAgB,aAAa,CAAC,IAAiB;IAC9C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,OAAO,CAAC,IAAiB;IACjC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBAChD,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;gBAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;gBACjE,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAChC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;gBAC5F,IAAI,CAAC,OAAO;oBAAE,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;gBAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,CAAC;YACD,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QACD,KAAK,SAAS;YACb,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,QAAQ;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,OAAO;YACX,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,UAAU;YACd,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Rule R8: scan validation.
3
+ *
4
+ * After all pushdowns, we walk every Scan in the plan and check that the
5
+ * Resource API will accept the resulting target. Specifically: if no usable
6
+ * index condition was pushed (and `allowFullScan` is off in config), we
7
+ * throw EngineUnsupportedError naming the offending scan so the router can
8
+ * fall back to legacy in 'auto' mode.
9
+ *
10
+ * Phase 1 keeps the check loose: any pushedFilter that maps to at least one
11
+ * Resource API condition with an indexed attribute is sufficient. Filtering
12
+ * decisions sit in optimizer/whereToConditions.ts.
13
+ */
14
+ import type { LogicalPlan } from '../../logical/op.ts';
15
+ export declare function validateScannable(plan: LogicalPlan): LogicalPlan | null;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * Rule R8: scan validation.
4
+ *
5
+ * After all pushdowns, we walk every Scan in the plan and check that the
6
+ * Resource API will accept the resulting target. Specifically: if no usable
7
+ * index condition was pushed (and `allowFullScan` is off in config), we
8
+ * throw EngineUnsupportedError naming the offending scan so the router can
9
+ * fall back to legacy in 'auto' mode.
10
+ *
11
+ * Phase 1 keeps the check loose: any pushedFilter that maps to at least one
12
+ * Resource API condition with an indexed attribute is sufficient. Filtering
13
+ * decisions sit in optimizer/whereToConditions.ts.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.validateScannable = validateScannable;
17
+ const errors_ts_1 = require("../../errors.js");
18
+ const whereToConditions_ts_1 = require("../whereToConditions.js");
19
+ const config_ts_1 = require("../../config.js");
20
+ function validateScannable(plan) {
21
+ const cfg = (0, config_ts_1.getSqlEngineConfig)();
22
+ walk(plan, cfg.allowFullScan);
23
+ return null;
24
+ }
25
+ function walk(plan, allowFullScan) {
26
+ if (plan.kind === 'Scan') {
27
+ validateScan(plan, allowFullScan);
28
+ return;
29
+ }
30
+ if ('input' in plan)
31
+ walk(plan.input, allowFullScan);
32
+ if ('left' in plan)
33
+ walk(plan.left, allowFullScan);
34
+ if ('right' in plan)
35
+ walk(plan.right, allowFullScan);
36
+ }
37
+ function validateScan(scan, allowFullScan) {
38
+ if (allowFullScan)
39
+ return;
40
+ // Inner side of an index-nested-loop join: served by a per-outer-row indexed
41
+ // equality probe, not a standalone scan.
42
+ if (scan.joinProbe)
43
+ return;
44
+ // whereToConditions, given the table's attributes, pushes only conditions on
45
+ // indexed attributes (unindexed predicates are residualized into a post-scan
46
+ // Filter). The scan is valid only if at least one pushed condition can drive
47
+ // an index seek/range — a lone full-scan comparator (e.g. LIKE→contains) or a
48
+ // pushed sort is treated by Table.search as needFullScan and rejected under
49
+ // allowFullScan:false, so reject here too and let 'auto' fall back to legacy.
50
+ const { conditions } = (0, whereToConditions_ts_1.whereToConditions)(scan.pushedFilter, scan.boundTable?.attributes);
51
+ if (conditions.some((c) => (0, whereToConditions_ts_1.conditionUsesIndex)(c, scan.boundTable?.attributes)))
52
+ return;
53
+ // A sort pushed onto an indexed attribute drives the scan via the index's
54
+ // natural order (D-219): rows stream ordered from the index and a pushed LIMIT
55
+ // early-terminates, so it's a valid scan even with no index-driving predicate.
56
+ if ((0, whereToConditions_ts_1.sortDrivesIndex)(scan.pushedSort, scan.boundTable?.attributes))
57
+ return;
58
+ throw new errors_ts_1.EngineUnsupportedError(`scan on "${scan.table.database}.${scan.table.table}" has no usable index condition`, scan.pushedFilter);
59
+ }
60
+ //# sourceMappingURL=validateScannable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateScannable.js","sourceRoot":"","sources":["../../../../sqlEngine/optimizer/rules/validateScannable.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAOH,8CAIC;AARD,+CAAyD;AACzD,kEAAiG;AACjG,+CAAqD;AAErD,SAAgB,iBAAiB,CAAC,IAAiB;IAClD,MAAM,GAAG,GAAG,IAAA,8BAAkB,GAAE,CAAC;IACjC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9B,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,IAAI,CAAC,IAAiB,EAAE,aAAsB;IACtD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAClC,OAAO;IACR,CAAC;IACD,IAAI,OAAO,IAAI,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACrD,IAAI,MAAM,IAAI,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACnD,IAAI,OAAO,IAAI,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,YAAY,CAAC,IAAiB,EAAE,aAAsB;IAC9D,IAAI,aAAa;QAAE,OAAO;IAC1B,6EAA6E;IAC7E,yCAAyC;IACzC,IAAI,IAAI,CAAC,SAAS;QAAE,OAAO;IAC3B,6EAA6E;IAC7E,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,wCAAiB,EAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACzF,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,yCAAkB,EAAC,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAAE,OAAO;IACvF,0EAA0E;IAC1E,+EAA+E;IAC/E,+EAA+E;IAC/E,IAAI,IAAA,sCAAe,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;QAAE,OAAO;IAC1E,MAAM,IAAI,kCAAsB,CAC/B,YAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,iCAAiC,EACpF,IAAI,CAAC,YAAY,CACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Converts a (normalized) WHERE predicate into a Resource API condition tree
3
+ * plus an optional residual expression that the engine must apply as a
4
+ * post-scan Filter.
5
+ *
6
+ * The Resource API condition shape (see core/resources/search.ts:581):
7
+ * { attribute, value, comparator? }
8
+ * { conditions: Condition[], operator: 'and'|'or' }
9
+ *
10
+ * Comparator names use the canonical forms in
11
+ * core/resources/search.ts:204 (equals, ne, lt, le, gt, ge, between, gele,
12
+ * gelt, gtlt, gtle, starts_with, ends_with, contains).
13
+ *
14
+ * Anything that can't be represented as a condition (e.g., comparing two
15
+ * columns, function calls in WHERE, OR mixed with non-attribute predicates)
16
+ * is left in the residual.
17
+ */
18
+ import type { ExprNode } from '../parser/ast.ts';
19
+ export interface DirectCondition {
20
+ attribute?: string;
21
+ value?: unknown;
22
+ comparator?: string;
23
+ }
24
+ export interface CompoundCondition {
25
+ conditions: ConditionNode[];
26
+ operator: 'and' | 'or';
27
+ }
28
+ export type ConditionNode = DirectCondition | CompoundCondition;
29
+ export interface ConvertResult {
30
+ conditions: ConditionNode[];
31
+ operator: 'and' | 'or';
32
+ residual?: ExprNode;
33
+ }
34
+ export type IndexedAttribute = {
35
+ name: string;
36
+ indexed: boolean;
37
+ isPrimaryKey?: boolean;
38
+ indexNulls?: boolean;
39
+ };
40
+ export declare function whereToConditions(predicate: ExprNode | undefined, attributes?: IndexedAttribute[]): ConvertResult;
41
+ /**
42
+ * Whether a condition can be pushed into Table.search at all: every attribute it
43
+ * references must be indexed, because search runs searchByIndex per condition and
44
+ * throws on an unindexed attribute. Comparator-agnostic — a full-scan comparator
45
+ * on an indexed attribute is still pushable (it becomes a filter once another
46
+ * condition drives the index). Null-valued conditions (IS [NOT] NULL and the
47
+ * `!=`/NOT IN not-null guards) are pushable only when the index actually indexes
48
+ * nulls — search throws "not indexed for nulls" otherwise (F-145), even when a
49
+ * different condition drives the scan. Unpushable conditions become a residual
50
+ * Filter (the expression evaluator's three-valued logic keeps NULL exclusion
51
+ * correct on the residual path).
52
+ */
53
+ export declare function conditionIsPushable(cond: ConditionNode, attributes: IndexedAttribute[] | undefined): boolean;
54
+ /**
55
+ * Whether a condition can *drive* an index scan (seek/range), and therefore make
56
+ * the scan valid without a full-table traversal. Stricter than pushability:
57
+ * excludes full-scan comparators and unseekable inequalities. Shared with the R8
58
+ * validateScannable rule so scannability and pushdown decisions can't drift.
59
+ */
60
+ export declare function conditionUsesIndex(cond: ConditionNode, attributes: IndexedAttribute[] | undefined): boolean;
61
+ /**
62
+ * Whether a pushed sort can itself drive an index-ordered scan: its primary key
63
+ * is a single column on the table's PRIMARY KEY. Table.search aligns such a sort
64
+ * to the index's natural order (resources/Table.ts — it adds a `comparator:
65
+ * 'sort'` condition), so the rows stream from the index already ordered and a
66
+ * pushed LIMIT early-terminates (O(window)) — no separate in-memory sort. Shared
67
+ * by the R8 validateScannable rule and the physical scan builder so scannability
68
+ * and the `allowFullScan` flag can't drift. NOTE: because Table.search flags the
69
+ * sort scan as `needFullScan`, the physical scan must pass `allowFullScan: true`
70
+ * for it — see physicalIndexScan.
71
+ *
72
+ * Restricted to the PRIMARY KEY, because only there does index order provably
73
+ * equal legacy's full-scan-then-stable-sort order. A non-PK secondary index
74
+ * diverges from legacy in two ways (D-219): (1) a DESC sort reverses the whole
75
+ * composite `[value, primaryKey]` entry, so rows tying on `value` come back in
76
+ * primary-key-DESC order, whereas legacy's stable sort preserves primary-key-ASC
77
+ * order for ties; and (2) the secondary index omits rows whose sort attribute is
78
+ * null (they were never indexed), whereas a legacy full scan includes them. The
79
+ * PK is unique (no ties) and always present (no null keys), so its ordered scan
80
+ * matches legacy in both directions. Secondary-index sort streaming can be a
81
+ * follow-up once those two divergences are handled.
82
+ */
83
+ export declare function sortDrivesIndex(pushedSort: {
84
+ expr: ExprNode;
85
+ }[] | undefined, attributes: IndexedAttribute[] | undefined): boolean;