@malloydata/malloy 0.0.215 → 0.0.216-dev241118202522
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/functions/util.d.ts +8 -8
- package/dist/dialect/functions/util.js +15 -7
- package/dist/lang/ast/ast-utils.js +2 -0
- package/dist/lang/ast/expressions/expr-aggregate-function.js +1 -0
- package/dist/lang/ast/expressions/expr-compare.js +7 -14
- package/dist/lang/ast/expressions/expr-count-distinct.js +1 -0
- package/dist/lang/ast/expressions/expr-count.js +3 -0
- package/dist/lang/ast/expressions/expr-func.js +3 -0
- package/dist/lang/ast/expressions/expr-id-reference.js +10 -1
- package/dist/lang/ast/expressions/expr-now.js +2 -0
- package/dist/lang/ast/expressions/expr-ungroup.js +1 -0
- package/dist/lang/ast/field-space/dynamic-space.d.ts +1 -3
- package/dist/lang/ast/field-space/dynamic-space.js +11 -15
- package/dist/lang/ast/field-space/query-spaces.d.ts +19 -0
- package/dist/lang/ast/field-space/query-spaces.js +104 -12
- package/dist/lang/ast/field-space/reference-field.js +7 -1
- package/dist/lang/ast/field-space/refined-space.d.ts +1 -0
- package/dist/lang/ast/field-space/refined-space.js +9 -6
- package/dist/lang/ast/field-space/struct-space-field-base.js +4 -0
- package/dist/lang/ast/index.d.ts +1 -0
- package/dist/lang/ast/index.js +1 -0
- package/dist/lang/ast/query-builders/index-builder.js +1 -1
- package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -1
- package/dist/lang/ast/query-builders/reduce-builder.js +9 -5
- package/dist/lang/ast/query-elements/query-base.js +16 -3
- package/dist/lang/ast/query-items/field-declaration.js +3 -0
- package/dist/lang/ast/query-properties/filters.d.ts +3 -0
- package/dist/lang/ast/query-properties/filters.js +42 -26
- package/dist/lang/ast/query-properties/nest.d.ts +1 -0
- package/dist/lang/ast/query-properties/nest.js +5 -1
- package/dist/lang/ast/source-elements/composite-source.d.ts +16 -0
- package/dist/lang/ast/source-elements/composite-source.js +75 -0
- package/dist/lang/ast/source-elements/source.d.ts +2 -2
- package/dist/lang/ast/source-properties/join.js +2 -0
- package/dist/lang/ast/source-query-elements/sq-compose.d.ts +13 -0
- package/dist/lang/ast/source-query-elements/sq-compose.js +48 -0
- package/dist/lang/ast/typedesc-utils.js +7 -1
- package/dist/lang/ast/types/expr-value.js +4 -0
- package/dist/lang/ast/types/expression-def.js +4 -5
- package/dist/lang/ast/types/query-builder.d.ts +2 -1
- package/dist/lang/ast/types/space-field.js +14 -1
- package/dist/lang/ast/types/space-param.js +3 -0
- package/dist/lang/ast/view-elements/reference-view.js +1 -0
- package/dist/lang/ast/view-elements/refine-utils.js +2 -0
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +113 -112
- package/dist/lang/lib/Malloy/MalloyLexer.js +1149 -1143
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +126 -112
- package/dist/lang/lib/Malloy/MalloyParser.js +1380 -1282
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +13 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +8 -0
- package/dist/lang/malloy-to-ast.d.ts +1 -0
- package/dist/lang/malloy-to-ast.js +5 -0
- package/dist/lang/parse-log.d.ts +10 -1
- package/dist/lang/parse-log.js +7 -0
- package/dist/lang/test/composite-field-usage.spec.d.ts +1 -0
- package/dist/lang/test/composite-field-usage.spec.js +155 -0
- package/dist/lang/test/parse-expects.d.ts +2 -1
- package/dist/lang/test/parse-expects.js +36 -0
- package/dist/lang/test/source.spec.js +9 -0
- package/dist/lang/test/test-translator.d.ts +3 -1
- package/dist/lang/test/test-translator.js +15 -4
- package/dist/lang/utils.d.ts +1 -0
- package/dist/lang/utils.js +5 -1
- package/dist/model/composite_source_utils.d.ts +65 -0
- package/dist/model/composite_source_utils.js +279 -0
- package/dist/model/malloy_query.d.ts +3 -3
- package/dist/model/malloy_query.js +13 -6
- package/dist/model/malloy_types.d.ts +19 -2
- package/dist/model/malloy_types.js +15 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.compositeFieldUsageJoinPaths = exports.joinedCompositeFieldUsage = exports.compositeFieldUsageDifference = exports.emptyCompositeFieldUsage = exports.mergeCompositeFieldUsage = exports.unique = exports.formatCompositeFieldUsage = exports.compositeFieldUsageIsPlural = exports.isEmptyCompositeFieldUsage = exports.formatCompositeFieldUsages = exports.compositeFieldUsagePaths = exports.resolveCompositeSources = exports.narrowCompositeFieldResolution = exports.emptyNarrowedCompositeFieldResolution = void 0;
|
|
10
|
+
const utils_1 = require("../lang/utils");
|
|
11
|
+
const malloy_types_1 = require("./malloy_types");
|
|
12
|
+
function _resolveCompositeSources(path, source, compositeFieldUsage, narrowedCompositeFieldResolution = undefined) {
|
|
13
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
14
|
+
let base = { ...source };
|
|
15
|
+
let narrowedSources = undefined;
|
|
16
|
+
if (compositeFieldUsage.fields.length > 0) {
|
|
17
|
+
if (source.type === 'composite') {
|
|
18
|
+
let found = false;
|
|
19
|
+
// The narrowed source list is either the one given when this function was called,
|
|
20
|
+
// or we construct a new one from the given composite source's input sources.
|
|
21
|
+
narrowedSources =
|
|
22
|
+
(_a = narrowedCompositeFieldResolution === null || narrowedCompositeFieldResolution === void 0 ? void 0 : narrowedCompositeFieldResolution.source) !== null && _a !== void 0 ? _a : source.sources.map(s => ({ source: s, nested: undefined }));
|
|
23
|
+
// Make a copy, which we will mutate: if a source is invalid, we remove it from the list
|
|
24
|
+
// and move on; if the source is a nested composite source, we narrow the resolution of
|
|
25
|
+
// the inner sources and update the element in the list
|
|
26
|
+
const newNarrowedSources = [...narrowedSources];
|
|
27
|
+
// We iterate over the list of narrowed sources;
|
|
28
|
+
overSources: for (const { source: inputSource, nested, } of narrowedSources) {
|
|
29
|
+
const fieldNames = new Set();
|
|
30
|
+
for (const field of inputSource.fields) {
|
|
31
|
+
fieldNames.add((_b = field.as) !== null && _b !== void 0 ? _b : field.name);
|
|
32
|
+
}
|
|
33
|
+
for (const usage of compositeFieldUsage.fields) {
|
|
34
|
+
if (!fieldNames.has(usage)) {
|
|
35
|
+
newNarrowedSources.shift();
|
|
36
|
+
continue overSources;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const nonCompositeFields = getNonCompositeFields(source);
|
|
40
|
+
if (inputSource.type === 'composite') {
|
|
41
|
+
const resolveInner = _resolveCompositeSources(path, inputSource, compositeFieldUsageWithoutNonCompositeFields(compositeFieldUsage, inputSource),
|
|
42
|
+
// This looks wonky, but what we're doing is taking the nested sources
|
|
43
|
+
// and "promoting" them to look like they're top level sources; we will
|
|
44
|
+
// then reverse this when we update the real narrowed resolution.
|
|
45
|
+
{
|
|
46
|
+
source: nested !== null && nested !== void 0 ? nested : inputSource.sources.map(s => ({ source: s, nested: [] })),
|
|
47
|
+
// Composite source inputs cannot have joins, so we don't need to
|
|
48
|
+
// pass in the narrowed resolution
|
|
49
|
+
joined: {},
|
|
50
|
+
});
|
|
51
|
+
if ('error' in resolveInner) {
|
|
52
|
+
newNarrowedSources.shift();
|
|
53
|
+
continue overSources;
|
|
54
|
+
}
|
|
55
|
+
base = { ...resolveInner.success };
|
|
56
|
+
newNarrowedSources[0] = {
|
|
57
|
+
source: inputSource,
|
|
58
|
+
nested: resolveInner.narrowedCompositeFieldResolution.source,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
base = { ...inputSource };
|
|
63
|
+
}
|
|
64
|
+
found = true;
|
|
65
|
+
base = {
|
|
66
|
+
...base,
|
|
67
|
+
fields: [...nonCompositeFields, ...base.fields],
|
|
68
|
+
filterList: [
|
|
69
|
+
...((_c = source.filterList) !== null && _c !== void 0 ? _c : []),
|
|
70
|
+
...((_d = base.filterList) !== null && _d !== void 0 ? _d : []),
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (!found) {
|
|
76
|
+
return {
|
|
77
|
+
error: {
|
|
78
|
+
code: 'no_suitable_composite_source_input',
|
|
79
|
+
data: { fields: compositeFieldUsage.fields, path },
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
narrowedSources = newNarrowedSources;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return { error: { code: 'not_a_composite_source', data: { path } } };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const fieldsByName = {};
|
|
90
|
+
const narrowedJoinedSources = (_e = narrowedCompositeFieldResolution === null || narrowedCompositeFieldResolution === void 0 ? void 0 : narrowedCompositeFieldResolution.joined) !== null && _e !== void 0 ? _e : {};
|
|
91
|
+
for (const field of base.fields) {
|
|
92
|
+
fieldsByName[(_f = field.as) !== null && _f !== void 0 ? _f : field.name] = field;
|
|
93
|
+
}
|
|
94
|
+
for (const [joinName, joinedUsage] of Object.entries(compositeFieldUsage.joinedUsage)) {
|
|
95
|
+
const join = fieldsByName[joinName];
|
|
96
|
+
const newPath = [...path, joinName];
|
|
97
|
+
if (join === undefined) {
|
|
98
|
+
return {
|
|
99
|
+
error: { code: 'composite_source_not_defined', data: { path: newPath } },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (!(0, malloy_types_1.isJoined)(join) || !(0, malloy_types_1.isSourceDef)(join)) {
|
|
103
|
+
return {
|
|
104
|
+
error: { code: 'composite_source_not_a_join', data: { path: newPath } },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const resolved = _resolveCompositeSources(newPath, join, joinedUsage, narrowedJoinedSources[joinName]);
|
|
108
|
+
if ('error' in resolved) {
|
|
109
|
+
return resolved;
|
|
110
|
+
}
|
|
111
|
+
if (!(0, malloy_types_1.isJoinable)(resolved.success)) {
|
|
112
|
+
return {
|
|
113
|
+
error: {
|
|
114
|
+
code: 'composite_source_is_not_joinable',
|
|
115
|
+
data: { path: newPath },
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
fieldsByName[joinName] = {
|
|
120
|
+
...resolved.success,
|
|
121
|
+
join: join.join,
|
|
122
|
+
as: (_g = join.as) !== null && _g !== void 0 ? _g : join.name,
|
|
123
|
+
onExpression: join.onExpression,
|
|
124
|
+
};
|
|
125
|
+
narrowedJoinedSources[joinName] = resolved.narrowedCompositeFieldResolution;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
success: { ...base, fields: Object.values(fieldsByName) },
|
|
129
|
+
narrowedCompositeFieldResolution: {
|
|
130
|
+
source: narrowedSources,
|
|
131
|
+
joined: narrowedJoinedSources,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function emptyNarrowedCompositeFieldResolution() {
|
|
136
|
+
return { source: undefined, joined: {} };
|
|
137
|
+
}
|
|
138
|
+
exports.emptyNarrowedCompositeFieldResolution = emptyNarrowedCompositeFieldResolution;
|
|
139
|
+
// Should always give the _full_ `compositeFieldUsage`, because we only
|
|
140
|
+
// cross off sources until we find one that works, but that does not
|
|
141
|
+
// guarantee that all the remaining sources will work.
|
|
142
|
+
function narrowCompositeFieldResolution(source, compositeFieldUsage, narrowedCompositeFieldResolution) {
|
|
143
|
+
const result = _resolveCompositeSources([], source, compositeFieldUsage, narrowedCompositeFieldResolution);
|
|
144
|
+
if ('success' in result) {
|
|
145
|
+
return {
|
|
146
|
+
narrowedCompositeFieldResolution: result.narrowedCompositeFieldResolution,
|
|
147
|
+
error: undefined,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return { narrowedCompositeFieldResolution: undefined, error: result.error };
|
|
151
|
+
}
|
|
152
|
+
exports.narrowCompositeFieldResolution = narrowCompositeFieldResolution;
|
|
153
|
+
function resolveCompositeSources(source, compositeFieldUsage) {
|
|
154
|
+
const result = _resolveCompositeSources([], source, compositeFieldUsage);
|
|
155
|
+
if ('success' in result) {
|
|
156
|
+
return { sourceDef: result.success, error: undefined };
|
|
157
|
+
}
|
|
158
|
+
return { sourceDef: undefined, error: result.error };
|
|
159
|
+
}
|
|
160
|
+
exports.resolveCompositeSources = resolveCompositeSources;
|
|
161
|
+
function compositeFieldUsagePaths(compositeFieldUsage) {
|
|
162
|
+
return [
|
|
163
|
+
...compositeFieldUsage.fields.map(f => [f]),
|
|
164
|
+
...Object.entries(compositeFieldUsage.joinedUsage)
|
|
165
|
+
.map(([joinName, joinedUsage]) => compositeFieldUsagePaths(joinedUsage).map(path => [joinName, ...path]))
|
|
166
|
+
.flat(),
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
exports.compositeFieldUsagePaths = compositeFieldUsagePaths;
|
|
170
|
+
function formatCompositeFieldUsages(compositeFieldUsage) {
|
|
171
|
+
return compositeFieldUsagePaths(compositeFieldUsage)
|
|
172
|
+
.map(compositeFieldUsage => formatCompositeFieldUsage(compositeFieldUsage))
|
|
173
|
+
.join(', ');
|
|
174
|
+
}
|
|
175
|
+
exports.formatCompositeFieldUsages = formatCompositeFieldUsages;
|
|
176
|
+
function countCompositeFieldUsage(compositeFieldUsage) {
|
|
177
|
+
return Object.values(compositeFieldUsage.joinedUsage).reduce((a, b) => a + countCompositeFieldUsage(b), compositeFieldUsage.fields.length);
|
|
178
|
+
}
|
|
179
|
+
function isEmptyCompositeFieldUsage(compositeFieldUsage) {
|
|
180
|
+
return countCompositeFieldUsage(compositeFieldUsage) === 0;
|
|
181
|
+
}
|
|
182
|
+
exports.isEmptyCompositeFieldUsage = isEmptyCompositeFieldUsage;
|
|
183
|
+
function compositeFieldUsageIsPlural(compositeFieldUsage) {
|
|
184
|
+
return countCompositeFieldUsage(compositeFieldUsage) > 1;
|
|
185
|
+
}
|
|
186
|
+
exports.compositeFieldUsageIsPlural = compositeFieldUsageIsPlural;
|
|
187
|
+
function formatCompositeFieldUsage(compositeFieldUsage) {
|
|
188
|
+
return `\`${compositeFieldUsage.join('.')}\``;
|
|
189
|
+
}
|
|
190
|
+
exports.formatCompositeFieldUsage = formatCompositeFieldUsage;
|
|
191
|
+
function unique(values) {
|
|
192
|
+
return Array.from(new Set(values));
|
|
193
|
+
}
|
|
194
|
+
exports.unique = unique;
|
|
195
|
+
function mergeCompositeFieldUsage(...usages) {
|
|
196
|
+
const nonEmptyUsages = usages.filter(utils_1.isNotUndefined);
|
|
197
|
+
const joinNames = new Set(nonEmptyUsages.map(u => Object.keys(u.joinedUsage)).flat());
|
|
198
|
+
const joinedUsage = {};
|
|
199
|
+
for (const joinName of joinNames) {
|
|
200
|
+
joinedUsage[joinName] = mergeCompositeFieldUsage(...nonEmptyUsages
|
|
201
|
+
.map(u => u === null || u === void 0 ? void 0 : u.joinedUsage[joinName])
|
|
202
|
+
.filter(utils_1.isNotUndefined));
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
fields: unique(nonEmptyUsages.map(u => u.fields).flat()),
|
|
206
|
+
joinedUsage,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
exports.mergeCompositeFieldUsage = mergeCompositeFieldUsage;
|
|
210
|
+
function emptyCompositeFieldUsage() {
|
|
211
|
+
return { fields: [], joinedUsage: {} };
|
|
212
|
+
}
|
|
213
|
+
exports.emptyCompositeFieldUsage = emptyCompositeFieldUsage;
|
|
214
|
+
function arrayDifference(a, b) {
|
|
215
|
+
const bSet = new Set(b);
|
|
216
|
+
const ret = [];
|
|
217
|
+
for (const value of a) {
|
|
218
|
+
if (bSet.has(value))
|
|
219
|
+
continue;
|
|
220
|
+
ret.push(value);
|
|
221
|
+
}
|
|
222
|
+
return ret;
|
|
223
|
+
}
|
|
224
|
+
// Return all of `a`'s usage without any of `b`'s usage
|
|
225
|
+
function compositeFieldUsageDifference(a, b) {
|
|
226
|
+
return {
|
|
227
|
+
fields: arrayDifference(a.fields, b.fields),
|
|
228
|
+
joinedUsage: Object.fromEntries(Object.entries(a.joinedUsage)
|
|
229
|
+
.map(([joinName, joinedUsage]) => [
|
|
230
|
+
joinName,
|
|
231
|
+
joinName in b.joinedUsage
|
|
232
|
+
? compositeFieldUsageDifference(joinedUsage, b.joinedUsage[joinName])
|
|
233
|
+
: joinedUsage,
|
|
234
|
+
])
|
|
235
|
+
.filter(([_, joinedUsage]) => countCompositeFieldUsage(joinedUsage) > 0)),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
exports.compositeFieldUsageDifference = compositeFieldUsageDifference;
|
|
239
|
+
function joinedCompositeFieldUsage(joinPath, compositeFieldUsage) {
|
|
240
|
+
if (joinPath.length === 0)
|
|
241
|
+
return compositeFieldUsage;
|
|
242
|
+
return joinedCompositeFieldUsage(joinPath.slice(0, -1), {
|
|
243
|
+
fields: [],
|
|
244
|
+
joinedUsage: { [joinPath[joinPath.length - 1]]: compositeFieldUsage },
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
exports.joinedCompositeFieldUsage = joinedCompositeFieldUsage;
|
|
248
|
+
function compositeFieldUsageJoinPaths(compositeFieldUsage) {
|
|
249
|
+
const joinsUsed = Object.keys(compositeFieldUsage.joinedUsage);
|
|
250
|
+
return [
|
|
251
|
+
...joinsUsed.map(joinName => [joinName]),
|
|
252
|
+
...joinsUsed
|
|
253
|
+
.map(joinName => compositeFieldUsageJoinPaths(compositeFieldUsage.joinedUsage[joinName]).map(path => [joinName, ...path]))
|
|
254
|
+
.flat(),
|
|
255
|
+
];
|
|
256
|
+
}
|
|
257
|
+
exports.compositeFieldUsageJoinPaths = compositeFieldUsageJoinPaths;
|
|
258
|
+
function isCompositeField(fieldDef) {
|
|
259
|
+
var _a;
|
|
260
|
+
return 'e' in fieldDef && ((_a = fieldDef.e) === null || _a === void 0 ? void 0 : _a.node) === 'compositeField';
|
|
261
|
+
}
|
|
262
|
+
function getNonCompositeFields(source) {
|
|
263
|
+
return source.fields.filter(f => !isCompositeField(f));
|
|
264
|
+
}
|
|
265
|
+
// This is specifically for the case where the source `source` is a composite and the chosen input
|
|
266
|
+
// source is also a composite; if the `source` defines some fields outright, when resolving the inner
|
|
267
|
+
// composite, we don't want to include those fields.
|
|
268
|
+
function compositeFieldUsageWithoutNonCompositeFields(compositeFieldUsage, source) {
|
|
269
|
+
var _a;
|
|
270
|
+
const sourceFieldsByName = {};
|
|
271
|
+
for (const field of source.fields) {
|
|
272
|
+
sourceFieldsByName[(_a = field.as) !== null && _a !== void 0 ? _a : field.name] = field;
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
fields: compositeFieldUsage.fields.filter(f => isCompositeField(sourceFieldsByName[f])),
|
|
276
|
+
joinedUsage: compositeFieldUsage.joinedUsage,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=composite_source_utils.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dialect, DialectFieldList } from '../dialect';
|
|
2
|
-
import { AggregateFunctionType, Annotation, CompiledQuery, Expr, FieldDef, Filtered, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldNode,
|
|
2
|
+
import { AggregateFunctionType, Annotation, CompiledQuery, Expr, FieldDef, Filtered, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldNode, ParameterNode, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SegmentFieldDef, StructDef, StructRef, TurtleDef, FunctionOrderBy, Argument, AggregateExpr, FilterCondition, GenericSQLExpr, FieldnameNode, FunctionCallNode, UngroupNode, SourceReferenceNode, SpreadExpr, FilteredExpr, SourceDef, AtomicFieldDef, BooleanFieldDef, QueryToMaterialize, PrepareResultOptions, CaseExpr } from './malloy_types';
|
|
3
3
|
import { Connection } from '../connection/types';
|
|
4
4
|
import { AndChain } from './utils';
|
|
5
5
|
import { QueryInfo } from '../dialect/dialect';
|
|
@@ -308,10 +308,10 @@ declare class QueryStruct extends QueryNode {
|
|
|
308
308
|
connectionName: string;
|
|
309
309
|
constructor(structDef: StructDef, sourceArguments: Record<string, Argument> | undefined, parent: ParentQueryStruct | ParentQueryModel, prepareResultOptions: PrepareResultOptions, referenceId?: string);
|
|
310
310
|
maybeEmitParameterizedSourceUsage(): void;
|
|
311
|
-
resolveParentParameterReferences
|
|
311
|
+
private resolveParentParameterReferences;
|
|
312
312
|
private _arguments;
|
|
313
313
|
arguments(): Record<string, Argument>;
|
|
314
|
-
addFieldsFromFieldList
|
|
314
|
+
private addFieldsFromFieldList;
|
|
315
315
|
getAliasIdentifier(): string;
|
|
316
316
|
getSQLIdentifier(): string;
|
|
317
317
|
getIdentifier(): string;
|
|
@@ -878,6 +878,8 @@ class QueryField extends QueryNode {
|
|
|
878
878
|
case 'functionDefaultOrderBy':
|
|
879
879
|
case 'functionOrderBy':
|
|
880
880
|
return '';
|
|
881
|
+
case 'compositeField':
|
|
882
|
+
return '{COMPOSITE_FIELD}';
|
|
881
883
|
default:
|
|
882
884
|
throw new Error(`Internal Error: Unknown expression node '${expr.node}' ${JSON.stringify(expr, undefined, 2)}`);
|
|
883
885
|
}
|
|
@@ -3279,6 +3281,8 @@ class QueryStruct extends QueryNode {
|
|
|
3279
3281
|
switch (this.structDef.type) {
|
|
3280
3282
|
case 'table':
|
|
3281
3283
|
return this.dialect.quoteTablePath(this.structDef.tablePath);
|
|
3284
|
+
case 'composite':
|
|
3285
|
+
return '{COMPOSITE SOURCE}';
|
|
3282
3286
|
case 'finalize':
|
|
3283
3287
|
return this.structDef.name;
|
|
3284
3288
|
case 'sql_select':
|
|
@@ -3457,6 +3461,7 @@ class QueryModel {
|
|
|
3457
3461
|
return new QueryStruct(structRef, sourceArguments, { model: this }, prepareResultOptions);
|
|
3458
3462
|
}
|
|
3459
3463
|
loadQuery(query, stageWriter, prepareResultOptions, emitFinalStage = false, isJoinedSubquery = false) {
|
|
3464
|
+
var _a;
|
|
3460
3465
|
const malloy = '';
|
|
3461
3466
|
if (!stageWriter) {
|
|
3462
3467
|
stageWriter = new StageWriter(true, undefined);
|
|
@@ -3467,7 +3472,8 @@ class QueryModel {
|
|
|
3467
3472
|
pipeline: query.pipeline,
|
|
3468
3473
|
filterList: query.filterList,
|
|
3469
3474
|
};
|
|
3470
|
-
const
|
|
3475
|
+
const structRef = (_a = query.compositeResolvedSourceDef) !== null && _a !== void 0 ? _a : query.structRef;
|
|
3476
|
+
const q = QueryQuery.makeQuery(turtleDef, this.getStructFromRef(structRef, query.sourceArguments, prepareResultOptions), stageWriter, isJoinedSubquery);
|
|
3471
3477
|
const ret = q.generateSQLFromPipeline(stageWriter);
|
|
3472
3478
|
if (emitFinalStage && q.parent.dialect.hasFinalStage) {
|
|
3473
3479
|
// const fieldNames: string[] = [];
|
|
@@ -3486,13 +3492,14 @@ class QueryModel {
|
|
|
3486
3492
|
};
|
|
3487
3493
|
}
|
|
3488
3494
|
compileQuery(query, prepareResultOptions, finalize = true) {
|
|
3489
|
-
var _a;
|
|
3495
|
+
var _a, _b;
|
|
3490
3496
|
let newModel;
|
|
3491
3497
|
const m = newModel || this;
|
|
3492
3498
|
const ret = m.loadQuery(query, undefined, prepareResultOptions, finalize, false);
|
|
3493
|
-
const
|
|
3494
|
-
|
|
3495
|
-
|
|
3499
|
+
const structRef = (_a = query.compositeResolvedSourceDef) !== null && _a !== void 0 ? _a : query.structRef;
|
|
3500
|
+
const sourceExplore = typeof structRef === 'string'
|
|
3501
|
+
? structRef
|
|
3502
|
+
: structRef.as || structRef.name;
|
|
3496
3503
|
// LTNote: I don't understand why this might be here. It should have happened in loadQuery...
|
|
3497
3504
|
if (finalize && this.dialect.hasFinalStage) {
|
|
3498
3505
|
ret.lastStageName = ret.stageWriter.addStage(
|
|
@@ -3505,7 +3512,7 @@ class QueryModel {
|
|
|
3505
3512
|
sql: ret.stageWriter.generateSQLStages(),
|
|
3506
3513
|
dependenciesToMaterialize: ret.stageWriter.dependenciesToMaterialize,
|
|
3507
3514
|
materialization: (0, utils_2.shouldMaterialize)(query.annotation)
|
|
3508
|
-
? (0, utils_2.buildQueryMaterializationSpec)((
|
|
3515
|
+
? (0, utils_2.buildQueryMaterializationSpec)((_b = query.location) === null || _b === void 0 ? void 0 : _b.url, query.name, prepareResultOptions === null || prepareResultOptions === void 0 ? void 0 : prepareResultOptions.materializedTablePrefix)
|
|
3509
3516
|
: undefined,
|
|
3510
3517
|
structs: ret.structs,
|
|
3511
3518
|
sourceExplore,
|
|
@@ -24,7 +24,7 @@ export type AnyExpr = ExprE | ExprOptionalE | ExprWithKids | ExprLeaf;
|
|
|
24
24
|
export declare function exprHasKids(e: AnyExpr): e is ExprWithKids;
|
|
25
25
|
export declare function exprHasE(e: AnyExpr): e is ExprE;
|
|
26
26
|
export declare function exprIsLeaf(e: AnyExpr): boolean;
|
|
27
|
-
export type Expr = BinaryExpr | UnaryExpr | FunctionCallNode | OutputFieldNode | FilterCondition | FilteredExpr | AggregateExpr | EmptyExpr | UngroupNode | FunctionParameterNode | SpreadExpr | AggregateOrderByNode | AggregateLimitNode | FieldnameNode | SourceReferenceNode | ParameterNode | NowNode | MeasureTimeExpr | TimeExtractExpr | TimeDeltaExpr | TimeTruncExpr | TimeLiteralNode | TypecastExpr | RegexMatchExpr | RegexLiteralNode | StringLiteralNode | NumberLiteralNode | BooleanLiteralNode | RecordLiteralNode | ArrayLiteralNode | FunctionOrderBy | GenericSQLExpr | NullNode | CaseExpr | InCompareExpr | ErrorNode;
|
|
27
|
+
export type Expr = BinaryExpr | UnaryExpr | FunctionCallNode | OutputFieldNode | FilterCondition | FilteredExpr | AggregateExpr | EmptyExpr | UngroupNode | FunctionParameterNode | SpreadExpr | AggregateOrderByNode | AggregateLimitNode | FieldnameNode | SourceReferenceNode | ParameterNode | NowNode | MeasureTimeExpr | TimeExtractExpr | TimeDeltaExpr | TimeTruncExpr | TimeLiteralNode | TypecastExpr | RegexMatchExpr | RegexLiteralNode | StringLiteralNode | NumberLiteralNode | BooleanLiteralNode | RecordLiteralNode | ArrayLiteralNode | FunctionOrderBy | GenericSQLExpr | NullNode | CaseExpr | InCompareExpr | CompositeFieldExpr | ErrorNode;
|
|
28
28
|
interface HasTypeDef {
|
|
29
29
|
typeDef: AtomicTypeDef;
|
|
30
30
|
}
|
|
@@ -63,6 +63,7 @@ export interface FilterCondition extends ExprE {
|
|
|
63
63
|
node: 'filterCondition';
|
|
64
64
|
code: string;
|
|
65
65
|
expressionType: ExpressionType;
|
|
66
|
+
compositeFieldUsage?: CompositeFieldUsage;
|
|
66
67
|
}
|
|
67
68
|
export interface FilteredExpr extends ExprWithKids {
|
|
68
69
|
node: 'filteredExpr';
|
|
@@ -227,6 +228,9 @@ export interface CaseExpr extends ExprWithKids {
|
|
|
227
228
|
caseElse?: Expr;
|
|
228
229
|
};
|
|
229
230
|
}
|
|
231
|
+
export interface CompositeFieldExpr extends ExprLeaf {
|
|
232
|
+
node: 'compositeField';
|
|
233
|
+
}
|
|
230
234
|
export interface InCompareExpr extends ExprWithKids {
|
|
231
235
|
node: 'in';
|
|
232
236
|
not: boolean;
|
|
@@ -238,6 +242,7 @@ export interface InCompareExpr extends ExprWithKids {
|
|
|
238
242
|
export type ExpressionType = 'scalar' | 'aggregate' | 'scalar_analytic' | 'aggregate_analytic' | 'ungrouped_aggregate';
|
|
239
243
|
export interface Expression {
|
|
240
244
|
e?: Expr;
|
|
245
|
+
compositeFieldUsage?: CompositeFieldUsage;
|
|
241
246
|
expressionType?: ExpressionType;
|
|
242
247
|
code?: string;
|
|
243
248
|
}
|
|
@@ -410,6 +415,7 @@ export interface JoinBase {
|
|
|
410
415
|
join: JoinType;
|
|
411
416
|
matrixOperation?: MatrixOperation;
|
|
412
417
|
onExpression?: Expr;
|
|
418
|
+
onCompositeFieldUsage?: CompositeFieldUsage;
|
|
413
419
|
}
|
|
414
420
|
export type Joinable = TableSourceDef | SQLSourceDef | QuerySourceDef | RecordFieldDef | ArrayDef;
|
|
415
421
|
export type JoinFieldDef = JoinBase & Joinable;
|
|
@@ -492,6 +498,7 @@ export interface Query extends Pipeline, Filtered, HasLocation {
|
|
|
492
498
|
sourceArguments?: Record<string, Argument>;
|
|
493
499
|
annotation?: Annotation;
|
|
494
500
|
modelAnnotation?: Annotation;
|
|
501
|
+
compositeResolvedSourceDef?: SourceDef;
|
|
495
502
|
}
|
|
496
503
|
export type NamedQuery = Query & NamedObject;
|
|
497
504
|
export type PipeSegment = QuerySegment | IndexSegment | RawSegment;
|
|
@@ -539,6 +546,10 @@ export interface IndexSegment extends Filtered {
|
|
|
539
546
|
alwaysJoins?: string[];
|
|
540
547
|
}
|
|
541
548
|
export declare function isIndexSegment(pe: PipeSegment): pe is IndexSegment;
|
|
549
|
+
export interface CompositeFieldUsage {
|
|
550
|
+
fields: string[];
|
|
551
|
+
joinedUsage: Record<string, CompositeFieldUsage>;
|
|
552
|
+
}
|
|
542
553
|
export interface QuerySegment extends Filtered {
|
|
543
554
|
type: 'reduce' | 'project' | 'partial';
|
|
544
555
|
queryFields: QueryFieldDef[];
|
|
@@ -548,6 +559,7 @@ export interface QuerySegment extends Filtered {
|
|
|
548
559
|
orderBy?: OrderBy[];
|
|
549
560
|
queryTimezone?: string;
|
|
550
561
|
alwaysJoins?: string[];
|
|
562
|
+
compositeFieldUsage?: CompositeFieldUsage;
|
|
551
563
|
}
|
|
552
564
|
export interface TurtleDef extends NamedObject, Pipeline {
|
|
553
565
|
type: 'turtle';
|
|
@@ -573,6 +585,10 @@ export interface TableSourceDef extends SourceDefBase {
|
|
|
573
585
|
type: 'table';
|
|
574
586
|
tablePath: string;
|
|
575
587
|
}
|
|
588
|
+
export interface CompositeSourceDef extends SourceDefBase {
|
|
589
|
+
type: 'composite';
|
|
590
|
+
sources: SourceDef[];
|
|
591
|
+
}
|
|
576
592
|
export interface SQLStringSegment {
|
|
577
593
|
sql: string;
|
|
578
594
|
}
|
|
@@ -603,7 +619,7 @@ export interface FinalizeSourceDef extends SourceDefBase {
|
|
|
603
619
|
}
|
|
604
620
|
export declare function sourceBase(sd: SourceDefBase): SourceDefBase;
|
|
605
621
|
export declare function isSourceDef(sd: NamedModelObject | FieldDef): sd is SourceDef;
|
|
606
|
-
export type SourceDef = TableSourceDef | SQLSourceDef | QuerySourceDef | QueryResultDef | FinalizeSourceDef | NestSourceDef;
|
|
622
|
+
export type SourceDef = TableSourceDef | SQLSourceDef | QuerySourceDef | QueryResultDef | FinalizeSourceDef | NestSourceDef | CompositeSourceDef;
|
|
607
623
|
/** Is this the "FROM" table of a query tree */
|
|
608
624
|
export declare function isBaseTable(def: StructDef): def is SourceDef;
|
|
609
625
|
export declare function isScalarArray(def: FieldDef | StructDef): boolean;
|
|
@@ -618,6 +634,7 @@ export type LeafExpressionType = Exclude<ExpressionValueType, JoinElementType |
|
|
|
618
634
|
export type TypeInfo = {
|
|
619
635
|
expressionType: ExpressionType;
|
|
620
636
|
evalSpace: EvalSpace;
|
|
637
|
+
compositeFieldUsage: CompositeFieldUsage;
|
|
621
638
|
};
|
|
622
639
|
export type TypeDesc = ExpressionValueTypeDef & TypeInfo;
|
|
623
640
|
export type FunctionParamType = ExpressionValueTypeDef | {
|
|
@@ -178,7 +178,11 @@ function fieldIsIntrinsic(f) {
|
|
|
178
178
|
exports.fieldIsIntrinsic = fieldIsIntrinsic;
|
|
179
179
|
function arrayEachFields(arrayOf) {
|
|
180
180
|
return [
|
|
181
|
-
{
|
|
181
|
+
{
|
|
182
|
+
name: 'each',
|
|
183
|
+
...arrayOf,
|
|
184
|
+
e: { node: 'field', path: ['value'] },
|
|
185
|
+
},
|
|
182
186
|
{ name: 'value', ...arrayOf },
|
|
183
187
|
];
|
|
184
188
|
}
|
|
@@ -192,7 +196,14 @@ function isMatrixOperation(x) {
|
|
|
192
196
|
}
|
|
193
197
|
exports.isMatrixOperation = isMatrixOperation;
|
|
194
198
|
function isJoinable(sd) {
|
|
195
|
-
return [
|
|
199
|
+
return [
|
|
200
|
+
'table',
|
|
201
|
+
'sql_select',
|
|
202
|
+
'query_source',
|
|
203
|
+
'array',
|
|
204
|
+
'record',
|
|
205
|
+
'composite',
|
|
206
|
+
].includes(sd.type);
|
|
196
207
|
}
|
|
197
208
|
exports.isJoinable = isJoinable;
|
|
198
209
|
function isJoined(fd) {
|
|
@@ -314,7 +325,8 @@ function isSourceDef(sd) {
|
|
|
314
325
|
sd.type === 'query_source' ||
|
|
315
326
|
sd.type === 'query_result' ||
|
|
316
327
|
sd.type === 'finalize' ||
|
|
317
|
-
sd.type === 'nest_source'
|
|
328
|
+
sd.type === 'nest_source' ||
|
|
329
|
+
sd.type === 'composite');
|
|
318
330
|
}
|
|
319
331
|
exports.isSourceDef = isSourceDef;
|
|
320
332
|
/** Is this the "FROM" table of a query tree */
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.216";
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MALLOY_VERSION = void 0;
|
|
4
4
|
// generated with 'generate-version-file' script; do not edit manually
|
|
5
|
-
exports.MALLOY_VERSION = '0.0.
|
|
5
|
+
exports.MALLOY_VERSION = '0.0.216';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|