@malloydata/malloy 0.0.223-dev241213043533 → 0.0.223-dev241216191808
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/dist/dialect/duckdb/dialect_functions.js +19 -0
- package/dist/dialect/functions/malloy_standard_functions.js +19 -19
- package/dist/dialect/functions/util.d.ts +46 -34
- package/dist/dialect/functions/util.js +98 -93
- package/dist/dialect/trino/dialect_functions.js +3 -3
- package/dist/lang/ast/expressions/expr-func.js +180 -14
- package/dist/lang/ast/types/dialect-name-space.js +1 -0
- package/dist/lang/ast/types/global-name-space.js +1 -0
- package/dist/lang/parse-log.d.ts +7 -0
- package/dist/model/malloy_types.d.ts +54 -7
- package/dist/model/malloy_types.js +9 -4
- package/package.json +1 -1
|
@@ -7,11 +7,27 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.DUCKDB_DIALECT_FUNCTIONS = void 0;
|
|
10
|
+
const list_extract = {
|
|
11
|
+
takes: { 'value': { array: { generic: 'T' } }, 'index': 'number' },
|
|
12
|
+
generic: { 'T': ['any'] },
|
|
13
|
+
returns: { generic: 'T' },
|
|
14
|
+
impl: { sql: 'list_extract(${value}, ${index})' },
|
|
15
|
+
};
|
|
10
16
|
const dayname = {
|
|
11
17
|
takes: { 'date_value': ['date', 'timestamp'] },
|
|
12
18
|
returns: 'string',
|
|
13
19
|
impl: { function: 'DAYNAME' },
|
|
14
20
|
};
|
|
21
|
+
const date_part = {
|
|
22
|
+
takes: { 'part': 'string', 'interval': { sql_native: 'interval' } },
|
|
23
|
+
returns: 'number',
|
|
24
|
+
impl: { function: 'DATE_PART' },
|
|
25
|
+
};
|
|
26
|
+
const to_seconds = {
|
|
27
|
+
takes: { 'seconds': 'number' },
|
|
28
|
+
returns: { sql_native: 'interval' },
|
|
29
|
+
impl: { function: 'TO_SECONDS' },
|
|
30
|
+
};
|
|
15
31
|
const to_timestamp = {
|
|
16
32
|
takes: { 'epoch_seconds': 'number' },
|
|
17
33
|
returns: 'timestamp',
|
|
@@ -65,10 +81,13 @@ const string_agg_distinct = {
|
|
|
65
81
|
},
|
|
66
82
|
};
|
|
67
83
|
exports.DUCKDB_DIALECT_FUNCTIONS = {
|
|
84
|
+
list_extract,
|
|
68
85
|
count_approx,
|
|
69
86
|
dayname,
|
|
70
87
|
to_timestamp,
|
|
71
88
|
string_agg,
|
|
72
89
|
string_agg_distinct,
|
|
90
|
+
to_seconds,
|
|
91
|
+
date_part,
|
|
73
92
|
};
|
|
74
93
|
//# sourceMappingURL=dialect_functions.js.map
|
|
@@ -54,7 +54,7 @@ const chr = {
|
|
|
54
54
|
impl: { sql: "CASE WHEN ${value} = 0 THEN '' ELSE CHR(${value}) END" },
|
|
55
55
|
};
|
|
56
56
|
const coalesce = {
|
|
57
|
-
generic:
|
|
57
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
58
58
|
takes: { 'value': { variadic: { generic: 'T' } } },
|
|
59
59
|
returns: { generic: 'T' },
|
|
60
60
|
impl: { function: 'COALESCE' },
|
|
@@ -101,13 +101,13 @@ const floor = {
|
|
|
101
101
|
impl: { function: 'FLOOR' },
|
|
102
102
|
};
|
|
103
103
|
const greatest = {
|
|
104
|
-
generic:
|
|
104
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
105
105
|
takes: { 'values': { variadic: { generic: 'T' } } },
|
|
106
106
|
returns: { generic: 'T' },
|
|
107
107
|
impl: { function: 'GREATEST' },
|
|
108
108
|
};
|
|
109
109
|
const ifnull = {
|
|
110
|
-
generic:
|
|
110
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
111
111
|
takes: { 'value': { generic: 'T' }, 'default': { generic: 'T' } },
|
|
112
112
|
returns: { generic: 'T' },
|
|
113
113
|
impl: { function: 'IFNULL' },
|
|
@@ -162,7 +162,7 @@ const ltrim = {
|
|
|
162
162
|
},
|
|
163
163
|
};
|
|
164
164
|
const nullif = {
|
|
165
|
-
generic:
|
|
165
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
166
166
|
takes: { 'value1': { generic: 'T' }, 'value2': { generic: 'T' } },
|
|
167
167
|
returns: { generic: 'T' },
|
|
168
168
|
impl: { function: 'NULLIF' },
|
|
@@ -331,7 +331,7 @@ const stddev = {
|
|
|
331
331
|
// Analytic functions
|
|
332
332
|
const avg_moving = {
|
|
333
333
|
'preceding': {
|
|
334
|
-
generic:
|
|
334
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
335
335
|
takes: {
|
|
336
336
|
'value': { measure: { generic: 'T' } },
|
|
337
337
|
'preceding': { literal: 'number' },
|
|
@@ -344,7 +344,7 @@ const avg_moving = {
|
|
|
344
344
|
},
|
|
345
345
|
},
|
|
346
346
|
'following': {
|
|
347
|
-
generic:
|
|
347
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
348
348
|
takes: {
|
|
349
349
|
'value': { measure: { generic: 'T' } },
|
|
350
350
|
'preceding': { literal: 'number' },
|
|
@@ -359,7 +359,7 @@ const avg_moving = {
|
|
|
359
359
|
},
|
|
360
360
|
};
|
|
361
361
|
const first_value = {
|
|
362
|
-
generic:
|
|
362
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
363
363
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
364
364
|
returns: { calculation: { generic: 'T' } },
|
|
365
365
|
impl: { function: 'FIRST_VALUE', needsWindowOrderBy: true },
|
|
@@ -374,7 +374,7 @@ const LAG_TYPES = [
|
|
|
374
374
|
];
|
|
375
375
|
const lag = {
|
|
376
376
|
'bare': {
|
|
377
|
-
generic:
|
|
377
|
+
generic: { 'T': LAG_TYPES },
|
|
378
378
|
takes: {
|
|
379
379
|
'value': { measure: { generic: 'T' } },
|
|
380
380
|
},
|
|
@@ -382,7 +382,7 @@ const lag = {
|
|
|
382
382
|
impl: { function: 'LAG', needsWindowOrderBy: true },
|
|
383
383
|
},
|
|
384
384
|
'with_offset': {
|
|
385
|
-
generic:
|
|
385
|
+
generic: { 'T': LAG_TYPES },
|
|
386
386
|
takes: {
|
|
387
387
|
'value': { measure: { generic: 'T' } },
|
|
388
388
|
'offset': { literal: 'number' },
|
|
@@ -391,7 +391,7 @@ const lag = {
|
|
|
391
391
|
impl: { function: 'LAG', needsWindowOrderBy: true },
|
|
392
392
|
},
|
|
393
393
|
'with_default': {
|
|
394
|
-
generic:
|
|
394
|
+
generic: { 'T': LAG_TYPES },
|
|
395
395
|
takes: {
|
|
396
396
|
'value': { measure: { generic: 'T' } },
|
|
397
397
|
'offset': { literal: 'number' },
|
|
@@ -402,7 +402,7 @@ const lag = {
|
|
|
402
402
|
},
|
|
403
403
|
};
|
|
404
404
|
const last_value = {
|
|
405
|
-
generic:
|
|
405
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date', 'json'] },
|
|
406
406
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
407
407
|
returns: { calculation: { generic: 'T' } },
|
|
408
408
|
impl: {
|
|
@@ -426,25 +426,25 @@ const lead = {
|
|
|
426
426
|
},
|
|
427
427
|
};
|
|
428
428
|
const max_cumulative = {
|
|
429
|
-
generic:
|
|
429
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
430
430
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
431
431
|
returns: { calculation: { generic: 'T' } },
|
|
432
432
|
impl: { function: 'MAX', needsWindowOrderBy: true },
|
|
433
433
|
};
|
|
434
434
|
const max_window = {
|
|
435
|
-
generic:
|
|
435
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
436
436
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
437
437
|
returns: { calculation: { generic: 'T' } },
|
|
438
438
|
impl: { function: 'MAX', needsWindowOrderBy: false },
|
|
439
439
|
};
|
|
440
440
|
const min_cumulative = {
|
|
441
|
-
generic:
|
|
441
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
442
442
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
443
443
|
returns: { calculation: { generic: 'T' } },
|
|
444
444
|
impl: { function: 'MIN', needsWindowOrderBy: true },
|
|
445
445
|
};
|
|
446
446
|
const min_window = {
|
|
447
|
-
generic:
|
|
447
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
448
448
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
449
449
|
returns: { calculation: { generic: 'T' } },
|
|
450
450
|
impl: { function: 'MIN', needsWindowOrderBy: false },
|
|
@@ -461,14 +461,14 @@ const row_number = {
|
|
|
461
461
|
impl: { function: 'ROW_NUMBER', needsWindowOrderBy: true },
|
|
462
462
|
};
|
|
463
463
|
const sum_cumulative = {
|
|
464
|
-
generic:
|
|
464
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
465
465
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
466
466
|
returns: { calculation: { generic: 'T' } },
|
|
467
467
|
impl: { function: 'SUM', needsWindowOrderBy: true },
|
|
468
468
|
};
|
|
469
469
|
const sum_moving = {
|
|
470
470
|
'preceding': {
|
|
471
|
-
generic:
|
|
471
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
472
472
|
takes: {
|
|
473
473
|
'value': { measure: { generic: 'T' } },
|
|
474
474
|
'preceding': { literal: 'number' },
|
|
@@ -481,7 +481,7 @@ const sum_moving = {
|
|
|
481
481
|
},
|
|
482
482
|
},
|
|
483
483
|
'following': {
|
|
484
|
-
generic:
|
|
484
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
485
485
|
takes: {
|
|
486
486
|
'value': { measure: { generic: 'T' } },
|
|
487
487
|
'preceding': { literal: 'number' },
|
|
@@ -496,7 +496,7 @@ const sum_moving = {
|
|
|
496
496
|
},
|
|
497
497
|
};
|
|
498
498
|
const sum_window = {
|
|
499
|
-
generic:
|
|
499
|
+
generic: { 'T': ['string', 'number', 'timestamp', 'date'] },
|
|
500
500
|
takes: { 'value': { measure: { generic: 'T' } } },
|
|
501
501
|
returns: { calculation: { generic: 'T' } },
|
|
502
502
|
impl: { function: 'SUM', needsWindowOrderBy: false },
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { FunctionParameterDef, TypeDesc, Expr, FunctionParamTypeDesc, LeafExpressionType } from '../../model/malloy_types';
|
|
1
|
+
import { FunctionParameterDef, TypeDesc, Expr, FunctionParamTypeDesc, LeafExpressionType, FunctionReturnTypeDesc, FunctionParameterTypeDef, ExpressionType, EvalSpace, FunctionGenericTypeDef } from '../../model/malloy_types';
|
|
2
2
|
import { SQLExprElement } from '../../model/utils';
|
|
3
3
|
export interface DialectFunctionOverloadDef {
|
|
4
|
-
returnType:
|
|
4
|
+
returnType: FunctionReturnTypeDesc;
|
|
5
5
|
params: FunctionParameterDef[];
|
|
6
|
+
genericTypes?: {
|
|
7
|
+
name: string;
|
|
8
|
+
acceptibleTypes: FunctionGenericTypeDef[];
|
|
9
|
+
}[];
|
|
6
10
|
e: Expr;
|
|
7
11
|
needsWindowOrderBy?: boolean;
|
|
8
12
|
isSymmetric?: boolean;
|
|
@@ -17,9 +21,15 @@ export interface DialectFunctionOverloadDef {
|
|
|
17
21
|
export declare function arg(name: string): Expr;
|
|
18
22
|
export declare function spread(e: Expr, prefix?: string | undefined, suffix?: string | undefined): Expr;
|
|
19
23
|
export declare function sql(strings: TemplateStringsArray, ...subExprs: SQLExprElement[]): Expr;
|
|
20
|
-
export declare function constant
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
export declare function constant<T extends {
|
|
25
|
+
expressionType: ExpressionType | undefined;
|
|
26
|
+
}>(type: T): T & TypeDescExtras;
|
|
27
|
+
export declare function output<T extends {
|
|
28
|
+
expressionType: ExpressionType | undefined;
|
|
29
|
+
}>(type: T): T & TypeDescExtras;
|
|
30
|
+
export declare function literal<T extends {
|
|
31
|
+
expressionType: ExpressionType | undefined;
|
|
32
|
+
}>(type: T): T & TypeDescExtras;
|
|
23
33
|
export declare function variadicParam(name: string, ...allowedTypes: FunctionParamTypeDesc[]): FunctionParameterDef;
|
|
24
34
|
/**
|
|
25
35
|
* Prefer `makeParam` for future function definitions
|
|
@@ -29,14 +39,18 @@ export declare function makeParam(name: string, ...allowedTypes: FunctionParamTy
|
|
|
29
39
|
param: FunctionParameterDef;
|
|
30
40
|
arg: Expr;
|
|
31
41
|
};
|
|
32
|
-
export declare function maxScalar(type:
|
|
33
|
-
export declare function maxAggregate(type:
|
|
34
|
-
export declare function anyExprType(type:
|
|
35
|
-
export declare function maxUngroupedAggregate(type:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
export declare function maxScalar<T>(type: T): T & TypeDescExtras;
|
|
43
|
+
export declare function maxAggregate<T>(type: T): T & TypeDescExtras;
|
|
44
|
+
export declare function anyExprType<T>(type: T): T & TypeDescExtras;
|
|
45
|
+
export declare function maxUngroupedAggregate(type: FunctionParameterTypeDef): FunctionParamTypeDesc;
|
|
46
|
+
type TypeDescExtras = {
|
|
47
|
+
expressionType: ExpressionType | undefined;
|
|
48
|
+
evalSpace: EvalSpace;
|
|
49
|
+
};
|
|
50
|
+
export declare function maxAnalytic<T>(type: T): T & TypeDescExtras;
|
|
51
|
+
export declare function minScalar<T>(type: T): T & TypeDescExtras;
|
|
52
|
+
export declare function minAggregate<T>(type: T): T & TypeDescExtras;
|
|
53
|
+
export declare function minAnalytic<T>(type: T): T & TypeDescExtras;
|
|
40
54
|
export declare function overload(returnType: TypeDesc, params: FunctionParameterDef[], e: Expr, options?: {
|
|
41
55
|
needsWindowOrderBy?: boolean;
|
|
42
56
|
between?: {
|
|
@@ -49,40 +63,38 @@ export declare function overload(returnType: TypeDesc, params: FunctionParameter
|
|
|
49
63
|
supportsOrderBy?: boolean | 'only_default';
|
|
50
64
|
}): DialectFunctionOverloadDef;
|
|
51
65
|
export interface ArrayBlueprint {
|
|
52
|
-
array:
|
|
66
|
+
array: TypeDescElementBlueprintOrNamedGeneric;
|
|
53
67
|
}
|
|
68
|
+
export type TypeDescElementBlueprintOrNamedGeneric = TypeDescElementBlueprint | NamedGeneric;
|
|
54
69
|
export interface RecordBlueprint {
|
|
55
|
-
record: Record<string,
|
|
70
|
+
record: Record<string, TypeDescElementBlueprintOrNamedGeneric>;
|
|
71
|
+
}
|
|
72
|
+
export interface SQLNativeTypeBlueprint {
|
|
73
|
+
sql_native: string;
|
|
56
74
|
}
|
|
57
|
-
export type
|
|
58
|
-
export type
|
|
75
|
+
export type LeafPlusType = LeafExpressionType | 'any';
|
|
76
|
+
export type TypeDescElementBlueprint = LeafPlusType | ArrayBlueprint | RecordBlueprint | SQLNativeTypeBlueprint;
|
|
77
|
+
export type NamedGeneric = {
|
|
59
78
|
generic: string;
|
|
79
|
+
};
|
|
80
|
+
export type TypeDescBlueprint = TypeDescElementBlueprintOrNamedGeneric | {
|
|
81
|
+
literal: TypeDescElementBlueprintOrNamedGeneric;
|
|
60
82
|
} | {
|
|
61
|
-
|
|
62
|
-
generic: string;
|
|
63
|
-
};
|
|
64
|
-
} | {
|
|
65
|
-
constant: LeafExpressionType | {
|
|
66
|
-
generic: string;
|
|
67
|
-
};
|
|
83
|
+
constant: TypeDescElementBlueprintOrNamedGeneric;
|
|
68
84
|
} | {
|
|
69
|
-
dimension:
|
|
70
|
-
generic: string;
|
|
71
|
-
};
|
|
85
|
+
dimension: TypeDescElementBlueprintOrNamedGeneric;
|
|
72
86
|
} | {
|
|
73
|
-
measure:
|
|
74
|
-
generic: string;
|
|
75
|
-
};
|
|
87
|
+
measure: TypeDescElementBlueprintOrNamedGeneric;
|
|
76
88
|
} | {
|
|
77
|
-
calculation:
|
|
78
|
-
generic: string;
|
|
79
|
-
};
|
|
89
|
+
calculation: TypeDescElementBlueprintOrNamedGeneric;
|
|
80
90
|
};
|
|
81
91
|
type ParamTypeBlueprint = TypeDescBlueprint | TypeDescBlueprint[] | {
|
|
82
92
|
variadic: TypeDescBlueprint | TypeDescBlueprint[];
|
|
83
93
|
};
|
|
84
94
|
export interface SignatureBlueprint {
|
|
85
|
-
generic?:
|
|
95
|
+
generic?: {
|
|
96
|
+
[name: string]: TypeDescElementBlueprintOrNamedGeneric[];
|
|
97
|
+
};
|
|
86
98
|
takes: {
|
|
87
99
|
[name: string]: ParamTypeBlueprint;
|
|
88
100
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright 2023 Google LLC
|
|
4
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
5
|
*
|
|
5
6
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
6
7
|
* a copy of this software and associated documentation files
|
|
@@ -23,7 +24,6 @@
|
|
|
23
24
|
*/
|
|
24
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
26
|
exports.expandOverrideMapFromBase = exports.expandBlueprintMap = exports.overload = exports.minAnalytic = exports.minAggregate = exports.minScalar = exports.maxAnalytic = exports.maxUngroupedAggregate = exports.anyExprType = exports.maxAggregate = exports.maxScalar = exports.makeParam = exports.param = exports.variadicParam = exports.literal = exports.output = exports.constant = exports.sql = exports.spread = exports.arg = void 0;
|
|
26
|
-
const composite_source_utils_1 = require("../../model/composite_source_utils");
|
|
27
27
|
const malloy_types_1 = require("../../model/malloy_types");
|
|
28
28
|
function arg(name) {
|
|
29
29
|
return { node: 'function_parameter', name };
|
|
@@ -106,39 +106,35 @@ function makeParam(name, ...allowedTypes) {
|
|
|
106
106
|
}
|
|
107
107
|
exports.makeParam = makeParam;
|
|
108
108
|
function maxScalar(type) {
|
|
109
|
-
return { type, expressionType: 'scalar', evalSpace: 'input' };
|
|
109
|
+
return { ...type, expressionType: 'scalar', evalSpace: 'input' };
|
|
110
110
|
}
|
|
111
111
|
exports.maxScalar = maxScalar;
|
|
112
112
|
function maxAggregate(type) {
|
|
113
|
-
return { type, expressionType: 'aggregate', evalSpace: 'input' };
|
|
113
|
+
return { ...type, expressionType: 'aggregate', evalSpace: 'input' };
|
|
114
114
|
}
|
|
115
115
|
exports.maxAggregate = maxAggregate;
|
|
116
116
|
function anyExprType(type) {
|
|
117
|
-
return { type, expressionType: undefined, evalSpace: 'input' };
|
|
117
|
+
return { ...type, expressionType: undefined, evalSpace: 'input' };
|
|
118
118
|
}
|
|
119
119
|
exports.anyExprType = anyExprType;
|
|
120
|
-
function anyExprTypeBP(type, generic) {
|
|
121
|
-
const typeDesc = expandReturnTypeBlueprint(type, generic);
|
|
122
|
-
return { ...typeDesc, expressionType: undefined, evalSpace: 'input' };
|
|
123
|
-
}
|
|
124
120
|
function maxUngroupedAggregate(type) {
|
|
125
|
-
return { type, expressionType: 'ungrouped_aggregate', evalSpace: 'input' };
|
|
121
|
+
return { ...type, expressionType: 'ungrouped_aggregate', evalSpace: 'input' };
|
|
126
122
|
}
|
|
127
123
|
exports.maxUngroupedAggregate = maxUngroupedAggregate;
|
|
128
124
|
function maxAnalytic(type) {
|
|
129
|
-
return { type, expressionType: 'aggregate_analytic', evalSpace: 'input' };
|
|
125
|
+
return { ...type, expressionType: 'aggregate_analytic', evalSpace: 'input' };
|
|
130
126
|
}
|
|
131
127
|
exports.maxAnalytic = maxAnalytic;
|
|
132
128
|
function minScalar(type) {
|
|
133
|
-
return { type, expressionType: 'scalar', evalSpace: 'input' };
|
|
129
|
+
return { ...type, expressionType: 'scalar', evalSpace: 'input' };
|
|
134
130
|
}
|
|
135
131
|
exports.minScalar = minScalar;
|
|
136
132
|
function minAggregate(type) {
|
|
137
|
-
return { type, expressionType: 'aggregate', evalSpace: 'input' };
|
|
133
|
+
return { ...type, expressionType: 'aggregate', evalSpace: 'input' };
|
|
138
134
|
}
|
|
139
135
|
exports.minAggregate = minAggregate;
|
|
140
136
|
function minAnalytic(type) {
|
|
141
|
-
return { type, expressionType: 'scalar_analytic', evalSpace: 'input' };
|
|
137
|
+
return { ...type, expressionType: 'scalar_analytic', evalSpace: 'input' };
|
|
142
138
|
}
|
|
143
139
|
exports.minAnalytic = minAnalytic;
|
|
144
140
|
function overload(returnType, params, e, options) {
|
|
@@ -155,86 +151,89 @@ function overload(returnType, params, e, options) {
|
|
|
155
151
|
};
|
|
156
152
|
}
|
|
157
153
|
exports.overload = overload;
|
|
158
|
-
function
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
if (type.generic !== (generic === null || generic === void 0 ? void 0 : generic.name)) {
|
|
163
|
-
throw new Error(`Cannot expand generic name ${type.generic}`);
|
|
154
|
+
function expandTypeDescElementBlueprint(blueprint, allowAny = true, allowGenerics = true) {
|
|
155
|
+
if (!allowAny && blueprint === 'any') {
|
|
156
|
+
throw new Error('Return type cannot include any');
|
|
164
157
|
}
|
|
165
|
-
return generic.type;
|
|
166
|
-
}
|
|
167
|
-
function expandReturnTypeBlueprint(blueprint, generic) {
|
|
168
|
-
var _a;
|
|
169
|
-
let base;
|
|
170
158
|
if (typeof blueprint === 'string') {
|
|
171
|
-
|
|
159
|
+
return { type: blueprint };
|
|
172
160
|
}
|
|
173
161
|
else if ('array' in blueprint) {
|
|
174
|
-
const innerType =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
base = {
|
|
187
|
-
type: 'array',
|
|
188
|
-
elementTypeDef: { type: 'record_element' },
|
|
189
|
-
fields: innerType.fields,
|
|
190
|
-
expressionType,
|
|
191
|
-
evalSpace,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
// mtoy todo fix by doing "exapndElementBlueprint" ...
|
|
197
|
-
throw new Error(`TypeDescElementBlueprint should never allow ${blueprint.array}`);
|
|
162
|
+
const innerType = allowAny
|
|
163
|
+
? expandTypeDescElementBlueprint(blueprint.array, true)
|
|
164
|
+
: expandTypeDescElementBlueprint(blueprint.array, false);
|
|
165
|
+
if (innerType.type === 'record') {
|
|
166
|
+
return {
|
|
167
|
+
type: 'array',
|
|
168
|
+
elementTypeDef: { type: 'record_element' },
|
|
169
|
+
fields: innerType.fields,
|
|
170
|
+
};
|
|
198
171
|
}
|
|
172
|
+
return {
|
|
173
|
+
type: 'array',
|
|
174
|
+
elementTypeDef: innerType,
|
|
175
|
+
};
|
|
199
176
|
}
|
|
200
177
|
else if ('record' in blueprint) {
|
|
201
178
|
const fields = [];
|
|
202
179
|
for (const [fieldName, fieldBlueprint] of Object.entries(blueprint.record)) {
|
|
203
|
-
const fieldDesc =
|
|
180
|
+
const fieldDesc = allowAny
|
|
181
|
+
? expandTypeDescElementBlueprint(fieldBlueprint, true)
|
|
182
|
+
: expandTypeDescElementBlueprint(fieldBlueprint, false);
|
|
204
183
|
if (malloy_types_1.TD.isAtomic(fieldDesc)) {
|
|
205
184
|
fields.push((0, malloy_types_1.mkFieldDef)(fieldDesc, fieldName));
|
|
206
185
|
}
|
|
207
186
|
}
|
|
208
|
-
|
|
187
|
+
return {
|
|
209
188
|
type: 'record',
|
|
210
189
|
fields,
|
|
211
|
-
evalSpace: 'input',
|
|
212
|
-
expressionType: 'scalar',
|
|
213
190
|
};
|
|
214
191
|
}
|
|
215
192
|
else if ('generic' in blueprint) {
|
|
216
|
-
|
|
193
|
+
if (!allowGenerics) {
|
|
194
|
+
throw new Error('Cannot use generic');
|
|
195
|
+
}
|
|
196
|
+
return { type: 'generic', generic: blueprint.generic };
|
|
197
|
+
}
|
|
198
|
+
else if ('sql_native' in blueprint) {
|
|
199
|
+
return { type: 'sql native', rawType: blueprint.sql_native };
|
|
200
|
+
}
|
|
201
|
+
throw new Error('Cannot figure out type');
|
|
202
|
+
}
|
|
203
|
+
function expandReturnTypeBlueprint(blueprint) {
|
|
204
|
+
if (blueprint === 'any') {
|
|
205
|
+
throw new Error('Cannot return any type');
|
|
206
|
+
}
|
|
207
|
+
if (typeof blueprint === 'string') {
|
|
208
|
+
return minScalar({ type: blueprint });
|
|
209
|
+
}
|
|
210
|
+
else if ('array' in blueprint) {
|
|
211
|
+
return anyExprType(expandTypeDescElementBlueprint(blueprint, false));
|
|
212
|
+
}
|
|
213
|
+
else if ('record' in blueprint) {
|
|
214
|
+
return anyExprType(expandTypeDescElementBlueprint(blueprint, false));
|
|
215
|
+
}
|
|
216
|
+
else if ('generic' in blueprint) {
|
|
217
|
+
return minScalar(expandTypeDescElementBlueprint(blueprint, false));
|
|
217
218
|
}
|
|
218
219
|
else if ('literal' in blueprint) {
|
|
219
|
-
|
|
220
|
+
return literal(minScalar(expandTypeDescElementBlueprint(blueprint.literal, false)));
|
|
220
221
|
}
|
|
221
222
|
else if ('constant' in blueprint) {
|
|
222
|
-
|
|
223
|
+
return constant(minScalar(expandTypeDescElementBlueprint(blueprint.constant, false)));
|
|
223
224
|
}
|
|
224
225
|
else if ('dimension' in blueprint) {
|
|
225
|
-
|
|
226
|
+
return minScalar(expandTypeDescElementBlueprint(blueprint.dimension, false));
|
|
226
227
|
}
|
|
227
228
|
else if ('measure' in blueprint) {
|
|
228
|
-
|
|
229
|
+
return minAggregate(expandTypeDescElementBlueprint(blueprint.measure, false));
|
|
230
|
+
}
|
|
231
|
+
else if ('sql_native' in blueprint) {
|
|
232
|
+
return anyExprType({ type: 'sql native', rawType: blueprint.sql_native });
|
|
229
233
|
}
|
|
230
234
|
else {
|
|
231
|
-
|
|
235
|
+
return minAnalytic(expandTypeDescElementBlueprint(blueprint.calculation, false));
|
|
232
236
|
}
|
|
233
|
-
return {
|
|
234
|
-
...base,
|
|
235
|
-
compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
|
|
236
|
-
expressionType: (_a = base.expressionType) !== null && _a !== void 0 ? _a : 'scalar',
|
|
237
|
-
};
|
|
238
237
|
}
|
|
239
238
|
function isTypeDescBlueprint(blueprint) {
|
|
240
239
|
return (typeof blueprint === 'string' ||
|
|
@@ -245,7 +244,8 @@ function isTypeDescBlueprint(blueprint) {
|
|
|
245
244
|
'constant' in blueprint ||
|
|
246
245
|
'dimension' in blueprint ||
|
|
247
246
|
'measure' in blueprint ||
|
|
248
|
-
'calculation' in blueprint
|
|
247
|
+
'calculation' in blueprint ||
|
|
248
|
+
'sql_native' in blueprint);
|
|
249
249
|
}
|
|
250
250
|
function extractParamTypeBlueprints(blueprint) {
|
|
251
251
|
if (isTypeDescBlueprint(blueprint)) {
|
|
@@ -261,51 +261,54 @@ function extractParamTypeBlueprints(blueprint) {
|
|
|
261
261
|
return blueprint.variadic;
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
-
function expandParamTypeBlueprint(blueprint
|
|
264
|
+
function expandParamTypeBlueprint(blueprint) {
|
|
265
265
|
if (typeof blueprint === 'string') {
|
|
266
|
-
return anyExprType(blueprint);
|
|
266
|
+
return anyExprType({ type: blueprint });
|
|
267
267
|
}
|
|
268
268
|
else if ('generic' in blueprint) {
|
|
269
|
-
return anyExprType(
|
|
269
|
+
return anyExprType(expandTypeDescElementBlueprint(blueprint));
|
|
270
270
|
}
|
|
271
271
|
else if ('literal' in blueprint) {
|
|
272
|
-
return literal(maxScalar(
|
|
272
|
+
return literal(maxScalar(expandTypeDescElementBlueprint(blueprint.literal)));
|
|
273
273
|
}
|
|
274
274
|
else if ('constant' in blueprint) {
|
|
275
|
-
return constant(maxScalar(
|
|
275
|
+
return constant(maxScalar(expandTypeDescElementBlueprint(blueprint.constant)));
|
|
276
276
|
}
|
|
277
277
|
else if ('dimension' in blueprint) {
|
|
278
|
-
return maxScalar(
|
|
278
|
+
return maxScalar(expandTypeDescElementBlueprint(blueprint.dimension));
|
|
279
279
|
}
|
|
280
280
|
else if ('measure' in blueprint) {
|
|
281
|
-
return maxAggregate(
|
|
281
|
+
return maxAggregate(expandTypeDescElementBlueprint(blueprint.measure));
|
|
282
282
|
}
|
|
283
283
|
else if ('array' in blueprint) {
|
|
284
|
-
return
|
|
284
|
+
return anyExprType(expandTypeDescElementBlueprint(blueprint, false));
|
|
285
285
|
}
|
|
286
286
|
else if ('record' in blueprint) {
|
|
287
|
-
return
|
|
287
|
+
return anyExprType(expandTypeDescElementBlueprint(blueprint, false));
|
|
288
|
+
}
|
|
289
|
+
else if ('sql_native' in blueprint) {
|
|
290
|
+
return anyExprType({ type: 'sql native', rawType: blueprint.sql_native });
|
|
288
291
|
}
|
|
289
292
|
else {
|
|
290
|
-
return maxAnalytic(
|
|
293
|
+
return maxAnalytic(expandTypeDescElementBlueprint(blueprint.calculation));
|
|
291
294
|
}
|
|
292
295
|
}
|
|
293
|
-
function expandParamTypeBlueprints(blueprints
|
|
294
|
-
return blueprints.map(blueprint => expandParamTypeBlueprint(blueprint
|
|
296
|
+
function expandParamTypeBlueprints(blueprints) {
|
|
297
|
+
return blueprints.map(blueprint => expandParamTypeBlueprint(blueprint));
|
|
295
298
|
}
|
|
296
299
|
function isVariadicParamBlueprint(blueprint) {
|
|
297
300
|
return typeof blueprint !== 'string' && 'variadic' in blueprint;
|
|
298
301
|
}
|
|
299
|
-
function expandParamBlueprint(name, blueprint
|
|
302
|
+
function expandParamBlueprint(name, blueprint) {
|
|
300
303
|
return {
|
|
301
304
|
name,
|
|
302
|
-
allowedTypes: expandParamTypeBlueprints(extractParamTypeBlueprints(blueprint)
|
|
305
|
+
allowedTypes: expandParamTypeBlueprints(extractParamTypeBlueprints(blueprint)),
|
|
303
306
|
isVariadic: isVariadicParamBlueprint(blueprint),
|
|
304
307
|
};
|
|
305
308
|
}
|
|
306
|
-
function expandParamsBlueprints(blueprints
|
|
309
|
+
function expandParamsBlueprints(blueprints) {
|
|
307
310
|
const paramsArray = Object.entries(blueprints);
|
|
308
|
-
return paramsArray.map(blueprint => expandParamBlueprint(blueprint[0], blueprint[1]
|
|
311
|
+
return paramsArray.map(blueprint => expandParamBlueprint(blueprint[0], blueprint[1]));
|
|
309
312
|
}
|
|
310
313
|
function expandBlueprintSqlInterpolation(sql) {
|
|
311
314
|
const src = [];
|
|
@@ -393,23 +396,25 @@ function expandImplBlueprint(blueprint) {
|
|
|
393
396
|
defaultOrderByArgIndex: blueprint.impl.defaultOrderByArgIndex,
|
|
394
397
|
};
|
|
395
398
|
}
|
|
396
|
-
function
|
|
399
|
+
function expandGenericDefinitions(blueprint) {
|
|
400
|
+
if (blueprint === undefined)
|
|
401
|
+
return undefined;
|
|
402
|
+
return Object.entries(blueprint).map(([name, acceptibleTypes]) => ({
|
|
403
|
+
name: name,
|
|
404
|
+
acceptibleTypes: acceptibleTypes.map(t => expandTypeDescElementBlueprint(t, true, false)),
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
function expandBlueprint(blueprint) {
|
|
397
408
|
return {
|
|
398
|
-
returnType: expandReturnTypeBlueprint(blueprint.returns
|
|
399
|
-
params: expandParamsBlueprints(blueprint.takes
|
|
409
|
+
returnType: expandReturnTypeBlueprint(blueprint.returns),
|
|
410
|
+
params: expandParamsBlueprints(blueprint.takes),
|
|
400
411
|
isSymmetric: blueprint.isSymmetric,
|
|
401
412
|
supportsOrderBy: blueprint.supportsOrderBy,
|
|
402
413
|
supportsLimit: blueprint.supportsLimit,
|
|
414
|
+
genericTypes: expandGenericDefinitions(blueprint.generic),
|
|
403
415
|
...expandImplBlueprint(blueprint),
|
|
404
416
|
};
|
|
405
417
|
}
|
|
406
|
-
function expandBlueprint(blueprint) {
|
|
407
|
-
if (blueprint.generic !== undefined) {
|
|
408
|
-
const name = blueprint.generic[0];
|
|
409
|
-
return blueprint.generic[1].map(type => expandOneBlueprint(blueprint, { name, type }));
|
|
410
|
-
}
|
|
411
|
-
return [expandOneBlueprint(blueprint)];
|
|
412
|
-
}
|
|
413
418
|
function isDefinitionBlueprint(blueprint) {
|
|
414
419
|
return 'takes' in blueprint && 'returns' in blueprint && 'impl' in blueprint;
|
|
415
420
|
}
|
|
@@ -418,7 +423,7 @@ function isImplementationBlueprint(blueprint) {
|
|
|
418
423
|
}
|
|
419
424
|
function expandOverloadedBlueprint(blueprint) {
|
|
420
425
|
if (isDefinitionBlueprint(blueprint)) {
|
|
421
|
-
return expandBlueprint(blueprint);
|
|
426
|
+
return [expandBlueprint(blueprint)];
|
|
422
427
|
}
|
|
423
428
|
else {
|
|
424
429
|
return Object.values(blueprint).flatMap(overload => expandBlueprint(overload));
|
|
@@ -433,7 +438,7 @@ function expandBlueprintMap(blueprints) {
|
|
|
433
438
|
}
|
|
434
439
|
exports.expandBlueprintMap = expandBlueprintMap;
|
|
435
440
|
function expandImplementationBlueprint(base, impl) {
|
|
436
|
-
return expandBlueprint({ ...base, impl });
|
|
441
|
+
return [expandBlueprint({ ...base, impl })];
|
|
437
442
|
}
|
|
438
443
|
function expandOverloadedOverrideBlueprint(name, base, blueprint) {
|
|
439
444
|
if (isImplementationBlueprint(blueprint)) {
|
|
@@ -20,7 +20,7 @@ const approx_percentile = {
|
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
22
|
const arbitrary = {
|
|
23
|
-
generic:
|
|
23
|
+
generic: { 'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'] },
|
|
24
24
|
takes: { 'value': { dimension: { generic: 'T' } } },
|
|
25
25
|
returns: { measure: { generic: 'T' } },
|
|
26
26
|
impl: { function: 'ARBITRARY' },
|
|
@@ -64,7 +64,7 @@ const count_approx = {
|
|
|
64
64
|
isSymmetric: true,
|
|
65
65
|
};
|
|
66
66
|
const max_by = {
|
|
67
|
-
generic:
|
|
67
|
+
generic: { 'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'] },
|
|
68
68
|
takes: {
|
|
69
69
|
'value': { dimension: { generic: 'T' } },
|
|
70
70
|
'order_by_val': { dimension: 'any' },
|
|
@@ -74,7 +74,7 @@ const max_by = {
|
|
|
74
74
|
isSymmetric: true,
|
|
75
75
|
};
|
|
76
76
|
const min_by = {
|
|
77
|
-
generic:
|
|
77
|
+
generic: { 'T': ['string', 'number', 'date', 'timestamp', 'boolean', 'json'] },
|
|
78
78
|
takes: {
|
|
79
79
|
'value': { dimension: { generic: 'T' } },
|
|
80
80
|
'order_by_val': { dimension: 'any' },
|
|
@@ -101,7 +101,7 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
101
101
|
return { found: func, error: undefined };
|
|
102
102
|
}
|
|
103
103
|
getPropsExpression(fs, props) {
|
|
104
|
-
var _a, _b, _c;
|
|
104
|
+
var _a, _b, _c, _d;
|
|
105
105
|
const argExprsWithoutImplicit = this.args.map(arg => arg.getExpression(fs));
|
|
106
106
|
if (this.isRaw) {
|
|
107
107
|
const funcCall = [`${this.name}(`];
|
|
@@ -167,7 +167,7 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
167
167
|
.map(e => e.type)
|
|
168
168
|
.join(', ')})`);
|
|
169
169
|
}
|
|
170
|
-
const { overload, expressionTypeErrors, evalSpaceErrors, nullabilityErrors } = result;
|
|
170
|
+
const { overload, expressionTypeErrors, evalSpaceErrors, nullabilityErrors, returnType, } = result;
|
|
171
171
|
// Report errors for expression type mismatch
|
|
172
172
|
for (const error of expressionTypeErrors) {
|
|
173
173
|
const adjustedIndex = error.argIndex - (implicitExpr ? 1 : 0);
|
|
@@ -194,9 +194,13 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
194
194
|
const arg = this.args[adjustedIndex];
|
|
195
195
|
arg.logError('literal-null-function-argument', `Parameter ${error.argIndex + 1} ('${error.param.name}') of ${this.name} must not be a literal null`);
|
|
196
196
|
}
|
|
197
|
+
// Report return type error
|
|
198
|
+
if (result.returnTypeError) {
|
|
199
|
+
this.logError(result.returnTypeError.code, result.returnTypeError.parameters);
|
|
200
|
+
}
|
|
197
201
|
const type = overload.returnType;
|
|
198
202
|
const expressionType = (0, malloy_types_1.maxOfExpressionTypes)([
|
|
199
|
-
type.expressionType,
|
|
203
|
+
(_d = type.expressionType) !== null && _d !== void 0 ? _d : 'scalar',
|
|
200
204
|
...argExprs.map(e => e.expressionType),
|
|
201
205
|
]);
|
|
202
206
|
if (!(0, malloy_types_1.expressionIsAggregate)(overload.returnType.expressionType) &&
|
|
@@ -316,9 +320,6 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
316
320
|
funcCall = (0, utils_1.composeSQLExpr)(expr);
|
|
317
321
|
}
|
|
318
322
|
}
|
|
319
|
-
if (type.type === 'any') {
|
|
320
|
-
return this.loggedErrorExpr('function-returns-any', `Invalid return type ${type.type} for function '${this.name}'`);
|
|
321
|
-
}
|
|
322
323
|
const maxEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(...argExprs.map(e => e.evalSpace));
|
|
323
324
|
// If the merged eval space of all args is constant, the result is constant.
|
|
324
325
|
// If the expression is scalar, then the eval space is that merged eval space.
|
|
@@ -333,7 +334,8 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
333
334
|
// TODO consider if I can use `computedExprValue` here...
|
|
334
335
|
// seems like the rules for the evalSpace is a bit different from normal though
|
|
335
336
|
return {
|
|
336
|
-
|
|
337
|
+
// TODO need to handle this???
|
|
338
|
+
...((0, malloy_types_1.isAtomic)(returnType) ? TDU.atomicDef(returnType) : returnType),
|
|
337
339
|
expressionType,
|
|
338
340
|
value: funcCall,
|
|
339
341
|
evalSpace,
|
|
@@ -343,7 +345,10 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
343
345
|
}
|
|
344
346
|
exports.ExprFunc = ExprFunc;
|
|
345
347
|
function findOverload(func, args) {
|
|
348
|
+
var _a;
|
|
346
349
|
for (const overload of func.overloads) {
|
|
350
|
+
// Map from generic name to selected type
|
|
351
|
+
const genericsSelected = new Map();
|
|
347
352
|
let paramIndex = 0;
|
|
348
353
|
let ok = true;
|
|
349
354
|
let matchedVariadic = false;
|
|
@@ -358,15 +363,13 @@ function findOverload(func, args) {
|
|
|
358
363
|
break;
|
|
359
364
|
}
|
|
360
365
|
const argOk = param.allowedTypes.some(paramT => {
|
|
366
|
+
var _a;
|
|
361
367
|
// Check whether types match (allowing for nullability errors, expression type errors,
|
|
362
368
|
// eval space errors, and unknown types due to prior errors in args)
|
|
363
|
-
const dataTypeMatch =
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
// so little control over nullability.
|
|
368
|
-
arg.type === 'null' ||
|
|
369
|
-
arg.type === 'error';
|
|
369
|
+
const { dataTypeMatch, genericsSet } = isDataTypeMatch(genericsSelected, (_a = overload.genericTypes) !== null && _a !== void 0 ? _a : [], arg, paramT);
|
|
370
|
+
for (const genericSet of genericsSet) {
|
|
371
|
+
genericsSelected.set(genericSet.name, genericSet.type);
|
|
372
|
+
}
|
|
370
373
|
// Check expression type errors
|
|
371
374
|
if (paramT.expressionType) {
|
|
372
375
|
const expressionTypeMatch = (0, malloy_types_1.isExpressionTypeLEQ)(arg.expressionType, paramT.expressionType);
|
|
@@ -425,12 +428,16 @@ function findOverload(func, args) {
|
|
|
425
428
|
(paramIndex !== args.length || paramIndex !== overload.params.length)) {
|
|
426
429
|
continue;
|
|
427
430
|
}
|
|
431
|
+
const resolveReturnType = resolveGenerics(overload.returnType, genericsSelected);
|
|
432
|
+
const returnType = (_a = resolveReturnType.returnType) !== null && _a !== void 0 ? _a : { type: 'number' };
|
|
428
433
|
if (ok) {
|
|
429
434
|
return {
|
|
430
435
|
overload,
|
|
431
436
|
expressionTypeErrors,
|
|
432
437
|
evalSpaceErrors,
|
|
433
438
|
nullabilityErrors,
|
|
439
|
+
returnTypeError: resolveReturnType.error,
|
|
440
|
+
returnType,
|
|
434
441
|
};
|
|
435
442
|
}
|
|
436
443
|
}
|
|
@@ -462,4 +469,163 @@ function parseSQLInterpolation(template) {
|
|
|
462
469
|
}
|
|
463
470
|
return parts;
|
|
464
471
|
}
|
|
472
|
+
function isDataTypeMatch(genericsAlreadySelected, genericTypes, arg, paramT) {
|
|
473
|
+
var _a, _b, _c, _d;
|
|
474
|
+
if (malloy_types_1.TD.eq(paramT, arg) ||
|
|
475
|
+
paramT.type === 'any' ||
|
|
476
|
+
// TODO We should consider whether `nulls` should always be allowed. It probably
|
|
477
|
+
// does not make sense to limit function calls to not allow nulls, since have
|
|
478
|
+
// so little control over nullability.
|
|
479
|
+
(paramT.type !== 'generic' && (arg.type === 'null' || arg.type === 'error'))) {
|
|
480
|
+
return { dataTypeMatch: true, genericsSet: [] };
|
|
481
|
+
}
|
|
482
|
+
if (paramT.type === 'array' && arg.type === 'array') {
|
|
483
|
+
if ((0, malloy_types_1.isScalarArray)(arg)) {
|
|
484
|
+
if (!(0, malloy_types_1.isRepeatedRecordFunctionParam)(paramT)) {
|
|
485
|
+
return isDataTypeMatch(genericsAlreadySelected, genericTypes, arg.elementTypeDef, paramT.elementTypeDef);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
return { dataTypeMatch: false, genericsSet: [] };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
else if ((0, malloy_types_1.isRepeatedRecordFunctionParam)(paramT)) {
|
|
492
|
+
const fakeParamRecord = {
|
|
493
|
+
type: 'record',
|
|
494
|
+
fields: paramT.fields,
|
|
495
|
+
};
|
|
496
|
+
const fakeArgRecord = {
|
|
497
|
+
type: 'record',
|
|
498
|
+
fields: arg.fields,
|
|
499
|
+
};
|
|
500
|
+
return isDataTypeMatch(genericsAlreadySelected, genericTypes, fakeArgRecord, fakeParamRecord);
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
return { dataTypeMatch: false, genericsSet: [] };
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
else if (paramT.type === 'record' && arg.type === 'record') {
|
|
507
|
+
const genericsSet = [];
|
|
508
|
+
const paramFieldsByName = new Map();
|
|
509
|
+
for (const field of paramT.fields) {
|
|
510
|
+
paramFieldsByName.set((_a = field.as) !== null && _a !== void 0 ? _a : field.name, field);
|
|
511
|
+
}
|
|
512
|
+
for (const field of arg.fields) {
|
|
513
|
+
const match = paramFieldsByName.get((_b = field.as) !== null && _b !== void 0 ? _b : field.name);
|
|
514
|
+
if (match === undefined) {
|
|
515
|
+
return { dataTypeMatch: false, genericsSet: [] };
|
|
516
|
+
}
|
|
517
|
+
const result = isDataTypeMatch(new Map([
|
|
518
|
+
...genericsAlreadySelected.entries(),
|
|
519
|
+
...genericsSet.map(x => [x.name, x.type]),
|
|
520
|
+
]), genericTypes, field, match);
|
|
521
|
+
genericsSet.push(...result.genericsSet);
|
|
522
|
+
}
|
|
523
|
+
return { dataTypeMatch: true, genericsSet };
|
|
524
|
+
}
|
|
525
|
+
else if (paramT.type === 'generic') {
|
|
526
|
+
const alreadySelected = genericsAlreadySelected.get(paramT.generic);
|
|
527
|
+
if (alreadySelected !== undefined &&
|
|
528
|
+
alreadySelected.type !== 'null' &&
|
|
529
|
+
alreadySelected.type !== 'error') {
|
|
530
|
+
return isDataTypeMatch(genericsAlreadySelected, genericTypes, arg, alreadySelected);
|
|
531
|
+
}
|
|
532
|
+
const allowedTypes = (_d = (_c = genericTypes.find(t => t.name === paramT.generic)) === null || _c === void 0 ? void 0 : _c.acceptibleTypes) !== null && _d !== void 0 ? _d : [];
|
|
533
|
+
for (const type of allowedTypes) {
|
|
534
|
+
const result = isDataTypeMatch(genericsAlreadySelected, genericTypes, arg, type);
|
|
535
|
+
if (result.dataTypeMatch) {
|
|
536
|
+
if (!(0, malloy_types_1.isAtomic)(arg) && arg.type !== 'null') {
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
const newGenericSet = {
|
|
540
|
+
name: paramT.generic,
|
|
541
|
+
type: arg,
|
|
542
|
+
};
|
|
543
|
+
return {
|
|
544
|
+
dataTypeMatch: true,
|
|
545
|
+
genericsSet: [...result.genericsSet, newGenericSet],
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return { dataTypeMatch: false, genericsSet: [] };
|
|
551
|
+
}
|
|
552
|
+
function resolveGenerics(returnType, genericsSelected) {
|
|
553
|
+
switch (returnType.type) {
|
|
554
|
+
case 'array': {
|
|
555
|
+
if ('fields' in returnType) {
|
|
556
|
+
const fields = returnType.fields.map(f => {
|
|
557
|
+
const type = resolveGenerics(f, genericsSelected);
|
|
558
|
+
return {
|
|
559
|
+
...f,
|
|
560
|
+
...type,
|
|
561
|
+
};
|
|
562
|
+
});
|
|
563
|
+
return {
|
|
564
|
+
error: undefined,
|
|
565
|
+
returnType: {
|
|
566
|
+
type: 'array',
|
|
567
|
+
elementTypeDef: returnType.elementTypeDef,
|
|
568
|
+
fields,
|
|
569
|
+
},
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
const resolve = resolveGenerics(returnType.elementTypeDef, genericsSelected);
|
|
573
|
+
if (resolve.error) {
|
|
574
|
+
return resolve;
|
|
575
|
+
}
|
|
576
|
+
const elementTypeDef = resolve.returnType;
|
|
577
|
+
if (elementTypeDef.type === 'record') {
|
|
578
|
+
return {
|
|
579
|
+
error: undefined,
|
|
580
|
+
returnType: {
|
|
581
|
+
type: 'array',
|
|
582
|
+
elementTypeDef: { type: 'record_element' },
|
|
583
|
+
fields: elementTypeDef.fields,
|
|
584
|
+
},
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
if (!(0, malloy_types_1.isAtomic)(elementTypeDef)) {
|
|
588
|
+
return {
|
|
589
|
+
error: {
|
|
590
|
+
code: 'invalid-resolved-type-for-array',
|
|
591
|
+
parameters: 'Invalid resolved type for array; cannot be non-atomic',
|
|
592
|
+
},
|
|
593
|
+
returnType: undefined,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
error: undefined,
|
|
598
|
+
returnType: { type: 'array', elementTypeDef },
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
case 'record': {
|
|
602
|
+
const fields = returnType.fields.map(f => {
|
|
603
|
+
const type = resolveGenerics(f, genericsSelected);
|
|
604
|
+
return {
|
|
605
|
+
...f,
|
|
606
|
+
...type,
|
|
607
|
+
};
|
|
608
|
+
});
|
|
609
|
+
return { error: undefined, returnType: { type: 'record', fields } };
|
|
610
|
+
}
|
|
611
|
+
case 'generic': {
|
|
612
|
+
const resolved = genericsSelected.get(returnType.generic);
|
|
613
|
+
if (resolved === undefined) {
|
|
614
|
+
return {
|
|
615
|
+
error: {
|
|
616
|
+
code: 'generic-not-resolved',
|
|
617
|
+
parameters: `Generic ${returnType.generic} in return type could not be resolved`,
|
|
618
|
+
},
|
|
619
|
+
returnType: undefined,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
error: undefined,
|
|
624
|
+
returnType: resolved,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
default:
|
|
628
|
+
return { error: undefined, returnType };
|
|
629
|
+
}
|
|
630
|
+
}
|
|
465
631
|
//# sourceMappingURL=expr-func.js.map
|
|
@@ -82,6 +82,7 @@ function getDialectFunctions() {
|
|
|
82
82
|
dialect: {},
|
|
83
83
|
supportsOrderBy: baseOverload.supportsOrderBy,
|
|
84
84
|
supportsLimit: baseOverload.supportsLimit,
|
|
85
|
+
genericTypes: baseOverload.genericTypes,
|
|
85
86
|
isSymmetric: baseOverload.isSymmetric,
|
|
86
87
|
};
|
|
87
88
|
for (const dialect of dialects) {
|
package/dist/lang/parse-log.d.ts
CHANGED
|
@@ -357,6 +357,8 @@ type MessageParameterTypes = {
|
|
|
357
357
|
'exclude-after-include': string;
|
|
358
358
|
'cannot-rename-non-field': string;
|
|
359
359
|
'array-values-incompatible': string;
|
|
360
|
+
'invalid-resolved-type-for-array': string;
|
|
361
|
+
'generic-not-resolved': string;
|
|
360
362
|
'cannot-tag-include-except': string;
|
|
361
363
|
'unsupported-path-in-include': string;
|
|
362
364
|
'wildcard-include-rename': string;
|
|
@@ -364,6 +366,11 @@ type MessageParameterTypes = {
|
|
|
364
366
|
export declare const MESSAGE_FORMATTERS: PartialErrorCodeMessageMap;
|
|
365
367
|
export type MessageCode = keyof MessageParameterTypes;
|
|
366
368
|
export type MessageParameterType<T extends MessageCode> = MessageParameterTypes[T];
|
|
369
|
+
type MessageCodeAndParameters<T extends MessageCode> = {
|
|
370
|
+
code: T;
|
|
371
|
+
parameters: MessageParameterType<T>;
|
|
372
|
+
};
|
|
373
|
+
export type AnyMessageCodeAndParameters = MessageCodeAndParameters<MessageCode>;
|
|
367
374
|
type MessageFormatter<T extends MessageCode> = MessageInfo | ((parameters: MessageParameterType<T>) => MessageInfo);
|
|
368
375
|
type ErrorCodeMessageMap = {
|
|
369
376
|
[key in keyof MessageParameterTypes]: MessageFormatter<key>;
|
|
@@ -414,6 +414,7 @@ export interface RepeatedRecordDef extends RepeatedRecordTypeDef, StructDefBase,
|
|
|
414
414
|
}
|
|
415
415
|
export type ArrayTypeDef = ScalarArrayTypeDef | RepeatedRecordTypeDef;
|
|
416
416
|
export type ArrayDef = ScalarArrayDef | RepeatedRecordDef;
|
|
417
|
+
export declare function isRepeatedRecordFunctionParam(paramT: FunctionParameterTypeDef): paramT is RepeatedRecordFunctionParameterTypeDef;
|
|
417
418
|
export declare function isRepeatedRecord(fd: FieldDef | QueryFieldDef | StructDef | AtomicTypeDef): fd is RepeatedRecordTypeDef;
|
|
418
419
|
export declare function isScalarArray(td: AtomicTypeDef | FieldDef | QueryFieldDef | StructDef): td is ScalarArrayTypeDef;
|
|
419
420
|
export interface ErrorTypeDef {
|
|
@@ -630,7 +631,7 @@ export type SourceDef = TableSourceDef | SQLSourceDef | QuerySourceDef | QueryRe
|
|
|
630
631
|
/** Is this the "FROM" table of a query tree */
|
|
631
632
|
export declare function isBaseTable(def: StructDef): def is SourceDef;
|
|
632
633
|
export type StructDef = SourceDef | RecordDef | ArrayDef;
|
|
633
|
-
export type NonAtomicType = Exclude<JoinElementType, 'array' | 'record'> | 'turtle' | 'null' | 'duration' | '
|
|
634
|
+
export type NonAtomicType = Exclude<JoinElementType, 'array' | 'record'> | 'turtle' | 'null' | 'duration' | 'regular expression';
|
|
634
635
|
export interface NonAtomicTypeDef {
|
|
635
636
|
type: NonAtomicType;
|
|
636
637
|
}
|
|
@@ -643,13 +644,54 @@ export type TypeInfo = {
|
|
|
643
644
|
compositeFieldUsage: CompositeFieldUsage;
|
|
644
645
|
};
|
|
645
646
|
export type TypeDesc = ExpressionValueTypeDef & TypeInfo;
|
|
646
|
-
export type
|
|
647
|
-
|
|
647
|
+
export type FunctionParameterTypeDef = ExpressionValueExtTypeDef<FunctionParameterTypeExtensions>;
|
|
648
|
+
export type FunctionParamTypeDesc = FunctionParameterTypeDef & {
|
|
649
|
+
expressionType: ExpressionType | undefined;
|
|
650
|
+
evalSpace: EvalSpace;
|
|
648
651
|
};
|
|
649
|
-
|
|
652
|
+
interface ScalarArrayExtTypeDef<TypeExtensions> {
|
|
653
|
+
type: 'array';
|
|
654
|
+
elementTypeDef: Exclude<ExpressionValueExtTypeDef<TypeExtensions>, RecordExtTypeDef<TypeExtensions>>;
|
|
655
|
+
}
|
|
656
|
+
type ExpressionValueExtTypeDef<TypeExtensions> = AtomicTypeDef | NonAtomicTypeDef | ScalarArrayExtTypeDef<TypeExtensions> | RecordExtTypeDef<TypeExtensions> | RepeatedRecordExtTypeDef<TypeExtensions> | TypeExtensions;
|
|
657
|
+
interface RecordExtTypeDef<TypeExtensions> {
|
|
658
|
+
type: 'record';
|
|
659
|
+
fields: ExtFieldDef<TypeExtensions>[];
|
|
660
|
+
}
|
|
661
|
+
type ExtFieldDef<TypeExtensions> = FieldDef | (TypeExtensions & FieldBase);
|
|
662
|
+
interface RepeatedRecordExtTypeDef<TypeExtensions> {
|
|
663
|
+
type: 'array';
|
|
664
|
+
elementTypeDef: RecordElementTypeDef;
|
|
665
|
+
fields: ExtFieldDef<TypeExtensions>[];
|
|
666
|
+
}
|
|
667
|
+
type FunctionReturnTypeExtensions = GenericTypeDef;
|
|
668
|
+
export type ScalarArrayFunctionReturnTypeDef = ScalarArrayExtTypeDef<FunctionReturnTypeExtensions>;
|
|
669
|
+
export type FunctionReturnFieldDef = ExtFieldDef<FunctionReturnTypeExtensions>;
|
|
670
|
+
export type RecordFunctionReturnTypeDef = RecordExtTypeDef<FunctionReturnTypeExtensions>;
|
|
671
|
+
export type RepeatedRecordFunctionReturnTypeDef = RepeatedRecordExtTypeDef<FunctionReturnTypeExtensions>;
|
|
672
|
+
type FunctionParameterTypeExtensions = GenericTypeDef | AnyTypeDef;
|
|
673
|
+
export type ScalarArrayFunctionParameterTypeDef = ScalarArrayExtTypeDef<FunctionParameterTypeExtensions>;
|
|
674
|
+
export type FunctionParameterFieldDef = ExtFieldDef<FunctionParameterTypeExtensions>;
|
|
675
|
+
export type RecordFunctionParameterTypeDef = RecordExtTypeDef<FunctionParameterTypeExtensions>;
|
|
676
|
+
export type RepeatedRecordFunctionParameterTypeDef = RepeatedRecordExtTypeDef<FunctionParameterTypeExtensions>;
|
|
677
|
+
type FunctionGenericTypeExtensions = AnyTypeDef;
|
|
678
|
+
export type ScalarArrayFunctionGenericTypeDef = ScalarArrayExtTypeDef<FunctionGenericTypeExtensions>;
|
|
679
|
+
export type FunctionGenericFieldDef = ExtFieldDef<FunctionGenericTypeExtensions>;
|
|
680
|
+
export type RecordFunctionGenericTypeDef = RecordExtTypeDef<FunctionGenericTypeExtensions>;
|
|
681
|
+
export type RepeatedRecordFunctionGenericTypeDef = RepeatedRecordExtTypeDef<FunctionGenericTypeExtensions>;
|
|
682
|
+
export interface GenericTypeDef {
|
|
683
|
+
type: 'generic';
|
|
684
|
+
generic: string;
|
|
685
|
+
}
|
|
686
|
+
export interface AnyTypeDef {
|
|
687
|
+
type: 'any';
|
|
688
|
+
}
|
|
689
|
+
export type TypeDescExtensions = {
|
|
650
690
|
expressionType: ExpressionType | undefined;
|
|
651
691
|
evalSpace: EvalSpace;
|
|
652
692
|
};
|
|
693
|
+
export type FunctionReturnTypeDef = ExpressionValueExtTypeDef<FunctionReturnTypeExtensions>;
|
|
694
|
+
export type FunctionReturnTypeDesc = FunctionReturnTypeDef & TypeDescExtensions;
|
|
653
695
|
export type EvalSpace = 'constant' | 'input' | 'output' | 'literal';
|
|
654
696
|
export declare function isLiteral(evalSpace: EvalSpace): boolean;
|
|
655
697
|
export declare function mergeEvalSpaces(...evalSpaces: EvalSpace[]): EvalSpace;
|
|
@@ -658,12 +700,17 @@ export interface FunctionParameterDef {
|
|
|
658
700
|
allowedTypes: FunctionParamTypeDesc[];
|
|
659
701
|
isVariadic: boolean;
|
|
660
702
|
}
|
|
703
|
+
export type FunctionGenericTypeDef = ExpressionValueExtTypeDef<FunctionGenericTypeExtensions>;
|
|
661
704
|
export interface FunctionOverloadDef {
|
|
662
|
-
returnType:
|
|
705
|
+
returnType: FunctionReturnTypeDesc;
|
|
663
706
|
isSymmetric?: boolean;
|
|
664
707
|
params: FunctionParameterDef[];
|
|
665
708
|
supportsOrderBy?: boolean | 'only_default';
|
|
666
709
|
supportsLimit?: boolean;
|
|
710
|
+
genericTypes?: {
|
|
711
|
+
name: string;
|
|
712
|
+
acceptibleTypes: FunctionGenericTypeDef[];
|
|
713
|
+
}[];
|
|
667
714
|
dialect: {
|
|
668
715
|
[dialect: string]: {
|
|
669
716
|
e: Expr;
|
|
@@ -776,7 +823,7 @@ export interface QueryResult extends CompiledQuery {
|
|
|
776
823
|
profilingUrl?: string;
|
|
777
824
|
}
|
|
778
825
|
export declare function isTurtle(def: TypedDef): def is TurtleDef;
|
|
779
|
-
export declare function isAtomic(def: TypedDef): def is AtomicTypeDef;
|
|
826
|
+
export declare function isAtomic(def: TypedDef | ExpressionValueTypeDef): def is AtomicTypeDef;
|
|
780
827
|
export interface SearchResultRow {
|
|
781
828
|
field_name: string;
|
|
782
829
|
field_value: string;
|
|
@@ -810,7 +857,7 @@ export interface PrepareResultOptions {
|
|
|
810
857
|
replaceMaterializedReferences?: boolean;
|
|
811
858
|
materializedTablePrefix?: string;
|
|
812
859
|
}
|
|
813
|
-
type UTD = AtomicTypeDef |
|
|
860
|
+
type UTD = AtomicTypeDef | TypedDef | FunctionParameterTypeDef | FunctionReturnTypeDef | undefined;
|
|
814
861
|
/**
|
|
815
862
|
* A set of utilities for asking questions TypeDef/TypeDesc
|
|
816
863
|
* (which is OK because TypeDesc is an extension of a TypeDef)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
3
|
* Copyright 2023 Google LLC
|
|
4
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
5
|
*
|
|
5
6
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
6
7
|
* a copy of this software and associated documentation files
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
24
|
*/
|
|
24
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.
|
|
26
|
-
exports.TD = exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isAtomic = exports.isTurtle = exports.getIdentifier = exports.isLeafAtomic = exports.mergeEvalSpaces = exports.isLiteral = void 0;
|
|
26
|
+
exports.isSourceDef = exports.sourceBase = exports.isSegmentSQL = exports.isIndexSegment = exports.isRawSegment = exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isPartialSegment = exports.isReduceSegment = exports.structHasErrors = exports.segmentHasErrors = exports.refIsStructDef = exports.ValueType = exports.isExtractUnit = exports.isTimestampUnit = exports.isDateUnit = exports.isJoinedSource = exports.isJoined = exports.isJoinable = exports.isMatrixOperation = exports.isScalarArray = exports.isRepeatedRecord = exports.isRepeatedRecordFunctionParam = exports.mkArrayDef = exports.mkFieldDef = exports.fieldIsIntrinsic = exports.isCastType = exports.canOrderBy = exports.isAtomicFieldType = exports.isTemporalType = exports.hasExpression = exports.maxOfExpressionTypes = exports.maxExpressionType = exports.isExpressionTypeLEQ = exports.expressionIsAnalytic = exports.expressionIsCalculation = exports.expressionInvolvesAggregate = exports.expressionIsUngroupedAggregate = exports.expressionIsAggregate = exports.expressionIsScalar = exports.paramHasValue = exports.isRawCast = exports.mkTemporal = exports.isAsymmetricExpr = exports.exprIsLeaf = exports.exprHasE = exports.exprHasKids = void 0;
|
|
27
|
+
exports.TD = exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isAtomic = exports.isTurtle = exports.getIdentifier = exports.isLeafAtomic = exports.mergeEvalSpaces = exports.isLiteral = exports.isBaseTable = void 0;
|
|
27
28
|
function exprHasKids(e) {
|
|
28
29
|
return 'kids' in e;
|
|
29
30
|
}
|
|
@@ -217,6 +218,10 @@ function mkArrayDef(ofType, name) {
|
|
|
217
218
|
};
|
|
218
219
|
}
|
|
219
220
|
exports.mkArrayDef = mkArrayDef;
|
|
221
|
+
function isRepeatedRecordFunctionParam(paramT) {
|
|
222
|
+
return (paramT.type === 'array' && paramT.elementTypeDef.type === 'record_element');
|
|
223
|
+
}
|
|
224
|
+
exports.isRepeatedRecordFunctionParam = isRepeatedRecordFunctionParam;
|
|
220
225
|
function isRepeatedRecord(fd) {
|
|
221
226
|
return fd.type === 'array' && fd.elementTypeDef.type === 'record_element';
|
|
222
227
|
}
|
|
@@ -477,10 +482,10 @@ exports.TD = {
|
|
|
477
482
|
) {
|
|
478
483
|
return exports.TD.eq(x.elementTypeDef, y.elementTypeDef);
|
|
479
484
|
}
|
|
480
|
-
return checkFields(x, y);
|
|
485
|
+
return exports.TD.isAtomic(x) && exports.TD.isAtomic(y) && checkFields(x, y);
|
|
481
486
|
}
|
|
482
487
|
else if (x.type === 'record' && y.type === 'record') {
|
|
483
|
-
return checkFields(x, y);
|
|
488
|
+
return exports.TD.isAtomic(x) && exports.TD.isAtomic(y) && checkFields(x, y);
|
|
484
489
|
}
|
|
485
490
|
if (x.type === 'sql native' && y.type === 'sql native') {
|
|
486
491
|
return x.rawType !== undefined && x.rawType === y.rawType;
|