@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.
- package/README.md +5 -1
- package/dist/src/common/datatype.d.ts +4 -5
- package/dist/src/common/datatype.d.ts.map +1 -1
- package/dist/src/common/datatype.js.map +1 -1
- package/dist/src/common/type-inference.d.ts +3 -6
- package/dist/src/common/type-inference.d.ts.map +1 -1
- package/dist/src/common/type-inference.js +17 -22
- package/dist/src/common/type-inference.js.map +1 -1
- package/dist/src/core/param.d.ts.map +1 -1
- package/dist/src/core/param.js +3 -18
- package/dist/src/core/param.js.map +1 -1
- package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
- package/dist/src/func/builtins/aggregate.js +24 -2
- package/dist/src/func/builtins/aggregate.js.map +1 -1
- package/dist/src/func/builtins/builtin-window-functions.js +10 -10
- package/dist/src/func/builtins/builtin-window-functions.js.map +1 -1
- package/dist/src/func/builtins/conversion.d.ts +10 -0
- package/dist/src/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +20 -1
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/datetime.js +9 -9
- package/dist/src/func/builtins/datetime.js.map +1 -1
- package/dist/src/func/builtins/explain.js +53 -53
- package/dist/src/func/builtins/explain.js.map +1 -1
- package/dist/src/func/builtins/generation.js +2 -2
- package/dist/src/func/builtins/generation.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +16 -1
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/json-tvf.js +17 -17
- package/dist/src/func/builtins/json-tvf.js.map +1 -1
- package/dist/src/func/builtins/json.js +11 -11
- package/dist/src/func/builtins/json.js.map +1 -1
- package/dist/src/func/builtins/scalar.d.ts.map +1 -1
- package/dist/src/func/builtins/scalar.js +202 -13
- package/dist/src/func/builtins/scalar.js.map +1 -1
- package/dist/src/func/builtins/schema.js +18 -18
- package/dist/src/func/builtins/schema.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +59 -50
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/func/builtins/timespan.d.ts +45 -0
- package/dist/src/func/builtins/timespan.d.ts.map +1 -0
- package/dist/src/func/builtins/timespan.js +147 -0
- package/dist/src/func/builtins/timespan.js.map +1 -0
- package/dist/src/func/registration.d.ts +26 -0
- package/dist/src/func/registration.d.ts.map +1 -1
- package/dist/src/func/registration.js +9 -5
- package/dist/src/func/registration.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/parser.js +2 -2
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +2 -2
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/building/delete.js +3 -3
- package/dist/src/planner/building/delete.js.map +1 -1
- package/dist/src/planner/building/function-call.d.ts.map +1 -1
- package/dist/src/planner/building/function-call.js +24 -4
- package/dist/src/planner/building/function-call.js.map +1 -1
- package/dist/src/planner/building/insert.js +3 -3
- package/dist/src/planner/building/insert.js.map +1 -1
- package/dist/src/planner/building/select.d.ts.map +1 -1
- package/dist/src/planner/building/select.js +3 -2
- package/dist/src/planner/building/select.js.map +1 -1
- package/dist/src/planner/building/update.js +7 -7
- package/dist/src/planner/building/update.js.map +1 -1
- package/dist/src/planner/nodes/aggregate-function.d.ts +2 -1
- package/dist/src/planner/nodes/aggregate-function.d.ts.map +1 -1
- package/dist/src/planner/nodes/aggregate-function.js +10 -3
- package/dist/src/planner/nodes/aggregate-function.js.map +1 -1
- package/dist/src/planner/nodes/cte-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/cte-node.js +2 -2
- package/dist/src/planner/nodes/cte-node.js.map +1 -1
- package/dist/src/planner/nodes/declarative-schema.js +3 -3
- package/dist/src/planner/nodes/declarative-schema.js.map +1 -1
- package/dist/src/planner/nodes/function.d.ts +2 -1
- package/dist/src/planner/nodes/function.d.ts.map +1 -1
- package/dist/src/planner/nodes/function.js +6 -3
- package/dist/src/planner/nodes/function.js.map +1 -1
- package/dist/src/planner/nodes/insert-node.js +1 -1
- package/dist/src/planner/nodes/insert-node.js.map +1 -1
- package/dist/src/planner/nodes/pragma.d.ts +1 -1
- package/dist/src/planner/nodes/pragma.d.ts.map +1 -1
- package/dist/src/planner/nodes/pragma.js +3 -3
- package/dist/src/planner/nodes/pragma.js.map +1 -1
- package/dist/src/planner/nodes/reference.js +1 -1
- package/dist/src/planner/nodes/reference.js.map +1 -1
- package/dist/src/planner/nodes/scalar.d.ts.map +1 -1
- package/dist/src/planner/nodes/scalar.js +55 -101
- package/dist/src/planner/nodes/scalar.js.map +1 -1
- package/dist/src/planner/nodes/sequencing-node.js +2 -2
- package/dist/src/planner/nodes/sequencing-node.js.map +1 -1
- package/dist/src/planner/nodes/sink-node.js +2 -2
- package/dist/src/planner/nodes/sink-node.js.map +1 -1
- package/dist/src/planner/nodes/subquery.d.ts.map +1 -1
- package/dist/src/planner/nodes/subquery.js +4 -7
- package/dist/src/planner/nodes/subquery.js.map +1 -1
- package/dist/src/planner/nodes/view-reference-node.d.ts.map +1 -1
- package/dist/src/planner/nodes/view-reference-node.js +2 -2
- package/dist/src/planner/nodes/view-reference-node.js.map +1 -1
- package/dist/src/planner/nodes/window-function.js +3 -3
- package/dist/src/planner/nodes/window-function.js.map +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js +1 -1
- package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/scopes/global.js +3 -3
- package/dist/src/planner/scopes/global.js.map +1 -1
- package/dist/src/planner/scopes/param.d.ts.map +1 -1
- package/dist/src/planner/scopes/param.js +2 -2
- package/dist/src/planner/scopes/param.js.map +1 -1
- package/dist/src/planner/type-utils.d.ts +2 -12
- package/dist/src/planner/type-utils.d.ts.map +1 -1
- package/dist/src/planner/type-utils.js +6 -21
- package/dist/src/planner/type-utils.js.map +1 -1
- package/dist/src/runtime/emit/between.js +2 -2
- package/dist/src/runtime/emit/between.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +66 -30
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/subquery.js +8 -8
- package/dist/src/runtime/emit/subquery.js.map +1 -1
- package/dist/src/runtime/emit/temporal-arithmetic.d.ts +33 -0
- package/dist/src/runtime/emit/temporal-arithmetic.d.ts.map +1 -0
- package/dist/src/runtime/emit/temporal-arithmetic.js +269 -0
- package/dist/src/runtime/emit/temporal-arithmetic.js.map +1 -0
- package/dist/src/runtime/emit/unary.d.ts.map +1 -1
- package/dist/src/runtime/emit/unary.js +16 -4
- package/dist/src/runtime/emit/unary.js.map +1 -1
- package/dist/src/schema/catalog.js +3 -3
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/column.d.ts +0 -3
- package/dist/src/schema/column.d.ts.map +1 -1
- package/dist/src/schema/column.js +0 -2
- package/dist/src/schema/column.js.map +1 -1
- package/dist/src/schema/function.d.ts +29 -1
- package/dist/src/schema/function.d.ts.map +1 -1
- package/dist/src/schema/function.js.map +1 -1
- package/dist/src/schema/table.d.ts +3 -3
- package/dist/src/schema/table.d.ts.map +1 -1
- package/dist/src/schema/table.js +4 -6
- package/dist/src/schema/table.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/registry.d.ts.map +1 -1
- package/dist/src/types/registry.js +5 -1
- package/dist/src/types/registry.js.map +1 -1
- package/dist/src/types/temporal-types.d.ts +5 -0
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +122 -0
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/util/plan-formatter.d.ts.map +1 -1
- package/dist/src/util/plan-formatter.js +1 -5
- package/dist/src/util/plan-formatter.js.map +1 -1
- package/dist/src/util/row-descriptor.js +2 -2
- package/dist/src/util/row-descriptor.js.map +1 -1
- package/dist/src/vtab/best-access-plan.d.ts +4 -3
- package/dist/src/vtab/best-access-plan.d.ts.map +1 -1
- package/dist/src/vtab/best-access-plan.js.map +1 -1
- package/dist/src/vtab/memory/module.js +1 -1
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/package.json +1 -1
- package/src/common/datatype.ts +4 -5
- package/src/common/type-inference.ts +13 -22
- package/src/core/param.ts +4 -11
- package/src/func/builtins/aggregate.ts +24 -2
- package/src/func/builtins/builtin-window-functions.ts +10 -10
- package/src/func/builtins/conversion.ts +26 -1
- package/src/func/builtins/datetime.ts +9 -9
- package/src/func/builtins/explain.ts +53 -53
- package/src/func/builtins/generation.ts +2 -2
- package/src/func/builtins/index.ts +20 -1
- package/src/func/builtins/json-tvf.ts +17 -17
- package/src/func/builtins/json.ts +11 -11
- package/src/func/builtins/scalar.ts +205 -14
- package/src/func/builtins/schema.ts +18 -18
- package/src/func/builtins/string.ts +93 -80
- package/src/func/builtins/timespan.ts +179 -0
- package/src/func/registration.ts +35 -5
- package/src/index.ts +2 -1
- package/src/parser/parser.ts +2 -2
- package/src/planner/building/constraint-builder.ts +2 -2
- package/src/planner/building/delete.ts +3 -3
- package/src/planner/building/function-call.ts +44 -3
- package/src/planner/building/insert.ts +3 -3
- package/src/planner/building/select.ts +3 -2
- package/src/planner/building/update.ts +7 -7
- package/src/planner/nodes/aggregate-function.ts +13 -3
- package/src/planner/nodes/cte-node.ts +2 -2
- package/src/planner/nodes/declarative-schema.ts +3 -3
- package/src/planner/nodes/function.ts +8 -3
- package/src/planner/nodes/insert-node.ts +1 -1
- package/src/planner/nodes/pragma.ts +4 -3
- package/src/planner/nodes/reference.ts +1 -1
- package/src/planner/nodes/scalar.ts +54 -102
- package/src/planner/nodes/sequencing-node.ts +2 -2
- package/src/planner/nodes/sink-node.ts +2 -2
- package/src/planner/nodes/subquery.ts +5 -7
- package/src/planner/nodes/view-reference-node.ts +2 -2
- package/src/planner/nodes/window-function.ts +3 -3
- package/src/planner/rules/access/rule-select-access-path.ts +1 -1
- package/src/planner/rules/retrieve/rule-grow-retrieve.ts +1 -1
- package/src/planner/scopes/global.ts +3 -3
- package/src/planner/scopes/param.ts +2 -2
- package/src/planner/type-utils.ts +6 -14
- package/src/runtime/emit/between.ts +2 -2
- package/src/runtime/emit/binary.ts +74 -30
- package/src/runtime/emit/subquery.ts +8 -8
- package/src/runtime/emit/temporal-arithmetic.ts +302 -0
- package/src/runtime/emit/unary.ts +17 -4
- package/src/schema/catalog.ts +3 -3
- package/src/schema/column.ts +0 -3
- package/src/schema/function.ts +29 -1
- package/src/schema/table.ts +5 -7
- package/src/types/index.ts +1 -1
- package/src/types/registry.ts +5 -1
- package/src/types/temporal-types.ts +123 -0
- package/src/util/plan-formatter.ts +1 -4
- package/src/util/row-descriptor.ts +2 -2
- package/src/vtab/best-access-plan.ts +4 -3
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
459
|
+
if (typeof value !== 'string') return false;
|
|
460
460
|
const s = value.trim();
|
|
461
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return
|
|
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
|
|
464
|
+
return d.toString() === s;
|
|
465
465
|
} catch {
|
|
466
|
-
return
|
|
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
|
|
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
|
|
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
|
|
486
|
+
return true;
|
|
487
487
|
}
|
|
488
488
|
// Plain ISO local date-time
|
|
489
489
|
void Temporal.PlainDateTime.from(s);
|
|
490
|
-
return
|
|
490
|
+
return true;
|
|
491
491
|
} catch {
|
|
492
|
-
return
|
|
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',
|
|
85
|
-
{ name: 'parent_id', type: { typeClass: 'scalar',
|
|
86
|
-
{ name: 'subquery_level', type: { typeClass: 'scalar',
|
|
87
|
-
{ name: 'node_type', type: { typeClass: 'scalar',
|
|
88
|
-
{ name: 'op', type: { typeClass: 'scalar',
|
|
89
|
-
{ name: 'detail', type: { typeClass: 'scalar',
|
|
90
|
-
{ name: 'object_name', type: { typeClass: 'scalar',
|
|
91
|
-
{ name: 'alias', type: { typeClass: 'scalar',
|
|
92
|
-
{ name: 'properties', type: { typeClass: 'scalar',
|
|
93
|
-
{ name: 'physical', type: { typeClass: 'scalar',
|
|
94
|
-
{ name: 'est_cost', type: { typeClass: 'scalar',
|
|
95
|
-
{ name: 'est_rows', type: { typeClass: 'scalar',
|
|
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',
|
|
204
|
-
{ name: 'dependencies', type: { typeClass: 'scalar',
|
|
205
|
-
{ name: 'description', type: { typeClass: 'scalar',
|
|
206
|
-
{ name: 'estimated_cost', type: { typeClass: 'scalar',
|
|
207
|
-
{ name: 'is_subprogram', type: { typeClass: 'scalar',
|
|
208
|
-
{ name: 'parent_addr', type: { typeClass: 'scalar',
|
|
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',
|
|
284
|
-
{ name: 'depth', type: { typeClass: 'scalar',
|
|
285
|
-
{ name: 'location', type: { typeClass: 'scalar',
|
|
286
|
-
{ name: 'plan_node_type', type: { typeClass: 'scalar',
|
|
287
|
-
{ name: 'operation', type: { typeClass: 'scalar',
|
|
288
|
-
{ name: 'table_or_function', type: { typeClass: 'scalar',
|
|
289
|
-
{ name: 'is_virtual', type: { typeClass: 'scalar',
|
|
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',
|
|
391
|
-
{ name: 'operation', type: { typeClass: 'scalar',
|
|
392
|
-
{ name: 'dependencies', type: { typeClass: 'scalar',
|
|
393
|
-
{ name: 'input_values', type: { typeClass: 'scalar',
|
|
394
|
-
{ name: 'output_value', type: { typeClass: 'scalar',
|
|
395
|
-
{ name: 'duration_ms', type: { typeClass: 'scalar',
|
|
396
|
-
{ name: 'sub_programs', type: { typeClass: 'scalar',
|
|
397
|
-
{ name: 'error_message', type: { typeClass: 'scalar',
|
|
398
|
-
{ name: 'timestamp_ms', type: { typeClass: 'scalar',
|
|
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',
|
|
567
|
-
{ name: 'operation', type: { typeClass: 'scalar',
|
|
568
|
-
{ name: 'row_index', type: { typeClass: 'scalar',
|
|
569
|
-
{ name: 'row_data', type: { typeClass: 'scalar',
|
|
570
|
-
{ name: 'timestamp_ms', type: { typeClass: 'scalar',
|
|
571
|
-
{ name: 'row_count', type: { typeClass: 'scalar',
|
|
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',
|
|
675
|
-
{ name: 'object_name', type: { typeClass: 'scalar',
|
|
676
|
-
{ name: 'estimated_rows', type: { typeClass: 'scalar',
|
|
677
|
-
{ name: 'estimated_size_kb', type: { typeClass: 'scalar',
|
|
678
|
-
{ name: 'column_count', type: { typeClass: 'scalar',
|
|
679
|
-
{ name: 'index_count', type: { typeClass: 'scalar',
|
|
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',
|
|
702
|
-
{ name: 'relation_key', type: { typeClass: 'scalar',
|
|
703
|
-
{ name: 'base', type: { typeClass: 'scalar',
|
|
704
|
-
{ name: 'classification', type: { typeClass: 'scalar',
|
|
705
|
-
{ name: 'prepared_pk_params', type: { typeClass: 'scalar',
|
|
706
|
-
{ name: 'violation_sql', type: { typeClass: 'scalar',
|
|
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
|
-
|
|
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',
|
|
21
|
-
{ name: 'value', type: { typeClass: 'scalar',
|
|
22
|
-
{ name: 'type', type: { typeClass: 'scalar',
|
|
23
|
-
{ name: 'atom', type: { typeClass: 'scalar',
|
|
24
|
-
{ name: 'id', type: { typeClass: 'scalar',
|
|
25
|
-
{ name: 'parent', type: { typeClass: 'scalar',
|
|
26
|
-
{ name: 'fullkey', type: { typeClass: 'scalar',
|
|
27
|
-
{ name: 'path', type: { typeClass: 'scalar',
|
|
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',
|
|
123
|
-
{ name: 'value', type: { typeClass: 'scalar',
|
|
124
|
-
{ name: 'type', type: { typeClass: 'scalar',
|
|
125
|
-
{ name: 'atom', type: { typeClass: 'scalar',
|
|
126
|
-
{ name: 'id', type: { typeClass: 'scalar',
|
|
127
|
-
{ name: 'parent', type: { typeClass: 'scalar',
|
|
128
|
-
{ name: 'fullkey', type: { typeClass: 'scalar',
|
|
129
|
-
{ name: 'path', type: { typeClass: 'scalar',
|
|
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
|
|
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
|
|
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
|
|
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
|
|
81
|
+
return isValid;
|
|
82
82
|
} catch (e) {
|
|
83
83
|
errorLog('json_schema validation failed: %O', e);
|
|
84
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
133
|
+
return isValid;
|
|
134
134
|
} catch (e) {
|
|
135
135
|
errorLog('json_schema validation failed: %O', e);
|
|
136
|
-
return
|
|
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
|
|
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') {
|