@malloydata/malloy 0.0.309 → 0.0.310

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Malloy
2
2
 
3
- Malloy is an experimental language for describing data relationships and transformations. It is both a semantic modeling language and a querying language that runs queries against a relational database. Malloy currently connects to BigQuery and Postgres, and natively supports DuckDB. We've built a Visual Studio Code extension to facilitate building Malloy data models, querying and transforming data, and creating simple visualizations and dashboards.
3
+ Malloy is a modern open source language for describing data relationships and transformations. It is both a semantic modeling language and a querying language that runs queries against a relational database. Malloy currently connects to BigQuery and Postgres, and natively supports DuckDB. We've built a Visual Studio Code extension to facilitate building Malloy data models, querying and transforming data, and creating simple visualizations and dashboards.
4
4
 
5
5
  ## Building applications or products in javascript with @malloydata/malloy
6
6
 
@@ -65,6 +65,23 @@ const mysqlToMalloyTypes = {
65
65
  // TODO: Check if we need special handling for boolean.
66
66
  'tinyint(1)': { type: 'boolean' },
67
67
  };
68
+ function malloyTypeToJSONTableType(malloyType) {
69
+ switch (malloyType.type) {
70
+ case 'number':
71
+ return malloyType.numberType === 'integer' ? 'INT' : 'DOUBLE';
72
+ case 'string':
73
+ return 'CHAR(255)'; // JSON_TABLE needs a length
74
+ case 'boolean':
75
+ return 'INT'; // or TINYINT(1) if you prefer
76
+ case 'record':
77
+ case 'array':
78
+ return 'JSON';
79
+ case 'timestamp':
80
+ return 'DATETIME';
81
+ default:
82
+ return malloyType.type.toUpperCase();
83
+ }
84
+ }
68
85
  class MySQLDialect extends dialect_1.Dialect {
69
86
  constructor() {
70
87
  super(...arguments);
@@ -99,14 +116,16 @@ class MySQLDialect extends dialect_1.Dialect {
99
116
  malloyTypeToSQLType(malloyType) {
100
117
  switch (malloyType.type) {
101
118
  case 'number':
102
- return malloyType.numberType === 'integer' ? 'BIGINT' : 'DOUBLE';
119
+ return malloyType.numberType === 'integer' ? 'SIGNED' : 'DOUBLE';
103
120
  case 'string':
104
- return 'TEXT';
121
+ return 'CHAR';
122
+ case 'boolean':
123
+ return 'SIGNED';
105
124
  case 'record':
106
125
  case 'array':
107
126
  return 'JSON';
108
- case 'date':
109
127
  case 'timestamp':
128
+ return 'DATETIME';
110
129
  default:
111
130
  return malloyType.type;
112
131
  }
@@ -177,7 +196,7 @@ class MySQLDialect extends dialect_1.Dialect {
177
196
  var _a;
178
197
  const fields = [];
179
198
  for (const f of fieldList) {
180
- let fType = this.malloyTypeToSQLType(f.typeDef);
199
+ let fType = malloyTypeToJSONTableType(f.typeDef);
181
200
  if (f.typeDef.type === 'sql native' &&
182
201
  f.typeDef.rawType &&
183
202
  ((_a = f.typeDef.rawType) === null || _a === void 0 ? void 0 : _a.match(/json/))) {
@@ -519,7 +519,7 @@ ${(0, utils_1.indent)(sql)}
519
519
  const name = (_a = f.as) !== null && _a !== void 0 ? _a : f.name;
520
520
  rowVals.push((_b = lit.kids[name].sql) !== null && _b !== void 0 ? _b : 'internal-error-record-literal');
521
521
  const elType = this.malloyTypeToSQLType(f);
522
- rowTypes.push(`${name} ${elType}`);
522
+ rowTypes.push(`${this.sqlMaybeQuoteIdentifier(name)} ${elType}`);
523
523
  }
524
524
  }
525
525
  return `CAST(ROW(${rowVals.join(',')}) AS ROW(${rowTypes.join(',')}))`;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, MySQLDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, TinyParser, } from './dialect';
2
2
  export type { DialectFieldList, DialectFunctionOverloadDef, QueryInfo, MalloyStandardFunctionImplementations, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, TinyToken, } from './dialect';
3
- export type { QueryDataRow, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, Argument, Parameter, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryResultDef, QueryRunStats, QueryScalar, NamedQuery, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, BasicAtomicTypeDef, BasicAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, RecordDef, RepeatedRecordDef, RecordLiteralNode, StringLiteralNode, ArrayLiteralNode, SourceComponentInfo, } from './model';
4
- export { isSourceDef, isBasicAtomic, isJoined, isJoinedSource, isSamplingEnable, isSamplingPercent, isSamplingRows, isRepeatedRecord, isBasicArray, mkArrayDef, mkFieldDef, expressionIsAggregate, expressionIsAnalytic, expressionIsCalculation, expressionIsScalar, expressionIsUngroupedAggregate, indent, composeSQLExpr, isTimestampUnit, isDateUnit, } from './model';
3
+ export type { QueryDataRow, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, Argument, Parameter, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryResultDef, QueryRunStats, QueryScalar, NamedQuery, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, BasicAtomicTypeDef, BasicAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, RecordDef, RepeatedRecordDef, RecordLiteralNode, StringLiteralNode, ArrayLiteralNode, SourceComponentInfo, TimeLiteralNode, TypecastExpr, } from './model';
4
+ export { isSourceDef, isBasicAtomic, isJoined, isJoinedSource, isSamplingEnable, isSamplingPercent, isSamplingRows, isRepeatedRecord, isBasicArray, mkArrayDef, mkFieldDef, expressionIsAggregate, expressionIsAnalytic, expressionIsCalculation, expressionIsScalar, expressionIsUngroupedAggregate, indent, composeSQLExpr, isTimestampUnit, isDateUnit, constantExprToSQL, } from './model';
5
5
  export { malloyToQuery, MalloyTranslator, } from './lang';
6
6
  export type { LogMessage, TranslateResponse } from './lang';
7
7
  export { Model, Malloy, Runtime, AtomicFieldType, ConnectionRuntime, SingleConnectionRuntime, EmptyURLReader, InMemoryURLReader, FixedConnectionMap, MalloyError, JoinRelationship, SourceRelationship, DateTimeframe, TimestampTimeframe, PreparedResult, Result, QueryMaterializer, CSVWriter, JSONWriter, Parse, DataWriter, Explore, InMemoryModelCache, CacheManager, } from './malloy';
package/dist/index.js CHANGED
@@ -33,8 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = exports.malloyToQuery = exports.isDateUnit = exports.isTimestampUnit = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isBasicArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isBasicAtomic = exports.isSourceDef = exports.TinyParser = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
37
- exports.annotationToTaglines = exports.annotationToTag = exports.sqlKey = exports.API = exports.extractMalloyObjectFromTag = exports.writeMalloyObjectToTag = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = void 0;
36
+ exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = exports.malloyToQuery = exports.constantExprToSQL = exports.isDateUnit = exports.isTimestampUnit = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isBasicArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isBasicAtomic = exports.isSourceDef = exports.TinyParser = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
37
+ exports.annotationToTaglines = exports.annotationToTag = exports.sqlKey = exports.API = exports.extractMalloyObjectFromTag = exports.writeMalloyObjectToTag = exports.sourceDefToSourceInfo = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = void 0;
38
38
  /*
39
39
  * Copyright 2023 Google LLC
40
40
  *
@@ -102,6 +102,8 @@ Object.defineProperty(exports, "indent", { enumerable: true, get: function () {
102
102
  Object.defineProperty(exports, "composeSQLExpr", { enumerable: true, get: function () { return model_1.composeSQLExpr; } });
103
103
  Object.defineProperty(exports, "isTimestampUnit", { enumerable: true, get: function () { return model_1.isTimestampUnit; } });
104
104
  Object.defineProperty(exports, "isDateUnit", { enumerable: true, get: function () { return model_1.isDateUnit; } });
105
+ // Used in testing, not really public API
106
+ Object.defineProperty(exports, "constantExprToSQL", { enumerable: true, get: function () { return model_1.constantExprToSQL; } });
105
107
  var lang_1 = require("./lang");
106
108
  Object.defineProperty(exports, "malloyToQuery", { enumerable: true, get: function () { return lang_1.malloyToQuery; } });
107
109
  // Needed for tests only
@@ -39,7 +39,7 @@ sources) {
39
39
  let anyComposites = false;
40
40
  let joinsProcessed = false;
41
41
  const nonCompositeFields = getNonCompositeFields(source);
42
- const expandedForError = onlyCompositeUsage(_expandFieldUsage(fieldUsage, rootFields).result, source.fields);
42
+ const expandedForError = onlyCompositeUsage(expandFieldUsage(fieldUsage, rootFields).result, source.fields);
43
43
  if (source.type === 'composite') {
44
44
  let found = false;
45
45
  anyComposites = true;
@@ -66,7 +66,7 @@ sources) {
66
66
  }
67
67
  const fieldUsageWithWheres = (_b = mergeFieldUsage(getFieldUsageFromFilterList(inputSource), fieldUsage)) !== null && _b !== void 0 ? _b : [];
68
68
  const fieldsForLookup = [...nonCompositeFields, ...inputSource.fields];
69
- const expanded = _expandFieldUsage(fieldUsageWithWheres, fieldsForLookup);
69
+ const expanded = expandFieldUsage(fieldUsageWithWheres, fieldsForLookup);
70
70
  if (expanded.missingFields.length > 0) {
71
71
  // A lookup failed while expanding, which means this source certainly won't work
72
72
  for (const missingField of expanded.missingFields) {
@@ -177,7 +177,7 @@ sources) {
177
177
  }
178
178
  else if (source.partitionComposite !== undefined) {
179
179
  anyComposites = true;
180
- const expanded = _expandFieldUsage(fieldUsage, rootFields).result;
180
+ const expanded = expandFieldUsage(fieldUsage, rootFields).result;
181
181
  // TODO possibly abort if expanded has missing fields...
182
182
  const expandedCategorized = categorizeFieldUsage(expanded);
183
183
  const { partitionFilter, issues } = getPartitionCompositeFilter(source.partitionComposite, expandedCategorized.sourceUsage);
@@ -199,7 +199,7 @@ sources) {
199
199
  };
200
200
  }
201
201
  if (!joinsProcessed) {
202
- const expanded = _expandFieldUsage(fieldUsage, getJoinFields(rootFields, path));
202
+ const expanded = expandFieldUsage(fieldUsage, getJoinFields(rootFields, path));
203
203
  if (expanded.missingFields.length > 0) {
204
204
  return {
205
205
  error: {
@@ -278,7 +278,7 @@ function getExpandedSegment(segment, inputSource) {
278
278
  updatedSegment = { ...segment, queryFields: updatedQueryFields };
279
279
  }
280
280
  const allFieldUsage = mergeFieldUsage(getFieldUsageFromFilterList(inputSource), segment.fieldUsage);
281
- const expanded = _expandFieldUsage(allFieldUsage || [], fields);
281
+ const expanded = expandFieldUsage(allFieldUsage || [], fields);
282
282
  // Merge ungroupings from direct collection and field expansion
283
283
  const allUngroupings = [...collectedUngroupings, ...expanded.ungroupings];
284
284
  return {
@@ -334,7 +334,7 @@ function findActiveJoins(dependencies) {
334
334
  * - `missingFields`: References to fields which could not be resolved
335
335
  * - `activeJoins`: Topologically sorted list of joins needed to resolve these uses
336
336
  */
337
- function _expandFieldUsage(fieldUsage, fields) {
337
+ function expandFieldUsage(fieldUsage, fields) {
338
338
  var _a, _b, _c;
339
339
  const seen = {};
340
340
  const missingFields = [];
@@ -80,7 +80,7 @@ export declare class QueryStruct {
80
80
  /**
81
81
  * For fields which are a record, but the value is an expression
82
82
  * we capture the context needed to generate the expression in
83
- * QueryQuery.expandFields. Later in the compilation if a
83
+ * QueryQuery.expandRecordExpressions. Later in the compilation if a
84
84
  * reference passes through this struct, this will call
85
85
  * the expression compiler with the correct context
86
86
  * to compute the record value.
@@ -54,11 +54,11 @@ export declare class QueryQuery extends QueryField {
54
54
  * @param resultStruct - The FieldInstanceResult containing compilation context
55
55
  * @param source - The QueryStruct to traverse (initially the query's parent/input)
56
56
  */
57
- expandSource(resultStruct: FieldInstanceResult, source: QueryStruct): void;
57
+ expandRecordExpressions(resultStruct: FieldInstanceResult, source: QueryStruct): void;
58
58
  generateSQLFilters(resultStruct: FieldInstanceResult, which: 'where' | 'having'): AndChain;
59
59
  prepare(_stageWriter: StageWriter | undefined): void;
60
60
  private findJoins;
61
- addAlwaysJoins(rootResult: FieldInstanceResultRoot): void;
61
+ addAlwaysJoins(): void;
62
62
  getResultMetadata(fi: FieldInstance): ResultStructMetadataDef | ResultMetadataDef | undefined;
63
63
  /** returns a fields and primary key of a struct for this query */
64
64
  getResultStructDef(resultStruct?: FieldInstanceResult, isRoot?: boolean): QueryResultDef;
@@ -93,83 +93,52 @@ class QueryQuery extends query_node_1.QueryField {
93
93
  const as = field.getIdentifier();
94
94
  return { as, field };
95
95
  }
96
- addDependantPath(resultStruct, context, path, uniqueKeyRequirement) {
97
- if (path.length === 0) {
98
- return;
99
- }
100
- // Loop through path segments, ensuring each join exists
101
- let currentContext = context;
102
- for (const segment of path.slice(0, -1)) {
103
- // Try to get the field at this path segment
104
- let segmentField;
105
- try {
106
- segmentField = currentContext.getFieldByName([segment]);
107
- }
108
- catch {
109
- // Field doesn't exist, need to add the join
110
- // This is where we'd need to figure out how to create the missing join
111
- // Maybe we need more context about what join we're trying to add?
112
- throw new Error(`Cannot find join '${segment}' in ${path.join('.')} to add to query`);
113
- }
114
- if (segmentField instanceof query_node_1.QueryFieldStruct) {
115
- if ((0, malloy_types_1.isJoinedSource)(segmentField.fieldDef)) {
116
- resultStruct
117
- .root()
118
- .addStructToJoin(segmentField.queryStruct, undefined);
119
- currentContext = segmentField.queryStruct;
120
- }
121
- else {
122
- // Can't navigate deeper into non-joined sources like records
123
- break;
124
- }
125
- }
126
- }
127
- // Now handle the full path for the final dependency
128
- const node = context.getFieldByName(path);
96
+ addDependantPath(path, uniqueKeyRequirement) {
97
+ const node = this.parent.getFieldByName(path);
129
98
  const joinableParent = node instanceof query_node_1.QueryFieldStruct
130
99
  ? node.queryStruct.getJoinableParent()
131
100
  : node.parent.getJoinableParent();
132
- resultStruct.root().addStructToJoin(joinableParent, uniqueKeyRequirement);
101
+ this.rootResult.addStructToJoin(joinableParent, uniqueKeyRequirement);
133
102
  }
134
- dependenciesFromFieldUsage(resultStruct) {
103
+ dependenciesFromFieldUsage() {
104
+ const resultRoot = this.rootResult;
135
105
  // Only QuerySegment and IndexSegment have fieldUsage, RawSegment does not
136
106
  if (this.firstSegment.type === 'raw' ||
137
107
  this.firstSegment.type === 'partial') {
138
108
  throw new Error('QueryQuery attempt to load a raw or partial segment');
139
109
  }
140
110
  for (const joinUsage of this.firstSegment.activeJoins || []) {
141
- this.addDependantPath(resultStruct, this.parent, joinUsage.path, undefined);
111
+ this.addDependantPath(joinUsage.path, undefined);
142
112
  }
143
113
  for (const usage of this.firstSegment.expandedFieldUsage || []) {
144
114
  if (usage.analyticFunctionUse) {
145
- resultStruct.root().queryUsesPartitioning = true;
115
+ resultRoot.queryUsesPartitioning = true;
146
116
  // BigQuery-specific handling
147
117
  if (this.parent.dialect.cantPartitionWindowFunctionsOnExpressions &&
148
- resultStruct.firstSegment.type === 'reduce') {
118
+ resultRoot.firstSegment.type === 'reduce') {
149
119
  // force the use of a lateral_join_bag
150
- resultStruct.root().isComplexQuery = true;
151
- resultStruct.root().queryUsesPartitioning = true;
120
+ resultRoot.isComplexQuery = true;
121
+ resultRoot.queryUsesPartitioning = true;
152
122
  }
153
123
  continue;
154
124
  }
155
125
  if (usage.uniqueKeyRequirement) {
156
126
  if (usage.path.length === 0) {
157
- resultStruct.addStructToJoin(this.parent, usage.uniqueKeyRequirement);
127
+ resultRoot.addStructToJoin(this.parent, usage.uniqueKeyRequirement);
158
128
  }
159
129
  else {
160
- this.addDependantPath(resultStruct, this.parent, usage.path, usage.uniqueKeyRequirement);
130
+ this.addDependantPath(usage.path, usage.uniqueKeyRequirement);
161
131
  }
162
- continue;
163
132
  }
164
133
  }
165
134
  const expandedUngroupings = 'expandedUngroupings' in this.firstSegment
166
135
  ? this.firstSegment.expandedUngroupings || []
167
136
  : [];
168
137
  for (const ungrouping of expandedUngroupings) {
169
- resultStruct.root().isComplexQuery = true;
170
- resultStruct.root().queryUsesPartitioning = true;
138
+ resultRoot.isComplexQuery = true;
139
+ resultRoot.queryUsesPartitioning = true;
171
140
  // Navigate to correct result struct using ungrouping's path
172
- let destResult = resultStruct;
141
+ let destResult = resultRoot;
173
142
  for (const pathSegment of ungrouping.path) {
174
143
  const nextStruct = destResult.allFields.get(pathSegment);
175
144
  if (!(nextStruct instanceof field_instance_1.FieldInstanceResult)) {
@@ -264,7 +233,7 @@ class QueryQuery extends query_node_1.QueryField {
264
233
  * @param resultStruct - The FieldInstanceResult containing compilation context
265
234
  * @param source - The QueryStruct to traverse (initially the query's parent/input)
266
235
  */
267
- expandSource(resultStruct, source) {
236
+ expandRecordExpressions(resultStruct, source) {
268
237
  for (const field of source.nameMap.values()) {
269
238
  if (field instanceof query_node_1.QueryFieldStruct) {
270
239
  const qs = field.queryStruct;
@@ -277,7 +246,7 @@ class QueryQuery extends query_node_1.QueryField {
277
246
  qs.computeRecordExpression = () => (0, expression_compiler_1.exprToSQL)(resultStruct, parent, e);
278
247
  }
279
248
  // Recurse into this structure
280
- this.expandSource(resultStruct, qs);
249
+ this.expandRecordExpressions(resultStruct, qs);
281
250
  }
282
251
  }
283
252
  }
@@ -304,15 +273,15 @@ class QueryQuery extends query_node_1.QueryField {
304
273
  }
305
274
  prepare(_stageWriter) {
306
275
  if (!this.prepared) {
307
- this.expandSource(this.rootResult, this.parent);
276
+ this.expandRecordExpressions(this.rootResult, this.parent);
308
277
  // Add the root base join to the joins map
309
278
  this.rootResult.addStructToJoin(this.parent, undefined);
310
279
  // Expand fields (just adds them to result, no dependency tracking)
311
280
  this.expandFields(this.rootResult);
312
281
  // Process all dependencies from translator's fieldUsage
313
- this.dependenciesFromFieldUsage(this.rootResult);
282
+ this.dependenciesFromFieldUsage();
314
283
  // Handle always joins
315
- this.addAlwaysJoins(this.rootResult);
284
+ this.addAlwaysJoins();
316
285
  // Calculate symmetric aggregates based on the joins
317
286
  this.rootResult.calculateSymmetricAggregates();
318
287
  this.prepared = true;
@@ -328,7 +297,7 @@ class QueryQuery extends query_node_1.QueryField {
328
297
  this.findJoins(s);
329
298
  }
330
299
  }
331
- addAlwaysJoins(rootResult) {
300
+ addAlwaysJoins() {
332
301
  var _a;
333
302
  const stage = this.fieldDef.pipeline[0];
334
303
  if (stage.type !== 'raw') {
@@ -336,7 +305,7 @@ class QueryQuery extends query_node_1.QueryField {
336
305
  for (const joinName of alwaysJoins) {
337
306
  const qs = this.parent.getChildByName(joinName);
338
307
  if (qs instanceof query_node_1.QueryFieldStruct) {
339
- rootResult.addStructToJoin(qs.queryStruct, undefined);
308
+ this.rootResult.addStructToJoin(qs.queryStruct, undefined);
340
309
  }
341
310
  }
342
311
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const MALLOY_VERSION = "0.0.309";
1
+ export declare const MALLOY_VERSION = "0.0.310";
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.309';
5
+ exports.MALLOY_VERSION = '0.0.310';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.309",
3
+ "version": "0.0.310",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",
@@ -41,9 +41,9 @@
41
41
  "generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
42
42
  },
43
43
  "dependencies": {
44
- "@malloydata/malloy-filter": "0.0.309",
45
- "@malloydata/malloy-interfaces": "0.0.309",
46
- "@malloydata/malloy-tag": "0.0.309",
44
+ "@malloydata/malloy-filter": "0.0.310",
45
+ "@malloydata/malloy-interfaces": "0.0.310",
46
+ "@malloydata/malloy-tag": "0.0.310",
47
47
  "antlr4ts": "^0.5.0-alpha.4",
48
48
  "assert": "^2.0.0",
49
49
  "jaro-winkler": "^0.2.8",