@quereus/quereus 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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/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 +56 -47
- 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/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +40 -2
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/set-operation.d.ts.map +1 -1
- package/dist/src/runtime/emit/set-operation.js +33 -22
- package/dist/src/runtime/emit/set-operation.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 +12 -0
- 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/ast-stringify.js +1 -1
- package/dist/src/util/ast-stringify.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/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/scalar.ts +205 -14
- package/src/func/builtins/schema.ts +18 -18
- package/src/func/builtins/string.ts +91 -78
- 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/binary.ts +48 -2
- package/src/runtime/emit/set-operation.ts +52 -22
- package/src/runtime/emit/temporal-arithmetic.ts +302 -0
- package/src/runtime/emit/unary.ts +13 -0
- 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/ast-stringify.ts +1 -1
- 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
|
@@ -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: []
|
|
@@ -1,10 +1,64 @@
|
|
|
1
|
-
import type { SqlValue } from '../../common/types.js';
|
|
1
|
+
import type { SqlValue, DeepReadonly } from '../../common/types.js';
|
|
2
2
|
import { createScalarFunction } from '../registration.js';
|
|
3
3
|
import { compareSqlValues, getSqlDataTypeName } from '../../util/comparison.js';
|
|
4
|
+
import type { LogicalType } from '../../types/logical-type.js';
|
|
5
|
+
import { ANY_TYPE, INTEGER_TYPE, REAL_TYPE } from '../../types/builtin-types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Find the common type among multiple logical types.
|
|
9
|
+
* This implements type promotion rules for polymorphic functions.
|
|
10
|
+
*
|
|
11
|
+
* Rules:
|
|
12
|
+
* 1. If all types are the same, return that type
|
|
13
|
+
* 2. If mixing INTEGER and REAL, return REAL (numeric promotion)
|
|
14
|
+
* 3. Otherwise, return the first type (conservative approach)
|
|
15
|
+
*
|
|
16
|
+
* @param types Array of logical types to find common type for
|
|
17
|
+
* @returns The common logical type
|
|
18
|
+
*/
|
|
19
|
+
function findCommonType(types: ReadonlyArray<DeepReadonly<LogicalType>>): DeepReadonly<LogicalType> {
|
|
20
|
+
if (types.length === 0) return ANY_TYPE;
|
|
21
|
+
if (types.length === 1) return types[0];
|
|
22
|
+
|
|
23
|
+
// Check if all types are the same
|
|
24
|
+
const firstType = types[0];
|
|
25
|
+
const allSame = types.every(t => t.name === firstType.name);
|
|
26
|
+
if (allSame) return firstType;
|
|
27
|
+
|
|
28
|
+
// Check for numeric type promotion (INTEGER + REAL -> REAL)
|
|
29
|
+
const allNumeric = types.every(t => t.isNumeric === true);
|
|
30
|
+
if (allNumeric) {
|
|
31
|
+
// If any type is REAL, return REAL
|
|
32
|
+
const hasReal = types.some(t => t.name === 'REAL');
|
|
33
|
+
if (hasReal) return REAL_TYPE;
|
|
34
|
+
// All INTEGER
|
|
35
|
+
return INTEGER_TYPE;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// For non-numeric types, return the first type (conservative)
|
|
39
|
+
// In a more sophisticated implementation, we could:
|
|
40
|
+
// - Find a common supertype
|
|
41
|
+
// - Return ANY_TYPE if types are incompatible
|
|
42
|
+
// - Throw an error for incompatible types
|
|
43
|
+
return firstType;
|
|
44
|
+
}
|
|
4
45
|
|
|
5
46
|
// --- abs(X) ---
|
|
6
47
|
export const absFunc = createScalarFunction(
|
|
7
|
-
{
|
|
48
|
+
{
|
|
49
|
+
name: 'abs',
|
|
50
|
+
numArgs: 1,
|
|
51
|
+
deterministic: true,
|
|
52
|
+
// Type inference: return the same type as the input for numeric types
|
|
53
|
+
inferReturnType: (argTypes) => ({
|
|
54
|
+
typeClass: 'scalar',
|
|
55
|
+
logicalType: argTypes[0],
|
|
56
|
+
nullable: false,
|
|
57
|
+
isReadOnly: true
|
|
58
|
+
}),
|
|
59
|
+
// Validate that the argument is numeric
|
|
60
|
+
validateArgTypes: (argTypes) => argTypes[0].isNumeric === true
|
|
61
|
+
},
|
|
8
62
|
(arg: SqlValue): SqlValue => {
|
|
9
63
|
if (arg === null) return null;
|
|
10
64
|
if (typeof arg === 'bigint') return arg < 0n ? -arg : arg;
|
|
@@ -16,7 +70,19 @@ export const absFunc = createScalarFunction(
|
|
|
16
70
|
|
|
17
71
|
// --- round(X, Y?) ---
|
|
18
72
|
export const roundFunc = createScalarFunction(
|
|
19
|
-
{
|
|
73
|
+
{
|
|
74
|
+
name: 'round',
|
|
75
|
+
numArgs: -1,
|
|
76
|
+
deterministic: true,
|
|
77
|
+
// Type inference: return the same type as the input for numeric types
|
|
78
|
+
inferReturnType: (argTypes) => ({
|
|
79
|
+
typeClass: 'scalar',
|
|
80
|
+
logicalType: argTypes[0],
|
|
81
|
+
nullable: false,
|
|
82
|
+
isReadOnly: true
|
|
83
|
+
}),
|
|
84
|
+
validateArgTypes: (argTypes) => argTypes[0].isNumeric === true
|
|
85
|
+
},
|
|
20
86
|
(numVal: SqlValue, placesVal?: SqlValue): SqlValue => {
|
|
21
87
|
if (numVal === null) return null;
|
|
22
88
|
const x = Number(numVal);
|
|
@@ -40,7 +106,18 @@ export const roundFunc = createScalarFunction(
|
|
|
40
106
|
|
|
41
107
|
// --- coalesce(...) ---
|
|
42
108
|
export const coalesceFunc = createScalarFunction(
|
|
43
|
-
{
|
|
109
|
+
{
|
|
110
|
+
name: 'coalesce',
|
|
111
|
+
numArgs: -1,
|
|
112
|
+
deterministic: true,
|
|
113
|
+
// Type inference: find the common type among all arguments
|
|
114
|
+
inferReturnType: (argTypes) => ({
|
|
115
|
+
typeClass: 'scalar',
|
|
116
|
+
logicalType: findCommonType(argTypes),
|
|
117
|
+
nullable: true, // coalesce can return null if all args are null
|
|
118
|
+
isReadOnly: true
|
|
119
|
+
})
|
|
120
|
+
},
|
|
44
121
|
(...args: SqlValue[]): SqlValue => {
|
|
45
122
|
for (const arg of args) {
|
|
46
123
|
if (arg !== null) {
|
|
@@ -53,7 +130,18 @@ export const coalesceFunc = createScalarFunction(
|
|
|
53
130
|
|
|
54
131
|
// --- nullif(X, Y) ---
|
|
55
132
|
export const nullifFunc = createScalarFunction(
|
|
56
|
-
{
|
|
133
|
+
{
|
|
134
|
+
name: 'nullif',
|
|
135
|
+
numArgs: 2,
|
|
136
|
+
deterministic: true,
|
|
137
|
+
// Type inference: return the type of the first argument (nullable)
|
|
138
|
+
inferReturnType: (argTypes) => ({
|
|
139
|
+
typeClass: 'scalar',
|
|
140
|
+
logicalType: argTypes[0],
|
|
141
|
+
nullable: true, // nullif can always return null
|
|
142
|
+
isReadOnly: true
|
|
143
|
+
})
|
|
144
|
+
},
|
|
57
145
|
(argX: SqlValue, argY: SqlValue): SqlValue => {
|
|
58
146
|
const comparison = compareSqlValues(argX, argY);
|
|
59
147
|
return comparison === 0 ? null : argX;
|
|
@@ -96,7 +184,18 @@ export const randomblobFunc = createScalarFunction(
|
|
|
96
184
|
|
|
97
185
|
// --- iif(X, Y, Z) ---
|
|
98
186
|
export const iifFunc = createScalarFunction(
|
|
99
|
-
{
|
|
187
|
+
{
|
|
188
|
+
name: 'iif',
|
|
189
|
+
numArgs: 3,
|
|
190
|
+
deterministic: true,
|
|
191
|
+
// Type inference: find the common type between the true and false values
|
|
192
|
+
inferReturnType: (argTypes) => ({
|
|
193
|
+
typeClass: 'scalar',
|
|
194
|
+
logicalType: findCommonType([argTypes[1], argTypes[2]]), // Common type of Y and Z
|
|
195
|
+
nullable: true, // Could return either Y or Z, so nullable if either is
|
|
196
|
+
isReadOnly: true
|
|
197
|
+
})
|
|
198
|
+
},
|
|
100
199
|
(condition: SqlValue, trueVal: SqlValue, falseVal: SqlValue): SqlValue => {
|
|
101
200
|
let isTrue: boolean;
|
|
102
201
|
if (condition === null) {
|
|
@@ -118,7 +217,19 @@ export const iifFunc = createScalarFunction(
|
|
|
118
217
|
|
|
119
218
|
// --- sqrt(X) ---
|
|
120
219
|
export const sqrtFunc = createScalarFunction(
|
|
121
|
-
{
|
|
220
|
+
{
|
|
221
|
+
name: 'sqrt',
|
|
222
|
+
numArgs: 1,
|
|
223
|
+
deterministic: true,
|
|
224
|
+
// Type inference: sqrt always returns REAL (even for INTEGER input)
|
|
225
|
+
inferReturnType: (argTypes) => ({
|
|
226
|
+
typeClass: 'scalar',
|
|
227
|
+
logicalType: argTypes[0].name === 'INTEGER' ? argTypes[0] : argTypes[0], // Keep input type
|
|
228
|
+
nullable: false,
|
|
229
|
+
isReadOnly: true
|
|
230
|
+
}),
|
|
231
|
+
validateArgTypes: (argTypes) => argTypes[0].isNumeric === true
|
|
232
|
+
},
|
|
122
233
|
(arg: SqlValue): SqlValue => {
|
|
123
234
|
if (arg === null) return null;
|
|
124
235
|
const num = Number(arg);
|
|
@@ -149,7 +260,19 @@ export const powerFunc = createScalarFunction(
|
|
|
149
260
|
|
|
150
261
|
// --- floor(X) ---
|
|
151
262
|
export const floorFunc = createScalarFunction(
|
|
152
|
-
{
|
|
263
|
+
{
|
|
264
|
+
name: 'floor',
|
|
265
|
+
numArgs: 1,
|
|
266
|
+
deterministic: true,
|
|
267
|
+
// Type inference: preserve input type
|
|
268
|
+
inferReturnType: (argTypes) => ({
|
|
269
|
+
typeClass: 'scalar',
|
|
270
|
+
logicalType: argTypes[0],
|
|
271
|
+
nullable: false,
|
|
272
|
+
isReadOnly: true
|
|
273
|
+
}),
|
|
274
|
+
validateArgTypes: (argTypes) => argTypes[0].isNumeric === true
|
|
275
|
+
},
|
|
153
276
|
(arg: SqlValue): SqlValue => {
|
|
154
277
|
if (arg === null) return null;
|
|
155
278
|
const num = Number(arg);
|
|
@@ -167,19 +290,41 @@ const ceil = (arg: SqlValue): SqlValue => {
|
|
|
167
290
|
return Math.ceil(num);
|
|
168
291
|
};
|
|
169
292
|
|
|
293
|
+
const ceilTypeInference = {
|
|
294
|
+
inferReturnType: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => ({
|
|
295
|
+
typeClass: 'scalar' as const,
|
|
296
|
+
logicalType: argTypes[0],
|
|
297
|
+
nullable: false,
|
|
298
|
+
isReadOnly: true
|
|
299
|
+
}),
|
|
300
|
+
validateArgTypes: (argTypes: ReadonlyArray<DeepReadonly<LogicalType>>) => argTypes[0].isNumeric === true
|
|
301
|
+
};
|
|
302
|
+
|
|
170
303
|
export const ceilFunc = createScalarFunction(
|
|
171
|
-
{ name: 'ceil', numArgs: 1, deterministic: true },
|
|
304
|
+
{ name: 'ceil', numArgs: 1, deterministic: true, ...ceilTypeInference },
|
|
172
305
|
ceil
|
|
173
306
|
);
|
|
174
307
|
|
|
175
308
|
export const ceilingFunc = createScalarFunction(
|
|
176
|
-
{ name: 'ceiling', numArgs: 1, deterministic: true },
|
|
309
|
+
{ name: 'ceiling', numArgs: 1, deterministic: true, ...ceilTypeInference },
|
|
177
310
|
ceil
|
|
178
311
|
);
|
|
179
312
|
|
|
180
313
|
// Math clamp function
|
|
181
314
|
export const clampFunc = createScalarFunction(
|
|
182
|
-
{
|
|
315
|
+
{
|
|
316
|
+
name: 'clamp',
|
|
317
|
+
numArgs: 3,
|
|
318
|
+
deterministic: true,
|
|
319
|
+
// Type inference: return the type of the first argument (value)
|
|
320
|
+
inferReturnType: (argTypes) => ({
|
|
321
|
+
typeClass: 'scalar',
|
|
322
|
+
logicalType: argTypes[0],
|
|
323
|
+
nullable: true,
|
|
324
|
+
isReadOnly: true
|
|
325
|
+
}),
|
|
326
|
+
validateArgTypes: (argTypes) => argTypes[0].isNumeric === true && argTypes[1].isNumeric === true && argTypes[2].isNumeric === true
|
|
327
|
+
},
|
|
183
328
|
(value: SqlValue, min: SqlValue, max: SqlValue): SqlValue => {
|
|
184
329
|
const v = Number(value);
|
|
185
330
|
const minVal = Number(min);
|
|
@@ -192,7 +337,18 @@ export const clampFunc = createScalarFunction(
|
|
|
192
337
|
|
|
193
338
|
// Greatest-of function
|
|
194
339
|
export const greatestFunc = createScalarFunction(
|
|
195
|
-
{
|
|
340
|
+
{
|
|
341
|
+
name: 'greatest',
|
|
342
|
+
numArgs: -1,
|
|
343
|
+
deterministic: true,
|
|
344
|
+
// Type inference: find the common type among all arguments
|
|
345
|
+
inferReturnType: (argTypes) => ({
|
|
346
|
+
typeClass: 'scalar',
|
|
347
|
+
logicalType: findCommonType(argTypes),
|
|
348
|
+
nullable: true,
|
|
349
|
+
isReadOnly: true
|
|
350
|
+
})
|
|
351
|
+
},
|
|
196
352
|
(...args: SqlValue[]): SqlValue => {
|
|
197
353
|
if (args.length === 0) return null;
|
|
198
354
|
return args.reduce((max, current) => {
|
|
@@ -206,7 +362,18 @@ export const greatestFunc = createScalarFunction(
|
|
|
206
362
|
|
|
207
363
|
// Least-of function
|
|
208
364
|
export const leastFunc = createScalarFunction(
|
|
209
|
-
{
|
|
365
|
+
{
|
|
366
|
+
name: 'least',
|
|
367
|
+
numArgs: -1,
|
|
368
|
+
deterministic: true,
|
|
369
|
+
// Type inference: find the common type among all arguments
|
|
370
|
+
inferReturnType: (argTypes) => ({
|
|
371
|
+
typeClass: 'scalar',
|
|
372
|
+
logicalType: findCommonType(argTypes),
|
|
373
|
+
nullable: true,
|
|
374
|
+
isReadOnly: true
|
|
375
|
+
})
|
|
376
|
+
},
|
|
210
377
|
(...args: SqlValue[]): SqlValue => {
|
|
211
378
|
if (args.length === 0) return null;
|
|
212
379
|
return args.reduce((min, current) => {
|
|
@@ -220,7 +387,31 @@ export const leastFunc = createScalarFunction(
|
|
|
220
387
|
|
|
221
388
|
// Choose function
|
|
222
389
|
export const chooseFunc = createScalarFunction(
|
|
223
|
-
{
|
|
390
|
+
{
|
|
391
|
+
name: 'choose',
|
|
392
|
+
numArgs: -1,
|
|
393
|
+
deterministic: true,
|
|
394
|
+
// Type inference: find the common type among all value arguments (skip index at position 0)
|
|
395
|
+
inferReturnType: (argTypes) => {
|
|
396
|
+
if (argTypes.length < 2) {
|
|
397
|
+
// Need at least index and one value
|
|
398
|
+
return {
|
|
399
|
+
typeClass: 'scalar',
|
|
400
|
+
logicalType: argTypes[0] || ANY_TYPE,
|
|
401
|
+
nullable: true,
|
|
402
|
+
isReadOnly: true
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
// Find common type among all value arguments (skip the index at position 0)
|
|
406
|
+
const valueTypes = argTypes.slice(1);
|
|
407
|
+
return {
|
|
408
|
+
typeClass: 'scalar',
|
|
409
|
+
logicalType: findCommonType(valueTypes),
|
|
410
|
+
nullable: true,
|
|
411
|
+
isReadOnly: true
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
},
|
|
224
415
|
(...args: SqlValue[]): SqlValue => {
|
|
225
416
|
if (args.length === 0) return null;
|
|
226
417
|
const index = Number(args[0]);
|
|
@@ -1,6 +1,5 @@
|
|
|
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";
|
|
5
4
|
import { QuereusError } from "../../common/errors.js";
|
|
6
5
|
import { StatusCode } from "../../common/types.js";
|
|
@@ -8,6 +7,7 @@ import type { Database } from "../../core/database.js";
|
|
|
8
7
|
import type { FunctionSchema } from "../../schema/function.js";
|
|
9
8
|
import { isScalarFunctionSchema, isTableValuedFunctionSchema, isAggregateFunctionSchema, isWindowFunctionSchema } from "../../schema/function.js";
|
|
10
9
|
import { Schema } from "../../schema/schema.js";
|
|
10
|
+
import { INTEGER_TYPE, TEXT_TYPE } from "../../types/builtin-types.js";
|
|
11
11
|
import { ColumnSchema } from "../../schema/column.js";
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -31,10 +31,10 @@ export const schemaFunc = createIntegratedTableValuedFunction(
|
|
|
31
31
|
isReadOnly: true,
|
|
32
32
|
isSet: false,
|
|
33
33
|
columns: [
|
|
34
|
-
{ name: 'type', type: { typeClass: 'scalar',
|
|
35
|
-
{ name: 'name', type: { typeClass: 'scalar',
|
|
36
|
-
{ name: 'tbl_name', type: { typeClass: 'scalar',
|
|
37
|
-
{ name: 'sql', type: { typeClass: 'scalar',
|
|
34
|
+
{ name: 'type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
35
|
+
{ name: 'name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
36
|
+
{ name: 'tbl_name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
37
|
+
{ name: 'sql', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true }
|
|
38
38
|
],
|
|
39
39
|
keys: [],
|
|
40
40
|
rowConstraints: []
|
|
@@ -100,12 +100,12 @@ export const tableInfoFunc = createIntegratedTableValuedFunction(
|
|
|
100
100
|
isReadOnly: true,
|
|
101
101
|
isSet: false,
|
|
102
102
|
columns: [
|
|
103
|
-
{ name: 'cid', type: { typeClass: 'scalar',
|
|
104
|
-
{ name: 'name', type: { typeClass: 'scalar',
|
|
105
|
-
{ name: 'type', type: { typeClass: 'scalar',
|
|
106
|
-
{ name: 'notnull', type: { typeClass: 'scalar',
|
|
107
|
-
{ name: 'dflt_value', type: { typeClass: 'scalar',
|
|
108
|
-
{ name: 'pk', type: { typeClass: 'scalar',
|
|
103
|
+
{ name: 'cid', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
104
|
+
{ name: 'name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
105
|
+
{ name: 'type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
106
|
+
{ name: 'notnull', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
107
|
+
{ name: 'dflt_value', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: true, isReadOnly: true }, generated: true },
|
|
108
|
+
{ name: 'pk', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true }
|
|
109
109
|
],
|
|
110
110
|
keys: [],
|
|
111
111
|
rowConstraints: []
|
|
@@ -129,7 +129,7 @@ export const tableInfoFunc = createIntegratedTableValuedFunction(
|
|
|
129
129
|
yield [
|
|
130
130
|
i, // cid
|
|
131
131
|
column.name, // name
|
|
132
|
-
column.
|
|
132
|
+
column.logicalType.name, // type
|
|
133
133
|
column.notNull ? 1 : 0, // notnull
|
|
134
134
|
column.defaultValue?.toString() || null, // dflt_value
|
|
135
135
|
isPrimaryKey ? 1 : 0 // pk
|
|
@@ -154,12 +154,12 @@ export const functionInfoFunc = createIntegratedTableValuedFunction(
|
|
|
154
154
|
isReadOnly: true,
|
|
155
155
|
isSet: false,
|
|
156
156
|
columns: [
|
|
157
|
-
{ name: 'name', type: { typeClass: 'scalar',
|
|
158
|
-
{ name: 'num_args', type: { typeClass: 'scalar',
|
|
159
|
-
{ name: 'type', type: { typeClass: 'scalar',
|
|
160
|
-
{ name: 'deterministic', type: { typeClass: 'scalar',
|
|
161
|
-
{ name: 'flags', type: { typeClass: 'scalar',
|
|
162
|
-
{ name: 'signature', type: { typeClass: 'scalar',
|
|
157
|
+
{ name: 'name', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
158
|
+
{ name: 'num_args', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
159
|
+
{ name: 'type', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
160
|
+
{ name: 'deterministic', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
161
|
+
{ name: 'flags', type: { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false, isReadOnly: true }, generated: true },
|
|
162
|
+
{ name: 'signature', type: { typeClass: 'scalar', logicalType: TEXT_TYPE, nullable: false, isReadOnly: true }, generated: true }
|
|
163
163
|
],
|
|
164
164
|
keys: [],
|
|
165
165
|
rowConstraints: []
|