@quereus/quereus 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) 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/datetime.js +9 -9
  22. package/dist/src/func/builtins/datetime.js.map +1 -1
  23. package/dist/src/func/builtins/explain.js +53 -53
  24. package/dist/src/func/builtins/explain.js.map +1 -1
  25. package/dist/src/func/builtins/generation.js +2 -2
  26. package/dist/src/func/builtins/generation.js.map +1 -1
  27. package/dist/src/func/builtins/index.d.ts.map +1 -1
  28. package/dist/src/func/builtins/index.js +16 -1
  29. package/dist/src/func/builtins/index.js.map +1 -1
  30. package/dist/src/func/builtins/json-tvf.js +17 -17
  31. package/dist/src/func/builtins/json-tvf.js.map +1 -1
  32. package/dist/src/func/builtins/json.js +11 -11
  33. package/dist/src/func/builtins/json.js.map +1 -1
  34. package/dist/src/func/builtins/scalar.d.ts.map +1 -1
  35. package/dist/src/func/builtins/scalar.js +202 -13
  36. package/dist/src/func/builtins/scalar.js.map +1 -1
  37. package/dist/src/func/builtins/schema.js +18 -18
  38. package/dist/src/func/builtins/schema.js.map +1 -1
  39. package/dist/src/func/builtins/string.d.ts.map +1 -1
  40. package/dist/src/func/builtins/string.js +59 -50
  41. package/dist/src/func/builtins/string.js.map +1 -1
  42. package/dist/src/func/builtins/timespan.d.ts +45 -0
  43. package/dist/src/func/builtins/timespan.d.ts.map +1 -0
  44. package/dist/src/func/builtins/timespan.js +147 -0
  45. package/dist/src/func/builtins/timespan.js.map +1 -0
  46. package/dist/src/func/registration.d.ts +26 -0
  47. package/dist/src/func/registration.d.ts.map +1 -1
  48. package/dist/src/func/registration.js +9 -5
  49. package/dist/src/func/registration.js.map +1 -1
  50. package/dist/src/index.d.ts +1 -1
  51. package/dist/src/index.d.ts.map +1 -1
  52. package/dist/src/index.js +1 -1
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/parser/parser.js +2 -2
  55. package/dist/src/parser/parser.js.map +1 -1
  56. package/dist/src/planner/building/constraint-builder.js +2 -2
  57. package/dist/src/planner/building/constraint-builder.js.map +1 -1
  58. package/dist/src/planner/building/delete.js +3 -3
  59. package/dist/src/planner/building/delete.js.map +1 -1
  60. package/dist/src/planner/building/function-call.d.ts.map +1 -1
  61. package/dist/src/planner/building/function-call.js +24 -4
  62. package/dist/src/planner/building/function-call.js.map +1 -1
  63. package/dist/src/planner/building/insert.js +3 -3
  64. package/dist/src/planner/building/insert.js.map +1 -1
  65. package/dist/src/planner/building/select.d.ts.map +1 -1
  66. package/dist/src/planner/building/select.js +3 -2
  67. package/dist/src/planner/building/select.js.map +1 -1
  68. package/dist/src/planner/building/update.js +7 -7
  69. package/dist/src/planner/building/update.js.map +1 -1
  70. package/dist/src/planner/nodes/aggregate-function.d.ts +2 -1
  71. package/dist/src/planner/nodes/aggregate-function.d.ts.map +1 -1
  72. package/dist/src/planner/nodes/aggregate-function.js +10 -3
  73. package/dist/src/planner/nodes/aggregate-function.js.map +1 -1
  74. package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
  75. package/dist/src/planner/nodes/cte-node.js +2 -2
  76. package/dist/src/planner/nodes/cte-node.js.map +1 -1
  77. package/dist/src/planner/nodes/declarative-schema.js +3 -3
  78. package/dist/src/planner/nodes/declarative-schema.js.map +1 -1
  79. package/dist/src/planner/nodes/function.d.ts +2 -1
  80. package/dist/src/planner/nodes/function.d.ts.map +1 -1
  81. package/dist/src/planner/nodes/function.js +6 -3
  82. package/dist/src/planner/nodes/function.js.map +1 -1
  83. package/dist/src/planner/nodes/insert-node.js +1 -1
  84. package/dist/src/planner/nodes/insert-node.js.map +1 -1
  85. package/dist/src/planner/nodes/pragma.d.ts +1 -1
  86. package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
  87. package/dist/src/planner/nodes/pragma.js +3 -3
  88. package/dist/src/planner/nodes/pragma.js.map +1 -1
  89. package/dist/src/planner/nodes/reference.js +1 -1
  90. package/dist/src/planner/nodes/reference.js.map +1 -1
  91. package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
  92. package/dist/src/planner/nodes/scalar.js +55 -101
  93. package/dist/src/planner/nodes/scalar.js.map +1 -1
  94. package/dist/src/planner/nodes/sequencing-node.js +2 -2
  95. package/dist/src/planner/nodes/sequencing-node.js.map +1 -1
  96. package/dist/src/planner/nodes/sink-node.js +2 -2
  97. package/dist/src/planner/nodes/sink-node.js.map +1 -1
  98. package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
  99. package/dist/src/planner/nodes/subquery.js +4 -7
  100. package/dist/src/planner/nodes/subquery.js.map +1 -1
  101. package/dist/src/planner/nodes/view-reference-node.d.ts.map +1 -1
  102. package/dist/src/planner/nodes/view-reference-node.js +2 -2
  103. package/dist/src/planner/nodes/view-reference-node.js.map +1 -1
  104. package/dist/src/planner/nodes/window-function.js +3 -3
  105. package/dist/src/planner/nodes/window-function.js.map +1 -1
  106. package/dist/src/planner/rules/access/rule-select-access-path.js +1 -1
  107. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  108. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +1 -1
  109. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  110. package/dist/src/planner/scopes/global.js +3 -3
  111. package/dist/src/planner/scopes/global.js.map +1 -1
  112. package/dist/src/planner/scopes/param.d.ts.map +1 -1
  113. package/dist/src/planner/scopes/param.js +2 -2
  114. package/dist/src/planner/scopes/param.js.map +1 -1
  115. package/dist/src/planner/type-utils.d.ts +2 -12
  116. package/dist/src/planner/type-utils.d.ts.map +1 -1
  117. package/dist/src/planner/type-utils.js +6 -21
  118. package/dist/src/planner/type-utils.js.map +1 -1
  119. package/dist/src/runtime/emit/between.js +2 -2
  120. package/dist/src/runtime/emit/between.js.map +1 -1
  121. package/dist/src/runtime/emit/binary.d.ts.map +1 -1
  122. package/dist/src/runtime/emit/binary.js +66 -30
  123. package/dist/src/runtime/emit/binary.js.map +1 -1
  124. package/dist/src/runtime/emit/subquery.js +8 -8
  125. package/dist/src/runtime/emit/subquery.js.map +1 -1
  126. package/dist/src/runtime/emit/temporal-arithmetic.d.ts +33 -0
  127. package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -0
  128. package/dist/src/runtime/emit/temporal-arithmetic.js +269 -0
  129. package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -0
  130. package/dist/src/runtime/emit/unary.d.ts.map +1 -1
  131. package/dist/src/runtime/emit/unary.js +16 -4
  132. package/dist/src/runtime/emit/unary.js.map +1 -1
  133. package/dist/src/schema/catalog.js +3 -3
  134. package/dist/src/schema/catalog.js.map +1 -1
  135. package/dist/src/schema/column.d.ts +0 -3
  136. package/dist/src/schema/column.d.ts.map +1 -1
  137. package/dist/src/schema/column.js +0 -2
  138. package/dist/src/schema/column.js.map +1 -1
  139. package/dist/src/schema/function.d.ts +29 -1
  140. package/dist/src/schema/function.d.ts.map +1 -1
  141. package/dist/src/schema/function.js.map +1 -1
  142. package/dist/src/schema/table.d.ts +3 -3
  143. package/dist/src/schema/table.d.ts.map +1 -1
  144. package/dist/src/schema/table.js +4 -6
  145. package/dist/src/schema/table.js.map +1 -1
  146. package/dist/src/types/index.d.ts +1 -1
  147. package/dist/src/types/index.d.ts.map +1 -1
  148. package/dist/src/types/index.js +1 -1
  149. package/dist/src/types/index.js.map +1 -1
  150. package/dist/src/types/registry.d.ts.map +1 -1
  151. package/dist/src/types/registry.js +5 -1
  152. package/dist/src/types/registry.js.map +1 -1
  153. package/dist/src/types/temporal-types.d.ts +5 -0
  154. package/dist/src/types/temporal-types.d.ts.map +1 -1
  155. package/dist/src/types/temporal-types.js +122 -0
  156. package/dist/src/types/temporal-types.js.map +1 -1
  157. package/dist/src/util/plan-formatter.d.ts.map +1 -1
  158. package/dist/src/util/plan-formatter.js +1 -5
  159. package/dist/src/util/plan-formatter.js.map +1 -1
  160. package/dist/src/util/row-descriptor.js +2 -2
  161. package/dist/src/util/row-descriptor.js.map +1 -1
  162. package/dist/src/vtab/best-access-plan.d.ts +4 -3
  163. package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
  164. package/dist/src/vtab/best-access-plan.js.map +1 -1
  165. package/dist/src/vtab/memory/module.js +1 -1
  166. package/dist/src/vtab/memory/module.js.map +1 -1
  167. package/package.json +1 -1
  168. package/src/common/datatype.ts +4 -5
  169. package/src/common/type-inference.ts +13 -22
  170. package/src/core/param.ts +4 -11
  171. package/src/func/builtins/aggregate.ts +24 -2
  172. package/src/func/builtins/builtin-window-functions.ts +10 -10
  173. package/src/func/builtins/conversion.ts +26 -1
  174. package/src/func/builtins/datetime.ts +9 -9
  175. package/src/func/builtins/explain.ts +53 -53
  176. package/src/func/builtins/generation.ts +2 -2
  177. package/src/func/builtins/index.ts +20 -1
  178. package/src/func/builtins/json-tvf.ts +17 -17
  179. package/src/func/builtins/json.ts +11 -11
  180. package/src/func/builtins/scalar.ts +205 -14
  181. package/src/func/builtins/schema.ts +18 -18
  182. package/src/func/builtins/string.ts +93 -80
  183. package/src/func/builtins/timespan.ts +179 -0
  184. package/src/func/registration.ts +35 -5
  185. package/src/index.ts +2 -1
  186. package/src/parser/parser.ts +2 -2
  187. package/src/planner/building/constraint-builder.ts +2 -2
  188. package/src/planner/building/delete.ts +3 -3
  189. package/src/planner/building/function-call.ts +44 -3
  190. package/src/planner/building/insert.ts +3 -3
  191. package/src/planner/building/select.ts +3 -2
  192. package/src/planner/building/update.ts +7 -7
  193. package/src/planner/nodes/aggregate-function.ts +13 -3
  194. package/src/planner/nodes/cte-node.ts +2 -2
  195. package/src/planner/nodes/declarative-schema.ts +3 -3
  196. package/src/planner/nodes/function.ts +8 -3
  197. package/src/planner/nodes/insert-node.ts +1 -1
  198. package/src/planner/nodes/pragma.ts +4 -3
  199. package/src/planner/nodes/reference.ts +1 -1
  200. package/src/planner/nodes/scalar.ts +54 -102
  201. package/src/planner/nodes/sequencing-node.ts +2 -2
  202. package/src/planner/nodes/sink-node.ts +2 -2
  203. package/src/planner/nodes/subquery.ts +5 -7
  204. package/src/planner/nodes/view-reference-node.ts +2 -2
  205. package/src/planner/nodes/window-function.ts +3 -3
  206. package/src/planner/rules/access/rule-select-access-path.ts +1 -1
  207. package/src/planner/rules/retrieve/rule-grow-retrieve.ts +1 -1
  208. package/src/planner/scopes/global.ts +3 -3
  209. package/src/planner/scopes/param.ts +2 -2
  210. package/src/planner/type-utils.ts +6 -14
  211. package/src/runtime/emit/between.ts +2 -2
  212. package/src/runtime/emit/binary.ts +74 -30
  213. package/src/runtime/emit/subquery.ts +8 -8
  214. package/src/runtime/emit/temporal-arithmetic.ts +302 -0
  215. package/src/runtime/emit/unary.ts +17 -4
  216. package/src/schema/catalog.ts +3 -3
  217. package/src/schema/column.ts +0 -3
  218. package/src/schema/function.ts +29 -1
  219. package/src/schema/table.ts +5 -7
  220. package/src/types/index.ts +1 -1
  221. package/src/types/registry.ts +5 -1
  222. package/src/types/temporal-types.ts +123 -0
  223. package/src/util/plan-formatter.ts +1 -4
  224. package/src/util/row-descriptor.ts +2 -2
  225. package/src/vtab/best-access-plan.ts +4 -3
  226. package/src/vtab/memory/module.ts +1 -1
package/src/core/param.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ScalarType } from '../common/datatype.js';
2
- import { type SqlParameters, type SqlValue, SqlDataType } from '../common/types.js';
2
+ import { type SqlParameters, type SqlValue } from '../common/types.js';
3
+ import { inferLogicalTypeFromValue } from '../common/type-inference.js';
3
4
 
4
5
  export function getParameterTypeHints(params: SqlParameters | undefined): Map<string | number, ScalarType> | undefined {
5
6
  let results: Map<string | number, ScalarType> | undefined;
@@ -22,20 +23,12 @@ export function getParameterTypeHints(params: SqlParameters | undefined): Map<st
22
23
  }
23
24
 
24
25
  function getParameterScalarType(value: SqlValue): ScalarType {
25
- let affinity: SqlDataType;
26
- if (value === null) affinity = SqlDataType.NULL;
27
- else if (typeof value === 'number') affinity = SqlDataType.REAL;
28
- else if (typeof value === 'bigint') affinity = SqlDataType.INTEGER;
29
- else if (typeof value === 'string') affinity = SqlDataType.TEXT;
30
- else if (value instanceof Uint8Array) affinity = SqlDataType.BLOB;
31
- else if (typeof value === 'boolean') affinity = SqlDataType.INTEGER;
32
- else affinity = SqlDataType.BLOB;
26
+ const logicalType = inferLogicalTypeFromValue(value);
33
27
 
34
28
  return {
35
29
  typeClass: 'scalar',
36
- affinity: affinity,
30
+ logicalType,
37
31
  nullable: value === null,
38
32
  isReadOnly: true,
39
- datatype: affinity,
40
33
  };
41
34
  }
@@ -87,7 +87,18 @@ export const avgFunc = createAggregateFunction(
87
87
 
88
88
  // --- MIN(X) ---
89
89
  export const minFunc = createAggregateFunction(
90
- { name: 'min', numArgs: 1, initialValue: null },
90
+ {
91
+ name: 'min',
92
+ numArgs: 1,
93
+ initialValue: null,
94
+ // Type inference: return the same type as the input argument
95
+ inferReturnType: (argTypes) => ({
96
+ typeClass: 'scalar',
97
+ logicalType: argTypes[0],
98
+ nullable: true, // MIN can return NULL if all values are NULL or no rows
99
+ isReadOnly: true
100
+ })
101
+ },
91
102
  (acc: { min: SqlValue } | null, value: SqlValue): { min: SqlValue } | null => {
92
103
  if (value === null) return acc; // Ignore NULLs
93
104
  if (acc === null) return { min: value }; // First non-null value
@@ -100,7 +111,18 @@ export const minFunc = createAggregateFunction(
100
111
 
101
112
  // --- MAX(X) ---
102
113
  export const maxFunc = createAggregateFunction(
103
- { name: 'max', numArgs: 1, initialValue: null },
114
+ {
115
+ name: 'max',
116
+ numArgs: 1,
117
+ initialValue: null,
118
+ // Type inference: return the same type as the input argument
119
+ inferReturnType: (argTypes) => ({
120
+ typeClass: 'scalar',
121
+ logicalType: argTypes[0],
122
+ nullable: true, // MAX can return NULL if all values are NULL or no rows
123
+ isReadOnly: true
124
+ })
125
+ },
104
126
  (acc: { max: SqlValue } | null, value: SqlValue): { max: SqlValue } | null => {
105
127
  if (value === null) return acc; // Ignore NULLs
106
128
  if (acc === null) return { max: value }; // First non-null value
@@ -1,6 +1,6 @@
1
1
  import { registerWindowFunction } from '../../schema/window-function.js';
2
- import { SqlDataType } from '../../common/types.js';
3
2
  import { AggValue } from '../registration.js';
3
+ import { INTEGER_TYPE, REAL_TYPE } from '../../types/builtin-types.js';
4
4
 
5
5
  // Built-in window function schemas
6
6
  export function registerBuiltinWindowFunctions(): void {
@@ -10,7 +10,7 @@ export function registerBuiltinWindowFunctions(): void {
10
10
  argCount: 0,
11
11
  returnType: {
12
12
  typeClass: 'scalar',
13
- affinity: SqlDataType.INTEGER,
13
+ logicalType: INTEGER_TYPE,
14
14
  nullable: false,
15
15
  isReadOnly: true
16
16
  },
@@ -23,7 +23,7 @@ export function registerBuiltinWindowFunctions(): void {
23
23
  argCount: 0,
24
24
  returnType: {
25
25
  typeClass: 'scalar',
26
- affinity: SqlDataType.INTEGER,
26
+ logicalType: INTEGER_TYPE,
27
27
  nullable: false,
28
28
  isReadOnly: true
29
29
  },
@@ -36,7 +36,7 @@ export function registerBuiltinWindowFunctions(): void {
36
36
  argCount: 0,
37
37
  returnType: {
38
38
  typeClass: 'scalar',
39
- affinity: SqlDataType.INTEGER,
39
+ logicalType: INTEGER_TYPE,
40
40
  nullable: false,
41
41
  isReadOnly: true
42
42
  },
@@ -49,7 +49,7 @@ export function registerBuiltinWindowFunctions(): void {
49
49
  argCount: 1,
50
50
  returnType: {
51
51
  typeClass: 'scalar',
52
- affinity: SqlDataType.INTEGER,
52
+ logicalType: INTEGER_TYPE,
53
53
  nullable: false,
54
54
  isReadOnly: true
55
55
  },
@@ -63,7 +63,7 @@ export function registerBuiltinWindowFunctions(): void {
63
63
  argCount: 1,
64
64
  returnType: {
65
65
  typeClass: 'scalar',
66
- affinity: SqlDataType.INTEGER,
66
+ logicalType: INTEGER_TYPE,
67
67
  nullable: false,
68
68
  isReadOnly: true
69
69
  },
@@ -83,7 +83,7 @@ export function registerBuiltinWindowFunctions(): void {
83
83
  argCount: 1,
84
84
  returnType: {
85
85
  typeClass: 'scalar',
86
- affinity: SqlDataType.NUMERIC,
86
+ logicalType: REAL_TYPE,
87
87
  nullable: true,
88
88
  isReadOnly: true
89
89
  },
@@ -104,7 +104,7 @@ export function registerBuiltinWindowFunctions(): void {
104
104
  argCount: 1,
105
105
  returnType: {
106
106
  typeClass: 'scalar',
107
- affinity: SqlDataType.NUMERIC,
107
+ logicalType: REAL_TYPE,
108
108
  nullable: true,
109
109
  isReadOnly: true
110
110
  },
@@ -127,7 +127,7 @@ export function registerBuiltinWindowFunctions(): void {
127
127
  argCount: 1,
128
128
  returnType: {
129
129
  typeClass: 'scalar',
130
- affinity: SqlDataType.NUMERIC,
130
+ logicalType: REAL_TYPE,
131
131
  nullable: true,
132
132
  isReadOnly: true
133
133
  },
@@ -148,7 +148,7 @@ export function registerBuiltinWindowFunctions(): void {
148
148
  argCount: 1,
149
149
  returnType: {
150
150
  typeClass: 'scalar',
151
- affinity: SqlDataType.NUMERIC,
151
+ logicalType: REAL_TYPE,
152
152
  nullable: true,
153
153
  isReadOnly: true
154
154
  },
@@ -3,7 +3,7 @@ import { createScalarFunction } from '../registration.js';
3
3
  import { QuereusError } from '../../common/errors.js';
4
4
  import { StatusCode } from '../../common/types.js';
5
5
  import { INTEGER_TYPE, REAL_TYPE, TEXT_TYPE, BOOLEAN_TYPE } from '../../types/builtin-types.js';
6
- import { DATE_TYPE, TIME_TYPE, DATETIME_TYPE } from '../../types/temporal-types.js';
6
+ import { DATE_TYPE, TIME_TYPE, DATETIME_TYPE, TIMESPAN_TYPE } from '../../types/temporal-types.js';
7
7
  import { JSON_TYPE } from '../../types/json-type.js';
8
8
 
9
9
  /**
@@ -199,3 +199,28 @@ export const JSON_FUNC = createScalarFunction(
199
199
  }
200
200
  );
201
201
 
202
+ /**
203
+ * timespan() - Convert value to TIMESPAN
204
+ * Usage: timespan(value)
205
+ *
206
+ * Accepts:
207
+ * - ISO 8601 duration strings: 'PT1H30M', 'P1D', 'P1Y2M3D'
208
+ * - Human-readable strings: '1 hour', '30 minutes', '2 days 3 hours'
209
+ * - Numeric values (interpreted as seconds): 3600, 86400
210
+ */
211
+ export const TIMESPAN_FUNC = createScalarFunction(
212
+ { name: 'timespan', numArgs: 1, deterministic: true },
213
+ (value: SqlValue): SqlValue => {
214
+ if (value === null) return null;
215
+
216
+ try {
217
+ return TIMESPAN_TYPE.parse!(value);
218
+ } catch (e) {
219
+ throw new QuereusError(
220
+ `Cannot convert to TIMESPAN: ${e instanceof Error ? e.message : String(e)}`,
221
+ StatusCode.MISMATCH
222
+ );
223
+ }
224
+ }
225
+ );
226
+
@@ -456,14 +456,14 @@ export const strftimeFunc = createScalarFunction(
456
456
  export const isISODateFunc = createScalarFunction(
457
457
  { name: 'IsISODate', numArgs: 1, deterministic: true },
458
458
  (value: SqlValue): SqlValue => {
459
- if (typeof value !== 'string') return 0;
459
+ if (typeof value !== 'string') return false;
460
460
  const s = value.trim();
461
- if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return 0;
461
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return false;
462
462
  try {
463
463
  const d = Temporal.PlainDate.from(s);
464
- return d.toString() === s ? 1 : 0;
464
+ return d.toString() === s;
465
465
  } catch {
466
- return 0;
466
+ return false;
467
467
  }
468
468
  }
469
469
  );
@@ -472,24 +472,24 @@ export const isISODateFunc = createScalarFunction(
472
472
  export const isISODateTimeFunc = createScalarFunction(
473
473
  { name: 'IsISODateTime', numArgs: 1, deterministic: true },
474
474
  (value: SqlValue): SqlValue => {
475
- if (typeof value !== 'string') return 0;
475
+ if (typeof value !== 'string') return false;
476
476
  const s = value.trim();
477
477
  // YYYY-MM-DDTHH:MM[:SS[.fraction]] [timezone]
478
478
  const re =
479
479
  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:\d{2})?$/;
480
- if (!re.test(s)) return 0;
480
+ if (!re.test(s)) return false;
481
481
  const hasZone = /(?:Z|[+-]\d{2}:\d{2})$/.test(s);
482
482
  try {
483
483
  if (hasZone) {
484
484
  // Zoned ISO string
485
485
  void Temporal.Instant.from(s);
486
- return 1;
486
+ return true;
487
487
  }
488
488
  // Plain ISO local date-time
489
489
  void Temporal.PlainDateTime.from(s);
490
- return 1;
490
+ return true;
491
491
  } catch {
492
- return 0;
492
+ return false;
493
493
  }
494
494
  }
495
495
  );
@@ -1,7 +1,7 @@
1
1
  import type { Row } from "../../common/types.js";
2
2
  import type { SqlValue } from "../../common/types.js";
3
- import { SqlDataType } from "../../common/types.js";
4
3
  import { createIntegratedTableValuedFunction } from "../registration.js";
4
+ import { INTEGER_TYPE, REAL_TYPE, TEXT_TYPE } from "../../types/builtin-types.js";
5
5
  import { QuereusError } from "../../common/errors.js";
6
6
  import { StatusCode } from "../../common/types.js";
7
7
  import type { Database } from "../../core/database.js";
@@ -81,18 +81,18 @@ export const queryPlanFunc = createIntegratedTableValuedFunction(
81
81
  isReadOnly: true,
82
82
  isSet: false,
83
83
  columns: [
84
- { name: 'id', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
85
- { name: 'parent_id', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true },
86
- { name: 'subquery_level', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
87
- { name: 'node_type', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
88
- { name: 'op', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
89
- { name: 'detail', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
90
- { name: 'object_name', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
91
- { name: 'alias', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
92
- { name: 'properties', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
93
- { name: 'physical', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
94
- { name: 'est_cost', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: true, isReadOnly: true }, generated: true },
95
- { name: 'est_rows', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true }
84
+ { name: 'id', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
85
+ { name: 'parent_id', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true },
86
+ { name: 'subquery_level', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
87
+ { name: 'node_type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
88
+ { name: 'op', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
89
+ { name: 'detail', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
90
+ { name: 'object_name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
91
+ { name: 'alias', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
92
+ { name: 'properties', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
93
+ { name: 'physical', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
94
+ { name: 'est_cost', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true }, generated: true },
95
+ { name: 'est_rows', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true }
96
96
  ],
97
97
  keys: [],
98
98
  rowConstraints: []
@@ -200,12 +200,12 @@ export const schedulerProgramFunc = createIntegratedTableValuedFunction(
200
200
  isReadOnly: true,
201
201
  isSet: false,
202
202
  columns: [
203
- { name: 'addr', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
204
- { name: 'dependencies', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON array of dependency IDs
205
- { name: 'description', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
206
- { name: 'estimated_cost', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: true, isReadOnly: true }, generated: true },
207
- { name: 'is_subprogram', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true }, // 0/1 boolean
208
- { name: 'parent_addr', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true }
203
+ { name: 'addr', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
204
+ { name: 'dependencies', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON array of dependency IDs
205
+ { name: 'description', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
206
+ { name: 'estimated_cost', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true }, generated: true },
207
+ { name: 'is_subprogram', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true }, // 0/1 boolean
208
+ { name: 'parent_addr', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true }
209
209
  ],
210
210
  keys: [],
211
211
  rowConstraints: []
@@ -280,13 +280,13 @@ export const stackTraceFunc = createIntegratedTableValuedFunction(
280
280
  isReadOnly: true,
281
281
  isSet: false,
282
282
  columns: [
283
- { name: 'frame_id', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
284
- { name: 'depth', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
285
- { name: 'location', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
286
- { name: 'plan_node_type', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
287
- { name: 'operation', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
288
- { name: 'table_or_function', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
289
- { name: 'is_virtual', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true } // 0/1 boolean
283
+ { name: 'frame_id', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
284
+ { name: 'depth', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
285
+ { name: 'location', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
286
+ { name: 'plan_node_type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
287
+ { name: 'operation', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
288
+ { name: 'table_or_function', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
289
+ { name: 'is_virtual', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true } // 0/1 boolean
290
290
  ],
291
291
  keys: [],
292
292
  rowConstraints: []
@@ -387,15 +387,15 @@ export const executionTraceFunc = createIntegratedTableValuedFunction(
387
387
  isReadOnly: true,
388
388
  isSet: false,
389
389
  columns: [
390
- { name: 'instruction_index', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
391
- { name: 'operation', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
392
- { name: 'dependencies', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON array of instruction indices this depends on
393
- { name: 'input_values', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON
394
- { name: 'output_value', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON
395
- { name: 'duration_ms', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: true, isReadOnly: true }, generated: true },
396
- { name: 'sub_programs', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON
397
- { name: 'error_message', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
398
- { name: 'timestamp_ms', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: false, isReadOnly: true }, generated: true }
390
+ { name: 'instruction_index', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
391
+ { name: 'operation', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
392
+ { name: 'dependencies', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON array of instruction indices this depends on
393
+ { name: 'input_values', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON
394
+ { name: 'output_value', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON
395
+ { name: 'duration_ms', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true }, generated: true },
396
+ { name: 'sub_programs', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON
397
+ { name: 'error_message', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
398
+ { name: 'timestamp_ms', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: false, isReadOnly: true }, generated: true }
399
399
  ],
400
400
  keys: [],
401
401
  rowConstraints: []
@@ -563,12 +563,12 @@ export const rowTraceFunc = createIntegratedTableValuedFunction(
563
563
  isReadOnly: true,
564
564
  isSet: false,
565
565
  columns: [
566
- { name: 'instruction_index', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
567
- { name: 'operation', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
568
- { name: 'row_index', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
569
- { name: 'row_data', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true }, // JSON array of row values
570
- { name: 'timestamp_ms', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: false, isReadOnly: true }, generated: true },
571
- { name: 'row_count', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true } // Total rows for this instruction (filled in last row)
566
+ { name: 'instruction_index', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
567
+ { name: 'operation', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
568
+ { name: 'row_index', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
569
+ { name: 'row_data', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true }, // JSON array of row values
570
+ { name: 'timestamp_ms', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: false, isReadOnly: true }, generated: true },
571
+ { name: 'row_count', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true } // Total rows for this instruction (filled in last row)
572
572
  ],
573
573
  keys: [],
574
574
  rowConstraints: []
@@ -671,12 +671,12 @@ export const schemaSizeFunc = createIntegratedTableValuedFunction(
671
671
  isReadOnly: true,
672
672
  isSet: false,
673
673
  columns: [
674
- { name: 'object_type', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
675
- { name: 'object_name', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
676
- { name: 'estimated_rows', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true },
677
- { name: 'estimated_size_kb', type: { typeClass: 'scalar', affinity: SqlDataType.REAL, nullable: true, isReadOnly: true }, generated: true },
678
- { name: 'column_count', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
679
- { name: 'index_count', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true }
674
+ { name: 'object_type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
675
+ { name: 'object_name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
676
+ { name: 'estimated_rows', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true },
677
+ { name: 'estimated_size_kb', type: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true }, generated: true },
678
+ { name: 'column_count', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
679
+ { name: 'index_count', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true }
680
680
  ],
681
681
  keys: [],
682
682
  rowConstraints: []
@@ -698,12 +698,12 @@ export const explainAssertionFunc = createIntegratedTableValuedFunction(
698
698
  isReadOnly: true,
699
699
  isSet: false,
700
700
  columns: [
701
- { name: 'assertion', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
702
- { name: 'relation_key', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
703
- { name: 'base', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
704
- { name: 'classification', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
705
- { name: 'prepared_pk_params', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true }, // JSON array of param names or NULL
706
- { name: 'violation_sql', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true }
701
+ { name: 'assertion', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
702
+ { name: 'relation_key', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
703
+ { name: 'base', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
704
+ { name: 'classification', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
705
+ { name: 'prepared_pk_params', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }, // JSON array of param names or NULL
706
+ { name: 'violation_sql', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true }
707
707
  ],
708
708
  keys: [],
709
709
  rowConstraints: []
@@ -1,7 +1,7 @@
1
1
  import type { Row } from "../../common/types.js";
2
2
  import type { SqlValue } from "../../common/types.js";
3
- import { SqlDataType } from "../../common/types.js";
4
3
  import { createTableValuedFunction } from "../registration.js";
4
+ import { INTEGER_TYPE } from "../../types/builtin-types.js";
5
5
 
6
6
  // Generate a sequence of numbers (table-valued function)
7
7
  export const generateSeriesFunc = createTableValuedFunction(
@@ -18,7 +18,7 @@ export const generateSeriesFunc = createTableValuedFunction(
18
18
  name: 'value',
19
19
  type: {
20
20
  typeClass: 'scalar',
21
- affinity: SqlDataType.INTEGER,
21
+ logicalType: INTEGER_TYPE,
22
22
  nullable: false,
23
23
  isReadOnly: true
24
24
  },
@@ -21,7 +21,12 @@ import { generateSeriesFunc } from './generation.js';
21
21
  import { queryPlanFunc, schedulerProgramFunc, stackTraceFunc, executionTraceFunc, rowTraceFunc, explainAssertionFunc } from './explain.js';
22
22
  import { schemaFunc, tableInfoFunc, functionInfoFunc } from './schema.js';
23
23
  import { jsonEachFunc, jsonTreeFunc } from './json-tvf.js';
24
- import { INTEGER_FUNC, REAL_FUNC, TEXT_FUNC, BOOLEAN_FUNC, DATE_FUNC, TIME_FUNC, DATETIME_FUNC, JSON_FUNC } from './conversion.js';
24
+ import { INTEGER_FUNC, REAL_FUNC, TEXT_FUNC, BOOLEAN_FUNC, DATE_FUNC, TIME_FUNC, DATETIME_FUNC, TIMESPAN_FUNC, JSON_FUNC } from './conversion.js';
25
+ import {
26
+ timespanYearsFunc, timespanMonthsFunc, timespanWeeksFunc, timespanDaysFunc,
27
+ timespanHoursFunc, timespanMinutesFunc, timespanSecondsFunc,
28
+ timespanTotalSecondsFunc, timespanTotalMinutesFunc, timespanTotalHoursFunc, timespanTotalDaysFunc
29
+ } from './timespan.js';
25
30
 
26
31
  // Additional useful functions integrated from examples
27
32
 
@@ -35,6 +40,7 @@ export const BUILTIN_FUNCTIONS: FunctionSchema[] = [
35
40
  DATE_FUNC,
36
41
  TIME_FUNC,
37
42
  DATETIME_FUNC,
43
+ TIMESPAN_FUNC,
38
44
  // Scalar Functions
39
45
  absFunc,
40
46
  roundFunc,
@@ -93,6 +99,18 @@ export const BUILTIN_FUNCTIONS: FunctionSchema[] = [
93
99
  strftimeFunc,
94
100
  isISODateFunc,
95
101
  isISODateTimeFunc,
102
+ // Timespan Functions
103
+ timespanYearsFunc,
104
+ timespanMonthsFunc,
105
+ timespanWeeksFunc,
106
+ timespanDaysFunc,
107
+ timespanHoursFunc,
108
+ timespanMinutesFunc,
109
+ timespanSecondsFunc,
110
+ timespanTotalSecondsFunc,
111
+ timespanTotalMinutesFunc,
112
+ timespanTotalHoursFunc,
113
+ timespanTotalDaysFunc,
96
114
  // JSON Functions
97
115
  jsonValidFunc,
98
116
  jsonSchemaFunc,
@@ -136,6 +154,7 @@ export const BUILTIN_FUNCTIONS: FunctionSchema[] = [
136
154
  DATE_FUNC,
137
155
  TIME_FUNC,
138
156
  DATETIME_FUNC,
157
+ TIMESPAN_FUNC,
139
158
  JSON_FUNC,
140
159
  ];
141
160
 
@@ -1,10 +1,10 @@
1
1
  import type { Row, SqlValue, JSONValue } from "../../common/types.js";
2
- import { SqlDataType } from "../../common/types.js";
3
2
  import { createTableValuedFunction } from "../registration.js";
4
3
  import { QuereusError } from "../../common/errors.js";
5
4
  import { StatusCode } from "../../common/types.js";
6
5
  import { safeJsonParse, evaluateJsonPathBasic, getJsonType } from "./json-helpers.js";
7
6
  import { jsonStringify } from "../../util/serialization.js";
7
+ import { INTEGER_TYPE, TEXT_TYPE } from "../../types/builtin-types.js";
8
8
 
9
9
  // JSON Each table-valued function
10
10
  export const jsonEachFunc = createTableValuedFunction(
@@ -17,14 +17,14 @@ export const jsonEachFunc = createTableValuedFunction(
17
17
  isReadOnly: true,
18
18
  isSet: false,
19
19
  columns: [
20
- { name: 'key', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
21
- { name: 'value', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
22
- { name: 'type', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
23
- { name: 'atom', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
24
- { name: 'id', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
25
- { name: 'parent', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true },
26
- { name: 'fullkey', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
27
- { name: 'path', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true }
20
+ { name: 'key', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
21
+ { name: 'value', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
22
+ { name: 'type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
23
+ { name: 'atom', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
24
+ { name: 'id', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
25
+ { name: 'parent', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true },
26
+ { name: 'fullkey', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
27
+ { name: 'path', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true }
28
28
  ],
29
29
  keys: [],
30
30
  rowConstraints: []
@@ -119,14 +119,14 @@ export const jsonTreeFunc = createTableValuedFunction(
119
119
  isReadOnly: true,
120
120
  isSet: false,
121
121
  columns: [
122
- { name: 'key', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
123
- { name: 'value', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
124
- { name: 'type', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
125
- { name: 'atom', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: true, isReadOnly: true }, generated: true },
126
- { name: 'id', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: false, isReadOnly: true }, generated: true },
127
- { name: 'parent', type: { typeClass: 'scalar', affinity: SqlDataType.INTEGER, nullable: true, isReadOnly: true }, generated: true },
128
- { name: 'fullkey', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true },
129
- { name: 'path', type: { typeClass: 'scalar', affinity: SqlDataType.TEXT, nullable: false, isReadOnly: true }, generated: true }
122
+ { name: 'key', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
123
+ { name: 'value', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
124
+ { name: 'type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
125
+ { name: 'atom', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
126
+ { name: 'id', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
127
+ { name: 'parent', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: true, isReadOnly: true }, generated: true },
128
+ { name: 'fullkey', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
129
+ { name: 'path', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true }
130
130
  ],
131
131
  keys: [],
132
132
  rowConstraints: []
@@ -26,7 +26,7 @@ const errorLog = log.extend('error');
26
26
  export const jsonValidFunc = createScalarFunction(
27
27
  { name: 'json_valid', numArgs: 1, deterministic: true },
28
28
  (json: SqlValue): SqlValue => {
29
- return safeJsonParse(json) !== null ? 1 : 0;
29
+ return safeJsonParse(json) !== null;
30
30
  }
31
31
  );
32
32
 
@@ -65,23 +65,23 @@ function emitJsonSchema(
65
65
  // The validator is captured in the closure, so it lives with the plan
66
66
  function run(_rctx: RuntimeContext, ...args: any[]): SqlValue {
67
67
  const json = args[0];
68
- if (typeof json !== 'string') return 0;
68
+ if (typeof json !== 'string') return false;
69
69
 
70
70
  let data: JSONValue | null;
71
71
  try {
72
72
  data = JSON.parse(json) as JSONValue;
73
73
  } catch {
74
- return 0; // Invalid JSON
74
+ return false; // Invalid JSON
75
75
  }
76
76
 
77
77
  // Use the cached compiled validator
78
78
  try {
79
79
  // moat-maker's .matches() returns true if valid, false otherwise
80
80
  const isValid = compiledValidator.matches(data);
81
- return isValid ? 1 : 0;
81
+ return isValid;
82
82
  } catch (e) {
83
83
  errorLog('json_schema validation failed: %O', e);
84
- return 0;
84
+ return false;
85
85
  }
86
86
  }
87
87
 
@@ -111,16 +111,16 @@ export const jsonSchemaFunc = createScalarFunction(
111
111
  // (e.g., during direct function calls outside of query execution)
112
112
 
113
113
  // Schema definition must be a string
114
- if (typeof schemaDef !== 'string') return 0;
114
+ if (typeof schemaDef !== 'string') return false;
115
115
 
116
116
  // Parse the JSON value - need to check if it's valid JSON first
117
- if (typeof json !== 'string') return 0;
117
+ if (typeof json !== 'string') return false;
118
118
 
119
119
  let data: JSONValue | null;
120
120
  try {
121
121
  data = JSON.parse(json) as JSONValue;
122
122
  } catch {
123
- return 0; // Invalid JSON
123
+ return false; // Invalid JSON
124
124
  }
125
125
 
126
126
  // Compile and validate using moat-maker (no caching in fallback path)
@@ -130,10 +130,10 @@ export const jsonSchemaFunc = createScalarFunction(
130
130
  const compiledValidator = validator(parts, ...[]);
131
131
  // moat-maker's .matches() returns true if valid, false otherwise
132
132
  const isValid = compiledValidator.matches(data);
133
- return isValid ? 1 : 0;
133
+ return isValid;
134
134
  } catch (e) {
135
135
  errorLog('json_schema validation failed: %O', e);
136
- return 0;
136
+ return false;
137
137
  }
138
138
  }
139
139
  );
@@ -191,7 +191,7 @@ export const jsonExtractFunc = createScalarFunction(
191
191
  } else if (extractedValue === null) {
192
192
  return null;
193
193
  } else if (typeof extractedValue === 'boolean') {
194
- return extractedValue ? 1 : 0;
194
+ return extractedValue;
195
195
  } else if (typeof extractedValue === 'number') {
196
196
  return extractedValue; // Return as INTEGER or REAL
197
197
  } else if (typeof extractedValue === 'string') {