@quereus/quereus 0.5.2 → 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 (214) 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/temporal-arithmetic.d.ts +33 -0
  119. package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -0
  120. package/dist/src/runtime/emit/temporal-arithmetic.js +269 -0
  121. package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -0
  122. package/dist/src/runtime/emit/unary.d.ts.map +1 -1
  123. package/dist/src/runtime/emit/unary.js +12 -0
  124. package/dist/src/runtime/emit/unary.js.map +1 -1
  125. package/dist/src/schema/catalog.js +3 -3
  126. package/dist/src/schema/catalog.js.map +1 -1
  127. package/dist/src/schema/column.d.ts +0 -3
  128. package/dist/src/schema/column.d.ts.map +1 -1
  129. package/dist/src/schema/column.js +0 -2
  130. package/dist/src/schema/column.js.map +1 -1
  131. package/dist/src/schema/function.d.ts +29 -1
  132. package/dist/src/schema/function.d.ts.map +1 -1
  133. package/dist/src/schema/function.js.map +1 -1
  134. package/dist/src/schema/table.d.ts +3 -3
  135. package/dist/src/schema/table.d.ts.map +1 -1
  136. package/dist/src/schema/table.js +4 -6
  137. package/dist/src/schema/table.js.map +1 -1
  138. package/dist/src/types/index.d.ts +1 -1
  139. package/dist/src/types/index.d.ts.map +1 -1
  140. package/dist/src/types/index.js +1 -1
  141. package/dist/src/types/index.js.map +1 -1
  142. package/dist/src/types/registry.d.ts.map +1 -1
  143. package/dist/src/types/registry.js +5 -1
  144. package/dist/src/types/registry.js.map +1 -1
  145. package/dist/src/types/temporal-types.d.ts +5 -0
  146. package/dist/src/types/temporal-types.d.ts.map +1 -1
  147. package/dist/src/types/temporal-types.js +122 -0
  148. package/dist/src/types/temporal-types.js.map +1 -1
  149. package/dist/src/util/plan-formatter.d.ts.map +1 -1
  150. package/dist/src/util/plan-formatter.js +1 -5
  151. package/dist/src/util/plan-formatter.js.map +1 -1
  152. package/dist/src/util/row-descriptor.js +2 -2
  153. package/dist/src/util/row-descriptor.js.map +1 -1
  154. package/dist/src/vtab/best-access-plan.d.ts +4 -3
  155. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  156. package/dist/src/vtab/best-access-plan.js.map +1 -1
  157. package/dist/src/vtab/memory/module.js +1 -1
  158. package/dist/src/vtab/memory/module.js.map +1 -1
  159. package/package.json +1 -1
  160. package/src/common/datatype.ts +4 -5
  161. package/src/common/type-inference.ts +13 -22
  162. package/src/core/param.ts +4 -11
  163. package/src/func/builtins/aggregate.ts +24 -2
  164. package/src/func/builtins/builtin-window-functions.ts +10 -10
  165. package/src/func/builtins/conversion.ts +26 -1
  166. package/src/func/builtins/explain.ts +53 -53
  167. package/src/func/builtins/generation.ts +2 -2
  168. package/src/func/builtins/index.ts +20 -1
  169. package/src/func/builtins/json-tvf.ts +17 -17
  170. package/src/func/builtins/scalar.ts +205 -14
  171. package/src/func/builtins/schema.ts +18 -18
  172. package/src/func/builtins/string.ts +91 -78
  173. package/src/func/builtins/timespan.ts +179 -0
  174. package/src/func/registration.ts +35 -5
  175. package/src/index.ts +2 -1
  176. package/src/parser/parser.ts +2 -2
  177. package/src/planner/building/constraint-builder.ts +2 -2
  178. package/src/planner/building/delete.ts +3 -3
  179. package/src/planner/building/function-call.ts +44 -3
  180. package/src/planner/building/insert.ts +3 -3
  181. package/src/planner/building/select.ts +3 -2
  182. package/src/planner/building/update.ts +7 -7
  183. package/src/planner/nodes/aggregate-function.ts +13 -3
  184. package/src/planner/nodes/cte-node.ts +2 -2
  185. package/src/planner/nodes/declarative-schema.ts +3 -3
  186. package/src/planner/nodes/function.ts +8 -3
  187. package/src/planner/nodes/insert-node.ts +1 -1
  188. package/src/planner/nodes/pragma.ts +4 -3
  189. package/src/planner/nodes/reference.ts +1 -1
  190. package/src/planner/nodes/scalar.ts +54 -102
  191. package/src/planner/nodes/sequencing-node.ts +2 -2
  192. package/src/planner/nodes/sink-node.ts +2 -2
  193. package/src/planner/nodes/subquery.ts +5 -7
  194. package/src/planner/nodes/view-reference-node.ts +2 -2
  195. package/src/planner/nodes/window-function.ts +3 -3
  196. package/src/planner/rules/access/rule-select-access-path.ts +1 -1
  197. package/src/planner/rules/retrieve/rule-grow-retrieve.ts +1 -1
  198. package/src/planner/scopes/global.ts +3 -3
  199. package/src/planner/scopes/param.ts +2 -2
  200. package/src/planner/type-utils.ts +6 -14
  201. package/src/runtime/emit/binary.ts +48 -2
  202. package/src/runtime/emit/temporal-arithmetic.ts +302 -0
  203. package/src/runtime/emit/unary.ts +13 -0
  204. package/src/schema/catalog.ts +3 -3
  205. package/src/schema/column.ts +0 -3
  206. package/src/schema/function.ts +29 -1
  207. package/src/schema/table.ts +5 -7
  208. package/src/types/index.ts +1 -1
  209. package/src/types/registry.ts +5 -1
  210. package/src/types/temporal-types.ts +123 -0
  211. package/src/util/plan-formatter.ts +1 -4
  212. package/src/util/row-descriptor.ts +2 -2
  213. package/src/vtab/best-access-plan.ts +4 -3
  214. package/src/vtab/memory/module.ts +1 -1
@@ -101,7 +101,7 @@ function tableSchemaToCatalog(tableSchema: TableSchema): CatalogTable {
101
101
 
102
102
  const columns = tableSchema.columns.map(col => ({
103
103
  name: col.name,
104
- type: col.affinity?.toString() || 'TEXT',
104
+ type: col.logicalType.name,
105
105
  notNull: col.notNull,
106
106
  primaryKey: col.primaryKey
107
107
  }));
@@ -165,8 +165,8 @@ function generateTableDDL(tableSchema: TableSchema): string {
165
165
  const columnDefs: string[] = [];
166
166
  for (const col of tableSchema.columns) {
167
167
  let colDef = `"${col.name}"`;
168
- if (col.affinity) {
169
- colDef += ` ${col.affinity}`;
168
+ if (col.logicalType) {
169
+ colDef += ` ${col.logicalType.name}`;
170
170
  }
171
171
  if (col.notNull) {
172
172
  colDef += ' NOT NULL';
@@ -10,8 +10,6 @@ export interface ColumnSchema {
10
10
  name: string;
11
11
  /** Logical type definition */
12
12
  logicalType: LogicalType;
13
- /** Data type affinity (TEXT, INTEGER, REAL, BLOB, NUMERIC) - kept for backward compatibility during transition */
14
- affinity: SqlDataType;
15
13
  /** Whether the column has a NOT NULL constraint */
16
14
  notNull: boolean;
17
15
  /** Whether the column is part of the primary key */
@@ -43,7 +41,6 @@ export function createDefaultColumnSchema(name: string, defaultNotNull: boolean
43
41
  return {
44
42
  name: name,
45
43
  logicalType: TEXT_TYPE,
46
- affinity: SqlDataType.TEXT,
47
44
  notNull: defaultNotNull, // Third Manifesto: default to NOT NULL
48
45
  primaryKey: false,
49
46
  pkOrder: 0,
@@ -1,9 +1,10 @@
1
- import type { MaybePromise, Row, SqlValue } from '../common/types.js';
1
+ import type { MaybePromise, Row, SqlValue, DeepReadonly } from '../common/types.js';
2
2
  import { FunctionFlags } from '../common/constants.js';
3
3
  import { SqlDataType } from '../common/types.js';
4
4
  import type { Database } from '../core/database.js';
5
5
  import type { BaseType, ScalarType, RelationType } from '../common/datatype.js';
6
6
  import type { AggValue } from '../func/registration.js';
7
+ import type { LogicalType } from '../types/logical-type.js';
7
8
 
8
9
  /**
9
10
  * Type for a scalar function implementation.
@@ -74,6 +75,21 @@ export interface ScalarFunctionSchema extends BaseFunctionSchema {
74
75
  returnType: ScalarType;
75
76
  /** Direct scalar function implementation */
76
77
  implementation: ScalarFunc;
78
+ /**
79
+ * Optional type inference function for polymorphic functions.
80
+ * If provided, this function will be called at planning time to determine
81
+ * the return type based on the actual argument types.
82
+ * This allows functions like abs() to return INTEGER when given INTEGER,
83
+ * and REAL when given REAL.
84
+ */
85
+ inferReturnType?: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => ScalarType;
86
+ /**
87
+ * Optional argument type validation function.
88
+ * If provided, this function will be called at planning time to validate
89
+ * that the argument types are acceptable for this function.
90
+ * Should return true if types are valid, false otherwise.
91
+ */
92
+ validateArgTypes?: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => boolean;
77
93
  }
78
94
 
79
95
  /**
@@ -98,6 +114,18 @@ export interface AggregateFunctionSchema extends BaseFunctionSchema {
98
114
  finalizeFunction: AggregateFinalizer;
99
115
  /** Initial accumulator value for aggregates */
100
116
  initialValue?: AggValue;
117
+ /**
118
+ * Optional type inference function for polymorphic aggregate functions.
119
+ * If provided, this function will be called at planning time to determine
120
+ * the return type based on the actual argument types.
121
+ */
122
+ inferReturnType?: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => ScalarType;
123
+ /**
124
+ * Optional argument type validation function.
125
+ * If provided, this function will be called at planning time to validate
126
+ * that the argument types are acceptable for this function.
127
+ */
128
+ validateArgTypes?: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => boolean;
101
129
  }
102
130
 
103
131
  /**
@@ -3,7 +3,6 @@ import type { AnyVirtualTableModule } from '../vtab/module.js';
3
3
  import { MemoryTableModule } from '../vtab/memory/module.js';
4
4
  import type { Expression } from '../parser/ast.js';
5
5
  import { type ColumnDef, type TableConstraint } from '../parser/ast.js';
6
- import { getAffinity } from '../common/type-inference.js';
7
6
  import { RowOp, SqlDataType, StatusCode, type SqlValue } from '../common/types.js';
8
7
  import type * as AST from '../parser/ast.js';
9
8
  import { quereusError, QuereusError } from '../common/errors.js';
@@ -99,7 +98,6 @@ export function columnDefToSchema(def: ColumnDef, defaultNotNull: boolean = true
99
98
  const schema: Partial<ColumnSchema> & { name: string } = {
100
99
  name: def.name,
101
100
  logicalType: logicalType,
102
- affinity: getAffinity(def.dataType), // Keep for backward compatibility during transition
103
101
  notNull: defaultNotNull, // Default based on Third Manifesto principles
104
102
  primaryKey: false,
105
103
  pkOrder: 0,
@@ -166,8 +164,8 @@ export function columnDefToSchema(def: ColumnDef, defaultNotNull: boolean = true
166
164
  export interface MutationContextDefinition {
167
165
  /** Variable name */
168
166
  name: string;
169
- /** Type affinity of the variable */
170
- affinity: SqlDataType;
167
+ /** Logical type of the variable */
168
+ logicalType: import('../types/logical-type.js').LogicalType;
171
169
  /** Whether the variable is NOT NULL */
172
170
  notNull: boolean;
173
171
  }
@@ -182,7 +180,7 @@ export interface MutationContextDefinition {
182
180
  export function mutationContextVarToSchema(varDef: AST.MutationContextVar, defaultNotNull: boolean = true): MutationContextDefinition {
183
181
  return {
184
182
  name: varDef.name,
185
- affinity: getAffinity(varDef.dataType),
183
+ logicalType: inferType(varDef.dataType),
186
184
  notNull: varDef.notNull !== undefined ? varDef.notNull : defaultNotNull,
187
185
  };
188
186
  }
@@ -403,8 +401,8 @@ function findColumnPKDefinition(columns: ReadonlyArray<ColumnSchema>): ReadonlyA
403
401
 
404
402
  return Object.freeze(pkCols.map(col => ({
405
403
  index: col.originalIndex,
406
- desc: col.affinity === SqlDataType.INTEGER && col.pkDirection === 'desc',
407
- autoIncrement: col.affinity === SqlDataType.INTEGER,
404
+ desc: col.logicalType.name === 'INTEGER' && col.pkDirection === 'desc',
405
+ autoIncrement: col.logicalType.name === 'INTEGER',
408
406
  collation: col.collation || 'BINARY'
409
407
  })));
410
408
  }
@@ -5,7 +5,7 @@ export { PhysicalType, type LogicalType, getPhysicalType } from './logical-type.
5
5
  export { NULL_TYPE, INTEGER_TYPE, REAL_TYPE, TEXT_TYPE, BLOB_TYPE, BOOLEAN_TYPE, NUMERIC_TYPE, ANY_TYPE } from './builtin-types.js';
6
6
 
7
7
  // Temporal types
8
- export { DATE_TYPE, TIME_TYPE, DATETIME_TYPE } from './temporal-types.js';
8
+ export { DATE_TYPE, TIME_TYPE, DATETIME_TYPE, TIMESPAN_TYPE } from './temporal-types.js';
9
9
 
10
10
  // JSON type
11
11
  export { JSON_TYPE } from './json-type.js';
@@ -9,7 +9,7 @@ import {
9
9
  NUMERIC_TYPE,
10
10
  ANY_TYPE,
11
11
  } from './builtin-types.js';
12
- import { DATE_TYPE, TIME_TYPE, DATETIME_TYPE } from './temporal-types.js';
12
+ import { DATE_TYPE, TIME_TYPE, DATETIME_TYPE, TIMESPAN_TYPE } from './temporal-types.js';
13
13
  import { JSON_TYPE } from './json-type.js';
14
14
  import { createLogger } from '../common/logger.js';
15
15
 
@@ -36,9 +36,13 @@ class TypeRegistry {
36
36
  this.registerType(DATE_TYPE);
37
37
  this.registerType(TIME_TYPE);
38
38
  this.registerType(DATETIME_TYPE);
39
+ this.registerType(TIMESPAN_TYPE);
39
40
  this.registerType(JSON_TYPE);
40
41
 
41
42
  // Register common aliases
43
+ // Temporal type aliases
44
+ this.types.set('INTERVAL', TIMESPAN_TYPE); // SQL standard alias
45
+ this.types.set('DURATION', TIMESPAN_TYPE); // Alternative name
42
46
  this.types.set('INT', INTEGER_TYPE);
43
47
  this.types.set('BIGINT', INTEGER_TYPE);
44
48
  this.types.set('SMALLINT', INTEGER_TYPE);
@@ -165,3 +165,126 @@ export const DATETIME_TYPE: LogicalType = {
165
165
  supportedCollations: [],
166
166
  };
167
167
 
168
+ /**
169
+ * Parse human-readable duration strings into Temporal.Duration
170
+ * Supports formats like "1 hour", "30 minutes", "2 days 3 hours"
171
+ */
172
+ function parseHumanReadableDuration(input: string): Temporal.Duration | null {
173
+ const normalized = input.trim().toLowerCase();
174
+
175
+ // Handle negative durations
176
+ const isNegative = normalized.startsWith('-');
177
+ const workingInput = isNegative ? normalized.substring(1).trim() : normalized;
178
+
179
+ // Pattern: [number] [unit]
180
+ // Units: year(s), month(s), week(s), day(s), hour(s), minute(s), second(s), min(s), sec(s)
181
+ const pattern = /(\d+(?:\.\d+)?)\s*(years?|months?|weeks?|days?|hours?|minutes?|seconds?|mins?|secs?)/g;
182
+
183
+ const components: Record<string, number> = {};
184
+ let match;
185
+ let hasMatch = false;
186
+
187
+ while ((match = pattern.exec(workingInput)) !== null) {
188
+ hasMatch = true;
189
+ const value = parseFloat(match[1]);
190
+ const unit = match[2];
191
+
192
+ // Map unit to Temporal.Duration field
193
+ if (unit.startsWith('year')) {
194
+ components.years = (components.years || 0) + value;
195
+ } else if (unit.startsWith('month')) {
196
+ components.months = (components.months || 0) + value;
197
+ } else if (unit.startsWith('week')) {
198
+ components.weeks = (components.weeks || 0) + value;
199
+ } else if (unit.startsWith('day')) {
200
+ components.days = (components.days || 0) + value;
201
+ } else if (unit.startsWith('hour')) {
202
+ components.hours = (components.hours || 0) + value;
203
+ } else if (unit.startsWith('min')) {
204
+ components.minutes = (components.minutes || 0) + value;
205
+ } else if (unit.startsWith('sec')) {
206
+ components.seconds = (components.seconds || 0) + value;
207
+ }
208
+ }
209
+
210
+ if (!hasMatch) return null;
211
+
212
+ try {
213
+ const duration = Temporal.Duration.from(components);
214
+ return isNegative ? duration.negated() : duration;
215
+ } catch {
216
+ return null;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * TIMESPAN type - stores ISO 8601 duration strings
222
+ * Uses Temporal.Duration for validation and parsing
223
+ */
224
+ export const TIMESPAN_TYPE: LogicalType = {
225
+ name: 'TIMESPAN',
226
+ physicalType: PhysicalType.TEXT,
227
+ isTemporal: true,
228
+
229
+ validate: (v) => {
230
+ if (v === null) return true;
231
+ if (typeof v !== 'string') return false;
232
+ try {
233
+ Temporal.Duration.from(v);
234
+ return true;
235
+ } catch {
236
+ // Try parsing human-readable format
237
+ return parseHumanReadableDuration(v) !== null;
238
+ }
239
+ },
240
+
241
+ parse: (v) => {
242
+ if (v === null) return null;
243
+
244
+ if (typeof v === 'number') {
245
+ // Interpret as seconds
246
+ const duration = Temporal.Duration.from({ seconds: v });
247
+ return duration.toString();
248
+ }
249
+
250
+ if (typeof v === 'string') {
251
+ try {
252
+ // Try ISO 8601 first
253
+ const duration = Temporal.Duration.from(v);
254
+ return duration.toString();
255
+ } catch {
256
+ // Try human-readable format
257
+ const duration = parseHumanReadableDuration(v);
258
+ if (duration) return duration.toString();
259
+ throw new TypeError(`Cannot convert '${v}' to TIMESPAN`);
260
+ }
261
+ }
262
+
263
+ throw new TypeError(`Cannot convert ${typeof v} to TIMESPAN`);
264
+ },
265
+
266
+ compare: (a, b) => {
267
+ if (a === null && b === null) return 0;
268
+ if (a === null) return -1;
269
+ if (b === null) return 1;
270
+
271
+ try {
272
+ const durationA = Temporal.Duration.from(a as string);
273
+ const durationB = Temporal.Duration.from(b as string);
274
+
275
+ // Use a reference date to resolve calendar units
276
+ // This ensures consistent comparison of durations with months/years
277
+ const referenceDate = Temporal.PlainDate.from('2024-01-01');
278
+ const totalA = durationA.total({ unit: 'seconds', relativeTo: referenceDate });
279
+ const totalB = durationB.total({ unit: 'seconds', relativeTo: referenceDate });
280
+
281
+ return totalA < totalB ? -1 : totalA > totalB ? 1 : 0;
282
+ } catch {
283
+ // If parsing fails, fall back to string comparison
284
+ return (a as string).localeCompare(b as string);
285
+ }
286
+ },
287
+
288
+ supportedCollations: [],
289
+ };
290
+
@@ -21,10 +21,7 @@ export function formatExpressionList(nodes: readonly ScalarPlanNode[]): string {
21
21
  * Format a scalar type to a simple string representation.
22
22
  */
23
23
  export function formatScalarType(type: ScalarType): string {
24
- if (type.datatype !== undefined) {
25
- return SqlDataType[type.datatype];
26
- }
27
- return SqlDataType[type.affinity];
24
+ return type.logicalType.name;
28
25
  }
29
26
 
30
27
  /**
@@ -1,6 +1,6 @@
1
1
  import type { RowDescriptor, Attribute } from '../planner/nodes/plan-node.js';
2
2
  import type { Row } from '../common/types.js';
3
- import { SqlDataType } from '../common/types.js';
3
+ import { TEXT_TYPE } from '../types/builtin-types.js';
4
4
 
5
5
  /**
6
6
  * Utility to build a RowDescriptor (attributeId → columnIndex mapping)
@@ -94,7 +94,7 @@ export function buildAttributesFromFlatDescriptor(flatRowDescriptor: RowDescript
94
94
  name: `attr_${attrId}`,
95
95
  type: {
96
96
  typeClass: 'scalar' as const,
97
- affinity: SqlDataType.TEXT,
97
+ logicalType: TEXT_TYPE,
98
98
  nullable: true,
99
99
  isReadOnly: false
100
100
  },
@@ -5,7 +5,8 @@
5
5
 
6
6
  /* eslint-disable @typescript-eslint/no-explicit-any */
7
7
  import { quereusError } from '../common/errors.js';
8
- import { StatusCode, type SqlDataType, type SqlValue } from '../common/types.js';
8
+ import { StatusCode, type SqlValue } from '../common/types.js';
9
+ import type { LogicalType } from '../types/logical-type.js';
9
10
 
10
11
  /**
11
12
  * Constraint operators that can be pushed down to virtual tables
@@ -20,8 +21,8 @@ export interface ColumnMeta {
20
21
  index: number;
21
22
  /** Column name */
22
23
  name: string;
23
- /** SQL type information */
24
- type: SqlDataType;
24
+ /** Logical type information */
25
+ type: LogicalType;
25
26
  /** Whether this column is part of the primary key */
26
27
  isPrimaryKey: boolean;
27
28
  /** Whether this column has a unique constraint */
@@ -103,7 +103,7 @@ export class MemoryTableModule implements VirtualTableModule<MemoryTable, Memory
103
103
  return tableInfo.columns.map((col, index) => ({
104
104
  index,
105
105
  name: col.name,
106
- type: col.affinity,
106
+ type: col.logicalType,
107
107
  isPrimaryKey: tableInfo.primaryKeyDefinition.some(pk => pk.index === index),
108
108
  isUnique: col.primaryKey // Primary key columns are unique, others would be determined by constraints/indexes
109
109
  }));