@malloydata/malloy 0.0.221-dev241209191943 → 0.0.221-dev241211195814
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/lang/ast/field-space/index-field-space.js +24 -7
- package/dist/lang/ast/field-space/query-spaces.d.ts +9 -1
- package/dist/lang/ast/field-space/query-spaces.js +55 -50
- package/dist/lang/ast/query-builders/index-builder.d.ts +2 -1
- package/dist/lang/ast/query-builders/index-builder.js +9 -0
- package/dist/lang/ast/query-elements/query-base.js +3 -2
- package/dist/lang/test/composite-field-usage.spec.js +8 -3
- package/dist/model/composite_source_utils.d.ts +1 -1
- package/dist/model/composite_source_utils.js +7 -17
- package/dist/model/malloy_types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.IndexFieldSpace = void 0;
|
|
26
|
+
const composite_source_utils_1 = require("../../../model/composite_source_utils");
|
|
26
27
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
27
28
|
const field_references_1 = require("../query-items/field-references");
|
|
28
29
|
const space_field_1 = require("../types/space-field");
|
|
@@ -52,15 +53,20 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
52
53
|
this.logError('refinement-of-index-segment', 'index query operations cannot be refined');
|
|
53
54
|
return { type: 'index', indexFields: [] };
|
|
54
55
|
}
|
|
56
|
+
let compositeFieldUsage = (0, composite_source_utils_1.emptyCompositeFieldUsage)();
|
|
57
|
+
let narrowedCompositeFieldResolution = (0, composite_source_utils_1.emptyNarrowedCompositeFieldResolution)();
|
|
55
58
|
const indexFields = [];
|
|
59
|
+
const source = this.inputSpace().structDef();
|
|
56
60
|
for (const [name, field] of this.entries()) {
|
|
57
61
|
if (field instanceof space_field_1.SpaceField) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
let nextCompositeFieldUsage = undefined;
|
|
63
|
+
let logTo = undefined;
|
|
64
|
+
const wild = this.expandedWild[name];
|
|
65
|
+
if (wild) {
|
|
66
|
+
indexFields.push({ type: 'fieldref', path: wild.path });
|
|
67
|
+
nextCompositeFieldUsage = wild.entry.typeDesc().compositeFieldUsage;
|
|
62
68
|
}
|
|
63
|
-
if (field instanceof reference_field_1.ReferenceField) {
|
|
69
|
+
else if (field instanceof reference_field_1.ReferenceField) {
|
|
64
70
|
// attempt to cause a type check
|
|
65
71
|
const fieldRef = field.fieldRef;
|
|
66
72
|
const check = fieldRef.getField(this.exprSpace);
|
|
@@ -69,10 +75,18 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
69
75
|
}
|
|
70
76
|
else {
|
|
71
77
|
indexFields.push(fieldRef.refToField);
|
|
78
|
+
nextCompositeFieldUsage =
|
|
79
|
+
check.found.typeDesc().compositeFieldUsage;
|
|
80
|
+
logTo = fieldRef;
|
|
72
81
|
}
|
|
73
82
|
}
|
|
83
|
+
const next = this.applyNextCompositeFieldUsage(source, compositeFieldUsage, narrowedCompositeFieldResolution, nextCompositeFieldUsage, logTo);
|
|
84
|
+
compositeFieldUsage = next.compositeFieldUsage;
|
|
85
|
+
narrowedCompositeFieldResolution =
|
|
86
|
+
next.narrowedCompositeFieldResolution;
|
|
74
87
|
}
|
|
75
88
|
}
|
|
89
|
+
this._compositeFieldUsage = compositeFieldUsage;
|
|
76
90
|
return { type: 'index', indexFields };
|
|
77
91
|
}
|
|
78
92
|
addRefineFromFields(_refineThis) { }
|
|
@@ -115,7 +129,7 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
115
129
|
name,
|
|
116
130
|
]);
|
|
117
131
|
if (this.entry(indexName)) {
|
|
118
|
-
const conflict = (_a = this.expandedWild[indexName]) === null || _a === void 0 ? void 0 : _a.join('.');
|
|
132
|
+
const conflict = (_a = this.expandedWild[indexName].path) === null || _a === void 0 ? void 0 : _a.join('.');
|
|
119
133
|
wild.logError('name-conflict-in-wildcard-expansion', `Cannot expand '${name}' in '${wild.refString}' because a field with that name already exists${conflict ? ` (conflicts with ${conflict})` : ''}`);
|
|
120
134
|
}
|
|
121
135
|
else {
|
|
@@ -125,7 +139,10 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
125
139
|
(0, malloy_types_1.expressionIsScalar)(eTypeDesc.expressionType) &&
|
|
126
140
|
(dialect === undefined || !dialect.ignoreInProject(name))) {
|
|
127
141
|
expandEntries.push({ name: indexName, entry });
|
|
128
|
-
this.expandedWild[indexName] =
|
|
142
|
+
this.expandedWild[indexName] = {
|
|
143
|
+
path: joinPath.concat(name),
|
|
144
|
+
entry,
|
|
145
|
+
};
|
|
129
146
|
}
|
|
130
147
|
}
|
|
131
148
|
}
|
|
@@ -8,6 +8,7 @@ import { LookupResult } from '../types/lookup-result';
|
|
|
8
8
|
import { QueryInputSpace } from './query-input-space';
|
|
9
9
|
import { SpaceEntry } from '../types/space-entry';
|
|
10
10
|
import { LogMessageOptions, MessageCode, MessageParameterType } from '../../parse-log';
|
|
11
|
+
import { NarrowedCompositeFieldResolution } from '../../../model/composite_source_utils';
|
|
11
12
|
/**
|
|
12
13
|
* The output space of a query operation. It is not named "QueryOutputSpace"
|
|
13
14
|
* because this is the namespace of the Query which is a layer of an output and
|
|
@@ -20,7 +21,10 @@ export declare abstract class QueryOperationSpace extends RefinedSpace implement
|
|
|
20
21
|
readonly astEl: MalloyElement;
|
|
21
22
|
protected exprSpace: QueryInputSpace;
|
|
22
23
|
abstract readonly segmentType: 'reduce' | 'project' | 'index';
|
|
23
|
-
expandedWild: Record<string,
|
|
24
|
+
expandedWild: Record<string, {
|
|
25
|
+
path: string[];
|
|
26
|
+
entry: SpaceEntry;
|
|
27
|
+
}>;
|
|
24
28
|
compositeFieldUsers: ({
|
|
25
29
|
type: 'filter';
|
|
26
30
|
filter: model.FilterCondition;
|
|
@@ -44,6 +48,10 @@ export declare abstract class QueryOperationSpace extends RefinedSpace implement
|
|
|
44
48
|
protected getCompositeFieldUsageIncludingJoinOns(compositeFieldUsage: model.CompositeFieldUsage): model.CompositeFieldUsage;
|
|
45
49
|
addCompositeFieldUserFromFilter(filter: model.FilterCondition, logTo: MalloyElement): void;
|
|
46
50
|
newEntry(name: string, logTo: MalloyElement, entry: SpaceEntry): void;
|
|
51
|
+
protected applyNextCompositeFieldUsage(source: model.SourceDef, compositeFieldUsage: model.CompositeFieldUsage, narrowedCompositeFieldResolution: NarrowedCompositeFieldResolution, nextCompositeFieldUsage: model.CompositeFieldUsage | undefined, logTo: MalloyElement | undefined): {
|
|
52
|
+
compositeFieldUsage: model.CompositeFieldUsage;
|
|
53
|
+
narrowedCompositeFieldResolution: NarrowedCompositeFieldResolution;
|
|
54
|
+
};
|
|
47
55
|
}
|
|
48
56
|
export declare abstract class QuerySpace extends QueryOperationSpace {
|
|
49
57
|
addRefineFromFields(refineThis: model.PipeSegment): void;
|
|
@@ -77,7 +77,8 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
77
77
|
this.astEl = astEl;
|
|
78
78
|
this.expandedWild = {};
|
|
79
79
|
this.compositeFieldUsers = [];
|
|
80
|
-
// Composite field usage is not computed until `queryFieldDefs` is called
|
|
80
|
+
// Composite field usage is not computed until `queryFieldDefs` is called
|
|
81
|
+
// (or `getPipeSegment` for index segments); if anyone
|
|
81
82
|
// tries to access it before that, they'll get an error
|
|
82
83
|
this._compositeFieldUsage = undefined;
|
|
83
84
|
this.exprSpace = new query_input_space_1.QueryInputSpace(queryInputSpace.structDef(), this);
|
|
@@ -131,7 +132,7 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
131
132
|
continue;
|
|
132
133
|
}
|
|
133
134
|
if (this.entry(name)) {
|
|
134
|
-
const conflict = (_a = this.expandedWild[name]) === null || _a === void 0 ? void 0 : _a.join('.');
|
|
135
|
+
const conflict = (_a = this.expandedWild[name]) === null || _a === void 0 ? void 0 : _a.path.join('.');
|
|
135
136
|
wild.logError('name-conflict-in-wildcard-expansion', `Cannot expand '${name}' in '${wild.refString}' because a field with that name already exists${conflict ? ` (conflicts with ${conflict})` : ''}`);
|
|
136
137
|
}
|
|
137
138
|
else {
|
|
@@ -140,7 +141,10 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
140
141
|
model.expressionIsScalar(eType.expressionType) &&
|
|
141
142
|
(dialect === undefined || !dialect.ignoreInProject(name))) {
|
|
142
143
|
expandEntries.push({ name, entry });
|
|
143
|
-
this.expandedWild[name] =
|
|
144
|
+
this.expandedWild[name] = {
|
|
145
|
+
path: joinPath.concat(name),
|
|
146
|
+
entry,
|
|
147
|
+
};
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
}
|
|
@@ -163,7 +167,7 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
163
167
|
var _a;
|
|
164
168
|
const reference = joinPath.map(n => new field_space_1.FieldName(n));
|
|
165
169
|
this.astEl.has({ reference });
|
|
166
|
-
const lookup = this.
|
|
170
|
+
const lookup = this.exprSpace.lookup(reference);
|
|
167
171
|
// Should always be found...
|
|
168
172
|
if (lookup.found && lookup.found instanceof struct_space_field_base_1.StructSpaceFieldBase) {
|
|
169
173
|
return ((_a = lookup.found.fieldDef().onCompositeFieldUsage) !== null && _a !== void 0 ? _a : (0, composite_source_utils_1.emptyCompositeFieldUsage)());
|
|
@@ -189,6 +193,26 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
189
193
|
}
|
|
190
194
|
super.newEntry(name, logTo, entry);
|
|
191
195
|
}
|
|
196
|
+
applyNextCompositeFieldUsage(source, compositeFieldUsage, narrowedCompositeFieldResolution, nextCompositeFieldUsage, logTo) {
|
|
197
|
+
if (nextCompositeFieldUsage) {
|
|
198
|
+
const newCompositeFieldUsage = this.getCompositeFieldUsageIncludingJoinOns((0, composite_source_utils_1.compositeFieldUsageDifference)(nextCompositeFieldUsage, compositeFieldUsage));
|
|
199
|
+
compositeFieldUsage = (0, composite_source_utils_1.mergeCompositeFieldUsage)(compositeFieldUsage, newCompositeFieldUsage);
|
|
200
|
+
if (!(0, composite_source_utils_1.isEmptyCompositeFieldUsage)(newCompositeFieldUsage)) {
|
|
201
|
+
const result = (0, composite_source_utils_1.narrowCompositeFieldResolution)(source, compositeFieldUsage, narrowedCompositeFieldResolution);
|
|
202
|
+
if (result.error) {
|
|
203
|
+
(logTo !== null && logTo !== void 0 ? logTo : this).logError('invalid-composite-field-usage', {
|
|
204
|
+
newUsage: newCompositeFieldUsage,
|
|
205
|
+
allUsage: compositeFieldUsage,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
narrowedCompositeFieldResolution =
|
|
210
|
+
result.narrowedCompositeFieldResolution;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return { compositeFieldUsage, narrowedCompositeFieldResolution };
|
|
215
|
+
}
|
|
192
216
|
}
|
|
193
217
|
exports.QueryOperationSpace = QueryOperationSpace;
|
|
194
218
|
// Project and Reduce or "QuerySegments" are built from a QuerySpace
|
|
@@ -252,57 +276,38 @@ class QuerySpace extends QueryOperationSpace {
|
|
|
252
276
|
const { name, field } = user;
|
|
253
277
|
const wildPath = this.expandedWild[name];
|
|
254
278
|
if (wildPath) {
|
|
255
|
-
fields.push({ type: 'fieldref', path: wildPath });
|
|
256
|
-
|
|
279
|
+
fields.push({ type: 'fieldref', path: wildPath.path });
|
|
280
|
+
nextCompositeFieldUsage =
|
|
281
|
+
wildPath.entry.typeDesc().compositeFieldUsage;
|
|
257
282
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
// TODO I removed the error here because during calculation of the refinement space,
|
|
275
|
-
// (see creation of a QuerySpace) we add references to all the fields from
|
|
276
|
-
// the refinement, but they don't have definitions. So in the case where we
|
|
277
|
-
// don't have a field def, we "know" that that field is already in the query,
|
|
278
|
-
// and we don't need to worry about actually adding it. Previously, this was also true for
|
|
279
|
-
// project statements, where we added "*" as a field and also all the individual
|
|
280
|
-
// fields, but the individual fields didn't have field defs.
|
|
281
|
-
}
|
|
282
|
-
if (nextCompositeFieldUsage) {
|
|
283
|
-
const newCompositeFieldUsage = this.getCompositeFieldUsageIncludingJoinOns((0, composite_source_utils_1.compositeFieldUsageDifference)(nextCompositeFieldUsage, compositeFieldUsage));
|
|
284
|
-
compositeFieldUsage = (0, composite_source_utils_1.mergeCompositeFieldUsage)(compositeFieldUsage, newCompositeFieldUsage);
|
|
285
|
-
if (!(0, composite_source_utils_1.isEmptyCompositeFieldUsage)(newCompositeFieldUsage)) {
|
|
286
|
-
const result = (0, composite_source_utils_1.narrowCompositeFieldResolution)(source, compositeFieldUsage, narrowedCompositeFieldResolution);
|
|
287
|
-
if (result.error) {
|
|
288
|
-
if (user.logTo) {
|
|
289
|
-
user.logTo.logError('invalid-composite-field-usage', {
|
|
290
|
-
newUsage: newCompositeFieldUsage,
|
|
291
|
-
allUsage: compositeFieldUsage,
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
// This should not happen; logTo should only be not set for a field from a refinement,
|
|
296
|
-
// which should never fail the composite resolution
|
|
297
|
-
throw new Error('Unexpected invalid composite field resolution');
|
|
283
|
+
else {
|
|
284
|
+
const fieldQueryDef = field.getQueryFieldDef(this.exprSpace);
|
|
285
|
+
if (fieldQueryDef) {
|
|
286
|
+
const typeDesc = field.typeDesc();
|
|
287
|
+
nextCompositeFieldUsage = typeDesc.compositeFieldUsage;
|
|
288
|
+
// Filter out fields whose type is 'error', which means that a totally bad field
|
|
289
|
+
// isn't sent to the compiler, where it will wig out.
|
|
290
|
+
// TODO Figure out how to make errors generated by `canContain` go in the right place,
|
|
291
|
+
// maybe by adding a logable element to SpaceFields.
|
|
292
|
+
if (typeDesc &&
|
|
293
|
+
typeDesc.type !== 'error' &&
|
|
294
|
+
this.canContain(typeDesc) &&
|
|
295
|
+
!isEmptyNest(fieldQueryDef)) {
|
|
296
|
+
fields.push(fieldQueryDef);
|
|
298
297
|
}
|
|
299
298
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
299
|
+
// TODO I removed the error here because during calculation of the refinement space,
|
|
300
|
+
// (see creation of a QuerySpace) we add references to all the fields from
|
|
301
|
+
// the refinement, but they don't have definitions. So in the case where we
|
|
302
|
+
// don't have a field def, we "know" that that field is already in the query,
|
|
303
|
+
// and we don't need to worry about actually adding it. Previously, this was also true for
|
|
304
|
+
// project statements, where we added "*" as a field and also all the individual
|
|
305
|
+
// fields, but the individual fields didn't have field defs.
|
|
304
306
|
}
|
|
305
307
|
}
|
|
308
|
+
const next = this.applyNextCompositeFieldUsage(source, compositeFieldUsage, narrowedCompositeFieldResolution, nextCompositeFieldUsage, user.logTo);
|
|
309
|
+
compositeFieldUsage = next.compositeFieldUsage;
|
|
310
|
+
narrowedCompositeFieldResolution = next.narrowedCompositeFieldResolution;
|
|
306
311
|
}
|
|
307
312
|
this._compositeFieldUsage = compositeFieldUsage;
|
|
308
313
|
return fields;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilterCondition, PipeSegment, Sampling } from '../../../model/malloy_types';
|
|
1
|
+
import { CompositeFieldUsage, FilterCondition, PipeSegment, Sampling } from '../../../model/malloy_types';
|
|
2
2
|
import { FieldName, SourceFieldSpace } from '../types/field-space';
|
|
3
3
|
import { Limit } from '../query-properties/limit';
|
|
4
4
|
import { IndexFieldSpace } from '../field-space/index-field-space';
|
|
@@ -18,5 +18,6 @@ export declare class IndexBuilder implements QueryBuilder {
|
|
|
18
18
|
readonly type = "index";
|
|
19
19
|
constructor(inputFS: SourceFieldSpace, refineThis: PipeSegment | undefined, isNestIn: QueryOperationSpace | undefined, astEl: MalloyElement);
|
|
20
20
|
execute(qp: QueryProperty): void;
|
|
21
|
+
get compositeFieldUsage(): CompositeFieldUsage;
|
|
21
22
|
finalize(from: PipeSegment | undefined): PipeSegment;
|
|
22
23
|
}
|
|
@@ -30,6 +30,7 @@ const indexing_1 = require("../query-properties/indexing");
|
|
|
30
30
|
const limit_1 = require("../query-properties/limit");
|
|
31
31
|
const sampling_1 = require("../query-properties/sampling");
|
|
32
32
|
const index_field_space_1 = require("../field-space/index-field-space");
|
|
33
|
+
const composite_source_utils_1 = require("../../../model/composite_source_utils");
|
|
33
34
|
class IndexBuilder {
|
|
34
35
|
constructor(inputFS, refineThis, isNestIn, astEl) {
|
|
35
36
|
this.filters = [];
|
|
@@ -64,7 +65,11 @@ class IndexBuilder {
|
|
|
64
65
|
qp.logError('illegal-operation-for-index', 'Not legal in an index query operation');
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
get compositeFieldUsage() {
|
|
69
|
+
return this.resultFS.compositeFieldUsage;
|
|
70
|
+
}
|
|
67
71
|
finalize(from) {
|
|
72
|
+
var _a;
|
|
68
73
|
if (from && !(0, malloy_types_1.isIndexSegment)(from) && !(0, malloy_types_1.isPartialSegment)(from)) {
|
|
69
74
|
this.resultFS.logError('refinement-of-index-segment', `Can't refine index with ${from.type}`);
|
|
70
75
|
return error_factory_1.ErrorFactory.indexSegment;
|
|
@@ -95,6 +100,10 @@ class IndexBuilder {
|
|
|
95
100
|
if (this.alwaysJoins.length > 0) {
|
|
96
101
|
indexSegment.alwaysJoins = [...this.alwaysJoins];
|
|
97
102
|
}
|
|
103
|
+
const fromCompositeFieldUsage = from && from.type === 'index'
|
|
104
|
+
? (_a = from.compositeFieldUsage) !== null && _a !== void 0 ? _a : (0, composite_source_utils_1.emptyCompositeFieldUsage)()
|
|
105
|
+
: (0, composite_source_utils_1.emptyCompositeFieldUsage)();
|
|
106
|
+
indexSegment.compositeFieldUsage = (0, composite_source_utils_1.mergeCompositeFieldUsage)(fromCompositeFieldUsage, this.compositeFieldUsage);
|
|
98
107
|
return indexSegment;
|
|
99
108
|
}
|
|
100
109
|
}
|
|
@@ -31,9 +31,10 @@ class QueryBase extends malloy_element_1.MalloyElement {
|
|
|
31
31
|
query() {
|
|
32
32
|
var _a;
|
|
33
33
|
const { inputStruct, query } = this.queryComp(true);
|
|
34
|
-
// TODO add an error if a raw
|
|
34
|
+
// TODO add an error if a raw query is done against a composite source
|
|
35
35
|
let compositeResolvedSourceDef = undefined;
|
|
36
|
-
if (query.pipeline[0] &&
|
|
36
|
+
if (query.pipeline[0] &&
|
|
37
|
+
((0, malloy_types_1.isQuerySegment)(query.pipeline[0]) || (0, malloy_types_1.isIndexSegment)(query.pipeline[0]))) {
|
|
37
38
|
const compositeFieldUsage = (_a = query.pipeline[0].compositeFieldUsage) !== null && _a !== void 0 ? _a : (0, composite_source_utils_1.emptyCompositeFieldUsage)();
|
|
38
39
|
if (!(0, composite_source_utils_1.isEmptyCompositeFieldUsage)(compositeFieldUsage) ||
|
|
39
40
|
inputStruct.type === 'composite') {
|
|
@@ -137,10 +137,15 @@ describe('composite sources', () => {
|
|
|
137
137
|
##! experimental.composite_sources
|
|
138
138
|
run: compose(a, a extend { dimension: one is 1 }) -> { group_by: one }
|
|
139
139
|
`).toTranslate());
|
|
140
|
-
test
|
|
140
|
+
test('index on composite translates', () => expect(`
|
|
141
141
|
##! experimental.composite_sources
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
source: x is compose(
|
|
143
|
+
a extend { except: ai },
|
|
144
|
+
a
|
|
145
|
+
)
|
|
146
|
+
run: x -> { index: ai }
|
|
147
|
+
run: x -> { index: * }
|
|
148
|
+
`).toTranslate());
|
|
144
149
|
test('raw run of composite source fails', () => expect(`
|
|
145
150
|
##! experimental.composite_sources
|
|
146
151
|
run: compose(a extend { dimension: two is 2 }, a extend { dimension: one is 1 })
|
|
@@ -30,7 +30,7 @@ type SingleNarrowedCompositeFieldResolution = {
|
|
|
30
30
|
source: SourceDef;
|
|
31
31
|
nested?: SingleNarrowedCompositeFieldResolution | undefined;
|
|
32
32
|
}[];
|
|
33
|
-
interface NarrowedCompositeFieldResolution {
|
|
33
|
+
export interface NarrowedCompositeFieldResolution {
|
|
34
34
|
source: SingleNarrowedCompositeFieldResolution | undefined;
|
|
35
35
|
joined: {
|
|
36
36
|
[name: string]: NarrowedCompositeFieldResolution;
|
|
@@ -10,11 +10,11 @@ exports.compositeFieldUsageJoinPaths = exports.joinedCompositeFieldUsage = expor
|
|
|
10
10
|
const utils_1 = require("../lang/utils");
|
|
11
11
|
const malloy_types_1 = require("./malloy_types");
|
|
12
12
|
function _resolveCompositeSources(path, source, compositeFieldUsage, narrowedCompositeFieldResolution = undefined) {
|
|
13
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
13
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
14
14
|
let base = { ...source };
|
|
15
15
|
let narrowedSources = undefined;
|
|
16
16
|
const nonCompositeFields = getNonCompositeFields(source);
|
|
17
|
-
if (compositeFieldUsage.fields.length > 0) {
|
|
17
|
+
if (compositeFieldUsage.fields.length > 0 || source.type === 'composite') {
|
|
18
18
|
if (source.type === 'composite') {
|
|
19
19
|
let found = false;
|
|
20
20
|
// The narrowed source list is either the one given when this function was called,
|
|
@@ -86,18 +86,10 @@ function _resolveCompositeSources(path, source, compositeFieldUsage, narrowedCom
|
|
|
86
86
|
return { error: { code: 'not_a_composite_source', data: { path } } };
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
-
else if (source.type === 'composite') {
|
|
90
|
-
const first = source.sources[0];
|
|
91
|
-
base = {
|
|
92
|
-
...first,
|
|
93
|
-
fields: [...nonCompositeFields, ...base.fields],
|
|
94
|
-
filterList: [...((_e = source.filterList) !== null && _e !== void 0 ? _e : []), ...((_f = first.filterList) !== null && _f !== void 0 ? _f : [])],
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
89
|
const fieldsByName = {};
|
|
98
|
-
const narrowedJoinedSources = (
|
|
90
|
+
const narrowedJoinedSources = (_e = narrowedCompositeFieldResolution === null || narrowedCompositeFieldResolution === void 0 ? void 0 : narrowedCompositeFieldResolution.joined) !== null && _e !== void 0 ? _e : {};
|
|
99
91
|
for (const field of base.fields) {
|
|
100
|
-
fieldsByName[(
|
|
92
|
+
fieldsByName[(_f = field.as) !== null && _f !== void 0 ? _f : field.name] = field;
|
|
101
93
|
}
|
|
102
94
|
for (const [joinName, joinedUsage] of Object.entries(compositeFieldUsage.joinedUsage)) {
|
|
103
95
|
const join = fieldsByName[joinName];
|
|
@@ -127,7 +119,7 @@ function _resolveCompositeSources(path, source, compositeFieldUsage, narrowedCom
|
|
|
127
119
|
fieldsByName[joinName] = {
|
|
128
120
|
...resolved.success,
|
|
129
121
|
join: join.join,
|
|
130
|
-
as: (
|
|
122
|
+
as: (_g = join.as) !== null && _g !== void 0 ? _g : join.name,
|
|
131
123
|
onExpression: join.onExpression,
|
|
132
124
|
};
|
|
133
125
|
narrowedJoinedSources[joinName] = resolved.narrowedCompositeFieldResolution;
|
|
@@ -233,14 +225,12 @@ function arrayDifference(a, b) {
|
|
|
233
225
|
function compositeFieldUsageDifference(a, b) {
|
|
234
226
|
return {
|
|
235
227
|
fields: arrayDifference(a.fields, b.fields),
|
|
236
|
-
joinedUsage: Object.fromEntries(Object.entries(a.joinedUsage)
|
|
237
|
-
.map(([joinName, joinedUsage]) => [
|
|
228
|
+
joinedUsage: Object.fromEntries(Object.entries(a.joinedUsage).map(([joinName, joinedUsage]) => [
|
|
238
229
|
joinName,
|
|
239
230
|
joinName in b.joinedUsage
|
|
240
231
|
? compositeFieldUsageDifference(joinedUsage, b.joinedUsage[joinName])
|
|
241
232
|
: joinedUsage,
|
|
242
|
-
])
|
|
243
|
-
.filter(([_, joinedUsage]) => countCompositeFieldUsage(joinedUsage) > 0)),
|
|
233
|
+
])),
|
|
244
234
|
};
|
|
245
235
|
}
|
|
246
236
|
exports.compositeFieldUsageDifference = compositeFieldUsageDifference;
|
|
@@ -546,6 +546,7 @@ export interface IndexSegment extends Filtered {
|
|
|
546
546
|
weightMeasure?: string;
|
|
547
547
|
sample?: Sampling;
|
|
548
548
|
alwaysJoins?: string[];
|
|
549
|
+
compositeFieldUsage?: CompositeFieldUsage;
|
|
549
550
|
}
|
|
550
551
|
export declare function isIndexSegment(pe: PipeSegment): pe is IndexSegment;
|
|
551
552
|
export interface CompositeFieldUsage {
|