@malloydata/malloy 0.0.203-dev241021134413 → 0.0.203-dev241021171612
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/query-builders/index-builder.d.ts +1 -0
- package/dist/lang/ast/query-builders/index-builder.js +4 -0
- package/dist/lang/ast/query-builders/reduce-builder.d.ts +1 -0
- package/dist/lang/ast/query-builders/reduce-builder.js +4 -0
- package/dist/lang/ast/source-properties/join.js +1 -0
- package/dist/lang/ast/types/query-builder.d.ts +1 -0
- package/dist/lang/malloy-to-ast.js +1 -3
- package/dist/lang/test/query.spec.js +7 -2
- package/dist/model/malloy_query.d.ts +1 -0
- package/dist/model/malloy_query.js +14 -0
- package/dist/model/malloy_types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ export declare class IndexBuilder implements QueryBuilder {
|
|
|
14
14
|
sample?: Sampling;
|
|
15
15
|
resultFS: IndexFieldSpace;
|
|
16
16
|
inputFS: QueryInputSpace;
|
|
17
|
+
alwaysJoins: string[];
|
|
17
18
|
readonly type = "index";
|
|
18
19
|
constructor(inputFS: SourceFieldSpace, refineThis: PipeSegment | undefined, isNestIn: QueryOperationSpace | undefined, astEl: MalloyElement);
|
|
19
20
|
execute(qp: QueryProperty): void;
|
|
@@ -33,6 +33,7 @@ const index_field_space_1 = require("../field-space/index-field-space");
|
|
|
33
33
|
class IndexBuilder {
|
|
34
34
|
constructor(inputFS, refineThis, isNestIn, astEl) {
|
|
35
35
|
this.filters = [];
|
|
36
|
+
this.alwaysJoins = [];
|
|
36
37
|
this.type = 'index';
|
|
37
38
|
this.resultFS = new index_field_space_1.IndexFieldSpace(inputFS, refineThis, isNestIn, astEl);
|
|
38
39
|
this.inputFS = this.resultFS.inputSpace();
|
|
@@ -91,6 +92,9 @@ class IndexBuilder {
|
|
|
91
92
|
if (this.sample) {
|
|
92
93
|
indexSegment.sample = this.sample;
|
|
93
94
|
}
|
|
95
|
+
if (this.alwaysJoins.length > 0) {
|
|
96
|
+
indexSegment.alwaysJoins = [...this.alwaysJoins];
|
|
97
|
+
}
|
|
94
98
|
return indexSegment;
|
|
95
99
|
}
|
|
96
100
|
}
|
|
@@ -10,6 +10,7 @@ import { MalloyElement } from '../types/malloy-element';
|
|
|
10
10
|
export declare abstract class QuerySegmentBuilder implements QueryBuilder {
|
|
11
11
|
order?: Top | Ordering;
|
|
12
12
|
limit?: number;
|
|
13
|
+
alwaysJoins: string[];
|
|
13
14
|
abstract inputFS: QueryInputSpace;
|
|
14
15
|
abstract resultFS: QueryOperationSpace;
|
|
15
16
|
abstract readonly type: 'grouping' | 'project';
|
|
@@ -33,6 +33,7 @@ const query_spaces_1 = require("../field-space/query-spaces");
|
|
|
33
33
|
const definition_list_1 = require("../types/definition-list");
|
|
34
34
|
class QuerySegmentBuilder {
|
|
35
35
|
constructor() {
|
|
36
|
+
this.alwaysJoins = [];
|
|
36
37
|
this.filters = [];
|
|
37
38
|
}
|
|
38
39
|
execute(qp) {
|
|
@@ -113,6 +114,9 @@ class QuerySegmentBuilder {
|
|
|
113
114
|
else if (oldFilters) {
|
|
114
115
|
to.filterList = [...oldFilters, ...this.filters];
|
|
115
116
|
}
|
|
117
|
+
if (this.alwaysJoins.length > 0) {
|
|
118
|
+
to.alwaysJoins = [...this.alwaysJoins];
|
|
119
|
+
}
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
exports.QuerySegmentBuilder = QuerySegmentBuilder;
|
|
@@ -419,9 +419,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
419
419
|
return { joinAs, joinFrom: new ast.SQReference(joinAs), notes: [] };
|
|
420
420
|
}
|
|
421
421
|
visitQueryJoinStatement(pcx) {
|
|
422
|
-
|
|
423
|
-
this.m4advisory(pcx, 'join-statement-in-view', 'Joins in queries are deprecated, move into an `extend:` block.');
|
|
424
|
-
return result;
|
|
422
|
+
return this.astAt(this.visit(pcx.joinStatement()), pcx);
|
|
425
423
|
}
|
|
426
424
|
visitJoinOn(pcx) {
|
|
427
425
|
var _a;
|
|
@@ -923,8 +923,13 @@ describe('query:', () => {
|
|
|
923
923
|
source: a2 is a extend { ${'declare: x is 1'} }`).toLog((0, test_translator_1.warningMessage)('`declare:` is deprecated; use `dimension:` or `measure:` inside a source or `extend:` block'));
|
|
924
924
|
});
|
|
925
925
|
test('joins in query', () => {
|
|
926
|
-
expect((0, test_translator_1.markSource)
|
|
927
|
-
run: a -> {
|
|
926
|
+
expect((0, test_translator_1.markSource) `
|
|
927
|
+
run: a -> {
|
|
928
|
+
join_one: b on true
|
|
929
|
+
join_many: c is b on true
|
|
930
|
+
join_cross: d is b on true
|
|
931
|
+
group_by: b.astr
|
|
932
|
+
}`).toTranslate();
|
|
928
933
|
});
|
|
929
934
|
});
|
|
930
935
|
test('refine query with extended source', () => {
|
|
@@ -264,6 +264,7 @@ declare class QueryQuery extends QueryField {
|
|
|
264
264
|
expandFilters(resultStruct: FieldInstanceResult): void;
|
|
265
265
|
generateSQLFilters(resultStruct: FieldInstanceResult, which: 'where' | 'having'): AndChain;
|
|
266
266
|
prepare(_stageWriter: StageWriter | undefined): void;
|
|
267
|
+
addAlwaysJoins(rootResult: FieldInstanceResultRoot): void;
|
|
267
268
|
getResultMetadata(fi: FieldInstance): ResultStructMetadataDef | ResultMetadataDef | undefined;
|
|
268
269
|
/** returns a fields and primary key of a struct for this query */
|
|
269
270
|
getResultStructDef(resultStruct?: FieldInstanceResult, isRoot?: boolean): SourceDef;
|
|
@@ -1802,10 +1802,24 @@ class QueryQuery extends QueryField {
|
|
|
1802
1802
|
this.expandFields(this.rootResult);
|
|
1803
1803
|
this.rootResult.addStructToJoin(this.parent, this, undefined, []);
|
|
1804
1804
|
this.rootResult.findJoins(this);
|
|
1805
|
+
this.addAlwaysJoins(this.rootResult);
|
|
1805
1806
|
this.rootResult.calculateSymmetricAggregates();
|
|
1806
1807
|
this.prepared = true;
|
|
1807
1808
|
}
|
|
1808
1809
|
}
|
|
1810
|
+
addAlwaysJoins(rootResult) {
|
|
1811
|
+
var _a;
|
|
1812
|
+
const stage = this.fieldDef.pipeline[0];
|
|
1813
|
+
if (stage.type !== 'raw') {
|
|
1814
|
+
const alwaysJoins = (_a = stage.alwaysJoins) !== null && _a !== void 0 ? _a : [];
|
|
1815
|
+
for (const joinName of alwaysJoins) {
|
|
1816
|
+
const qs = this.parent.getChildByName(joinName);
|
|
1817
|
+
if (qs instanceof QueryStruct) {
|
|
1818
|
+
rootResult.addStructToJoin(qs, this, undefined, []);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1809
1823
|
// get the source fieldname and filters associated with the field (so we can drill later)
|
|
1810
1824
|
getResultMetadata(fi) {
|
|
1811
1825
|
if (fi instanceof FieldInstanceField) {
|
|
@@ -531,6 +531,7 @@ export interface IndexSegment extends Filtered {
|
|
|
531
531
|
limit?: number;
|
|
532
532
|
weightMeasure?: string;
|
|
533
533
|
sample?: Sampling;
|
|
534
|
+
alwaysJoins?: string[];
|
|
534
535
|
}
|
|
535
536
|
export declare function isIndexSegment(pe: PipeSegment): pe is IndexSegment;
|
|
536
537
|
export interface QuerySegment extends Filtered {
|
|
@@ -541,6 +542,7 @@ export interface QuerySegment extends Filtered {
|
|
|
541
542
|
by?: By;
|
|
542
543
|
orderBy?: OrderBy[];
|
|
543
544
|
queryTimezone?: string;
|
|
545
|
+
alwaysJoins?: string[];
|
|
544
546
|
}
|
|
545
547
|
export interface TurtleDef extends NamedObject, Pipeline {
|
|
546
548
|
type: 'turtle';
|