@quereus/quereus 0.5.1 → 0.6.0

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 (221) hide show
  1. package/README.md +5 -1
  2. package/dist/src/common/datatype.d.ts +4 -5
  3. package/dist/src/common/datatype.d.ts.map +1 -1
  4. package/dist/src/common/datatype.js.map +1 -1
  5. package/dist/src/common/type-inference.d.ts +3 -6
  6. package/dist/src/common/type-inference.d.ts.map +1 -1
  7. package/dist/src/common/type-inference.js +17 -22
  8. package/dist/src/common/type-inference.js.map +1 -1
  9. package/dist/src/core/param.d.ts.map +1 -1
  10. package/dist/src/core/param.js +3 -18
  11. package/dist/src/core/param.js.map +1 -1
  12. package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
  13. package/dist/src/func/builtins/aggregate.js +24 -2
  14. package/dist/src/func/builtins/aggregate.js.map +1 -1
  15. package/dist/src/func/builtins/builtin-window-functions.js +10 -10
  16. package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
  17. package/dist/src/func/builtins/conversion.d.ts +10 -0
  18. package/dist/src/func/builtins/conversion.d.ts.map +1 -1
  19. package/dist/src/func/builtins/conversion.js +20 -1
  20. package/dist/src/func/builtins/conversion.js.map +1 -1
  21. package/dist/src/func/builtins/explain.js +53 -53
  22. package/dist/src/func/builtins/explain.js.map +1 -1
  23. package/dist/src/func/builtins/generation.js +2 -2
  24. package/dist/src/func/builtins/generation.js.map +1 -1
  25. package/dist/src/func/builtins/index.d.ts.map +1 -1
  26. package/dist/src/func/builtins/index.js +16 -1
  27. package/dist/src/func/builtins/index.js.map +1 -1
  28. package/dist/src/func/builtins/json-tvf.js +17 -17
  29. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  30. package/dist/src/func/builtins/scalar.d.ts.map +1 -1
  31. package/dist/src/func/builtins/scalar.js +202 -13
  32. package/dist/src/func/builtins/scalar.js.map +1 -1
  33. package/dist/src/func/builtins/schema.js +18 -18
  34. package/dist/src/func/builtins/schema.js.map +1 -1
  35. package/dist/src/func/builtins/string.d.ts.map +1 -1
  36. package/dist/src/func/builtins/string.js +56 -47
  37. package/dist/src/func/builtins/string.js.map +1 -1
  38. package/dist/src/func/builtins/timespan.d.ts +45 -0
  39. package/dist/src/func/builtins/timespan.d.ts.map +1 -0
  40. package/dist/src/func/builtins/timespan.js +147 -0
  41. package/dist/src/func/builtins/timespan.js.map +1 -0
  42. package/dist/src/func/registration.d.ts +26 -0
  43. package/dist/src/func/registration.d.ts.map +1 -1
  44. package/dist/src/func/registration.js +9 -5
  45. package/dist/src/func/registration.js.map +1 -1
  46. package/dist/src/index.d.ts +1 -1
  47. package/dist/src/index.d.ts.map +1 -1
  48. package/dist/src/index.js +1 -1
  49. package/dist/src/index.js.map +1 -1
  50. package/dist/src/parser/parser.js +2 -2
  51. package/dist/src/parser/parser.js.map +1 -1
  52. package/dist/src/planner/building/constraint-builder.js +2 -2
  53. package/dist/src/planner/building/constraint-builder.js.map +1 -1
  54. package/dist/src/planner/building/delete.js +3 -3
  55. package/dist/src/planner/building/delete.js.map +1 -1
  56. package/dist/src/planner/building/function-call.d.ts.map +1 -1
  57. package/dist/src/planner/building/function-call.js +24 -4
  58. package/dist/src/planner/building/function-call.js.map +1 -1
  59. package/dist/src/planner/building/insert.js +3 -3
  60. package/dist/src/planner/building/insert.js.map +1 -1
  61. package/dist/src/planner/building/select.d.ts.map +1 -1
  62. package/dist/src/planner/building/select.js +3 -2
  63. package/dist/src/planner/building/select.js.map +1 -1
  64. package/dist/src/planner/building/update.js +7 -7
  65. package/dist/src/planner/building/update.js.map +1 -1
  66. package/dist/src/planner/nodes/aggregate-function.d.ts +2 -1
  67. package/dist/src/planner/nodes/aggregate-function.d.ts.map +1 -1
  68. package/dist/src/planner/nodes/aggregate-function.js +10 -3
  69. package/dist/src/planner/nodes/aggregate-function.js.map +1 -1
  70. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
  71. package/dist/src/planner/nodes/cte-node.js +2 -2
  72. package/dist/src/planner/nodes/cte-node.js.map +1 -1
  73. package/dist/src/planner/nodes/declarative-schema.js +3 -3
  74. package/dist/src/planner/nodes/declarative-schema.js.map +1 -1
  75. package/dist/src/planner/nodes/function.d.ts +2 -1
  76. package/dist/src/planner/nodes/function.d.ts.map +1 -1
  77. package/dist/src/planner/nodes/function.js +6 -3
  78. package/dist/src/planner/nodes/function.js.map +1 -1
  79. package/dist/src/planner/nodes/insert-node.js +1 -1
  80. package/dist/src/planner/nodes/insert-node.js.map +1 -1
  81. package/dist/src/planner/nodes/pragma.d.ts +1 -1
  82. package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
  83. package/dist/src/planner/nodes/pragma.js +3 -3
  84. package/dist/src/planner/nodes/pragma.js.map +1 -1
  85. package/dist/src/planner/nodes/reference.js +1 -1
  86. package/dist/src/planner/nodes/reference.js.map +1 -1
  87. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  88. package/dist/src/planner/nodes/scalar.js +55 -101
  89. package/dist/src/planner/nodes/scalar.js.map +1 -1
  90. package/dist/src/planner/nodes/sequencing-node.js +2 -2
  91. package/dist/src/planner/nodes/sequencing-node.js.map +1 -1
  92. package/dist/src/planner/nodes/sink-node.js +2 -2
  93. package/dist/src/planner/nodes/sink-node.js.map +1 -1
  94. package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
  95. package/dist/src/planner/nodes/subquery.js +4 -7
  96. package/dist/src/planner/nodes/subquery.js.map +1 -1
  97. package/dist/src/planner/nodes/view-reference-node.d.ts.map +1 -1
  98. package/dist/src/planner/nodes/view-reference-node.js +2 -2
  99. package/dist/src/planner/nodes/view-reference-node.js.map +1 -1
  100. package/dist/src/planner/nodes/window-function.js +3 -3
  101. package/dist/src/planner/nodes/window-function.js.map +1 -1
  102. package/dist/src/planner/rules/access/rule-select-access-path.js +1 -1
  103. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  104. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +1 -1
  105. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  106. package/dist/src/planner/scopes/global.js +3 -3
  107. package/dist/src/planner/scopes/global.js.map +1 -1
  108. package/dist/src/planner/scopes/param.d.ts.map +1 -1
  109. package/dist/src/planner/scopes/param.js +2 -2
  110. package/dist/src/planner/scopes/param.js.map +1 -1
  111. package/dist/src/planner/type-utils.d.ts +2 -12
  112. package/dist/src/planner/type-utils.d.ts.map +1 -1
  113. package/dist/src/planner/type-utils.js +6 -21
  114. package/dist/src/planner/type-utils.js.map +1 -1
  115. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  116. package/dist/src/runtime/emit/binary.js +40 -2
  117. package/dist/src/runtime/emit/binary.js.map +1 -1
  118. package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
  119. package/dist/src/runtime/emit/set-operation.js +33 -22
  120. package/dist/src/runtime/emit/set-operation.js.map +1 -1
  121. package/dist/src/runtime/emit/temporal-arithmetic.d.ts +33 -0
  122. package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -0
  123. package/dist/src/runtime/emit/temporal-arithmetic.js +269 -0
  124. package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -0
  125. package/dist/src/runtime/emit/unary.d.ts.map +1 -1
  126. package/dist/src/runtime/emit/unary.js +12 -0
  127. package/dist/src/runtime/emit/unary.js.map +1 -1
  128. package/dist/src/schema/catalog.js +3 -3
  129. package/dist/src/schema/catalog.js.map +1 -1
  130. package/dist/src/schema/column.d.ts +0 -3
  131. package/dist/src/schema/column.d.ts.map +1 -1
  132. package/dist/src/schema/column.js +0 -2
  133. package/dist/src/schema/column.js.map +1 -1
  134. package/dist/src/schema/function.d.ts +29 -1
  135. package/dist/src/schema/function.d.ts.map +1 -1
  136. package/dist/src/schema/function.js.map +1 -1
  137. package/dist/src/schema/table.d.ts +3 -3
  138. package/dist/src/schema/table.d.ts.map +1 -1
  139. package/dist/src/schema/table.js +4 -6
  140. package/dist/src/schema/table.js.map +1 -1
  141. package/dist/src/types/index.d.ts +1 -1
  142. package/dist/src/types/index.d.ts.map +1 -1
  143. package/dist/src/types/index.js +1 -1
  144. package/dist/src/types/index.js.map +1 -1
  145. package/dist/src/types/registry.d.ts.map +1 -1
  146. package/dist/src/types/registry.js +5 -1
  147. package/dist/src/types/registry.js.map +1 -1
  148. package/dist/src/types/temporal-types.d.ts +5 -0
  149. package/dist/src/types/temporal-types.d.ts.map +1 -1
  150. package/dist/src/types/temporal-types.js +122 -0
  151. package/dist/src/types/temporal-types.js.map +1 -1
  152. package/dist/src/util/ast-stringify.js +1 -1
  153. package/dist/src/util/ast-stringify.js.map +1 -1
  154. package/dist/src/util/plan-formatter.d.ts.map +1 -1
  155. package/dist/src/util/plan-formatter.js +1 -5
  156. package/dist/src/util/plan-formatter.js.map +1 -1
  157. package/dist/src/util/row-descriptor.js +2 -2
  158. package/dist/src/util/row-descriptor.js.map +1 -1
  159. package/dist/src/vtab/best-access-plan.d.ts +4 -3
  160. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  161. package/dist/src/vtab/best-access-plan.js.map +1 -1
  162. package/dist/src/vtab/memory/module.js +1 -1
  163. package/dist/src/vtab/memory/module.js.map +1 -1
  164. package/package.json +1 -1
  165. package/src/common/datatype.ts +4 -5
  166. package/src/common/type-inference.ts +13 -22
  167. package/src/core/param.ts +4 -11
  168. package/src/func/builtins/aggregate.ts +24 -2
  169. package/src/func/builtins/builtin-window-functions.ts +10 -10
  170. package/src/func/builtins/conversion.ts +26 -1
  171. package/src/func/builtins/explain.ts +53 -53
  172. package/src/func/builtins/generation.ts +2 -2
  173. package/src/func/builtins/index.ts +20 -1
  174. package/src/func/builtins/json-tvf.ts +17 -17
  175. package/src/func/builtins/scalar.ts +205 -14
  176. package/src/func/builtins/schema.ts +18 -18
  177. package/src/func/builtins/string.ts +91 -78
  178. package/src/func/builtins/timespan.ts +179 -0
  179. package/src/func/registration.ts +35 -5
  180. package/src/index.ts +2 -1
  181. package/src/parser/parser.ts +2 -2
  182. package/src/planner/building/constraint-builder.ts +2 -2
  183. package/src/planner/building/delete.ts +3 -3
  184. package/src/planner/building/function-call.ts +44 -3
  185. package/src/planner/building/insert.ts +3 -3
  186. package/src/planner/building/select.ts +3 -2
  187. package/src/planner/building/update.ts +7 -7
  188. package/src/planner/nodes/aggregate-function.ts +13 -3
  189. package/src/planner/nodes/cte-node.ts +2 -2
  190. package/src/planner/nodes/declarative-schema.ts +3 -3
  191. package/src/planner/nodes/function.ts +8 -3
  192. package/src/planner/nodes/insert-node.ts +1 -1
  193. package/src/planner/nodes/pragma.ts +4 -3
  194. package/src/planner/nodes/reference.ts +1 -1
  195. package/src/planner/nodes/scalar.ts +54 -102
  196. package/src/planner/nodes/sequencing-node.ts +2 -2
  197. package/src/planner/nodes/sink-node.ts +2 -2
  198. package/src/planner/nodes/subquery.ts +5 -7
  199. package/src/planner/nodes/view-reference-node.ts +2 -2
  200. package/src/planner/nodes/window-function.ts +3 -3
  201. package/src/planner/rules/access/rule-select-access-path.ts +1 -1
  202. package/src/planner/rules/retrieve/rule-grow-retrieve.ts +1 -1
  203. package/src/planner/scopes/global.ts +3 -3
  204. package/src/planner/scopes/param.ts +2 -2
  205. package/src/planner/type-utils.ts +6 -14
  206. package/src/runtime/emit/binary.ts +48 -2
  207. package/src/runtime/emit/set-operation.ts +52 -22
  208. package/src/runtime/emit/temporal-arithmetic.ts +302 -0
  209. package/src/runtime/emit/unary.ts +13 -0
  210. package/src/schema/catalog.ts +3 -3
  211. package/src/schema/column.ts +0 -3
  212. package/src/schema/function.ts +29 -1
  213. package/src/schema/table.ts +5 -7
  214. package/src/types/index.ts +1 -1
  215. package/src/types/registry.ts +5 -1
  216. package/src/types/temporal-types.ts +123 -0
  217. package/src/util/ast-stringify.ts +1 -1
  218. package/src/util/plan-formatter.ts +1 -4
  219. package/src/util/row-descriptor.ts +2 -2
  220. package/src/vtab/best-access-plan.ts +4 -3
  221. package/src/vtab/memory/module.ts +1 -1
@@ -1,13 +1,14 @@
1
1
  import { PlanNode, type ScalarPlanNode } from "./plan-node.js";
2
2
  import type { ScalarType } from "../../common/datatype.js";
3
3
  import type { RelationalPlanNode } from "./plan-node.js";
4
- import { type CompareFn, SqlDataType } from "../../common/types.js";
4
+ import { type CompareFn } from "../../common/types.js";
5
5
  import { PlanNodeType } from "./plan-node-type.js";
6
6
  import type { Scope } from "../scopes/scope.js";
7
7
  import { compareSqlValues } from "../../util/comparison.js";
8
8
  import type { Expression } from "../../parser/ast.js";
9
9
  import { formatExpression, formatScalarType } from "../../util/plan-formatter.js";
10
10
  import { quereusError } from "../../common/errors.js";
11
+ import { BLOB_TYPE, INTEGER_TYPE } from "../../types/builtin-types.js";
11
12
  import { StatusCode } from "../../common/types.js";
12
13
 
13
14
  export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
@@ -31,10 +32,9 @@ export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
31
32
  // Fallback to nullable BLOB if we can't determine type
32
33
  return {
33
34
  typeClass: 'scalar',
34
- affinity: SqlDataType.BLOB,
35
+ logicalType: BLOB_TYPE,
35
36
  nullable: true,
36
37
  isReadOnly: true,
37
- datatype: SqlDataType.BLOB,
38
38
  };
39
39
  }
40
40
 
@@ -103,10 +103,9 @@ export class InNode extends PlanNode implements ScalarPlanNode {
103
103
  getType(): ScalarType {
104
104
  return {
105
105
  typeClass: 'scalar',
106
- affinity: SqlDataType.INTEGER,
106
+ logicalType: INTEGER_TYPE,
107
107
  nullable: false,
108
108
  isReadOnly: true,
109
- datatype: SqlDataType.INTEGER,
110
109
  }
111
110
  }
112
111
 
@@ -216,10 +215,9 @@ export class ExistsNode extends PlanNode implements ScalarPlanNode {
216
215
  getType(): ScalarType {
217
216
  return {
218
217
  typeClass: 'scalar',
219
- affinity: SqlDataType.INTEGER,
218
+ logicalType: INTEGER_TYPE,
220
219
  nullable: false,
221
220
  isReadOnly: true,
222
- datatype: SqlDataType.INTEGER,
223
221
  };
224
222
  }
225
223
 
@@ -1,10 +1,10 @@
1
1
  import { PlanNode, type ZeroAryRelationalNode, type Attribute } from './plan-node.js';
2
2
  import type { RelationType } from '../../common/datatype.js';
3
- import { SqlDataType } from '../../common/types.js';
4
3
  import { PlanNodeType } from './plan-node-type.js';
5
4
  import type { Scope } from '../scopes/scope.js';
6
5
  import type { ViewSchema } from '../../schema/view.js';
7
6
  import { Cached } from '../../util/cached.js';
7
+ import { TEXT_TYPE } from '../../types/builtin-types.js';
8
8
 
9
9
  /**
10
10
  * Plan node for referencing a view in a FROM clause.
@@ -36,7 +36,7 @@ export class ViewReferenceNode extends PlanNode implements ZeroAryRelationalNode
36
36
  name: columnName,
37
37
  type: {
38
38
  typeClass: 'scalar' as const,
39
- affinity: SqlDataType.TEXT,
39
+ logicalType: TEXT_TYPE,
40
40
  nullable: true,
41
41
  isReadOnly: false
42
42
  }, // Default type, should be inferred
@@ -4,8 +4,8 @@ import type { ScalarType } from '../../common/datatype.js';
4
4
  import type { Scope } from '../scopes/scope.js';
5
5
  import type { WindowFunctionExpr } from '../../parser/ast.js';
6
6
  import { Cached } from '../../util/cached.js';
7
- import { SqlDataType } from '../../common/types.js';
8
7
  import { formatScalarType } from '../../util/plan-formatter.js';
8
+ import { INTEGER_TYPE, REAL_TYPE } from '../../types/builtin-types.js';
9
9
 
10
10
  /**
11
11
  * Represents a window function call in the query plan.
@@ -30,10 +30,10 @@ export class WindowFunctionCallNode extends PlanNode implements ZeroAryScalarNod
30
30
  // Most window functions return numeric types
31
31
  // row_number() specifically returns an integer
32
32
  if (this.functionName === 'row_number') {
33
- return { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false } satisfies ScalarType;
33
+ return { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false } satisfies ScalarType;
34
34
  }
35
35
  // Other window functions would have their own type inference
36
- return { typeClass: 'scalar', affinity: SqlDataType.NUMERIC, nullable: false } satisfies ScalarType;
36
+ return { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: false } satisfies ScalarType;
37
37
  });
38
38
  }
39
39
 
@@ -120,7 +120,7 @@ function createIndexBasedAccess(retrieveNode: RetrieveNode, context: OptContext)
120
120
  columns: tableSchema.columns.map((col, index) => ({
121
121
  index,
122
122
  name: col.name,
123
- type: col.affinity,
123
+ type: col.logicalType,
124
124
  isPrimaryKey: col.primaryKey || false,
125
125
  isUnique: col.primaryKey || false // For now, assume only PK columns are unique
126
126
  } as ColumnMeta)),
@@ -231,7 +231,7 @@ function fallbackIndexSupports(
231
231
  columns: tableSchema.columns.map((col, index) => ({
232
232
  index,
233
233
  name: col.name,
234
- type: col.affinity,
234
+ type: col.logicalType,
235
235
  isPrimaryKey: col.primaryKey || false,
236
236
  isUnique: col.primaryKey || false
237
237
  })),
@@ -5,8 +5,8 @@ import * as AST from "../../parser/ast.js";
5
5
  import { FunctionReferenceNode, TableReferenceNode } from "../nodes/reference.js";
6
6
  import { Ambiguous } from "./scope.js";
7
7
  import type { ScalarType } from "../../common/datatype.js";
8
- import { SqlDataType } from "../../common/types.js";
9
8
  import { isScalarFunctionSchema } from "../../schema/function.js";
9
+ import { REAL_TYPE } from "../../types/builtin-types.js";
10
10
 
11
11
  export class GlobalScope extends BaseScope {
12
12
  constructor(public readonly manager: SchemaManager) {
@@ -25,7 +25,7 @@ export class GlobalScope extends BaseScope {
25
25
  // Get the proper scalar type from the function schema
26
26
  const scalarType: ScalarType = isScalarFunctionSchema(func)
27
27
  ? func.returnType
28
- : { typeClass: 'scalar', affinity: SqlDataType.NUMERIC, nullable: true, isReadOnly: true };
28
+ : { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true };
29
29
 
30
30
  return new FunctionReferenceNode(this, func, scalarType);
31
31
  }
@@ -54,7 +54,7 @@ export class GlobalScope extends BaseScope {
54
54
  // Get the proper scalar type from the function schema
55
55
  const scalarType: ScalarType = isScalarFunctionSchema(func)
56
56
  ? func.returnType
57
- : { typeClass: 'scalar', affinity: SqlDataType.NUMERIC, nullable: true, isReadOnly: true };
57
+ : { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true };
58
58
 
59
59
  return new FunctionReferenceNode(this, func, scalarType);
60
60
  }
@@ -3,13 +3,13 @@ import { ParameterReferenceNode } from '../nodes/reference.js'; // Corrected imp
3
3
  import { BaseScope } from './base.js';
4
4
  import { Ambiguous, type Scope } from './scope.js';
5
5
  import type { ScalarType } from '../../common/datatype.js';
6
- import { SqlDataType } from '../../common/types.js';
7
6
  import type { PlanNode } from '../nodes/plan-node.js';
7
+ import { TEXT_TYPE } from '../../types/builtin-types.js';
8
8
 
9
9
  // Default type for parameters when not otherwise specified.
10
10
  const DEFAULT_PARAMETER_TYPE: ScalarType = {
11
11
  typeClass: 'scalar',
12
- affinity: SqlDataType.TEXT,
12
+ logicalType: TEXT_TYPE,
13
13
  nullable: true,
14
14
  };
15
15
 
@@ -4,8 +4,7 @@ import type { RelationType, ColumnDef, ScalarType, ColRef } from '../common/data
4
4
  import { SqlDataType, StatusCode, type DeepReadonly, type SqlValue } from '../common/types.js'; // Import SqlValue and ensure SqlDataType is not type-only
5
5
  import type { AstNode } from '../parser/ast.js';
6
6
  import { QuereusError } from '../common/errors.js';
7
- // Note: getAffinity from '../schema/column.js' is used by the ColumnSchema type from table.js itself if that's what we use.
8
- // If tableSchema.columns are of type from '../schema/column.js', then their affinity is already SqlDataType.
7
+ import { inferLogicalTypeFromValue } from '../common/type-inference.js';
9
8
 
10
9
  /**
11
10
  * Converts a TableSchema (from src/schema/table.ts) to a RelationType (from src/common/datatype.ts).
@@ -17,7 +16,7 @@ export function relationTypeFromTableSchema(tableSchema: TableSchema): RelationT
17
16
  name: col.name,
18
17
  type: {
19
18
  typeClass: 'scalar',
20
- affinity: col.affinity,
19
+ logicalType: col.logicalType,
21
20
  collationName: col.collation,
22
21
  nullable: !col.notNull,
23
22
  isReadOnly: false,
@@ -53,18 +52,11 @@ export function relationTypeFromTableSchema(tableSchema: TableSchema): RelationT
53
52
  * @returns A ScalarType representing the inferred type of the value.
54
53
  */
55
54
  export function getParameterScalarType(value: SqlValue): ScalarType {
56
- let affinity: SqlDataType;
57
- if (value === null) affinity = SqlDataType.NULL;
58
- else if (typeof value === 'number') affinity = SqlDataType.REAL;
59
- else if (typeof value === 'bigint') affinity = SqlDataType.INTEGER;
60
- else if (typeof value === 'string') affinity = SqlDataType.TEXT;
61
- else if (value instanceof Uint8Array) affinity = SqlDataType.BLOB;
62
- else if (typeof value === 'boolean') affinity = SqlDataType.INTEGER; // Store booleans as INTEGER
63
- else affinity = SqlDataType.BLOB; // Default for unknown types that might pass as SqlValue
55
+ const logicalType = inferLogicalTypeFromValue(value);
64
56
 
65
57
  return {
66
58
  typeClass: 'scalar',
67
- affinity: affinity,
59
+ logicalType,
68
60
  nullable: true, // No guarantees about the value, so it's nullable
69
61
  isReadOnly: true, // Parameters are read-only within the query execution context
70
62
  };
@@ -80,12 +72,12 @@ export function checkRelationsAssignable(source: RelationType, target: RelationT
80
72
  return checkColumnsAssignable(source.columns, target.columns, astNode);
81
73
  }
82
74
 
83
- export function columnSchemaToDef(colName: string, colDef: ColumnSchema): { name: string; type: { typeClass: "scalar"; affinity: SqlDataType; collationName: string; nullable: boolean; isReadOnly: false; }; generated: boolean; } {
75
+ export function columnSchemaToDef(colName: string, colDef: ColumnSchema): ColumnDef {
84
76
  return {
85
77
  name: colName,
86
78
  type: {
87
79
  typeClass: 'scalar',
88
- affinity: colDef.affinity,
80
+ logicalType: colDef.logicalType,
89
81
  collationName: colDef.collation,
90
82
  nullable: !colDef.notNull,
91
83
  isReadOnly: false,
@@ -8,6 +8,7 @@ import { compareSqlValuesFast, resolveCollation } from "../../util/comparison.js
8
8
  import { coerceForComparison, coerceToNumberForArithmetic } from "../../util/coercion.js";
9
9
  import { simpleLike } from "../../util/patterns.js";
10
10
  import type { EmissionContext } from "../emission-context.js";
11
+ import { tryTemporalArithmetic, tryTemporalComparison } from "./temporal-arithmetic.js";
11
12
 
12
13
  export function emitBinaryOp(plan: BinaryOpNode, ctx: EmissionContext): Instruction {
13
14
  // Normalize operator to uppercase for case-insensitive matching of keywords
@@ -73,6 +74,13 @@ export function emitNumericOp(plan: BinaryOpNode, ctx: EmissionContext): Instruc
73
74
  }
74
75
 
75
76
  function run(ctx: RuntimeContext, v1: SqlValue, v2: SqlValue): SqlValue {
77
+ // Try temporal arithmetic first
78
+ const temporalResult = tryTemporalArithmetic(plan.expression.operator, v1, v2);
79
+ if (temporalResult !== undefined) {
80
+ return temporalResult;
81
+ }
82
+
83
+ // Fall back to numeric arithmetic
76
84
  if (v1 !== null && v2 !== null) {
77
85
  if (typeof v1 === 'bigint' || typeof v2 === 'bigint') {
78
86
  try {
@@ -127,13 +135,21 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
127
135
  // Pre-resolve collation function for optimal performance
128
136
  const collationFunc = resolveCollation(collationName);
129
137
 
130
- switch (plan.expression.operator) {
138
+ const operator = plan.expression.operator;
139
+
140
+ switch (operator) {
131
141
  case '=':
132
142
  case '==':
133
143
  run = (ctx: RuntimeContext, v1: SqlValue, v2: SqlValue): SqlValue => {
134
144
  // SQL comparison: NULL = anything -> NULL
135
145
  if (v1 === null || v2 === null) return null;
136
146
 
147
+ // Try temporal comparison first
148
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
149
+ if (temporalResult !== undefined) {
150
+ return temporalResult;
151
+ }
152
+
137
153
  // Apply type coercion before comparison
138
154
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
139
155
  return compareSqlValuesFast(coercedV1, coercedV2, collationFunc) === 0 ? 1 : 0;
@@ -145,6 +161,12 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
145
161
  // SQL comparison: NULL != anything -> NULL
146
162
  if (v1 === null || v2 === null) return null;
147
163
 
164
+ // Try temporal comparison first
165
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
166
+ if (temporalResult !== undefined) {
167
+ return temporalResult;
168
+ }
169
+
148
170
  // Apply type coercion before comparison
149
171
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
150
172
  return compareSqlValuesFast(coercedV1, coercedV2, collationFunc) !== 0 ? 1 : 0;
@@ -155,6 +177,12 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
155
177
  // SQL comparison: NULL < anything -> NULL
156
178
  if (v1 === null || v2 === null) return null;
157
179
 
180
+ // Try temporal comparison first
181
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
182
+ if (temporalResult !== undefined) {
183
+ return temporalResult;
184
+ }
185
+
158
186
  // Apply type coercion before comparison
159
187
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
160
188
  return compareSqlValuesFast(coercedV1, coercedV2, collationFunc) < 0 ? 1 : 0;
@@ -165,6 +193,12 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
165
193
  // SQL comparison: NULL <= anything -> NULL
166
194
  if (v1 === null || v2 === null) return null;
167
195
 
196
+ // Try temporal comparison first
197
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
198
+ if (temporalResult !== undefined) {
199
+ return temporalResult;
200
+ }
201
+
168
202
  // Apply type coercion before comparison
169
203
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
170
204
  return compareSqlValuesFast(coercedV1, coercedV2, collationFunc) <= 0 ? 1 : 0;
@@ -177,6 +211,12 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
177
211
  return null;
178
212
  }
179
213
 
214
+ // Try temporal comparison first
215
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
216
+ if (temporalResult !== undefined) {
217
+ return temporalResult;
218
+ }
219
+
180
220
  // Apply type coercion before comparison
181
221
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
182
222
  const comparisonResult = compareSqlValuesFast(coercedV1, coercedV2, collationFunc);
@@ -189,13 +229,19 @@ export function emitComparisonOp(plan: BinaryOpNode, ctx: EmissionContext): Inst
189
229
  // SQL comparison: NULL >= anything -> NULL
190
230
  if (v1 === null || v2 === null) return null;
191
231
 
232
+ // Try temporal comparison first
233
+ const temporalResult = tryTemporalComparison(operator, v1, v2);
234
+ if (temporalResult !== undefined) {
235
+ return temporalResult;
236
+ }
237
+
192
238
  // Apply type coercion before comparison
193
239
  const [coercedV1, coercedV2] = coerceForComparison(v1, v2);
194
240
  return compareSqlValuesFast(coercedV1, coercedV2, collationFunc) >= 0 ? 1 : 0;
195
241
  };
196
242
  break;
197
243
  default:
198
- throw new QuereusError(`Unsupported comparison operator: ${plan.expression.operator}`, StatusCode.UNSUPPORTED);
244
+ throw new QuereusError(`Unsupported comparison operator: ${operator}`, StatusCode.UNSUPPORTED);
199
245
  }
200
246
 
201
247
  const leftExpr = emitPlanNode(plan.left, ctx);
@@ -3,6 +3,8 @@ import type { Instruction, RuntimeContext, InstructionRun } from '../types.js';
3
3
  import type { EmissionContext } from '../emission-context.js';
4
4
  import { emitPlanNode } from '../emitters.js';
5
5
  import type { Row } from '../../common/types.js';
6
+ import { BTree } from 'inheritree';
7
+ import { compareRows } from '../../util/comparison.js';
6
8
 
7
9
  export function emitSetOperation(plan: SetOperationNode, ctx: EmissionContext): Instruction {
8
10
  const leftInst = emitPlanNode(plan.left, ctx);
@@ -30,58 +32,86 @@ export function emitSetOperation(plan: SetOperationNode, ctx: EmissionContext):
30
32
  }
31
33
 
32
34
  async function* runUnionDistinct(rctx: RuntimeContext, leftRows: AsyncIterable<Row>, rightRows: AsyncIterable<Row>): AsyncIterable<Row> {
33
- const seen = new Set<string>();
34
- const hash = (row: Row) => JSON.stringify(row);
35
+ // Use BTree for proper SQL value comparison instead of JSON.stringify
36
+ const distinctTree = new BTree<Row, Row>(
37
+ (row: Row) => row,
38
+ compareRows
39
+ );
40
+
35
41
  for await (const row of leftRows) {
36
42
  const outputRow = createOutputRow(row);
37
- const h = hash(outputRow);
38
- if (!seen.has(h)) {
39
- seen.add(h);
43
+ const newPath = distinctTree.insert(outputRow);
44
+ if (newPath.on) {
45
+ // This is a new distinct row
40
46
  yield outputRow; // Let SortNode handle row context
41
47
  }
42
48
  }
43
49
  for await (const row of rightRows) {
44
50
  const outputRow = createOutputRow(row);
45
- const h = hash(outputRow);
46
- if (!seen.has(h)) {
47
- seen.add(h);
51
+ const newPath = distinctTree.insert(outputRow);
52
+ if (newPath.on) {
53
+ // This is a new distinct row
48
54
  yield outputRow; // Let SortNode handle row context
49
55
  }
50
56
  }
51
57
  }
52
58
 
53
59
  async function* runIntersect(rctx: RuntimeContext, leftRows: AsyncIterable<Row>, rightRows: AsyncIterable<Row>): AsyncIterable<Row> {
54
- const leftSet = new Set<string>();
55
- const hash = (row: Row) => JSON.stringify(row);
56
- const leftRowsArray: Row[] = [];
60
+ // Use BTree for proper SQL value comparison
61
+ const leftTree = new BTree<Row, Row>(
62
+ (row: Row) => row,
63
+ compareRows
64
+ );
65
+
66
+ // Build left set
57
67
  for await (const row of leftRows) {
58
68
  const outputRow = createOutputRow(row);
59
- leftSet.add(hash(outputRow));
60
- leftRowsArray.push(outputRow);
69
+ leftTree.insert(outputRow);
61
70
  }
71
+
72
+ // Check right rows against left set
73
+ const yielded = new BTree<Row, Row>(
74
+ (row: Row) => row,
75
+ compareRows
76
+ );
77
+
62
78
  for await (const row of rightRows) {
63
79
  const outputRow = createOutputRow(row);
64
- const h = hash(outputRow);
65
- if (leftSet.has(h)) {
66
- yield outputRow; // Let SortNode handle row context
67
- leftSet.delete(h);
80
+ const leftPath = leftTree.find(outputRow);
81
+ if (leftPath.on) {
82
+ // This row exists in left set - yield the LEFT row to preserve left-side types
83
+ const leftRow = leftTree.get(outputRow)!;
84
+ const yieldedPath = yielded.insert(leftRow);
85
+ if (yieldedPath.on) {
86
+ // Haven't yielded this row yet (handles duplicates in right)
87
+ yield leftRow; // Let SortNode handle row context
88
+ }
68
89
  }
69
90
  }
70
91
  }
71
92
 
72
93
  async function* runExcept(rctx: RuntimeContext, leftRows: AsyncIterable<Row>, rightRows: AsyncIterable<Row>): AsyncIterable<Row> {
73
- const rightSet = new Set<string>();
74
- const hash = (row: Row) => JSON.stringify(row);
94
+ // Use BTree for proper SQL value comparison
95
+ const rightTree = new BTree<Row, Row>(
96
+ (row: Row) => row,
97
+ compareRows
98
+ );
75
99
  const leftRowsArray: Row[] = [];
100
+
101
+ // Collect left rows
76
102
  for await (const row of leftRows) {
77
103
  leftRowsArray.push(createOutputRow(row));
78
104
  }
105
+
106
+ // Build right set
79
107
  for await (const row of rightRows) {
80
- rightSet.add(hash(createOutputRow(row)));
108
+ rightTree.insert(createOutputRow(row));
81
109
  }
110
+
111
+ // Yield left rows that are not in right set
82
112
  for (const outputRow of leftRowsArray) {
83
- const h = hash(outputRow);
84
- if (!rightSet.has(h)) {
113
+ const rightPath = rightTree.find(outputRow);
114
+ if (!rightPath.on) {
85
115
  yield outputRow; // Let SortNode handle row context
86
116
  }
87
117
  }