@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SqlValue } from '../../common/types.js';
|
|
2
2
|
import * as AST from '../../parser/ast.js';
|
|
3
3
|
import { Attribute, type RelationalPlanNode } from './plan-node.js';
|
|
4
4
|
import { PlanNodeType } from './plan-node-type.js';
|
|
@@ -6,6 +6,7 @@ import { expressionToString } from '../../util/ast-stringify.js';
|
|
|
6
6
|
import { PlanNode } from './plan-node.js';
|
|
7
7
|
import { RelationType } from '../../common/datatype.js';
|
|
8
8
|
import { Scope } from '../scopes/scope.js';
|
|
9
|
+
import { TEXT_TYPE } from '../../types/builtin-types.js';
|
|
9
10
|
|
|
10
11
|
export class PragmaPlanNode extends PlanNode implements RelationalPlanNode {
|
|
11
12
|
override readonly nodeType = PlanNodeType.Pragma;
|
|
@@ -29,7 +30,7 @@ export class PragmaPlanNode extends PlanNode implements RelationalPlanNode {
|
|
|
29
30
|
name: "name",
|
|
30
31
|
type: {
|
|
31
32
|
typeClass: 'scalar',
|
|
32
|
-
|
|
33
|
+
logicalType: TEXT_TYPE,
|
|
33
34
|
nullable: false,
|
|
34
35
|
isReadOnly: true,
|
|
35
36
|
},
|
|
@@ -39,7 +40,7 @@ export class PragmaPlanNode extends PlanNode implements RelationalPlanNode {
|
|
|
39
40
|
name: "value",
|
|
40
41
|
type: {
|
|
41
42
|
typeClass: 'scalar',
|
|
42
|
-
|
|
43
|
+
logicalType: TEXT_TYPE,
|
|
43
44
|
nullable: false,
|
|
44
45
|
},
|
|
45
46
|
generated: true,
|
|
@@ -38,7 +38,7 @@ export class TableReferenceNode extends PlanNode implements ZeroAryRelationalNod
|
|
|
38
38
|
name: column.name,
|
|
39
39
|
type: {
|
|
40
40
|
typeClass: 'scalar' as const,
|
|
41
|
-
|
|
41
|
+
logicalType: column.logicalType,
|
|
42
42
|
nullable: !column.notNull,
|
|
43
43
|
isReadOnly: false,
|
|
44
44
|
collationName: column.collation
|
|
@@ -8,6 +8,8 @@ import { Cached } from "../../util/cached.js";
|
|
|
8
8
|
import { formatExpression, formatScalarType } from "../../util/plan-formatter.js";
|
|
9
9
|
import { quereusError } from '../../common/errors.js';
|
|
10
10
|
import { StatusCode } from '../../common/types.js';
|
|
11
|
+
import { NULL_TYPE, INTEGER_TYPE, REAL_TYPE, TEXT_TYPE, BLOB_TYPE, BOOLEAN_TYPE } from "../../types/builtin-types.js";
|
|
12
|
+
import { typeRegistry } from "../../types/registry.js";
|
|
11
13
|
|
|
12
14
|
export class UnaryOpNode extends PlanNode implements UnaryScalarNode {
|
|
13
15
|
readonly nodeType = PlanNodeType.UnaryOp;
|
|
@@ -25,36 +27,31 @@ export class UnaryOpNode extends PlanNode implements UnaryScalarNode {
|
|
|
25
27
|
generateType = (): ScalarType => {
|
|
26
28
|
const operandType = this.operand.getType();
|
|
27
29
|
|
|
28
|
-
let
|
|
29
|
-
let affinity: SqlDataType = operandType.affinity;
|
|
30
|
+
let logicalType = operandType.logicalType;
|
|
30
31
|
let nullable = operandType.nullable;
|
|
31
32
|
|
|
32
33
|
switch (this.expression.operator) {
|
|
33
34
|
case 'NOT':
|
|
34
35
|
case 'IS NULL':
|
|
35
36
|
case 'IS NOT NULL':
|
|
36
|
-
|
|
37
|
-
affinity = SqlDataType.INTEGER;
|
|
37
|
+
logicalType = BOOLEAN_TYPE;
|
|
38
38
|
nullable = false; // Boolean results are never null
|
|
39
39
|
break;
|
|
40
40
|
case '-':
|
|
41
41
|
case '+':
|
|
42
|
-
// Numeric unary operators preserve type
|
|
43
|
-
datatype = operandType.datatype;
|
|
42
|
+
// Numeric unary operators preserve type
|
|
44
43
|
break;
|
|
45
44
|
case '~':
|
|
46
45
|
// Bitwise NOT - results in integer
|
|
47
|
-
|
|
48
|
-
affinity = SqlDataType.INTEGER;
|
|
46
|
+
logicalType = INTEGER_TYPE;
|
|
49
47
|
break;
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
return {
|
|
53
51
|
typeClass: 'scalar',
|
|
54
|
-
|
|
52
|
+
logicalType,
|
|
55
53
|
nullable,
|
|
56
54
|
isReadOnly: operandType.isReadOnly,
|
|
57
|
-
datatype,
|
|
58
55
|
collationName: operandType.collationName,
|
|
59
56
|
};
|
|
60
57
|
}
|
|
@@ -130,17 +127,11 @@ export class BinaryOpNode extends PlanNode implements BinaryScalarNode {
|
|
|
130
127
|
const leftType = this.left.getType();
|
|
131
128
|
const rightType = this.right.getType();
|
|
132
129
|
|
|
133
|
-
|
|
130
|
+
let logicalType = leftType.logicalType;
|
|
134
131
|
|
|
135
|
-
let datatype: SqlDataType | undefined;
|
|
136
132
|
switch (this.expression.operator) {
|
|
137
133
|
case 'OR':
|
|
138
134
|
case 'AND':
|
|
139
|
-
case '+':
|
|
140
|
-
case '-':
|
|
141
|
-
case '*':
|
|
142
|
-
case '/':
|
|
143
|
-
case '%':
|
|
144
135
|
case '=':
|
|
145
136
|
case '!=':
|
|
146
137
|
case '<':
|
|
@@ -150,10 +141,33 @@ export class BinaryOpNode extends PlanNode implements BinaryScalarNode {
|
|
|
150
141
|
case 'IS':
|
|
151
142
|
case 'IS NOT':
|
|
152
143
|
case 'IN':
|
|
153
|
-
|
|
144
|
+
// Comparison and logical operators return boolean
|
|
145
|
+
logicalType = BOOLEAN_TYPE;
|
|
146
|
+
break;
|
|
147
|
+
case '+':
|
|
148
|
+
case '-':
|
|
149
|
+
case '*':
|
|
150
|
+
case '/':
|
|
151
|
+
case '%':
|
|
152
|
+
// Arithmetic operators - implement numeric type promotion
|
|
153
|
+
// Rules: INTEGER + INTEGER -> INTEGER, INTEGER + REAL -> REAL, REAL + REAL -> REAL
|
|
154
|
+
if (leftType.logicalType.isNumeric && rightType.logicalType.isNumeric) {
|
|
155
|
+
// Both operands are numeric
|
|
156
|
+
if (leftType.logicalType.name === 'REAL' || rightType.logicalType.name === 'REAL') {
|
|
157
|
+
// If either is REAL, result is REAL
|
|
158
|
+
logicalType = REAL_TYPE;
|
|
159
|
+
} else {
|
|
160
|
+
// Both are INTEGER, result is INTEGER
|
|
161
|
+
logicalType = INTEGER_TYPE;
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
// Non-numeric operands - use left operand type (fallback)
|
|
165
|
+
logicalType = leftType.logicalType;
|
|
166
|
+
}
|
|
154
167
|
break;
|
|
155
168
|
case '||':
|
|
156
|
-
|
|
169
|
+
// String concatenation
|
|
170
|
+
logicalType = TEXT_TYPE;
|
|
157
171
|
break;
|
|
158
172
|
};
|
|
159
173
|
|
|
@@ -162,10 +176,9 @@ export class BinaryOpNode extends PlanNode implements BinaryScalarNode {
|
|
|
162
176
|
|
|
163
177
|
return {
|
|
164
178
|
typeClass: 'scalar',
|
|
165
|
-
|
|
179
|
+
logicalType,
|
|
166
180
|
nullable: leftType.nullable || rightType.nullable,
|
|
167
181
|
isReadOnly: leftType.isReadOnly || rightType.isReadOnly,
|
|
168
|
-
datatype,
|
|
169
182
|
collationName,
|
|
170
183
|
};
|
|
171
184
|
}
|
|
@@ -252,55 +265,49 @@ export class LiteralNode extends PlanNode implements ZeroAryScalarNode, Constant
|
|
|
252
265
|
if (value === null) {
|
|
253
266
|
return {
|
|
254
267
|
typeClass: 'scalar',
|
|
255
|
-
|
|
268
|
+
logicalType: NULL_TYPE,
|
|
256
269
|
nullable: true,
|
|
257
270
|
isReadOnly: true,
|
|
258
|
-
datatype: SqlDataType.NULL,
|
|
259
271
|
};
|
|
260
272
|
}
|
|
261
273
|
if (typeof value === 'number') {
|
|
262
274
|
return {
|
|
263
275
|
typeClass: 'scalar',
|
|
264
|
-
|
|
276
|
+
logicalType: REAL_TYPE,
|
|
265
277
|
nullable: false,
|
|
266
278
|
isReadOnly: true,
|
|
267
|
-
datatype: SqlDataType.REAL,
|
|
268
279
|
};
|
|
269
280
|
}
|
|
270
281
|
if (typeof value === 'bigint') {
|
|
271
282
|
return {
|
|
272
283
|
typeClass: 'scalar',
|
|
273
|
-
|
|
284
|
+
logicalType: INTEGER_TYPE,
|
|
274
285
|
nullable: false,
|
|
275
286
|
isReadOnly: true,
|
|
276
|
-
datatype: SqlDataType.INTEGER,
|
|
277
287
|
};
|
|
278
288
|
}
|
|
279
289
|
if (typeof value === 'string') {
|
|
280
290
|
return {
|
|
281
291
|
typeClass: 'scalar',
|
|
282
|
-
|
|
292
|
+
logicalType: TEXT_TYPE,
|
|
283
293
|
nullable: false,
|
|
284
294
|
isReadOnly: true,
|
|
285
|
-
datatype: SqlDataType.TEXT,
|
|
286
295
|
};
|
|
287
296
|
}
|
|
288
297
|
if (typeof value === 'boolean') {
|
|
289
298
|
return {
|
|
290
299
|
typeClass: 'scalar',
|
|
291
|
-
|
|
300
|
+
logicalType: BOOLEAN_TYPE,
|
|
292
301
|
nullable: false,
|
|
293
302
|
isReadOnly: true,
|
|
294
|
-
datatype: SqlDataType.INTEGER,
|
|
295
303
|
};
|
|
296
304
|
}
|
|
297
305
|
if (value instanceof Uint8Array) {
|
|
298
306
|
return {
|
|
299
307
|
typeClass: 'scalar',
|
|
300
|
-
|
|
308
|
+
logicalType: BLOB_TYPE,
|
|
301
309
|
nullable: false,
|
|
302
310
|
isReadOnly: true,
|
|
303
|
-
datatype: SqlDataType.BLOB,
|
|
304
311
|
};
|
|
305
312
|
}
|
|
306
313
|
quereusError(`Unknown literal type ${typeof value}`, StatusCode.INTERNAL);
|
|
@@ -377,16 +384,15 @@ export class CaseExprNode extends PlanNode implements NaryScalarNode {
|
|
|
377
384
|
// No THEN clauses and no ELSE - should not happen in valid SQL
|
|
378
385
|
return {
|
|
379
386
|
typeClass: 'scalar',
|
|
380
|
-
|
|
387
|
+
logicalType: NULL_TYPE,
|
|
381
388
|
nullable: true,
|
|
382
389
|
isReadOnly: true,
|
|
383
|
-
datatype: SqlDataType.NULL,
|
|
384
390
|
};
|
|
385
391
|
}
|
|
386
392
|
|
|
387
393
|
// Use the first result expression as the base type
|
|
388
394
|
const firstType = resultExpressions[0].getType();
|
|
389
|
-
let
|
|
395
|
+
let logicalType = firstType.logicalType;
|
|
390
396
|
let nullable = firstType.nullable;
|
|
391
397
|
let isReadOnly = firstType.isReadOnly;
|
|
392
398
|
let collationName = firstType.collationName;
|
|
@@ -411,9 +417,9 @@ export class CaseExprNode extends PlanNode implements NaryScalarNode {
|
|
|
411
417
|
}
|
|
412
418
|
|
|
413
419
|
// TODO: Implement proper type coercion rules for SQL
|
|
414
|
-
// For now, if types differ, default to TEXT
|
|
415
|
-
if (exprType.
|
|
416
|
-
|
|
420
|
+
// For now, if types differ, default to TEXT
|
|
421
|
+
if (exprType.logicalType !== logicalType) {
|
|
422
|
+
logicalType = TEXT_TYPE;
|
|
417
423
|
}
|
|
418
424
|
}
|
|
419
425
|
|
|
@@ -424,11 +430,10 @@ export class CaseExprNode extends PlanNode implements NaryScalarNode {
|
|
|
424
430
|
|
|
425
431
|
return {
|
|
426
432
|
typeClass: 'scalar',
|
|
427
|
-
|
|
433
|
+
logicalType,
|
|
428
434
|
nullable,
|
|
429
435
|
isReadOnly,
|
|
430
436
|
collationName,
|
|
431
|
-
// Don't set datatype since it can vary based on runtime conditions
|
|
432
437
|
};
|
|
433
438
|
}
|
|
434
439
|
|
|
@@ -558,69 +563,17 @@ export class CastNode extends PlanNode implements UnaryScalarNode {
|
|
|
558
563
|
|
|
559
564
|
generateType = (): ScalarType => {
|
|
560
565
|
const operandType = this.operand.getType();
|
|
561
|
-
const targetType = this.expression.targetType
|
|
562
|
-
|
|
563
|
-
//
|
|
564
|
-
|
|
565
|
-
let affinity: SqlDataType;
|
|
566
|
-
|
|
567
|
-
switch (targetType) {
|
|
568
|
-
case 'INTEGER':
|
|
569
|
-
case 'INT':
|
|
570
|
-
case 'TINYINT':
|
|
571
|
-
case 'SMALLINT':
|
|
572
|
-
case 'MEDIUMINT':
|
|
573
|
-
case 'BIGINT':
|
|
574
|
-
case 'UNSIGNED BIG INT':
|
|
575
|
-
case 'INT2':
|
|
576
|
-
case 'INT8':
|
|
577
|
-
datatype = SqlDataType.INTEGER;
|
|
578
|
-
affinity = SqlDataType.INTEGER;
|
|
579
|
-
break;
|
|
580
|
-
case 'REAL':
|
|
581
|
-
case 'DOUBLE':
|
|
582
|
-
case 'DOUBLE PRECISION':
|
|
583
|
-
case 'FLOAT':
|
|
584
|
-
datatype = SqlDataType.REAL;
|
|
585
|
-
affinity = SqlDataType.REAL;
|
|
586
|
-
break;
|
|
587
|
-
case 'TEXT':
|
|
588
|
-
case 'CHARACTER':
|
|
589
|
-
case 'VARCHAR':
|
|
590
|
-
case 'VARYING CHARACTER':
|
|
591
|
-
case 'NCHAR':
|
|
592
|
-
case 'NATIVE CHARACTER':
|
|
593
|
-
case 'NVARCHAR':
|
|
594
|
-
case 'CLOB':
|
|
595
|
-
datatype = SqlDataType.TEXT;
|
|
596
|
-
affinity = SqlDataType.TEXT;
|
|
597
|
-
break;
|
|
598
|
-
case 'BLOB':
|
|
599
|
-
datatype = SqlDataType.BLOB;
|
|
600
|
-
affinity = SqlDataType.BLOB;
|
|
601
|
-
break;
|
|
602
|
-
case 'NUMERIC':
|
|
603
|
-
case 'DECIMAL':
|
|
604
|
-
case 'BOOLEAN':
|
|
605
|
-
case 'DATE':
|
|
606
|
-
case 'DATETIME':
|
|
607
|
-
datatype = SqlDataType.NUMERIC;
|
|
608
|
-
affinity = SqlDataType.NUMERIC;
|
|
609
|
-
break;
|
|
610
|
-
default:
|
|
611
|
-
// For unknown types, default to BLOB affinity
|
|
612
|
-
datatype = SqlDataType.BLOB;
|
|
613
|
-
affinity = SqlDataType.BLOB;
|
|
614
|
-
break;
|
|
615
|
-
}
|
|
566
|
+
const targetType = this.expression.targetType;
|
|
567
|
+
|
|
568
|
+
// Look up the logical type from the type registry
|
|
569
|
+
const logicalType = typeRegistry.getTypeOrDefault(targetType);
|
|
616
570
|
|
|
617
571
|
return {
|
|
618
572
|
typeClass: 'scalar',
|
|
619
|
-
|
|
573
|
+
logicalType,
|
|
620
574
|
nullable: operandType.nullable, // CAST preserves nullability
|
|
621
575
|
isReadOnly: operandType.isReadOnly,
|
|
622
|
-
|
|
623
|
-
collationName: affinity === SqlDataType.TEXT ? operandType.collationName : undefined,
|
|
576
|
+
collationName: logicalType.isTextual ? operandType.collationName : undefined,
|
|
624
577
|
};
|
|
625
578
|
}
|
|
626
579
|
|
|
@@ -756,13 +709,12 @@ export class BetweenNode extends PlanNode implements TernaryScalarNode {
|
|
|
756
709
|
}
|
|
757
710
|
|
|
758
711
|
getType(): ScalarType {
|
|
759
|
-
// BETWEEN always returns
|
|
712
|
+
// BETWEEN always returns BOOLEAN
|
|
760
713
|
return {
|
|
761
714
|
typeClass: 'scalar',
|
|
762
|
-
|
|
715
|
+
logicalType: BOOLEAN_TYPE,
|
|
763
716
|
nullable: false,
|
|
764
717
|
isReadOnly: true,
|
|
765
|
-
datatype: SqlDataType.INTEGER,
|
|
766
718
|
};
|
|
767
719
|
}
|
|
768
720
|
|
|
@@ -3,7 +3,7 @@ import { isRelationalNode, PlanNode, type Attribute, type RelationalPlanNode, ty
|
|
|
3
3
|
import type { RelationType } from '../../common/datatype.js';
|
|
4
4
|
import type { Scope } from '../scopes/scope.js';
|
|
5
5
|
import { Cached } from '../../util/cached.js';
|
|
6
|
-
import {
|
|
6
|
+
import { INTEGER_TYPE } from '../../types/builtin-types.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Represents a sequencing operation that adds a row number column to convert bags to sets.
|
|
@@ -31,7 +31,7 @@ export class SequencingNode extends PlanNode implements UnaryRelationalNode {
|
|
|
31
31
|
name: this.sequenceColumnName,
|
|
32
32
|
type: {
|
|
33
33
|
typeClass: 'scalar' as const,
|
|
34
|
-
|
|
34
|
+
logicalType: INTEGER_TYPE,
|
|
35
35
|
nullable: false,
|
|
36
36
|
isReadOnly: true
|
|
37
37
|
},
|
|
@@ -2,7 +2,7 @@ import { PlanNodeType } from './plan-node-type.js';
|
|
|
2
2
|
import { PlanNode, type RelationalPlanNode } from './plan-node.js';
|
|
3
3
|
import type { ScalarType } from '../../common/datatype.js';
|
|
4
4
|
import type { Scope } from '../scopes/scope.js';
|
|
5
|
-
import {
|
|
5
|
+
import { INTEGER_TYPE } from '../../types/builtin-types.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A sink node that consumes an async iterable for side effects.
|
|
@@ -25,7 +25,7 @@ export class SinkNode extends PlanNode {
|
|
|
25
25
|
return {
|
|
26
26
|
typeClass: 'scalar',
|
|
27
27
|
isReadOnly: true,
|
|
28
|
-
|
|
28
|
+
logicalType: INTEGER_TYPE,
|
|
29
29
|
nullable: false
|
|
30
30
|
};
|
|
31
31
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { PlanNode, type ScalarPlanNode } from "./plan-node.js";
|
|
2
2
|
import type { ScalarType } from "../../common/datatype.js";
|
|
3
3
|
import type { RelationalPlanNode } from "./plan-node.js";
|
|
4
|
-
import { type CompareFn
|
|
4
|
+
import { type CompareFn } from "../../common/types.js";
|
|
5
5
|
import { PlanNodeType } from "./plan-node-type.js";
|
|
6
6
|
import type { Scope } from "../scopes/scope.js";
|
|
7
7
|
import { compareSqlValues } from "../../util/comparison.js";
|
|
8
8
|
import type { Expression } from "../../parser/ast.js";
|
|
9
9
|
import { formatExpression, formatScalarType } from "../../util/plan-formatter.js";
|
|
10
10
|
import { quereusError } from "../../common/errors.js";
|
|
11
|
+
import { BLOB_TYPE, BOOLEAN_TYPE, INTEGER_TYPE } from "../../types/builtin-types.js";
|
|
11
12
|
import { StatusCode } from "../../common/types.js";
|
|
12
13
|
|
|
13
14
|
export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
|
|
@@ -31,10 +32,9 @@ export class ScalarSubqueryNode extends PlanNode implements ScalarPlanNode {
|
|
|
31
32
|
// Fallback to nullable BLOB if we can't determine type
|
|
32
33
|
return {
|
|
33
34
|
typeClass: 'scalar',
|
|
34
|
-
|
|
35
|
+
logicalType: BLOB_TYPE,
|
|
35
36
|
nullable: true,
|
|
36
37
|
isReadOnly: true,
|
|
37
|
-
datatype: SqlDataType.BLOB,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -103,10 +103,9 @@ export class InNode extends PlanNode implements ScalarPlanNode {
|
|
|
103
103
|
getType(): ScalarType {
|
|
104
104
|
return {
|
|
105
105
|
typeClass: 'scalar',
|
|
106
|
-
|
|
106
|
+
logicalType: BOOLEAN_TYPE,
|
|
107
107
|
nullable: false,
|
|
108
108
|
isReadOnly: true,
|
|
109
|
-
datatype: SqlDataType.INTEGER,
|
|
110
109
|
}
|
|
111
110
|
}
|
|
112
111
|
|
|
@@ -216,10 +215,9 @@ export class ExistsNode extends PlanNode implements ScalarPlanNode {
|
|
|
216
215
|
getType(): ScalarType {
|
|
217
216
|
return {
|
|
218
217
|
typeClass: 'scalar',
|
|
219
|
-
|
|
218
|
+
logicalType: BOOLEAN_TYPE,
|
|
220
219
|
nullable: false,
|
|
221
220
|
isReadOnly: true,
|
|
222
|
-
datatype: SqlDataType.INTEGER,
|
|
223
221
|
};
|
|
224
222
|
}
|
|
225
223
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { PlanNode, type ZeroAryRelationalNode, type Attribute } from './plan-node.js';
|
|
2
2
|
import type { RelationType } from '../../common/datatype.js';
|
|
3
|
-
import { SqlDataType } from '../../common/types.js';
|
|
4
3
|
import { PlanNodeType } from './plan-node-type.js';
|
|
5
4
|
import type { Scope } from '../scopes/scope.js';
|
|
6
5
|
import type { ViewSchema } from '../../schema/view.js';
|
|
7
6
|
import { Cached } from '../../util/cached.js';
|
|
7
|
+
import { TEXT_TYPE } from '../../types/builtin-types.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Plan node for referencing a view in a FROM clause.
|
|
@@ -36,7 +36,7 @@ export class ViewReferenceNode extends PlanNode implements ZeroAryRelationalNode
|
|
|
36
36
|
name: columnName,
|
|
37
37
|
type: {
|
|
38
38
|
typeClass: 'scalar' as const,
|
|
39
|
-
|
|
39
|
+
logicalType: TEXT_TYPE,
|
|
40
40
|
nullable: true,
|
|
41
41
|
isReadOnly: false
|
|
42
42
|
}, // Default type, should be inferred
|
|
@@ -4,8 +4,8 @@ import type { ScalarType } from '../../common/datatype.js';
|
|
|
4
4
|
import type { Scope } from '../scopes/scope.js';
|
|
5
5
|
import type { WindowFunctionExpr } from '../../parser/ast.js';
|
|
6
6
|
import { Cached } from '../../util/cached.js';
|
|
7
|
-
import { SqlDataType } from '../../common/types.js';
|
|
8
7
|
import { formatScalarType } from '../../util/plan-formatter.js';
|
|
8
|
+
import { INTEGER_TYPE, REAL_TYPE } from '../../types/builtin-types.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Represents a window function call in the query plan.
|
|
@@ -30,10 +30,10 @@ export class WindowFunctionCallNode extends PlanNode implements ZeroAryScalarNod
|
|
|
30
30
|
// Most window functions return numeric types
|
|
31
31
|
// row_number() specifically returns an integer
|
|
32
32
|
if (this.functionName === 'row_number') {
|
|
33
|
-
return { typeClass: 'scalar',
|
|
33
|
+
return { typeClass: 'scalar', logicalType: INTEGER_TYPE, nullable: false } satisfies ScalarType;
|
|
34
34
|
}
|
|
35
35
|
// Other window functions would have their own type inference
|
|
36
|
-
return { typeClass: 'scalar',
|
|
36
|
+
return { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: false } satisfies ScalarType;
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -120,7 +120,7 @@ function createIndexBasedAccess(retrieveNode: RetrieveNode, context: OptContext)
|
|
|
120
120
|
columns: tableSchema.columns.map((col, index) => ({
|
|
121
121
|
index,
|
|
122
122
|
name: col.name,
|
|
123
|
-
type: col.
|
|
123
|
+
type: col.logicalType,
|
|
124
124
|
isPrimaryKey: col.primaryKey || false,
|
|
125
125
|
isUnique: col.primaryKey || false // For now, assume only PK columns are unique
|
|
126
126
|
} as ColumnMeta)),
|
|
@@ -231,7 +231,7 @@ function fallbackIndexSupports(
|
|
|
231
231
|
columns: tableSchema.columns.map((col, index) => ({
|
|
232
232
|
index,
|
|
233
233
|
name: col.name,
|
|
234
|
-
type: col.
|
|
234
|
+
type: col.logicalType,
|
|
235
235
|
isPrimaryKey: col.primaryKey || false,
|
|
236
236
|
isUnique: col.primaryKey || false
|
|
237
237
|
})),
|
|
@@ -5,8 +5,8 @@ import * as AST from "../../parser/ast.js";
|
|
|
5
5
|
import { FunctionReferenceNode, TableReferenceNode } from "../nodes/reference.js";
|
|
6
6
|
import { Ambiguous } from "./scope.js";
|
|
7
7
|
import type { ScalarType } from "../../common/datatype.js";
|
|
8
|
-
import { SqlDataType } from "../../common/types.js";
|
|
9
8
|
import { isScalarFunctionSchema } from "../../schema/function.js";
|
|
9
|
+
import { REAL_TYPE } from "../../types/builtin-types.js";
|
|
10
10
|
|
|
11
11
|
export class GlobalScope extends BaseScope {
|
|
12
12
|
constructor(public readonly manager: SchemaManager) {
|
|
@@ -25,7 +25,7 @@ export class GlobalScope extends BaseScope {
|
|
|
25
25
|
// Get the proper scalar type from the function schema
|
|
26
26
|
const scalarType: ScalarType = isScalarFunctionSchema(func)
|
|
27
27
|
? func.returnType
|
|
28
|
-
: { typeClass: 'scalar',
|
|
28
|
+
: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true };
|
|
29
29
|
|
|
30
30
|
return new FunctionReferenceNode(this, func, scalarType);
|
|
31
31
|
}
|
|
@@ -54,7 +54,7 @@ export class GlobalScope extends BaseScope {
|
|
|
54
54
|
// Get the proper scalar type from the function schema
|
|
55
55
|
const scalarType: ScalarType = isScalarFunctionSchema(func)
|
|
56
56
|
? func.returnType
|
|
57
|
-
: { typeClass: 'scalar',
|
|
57
|
+
: { typeClass: 'scalar', logicalType: REAL_TYPE, nullable: true, isReadOnly: true };
|
|
58
58
|
|
|
59
59
|
return new FunctionReferenceNode(this, func, scalarType);
|
|
60
60
|
}
|
|
@@ -3,13 +3,13 @@ import { ParameterReferenceNode } from '../nodes/reference.js'; // Corrected imp
|
|
|
3
3
|
import { BaseScope } from './base.js';
|
|
4
4
|
import { Ambiguous, type Scope } from './scope.js';
|
|
5
5
|
import type { ScalarType } from '../../common/datatype.js';
|
|
6
|
-
import { SqlDataType } from '../../common/types.js';
|
|
7
6
|
import type { PlanNode } from '../nodes/plan-node.js';
|
|
7
|
+
import { TEXT_TYPE } from '../../types/builtin-types.js';
|
|
8
8
|
|
|
9
9
|
// Default type for parameters when not otherwise specified.
|
|
10
10
|
const DEFAULT_PARAMETER_TYPE: ScalarType = {
|
|
11
11
|
typeClass: 'scalar',
|
|
12
|
-
|
|
12
|
+
logicalType: TEXT_TYPE,
|
|
13
13
|
nullable: true,
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -4,8 +4,7 @@ import type { RelationType, ColumnDef, ScalarType, ColRef } from '../common/data
|
|
|
4
4
|
import { SqlDataType, StatusCode, type DeepReadonly, type SqlValue } from '../common/types.js'; // Import SqlValue and ensure SqlDataType is not type-only
|
|
5
5
|
import type { AstNode } from '../parser/ast.js';
|
|
6
6
|
import { QuereusError } from '../common/errors.js';
|
|
7
|
-
|
|
8
|
-
// If tableSchema.columns are of type from '../schema/column.js', then their affinity is already SqlDataType.
|
|
7
|
+
import { inferLogicalTypeFromValue } from '../common/type-inference.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Converts a TableSchema (from src/schema/table.ts) to a RelationType (from src/common/datatype.ts).
|
|
@@ -17,7 +16,7 @@ export function relationTypeFromTableSchema(tableSchema: TableSchema): RelationT
|
|
|
17
16
|
name: col.name,
|
|
18
17
|
type: {
|
|
19
18
|
typeClass: 'scalar',
|
|
20
|
-
|
|
19
|
+
logicalType: col.logicalType,
|
|
21
20
|
collationName: col.collation,
|
|
22
21
|
nullable: !col.notNull,
|
|
23
22
|
isReadOnly: false,
|
|
@@ -53,18 +52,11 @@ export function relationTypeFromTableSchema(tableSchema: TableSchema): RelationT
|
|
|
53
52
|
* @returns A ScalarType representing the inferred type of the value.
|
|
54
53
|
*/
|
|
55
54
|
export function getParameterScalarType(value: SqlValue): ScalarType {
|
|
56
|
-
|
|
57
|
-
if (value === null) affinity = SqlDataType.NULL;
|
|
58
|
-
else if (typeof value === 'number') affinity = SqlDataType.REAL;
|
|
59
|
-
else if (typeof value === 'bigint') affinity = SqlDataType.INTEGER;
|
|
60
|
-
else if (typeof value === 'string') affinity = SqlDataType.TEXT;
|
|
61
|
-
else if (value instanceof Uint8Array) affinity = SqlDataType.BLOB;
|
|
62
|
-
else if (typeof value === 'boolean') affinity = SqlDataType.INTEGER; // Store booleans as INTEGER
|
|
63
|
-
else affinity = SqlDataType.BLOB; // Default for unknown types that might pass as SqlValue
|
|
55
|
+
const logicalType = inferLogicalTypeFromValue(value);
|
|
64
56
|
|
|
65
57
|
return {
|
|
66
58
|
typeClass: 'scalar',
|
|
67
|
-
|
|
59
|
+
logicalType,
|
|
68
60
|
nullable: true, // No guarantees about the value, so it's nullable
|
|
69
61
|
isReadOnly: true, // Parameters are read-only within the query execution context
|
|
70
62
|
};
|
|
@@ -80,12 +72,12 @@ export function checkRelationsAssignable(source: RelationType, target: RelationT
|
|
|
80
72
|
return checkColumnsAssignable(source.columns, target.columns, astNode);
|
|
81
73
|
}
|
|
82
74
|
|
|
83
|
-
export function columnSchemaToDef(colName: string, colDef: ColumnSchema):
|
|
75
|
+
export function columnSchemaToDef(colName: string, colDef: ColumnSchema): ColumnDef {
|
|
84
76
|
return {
|
|
85
77
|
name: colName,
|
|
86
78
|
type: {
|
|
87
79
|
typeClass: 'scalar',
|
|
88
|
-
|
|
80
|
+
logicalType: colDef.logicalType,
|
|
89
81
|
collationName: colDef.collation,
|
|
90
82
|
nullable: !colDef.notNull,
|
|
91
83
|
isReadOnly: false,
|
|
@@ -27,11 +27,11 @@ export function emitBetween(plan: BetweenNode, ctx: EmissionContext): Instructio
|
|
|
27
27
|
const upperResult = compareSqlValuesFast(coercedValue2, coercedUpper, collationFunc);
|
|
28
28
|
|
|
29
29
|
// value >= lowerBound AND value <= upperBound
|
|
30
|
-
const betweenResult = (lowerResult >= 0 && upperResult <= 0)
|
|
30
|
+
const betweenResult = (lowerResult >= 0 && upperResult <= 0);
|
|
31
31
|
|
|
32
32
|
// Handle NOT BETWEEN
|
|
33
33
|
if (plan.expression.not) {
|
|
34
|
-
return betweenResult
|
|
34
|
+
return !betweenResult;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return betweenResult;
|