@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.
@@ -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;
@@ -179,6 +179,7 @@ class JoinStatement extends definition_list_1.DefinitionList {
179
179
  queryExecute(executeFor) {
180
180
  for (const qel of this.list) {
181
181
  executeFor.inputFS.extendSource(qel);
182
+ executeFor.alwaysJoins.push(qel.name.refString);
182
183
  }
183
184
  }
184
185
  }
@@ -6,6 +6,7 @@ export interface QueryBuilder {
6
6
  type: 'grouping' | 'index' | 'project';
7
7
  inputFS: QueryInputSpace;
8
8
  resultFS: QueryOperationSpace;
9
+ alwaysJoins: string[];
9
10
  execute(qp: QueryProperty): void;
10
11
  finalize(refineFrom: PipeSegment | undefined): PipeSegment;
11
12
  }
@@ -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
- const result = this.astAt(this.visit(pcx.joinStatement()), pcx);
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) `##! m4warnings=warn
927
- run: a -> { ${'join_one: b on true'}; ${'join_many: c is b on true'}; ${'join_cross: d is b on true'}; group_by: b.astr }`).toLog((0, test_translator_1.warningMessage)('Joins in queries are deprecated, move into an `extend:` block.'), (0, test_translator_1.warningMessage)('Joins in queries are deprecated, move into an `extend:` block.'), (0, test_translator_1.warningMessage)('Joins in queries are deprecated, move into an `extend:` block.'));
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.203-dev241021134413",
3
+ "version": "0.0.203-dev241021171612",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",