@malloydata/malloy 0.0.195-dev241003204905 → 0.0.195-dev241007154000

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.
Files changed (144) hide show
  1. package/dist/connection/base_connection.d.ts +21 -7
  2. package/dist/connection/base_connection.js +62 -0
  3. package/dist/connection/types.d.ts +5 -5
  4. package/dist/dialect/dialect.d.ts +5 -3
  5. package/dist/dialect/dialect.js +15 -0
  6. package/dist/dialect/duckdb/duckdb.d.ts +3 -3
  7. package/dist/dialect/duckdb/duckdb.js +8 -3
  8. package/dist/dialect/postgres/postgres.d.ts +3 -3
  9. package/dist/dialect/postgres/postgres.js +5 -2
  10. package/dist/dialect/snowflake/snowflake.d.ts +3 -3
  11. package/dist/dialect/snowflake/snowflake.js +4 -1
  12. package/dist/dialect/standardsql/standardsql.d.ts +3 -3
  13. package/dist/dialect/standardsql/standardsql.js +5 -2
  14. package/dist/dialect/trino/trino.d.ts +3 -3
  15. package/dist/dialect/trino/trino.js +35 -3
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.js +6 -2
  18. package/dist/lang/ast/error-factory.d.ts +4 -3
  19. package/dist/lang/ast/error-factory.js +27 -17
  20. package/dist/lang/ast/expressions/constant-expression.d.ts +1 -0
  21. package/dist/lang/ast/expressions/constant-expression.js +3 -0
  22. package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +3 -7
  23. package/dist/lang/ast/expressions/expr-aggregate-function.js +50 -54
  24. package/dist/lang/ast/expressions/expr-cast.js +2 -4
  25. package/dist/lang/ast/expressions/expr-func.js +1 -1
  26. package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
  27. package/dist/lang/ast/expressions/expr-record-literal.d.ts +16 -0
  28. package/dist/lang/ast/expressions/expr-record-literal.js +57 -0
  29. package/dist/lang/ast/expressions/expr-time-extract.js +3 -3
  30. package/dist/lang/ast/expressions/expr-time.d.ts +3 -3
  31. package/dist/lang/ast/expressions/expr-time.js +1 -1
  32. package/dist/lang/ast/expressions/time-literal.d.ts +6 -6
  33. package/dist/lang/ast/expressions/time-literal.js +1 -1
  34. package/dist/lang/ast/field-space/column-space-field.d.ts +6 -5
  35. package/dist/lang/ast/field-space/column-space-field.js +7 -4
  36. package/dist/lang/ast/field-space/dynamic-space.d.ts +8 -6
  37. package/dist/lang/ast/field-space/dynamic-space.js +35 -11
  38. package/dist/lang/ast/field-space/index-field-space.js +6 -3
  39. package/dist/lang/ast/field-space/ir-view-field.d.ts +1 -0
  40. package/dist/lang/ast/field-space/ir-view-field.js +3 -1
  41. package/dist/lang/ast/field-space/join-space-field.d.ts +2 -2
  42. package/dist/lang/ast/field-space/join-space-field.js +2 -2
  43. package/dist/lang/ast/field-space/parameter-space.d.ts +1 -0
  44. package/dist/lang/ast/field-space/parameter-space.js +4 -1
  45. package/dist/lang/ast/field-space/query-input-space.d.ts +4 -4
  46. package/dist/lang/ast/field-space/query-input-space.js +3 -5
  47. package/dist/lang/ast/field-space/query-spaces.d.ts +4 -4
  48. package/dist/lang/ast/field-space/query-spaces.js +1 -1
  49. package/dist/lang/ast/field-space/reference-field.js +10 -8
  50. package/dist/lang/ast/field-space/refined-space.d.ts +2 -2
  51. package/dist/lang/ast/field-space/static-space.d.ts +14 -5
  52. package/dist/lang/ast/field-space/static-space.js +45 -20
  53. package/dist/lang/ast/field-space/struct-space-field-base.d.ts +6 -5
  54. package/dist/lang/ast/field-space/struct-space-field-base.js +12 -4
  55. package/dist/lang/ast/index.d.ts +2 -1
  56. package/dist/lang/ast/index.js +2 -1
  57. package/dist/lang/ast/query-builders/index-builder.d.ts +2 -2
  58. package/dist/lang/ast/query-builders/project-builder.d.ts +2 -2
  59. package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -2
  60. package/dist/lang/ast/query-elements/query-arrow.js +2 -2
  61. package/dist/lang/ast/query-elements/query-head-struct.d.ts +2 -2
  62. package/dist/lang/ast/query-elements/query-head-struct.js +2 -2
  63. package/dist/lang/ast/query-elements/query-raw.js +2 -2
  64. package/dist/lang/ast/query-elements/query-reference.js +1 -1
  65. package/dist/lang/ast/query-items/field-declaration.d.ts +8 -6
  66. package/dist/lang/ast/query-items/field-declaration.js +66 -24
  67. package/dist/lang/ast/query-properties/qop-desc.d.ts +2 -2
  68. package/dist/lang/ast/query-properties/qop-desc.js +1 -1
  69. package/dist/lang/ast/source-elements/named-source.d.ts +4 -4
  70. package/dist/lang/ast/source-elements/named-source.js +16 -8
  71. package/dist/lang/ast/source-elements/query-source.d.ts +3 -3
  72. package/dist/lang/ast/source-elements/query-source.js +5 -2
  73. package/dist/lang/ast/source-elements/refined-source.d.ts +3 -3
  74. package/dist/lang/ast/source-elements/refined-source.js +4 -4
  75. package/dist/lang/ast/source-elements/source.d.ts +2 -2
  76. package/dist/lang/ast/source-elements/source.js +2 -2
  77. package/dist/lang/ast/source-elements/sql-source.d.ts +4 -4
  78. package/dist/lang/ast/source-elements/sql-source.js +6 -6
  79. package/dist/lang/ast/source-elements/table-source.d.ts +2 -2
  80. package/dist/lang/ast/source-elements/table-source.js +1 -1
  81. package/dist/lang/ast/source-properties/{joins.d.ts → join.d.ts} +11 -14
  82. package/dist/lang/ast/source-properties/{joins.js → join.js} +35 -52
  83. package/dist/lang/ast/source-query-elements/sq-reference.js +6 -5
  84. package/dist/lang/ast/sql-elements/sql-string.d.ts +2 -2
  85. package/dist/lang/ast/statements/define-source.js +1 -1
  86. package/dist/lang/ast/struct-utils.d.ts +3 -3
  87. package/dist/lang/ast/struct-utils.js +12 -3
  88. package/dist/lang/ast/time-utils.d.ts +3 -3
  89. package/dist/lang/ast/types/document-compile-result.d.ts +2 -2
  90. package/dist/lang/ast/types/expression-def.js +4 -4
  91. package/dist/lang/ast/types/field-space.d.ts +8 -3
  92. package/dist/lang/ast/types/lookup-result.d.ts +8 -5
  93. package/dist/lang/ast/types/malloy-element.d.ts +3 -3
  94. package/dist/lang/ast/types/malloy-element.js +10 -21
  95. package/dist/lang/ast/types/op-desc.d.ts +2 -2
  96. package/dist/lang/ast/types/pipeline-comp.d.ts +2 -2
  97. package/dist/lang/ast/types/query-comp.d.ts +3 -3
  98. package/dist/lang/ast/types/query-extend-property.d.ts +1 -2
  99. package/dist/lang/ast/types/query-extend-property.js +4 -2
  100. package/dist/lang/ast/types/source-property.d.ts +2 -2
  101. package/dist/lang/ast/types/source-property.js +2 -2
  102. package/dist/lang/ast/types/space-field.d.ts +10 -3
  103. package/dist/lang/ast/types/space-field.js +11 -2
  104. package/dist/lang/ast/types/time-result.d.ts +2 -2
  105. package/dist/lang/ast/view-elements/qop-desc-view.d.ts +3 -3
  106. package/dist/lang/ast/view-elements/qop-desc-view.js +1 -1
  107. package/dist/lang/ast/view-elements/reference-view.d.ts +4 -4
  108. package/dist/lang/ast/view-elements/reference-view.js +2 -6
  109. package/dist/lang/ast/view-elements/view-refine.d.ts +2 -2
  110. package/dist/lang/index.d.ts +1 -1
  111. package/dist/lang/lib/Malloy/MalloyParser.d.ts +54 -21
  112. package/dist/lang/lib/Malloy/MalloyParser.js +1647 -1457
  113. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +57 -9
  114. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +35 -5
  115. package/dist/lang/malloy-to-ast.d.ts +4 -4
  116. package/dist/lang/malloy-to-ast.js +32 -4
  117. package/dist/lang/parse-log.d.ts +5 -9
  118. package/dist/lang/parse-malloy.d.ts +10 -10
  119. package/dist/lang/parse-malloy.js +2 -1
  120. package/dist/lang/test/annotation.spec.js +7 -1
  121. package/dist/lang/test/field-symbols.spec.js +21 -25
  122. package/dist/lang/test/imports.spec.js +12 -10
  123. package/dist/lang/test/lenses.spec.js +2 -2
  124. package/dist/lang/test/model_serialization.spec.d.ts +4 -4
  125. package/dist/lang/test/model_serialization.spec.js +19 -31
  126. package/dist/lang/test/parse.spec.js +3 -4
  127. package/dist/lang/test/query.spec.js +3 -2
  128. package/dist/lang/test/source.spec.js +7 -0
  129. package/dist/lang/test/sql-block.spec.js +8 -19
  130. package/dist/lang/test/test-translator.d.ts +4 -4
  131. package/dist/lang/test/test-translator.js +53 -61
  132. package/dist/lang/translate-response.d.ts +3 -3
  133. package/dist/malloy.d.ts +31 -149
  134. package/dist/malloy.js +109 -267
  135. package/dist/model/malloy_query.d.ts +25 -23
  136. package/dist/model/malloy_query.js +262 -323
  137. package/dist/model/malloy_types.d.ts +145 -155
  138. package/dist/model/malloy_types.js +81 -84
  139. package/dist/model/sql_block.d.ts +4 -4
  140. package/dist/model/sql_block.js +9 -12
  141. package/dist/tags.js +2 -2
  142. package/package.json +1 -1
  143. package/dist/lang/ast/space-seed.d.ts +0 -16
  144. package/dist/lang/ast/space-seed.js +0 -59
package/dist/malloy.js CHANGED
@@ -22,7 +22,7 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.ExploreMaterializer = exports.SQLBlockMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.ExploreField = exports.JoinRelationship = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicField = exports.AtomicFieldType = exports.Explore = exports.SourceRelationship = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.PreparedResult = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentTablePath = exports.Parse = exports.PreparedQuery = exports.Model = exports.MalloyError = exports.Malloy = void 0;
25
+ exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.ExploreMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.ExploreField = exports.JoinRelationship = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicField = exports.AtomicFieldType = exports.Explore = exports.SourceRelationship = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.PreparedResult = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentTablePath = exports.Parse = exports.PreparedQuery = exports.Model = exports.MalloyError = exports.Malloy = void 0;
26
26
  const lang_1 = require("./lang");
27
27
  const model_1 = require("./model");
28
28
  const luxon_1 = require("luxon");
@@ -84,12 +84,11 @@ class Malloy {
84
84
  : Date.now();
85
85
  }
86
86
  const translator = parse._translator;
87
- // eslint-disable-next-line no-constant-condition
88
- while (true) {
87
+ for (;;) {
89
88
  const result = translator.translate(model === null || model === void 0 ? void 0 : model._modelDef);
90
89
  if (result.final) {
91
90
  if (result.translated) {
92
- return new Model(result.translated.modelDef, result.translated.queryList, result.translated.sqlBlocks, result.problems || [], [...((_a = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _a !== void 0 ? _a : []), ...((_b = result.fromSources) !== null && _b !== void 0 ? _b : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
91
+ return new Model(result.translated.modelDef, result.translated.queryList, result.problems || [], [...((_a = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _a !== void 0 ? _a : []), ...((_b = result.fromSources) !== null && _b !== void 0 ? _b : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
93
92
  }
94
93
  else if (noThrowOnError) {
95
94
  const emptyModel = {
@@ -98,7 +97,7 @@ class Malloy {
98
97
  contents: {},
99
98
  };
100
99
  const modelFromCompile = (model === null || model === void 0 ? void 0 : model._modelDef) || emptyModel;
101
- return new Model(modelFromCompile, [], [], result.problems || [], [...((_c = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _c !== void 0 ? _c : []), ...((_d = result.fromSources) !== null && _d !== void 0 ? _d : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
100
+ return new Model(modelFromCompile, [], result.problems || [], [...((_c = model === null || model === void 0 ? void 0 : model.fromSources) !== null && _c !== void 0 ? _c : []), ...((_d = result.fromSources) !== null && _d !== void 0 ? _d : [])], (position) => translator.referenceAt(position), (position) => translator.importAt(position));
102
101
  }
103
102
  else {
104
103
  const errors = result.problems || [];
@@ -147,7 +146,7 @@ class Malloy {
147
146
  // TODO detect if the union of `Object.keys(tables)` and `Object.keys(errors)` is not the same
148
147
  // as `Object.keys(tablePathByKey)`, i.e. that all tables are accounted for. Otherwise
149
148
  // the translator runs into an infinite loop fetching tables.
150
- const { schemas: tables, errors } = await connection.fetchSchemaForTables(tablePathByKey, {
149
+ const { schemas: tables, errors } = await Malloy.safelyFetchTableSchema(connection, tablePathByKey, {
151
150
  refreshTimestamp,
152
151
  modelAnnotation,
153
152
  });
@@ -171,12 +170,12 @@ class Malloy {
171
170
  const connectionName = toCompile.connection;
172
171
  try {
173
172
  const conn = await connections.lookupConnection(connectionName);
174
- const expanded = Malloy.compileSQLBlock(result.partialModel, toCompile, {
173
+ const expanded = Malloy.compileSQLBlock(conn.dialectName, result.partialModel, toCompile, {
175
174
  replaceMaterializedReferences,
176
175
  materializedTablePrefix,
177
176
  eventStream,
178
177
  });
179
- const resolved = await conn.fetchSchemaForSQLBlock(expanded, {
178
+ const resolved = await conn.fetchSchemaForSQLStruct(expanded, {
180
179
  refreshTimestamp,
181
180
  modelAnnotation,
182
181
  });
@@ -186,11 +185,9 @@ class Malloy {
186
185
  });
187
186
  }
188
187
  if (resolved.structDef) {
189
- if ((0, model_1.isSQLBlockStruct)(resolved.structDef)) {
190
- translator.update({
191
- compileSQL: { [expanded.name]: resolved.structDef },
192
- });
193
- }
188
+ translator.update({
189
+ compileSQL: { [expanded.name]: resolved.structDef },
190
+ });
194
191
  }
195
192
  }
196
193
  catch (error) {
@@ -202,12 +199,26 @@ class Malloy {
202
199
  }
203
200
  }
204
201
  }
205
- static compileSQLBlock(partialModel, toCompile, options) {
202
+ /**
203
+ * A dialect must provide a response for every table, or the translator loop
204
+ * will never exit. Because there was a time when this happened, we throw
205
+ * instead of looping forever, but the fix is to correct the dialect.
206
+ */
207
+ static async safelyFetchTableSchema(connection, toFetch, opts) {
208
+ const ret = await connection.fetchSchemaForTables(toFetch, opts);
209
+ for (const req of Object.keys(toFetch)) {
210
+ if (ret.schemas[req] === undefined && ret.errors[req] === undefined) {
211
+ throw new Error(`Schema fetch error for ${connection.name}, no response for ${req} from ${connection.dialectName}`);
212
+ }
213
+ }
214
+ return ret;
215
+ }
216
+ static compileSQLBlock(dialect, partialModel, toCompile, options) {
206
217
  let queryModel = undefined;
207
218
  let selectStr = '';
208
219
  let parenAlready = false;
209
220
  for (const segment of toCompile.select) {
210
- if ((0, model_1.isSQLFragment)(segment)) {
221
+ if ((0, model_1.isSegmentSQL)(segment)) {
211
222
  selectStr += segment.sql;
212
223
  parenAlready = segment.sql.match(/\(\s*$/) !== null;
213
224
  }
@@ -225,32 +236,35 @@ class Malloy {
225
236
  }
226
237
  }
227
238
  const { name, connection } = toCompile;
228
- return { type: 'sqlBlock', name, connection, selectStr };
239
+ return {
240
+ type: 'sql_select',
241
+ name,
242
+ connection,
243
+ dialect,
244
+ selectStr,
245
+ fields: [],
246
+ };
229
247
  }
230
248
  static async run({ connections, preparedResult, sqlStruct, connection, options, }) {
231
- const sqlBlock = sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.structSource.sqlBlock;
232
249
  if (!connection) {
233
250
  if (!connections) {
234
251
  throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
235
252
  }
236
- const connectionName = (sqlBlock === null || sqlBlock === void 0 ? void 0 : sqlBlock.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
253
+ const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
237
254
  connection = await connections.lookupConnection(connectionName);
238
255
  }
239
- if (sqlStruct && sqlBlock) {
240
- if (sqlStruct.structRelationship.type !== 'basetable') {
241
- throw new Error("Expected schema's structRelationship type to be 'basetable'.");
242
- }
243
- const data = await connection.runSQL(sqlBlock.selectStr);
256
+ if (sqlStruct) {
257
+ const data = await connection.runSQL(sqlStruct.selectStr);
244
258
  return new Result({
245
259
  structs: [sqlStruct],
246
- sql: sqlBlock.selectStr,
260
+ sql: sqlStruct.selectStr,
247
261
  result: data.rows,
248
262
  totalRows: data.totalRows,
249
263
  runStats: data.runStats,
250
- lastStageName: sqlBlock.name,
264
+ lastStageName: sqlStruct.name,
251
265
  // TODO feature-sql-block There is no malloy code...
252
266
  malloy: '',
253
- connectionName: sqlStruct.structRelationship.connectionName,
267
+ connectionName: sqlStruct.connection,
254
268
  // TODO feature-sql-block There is no source explore...
255
269
  sourceExplore: '',
256
270
  sourceFilters: [],
@@ -276,11 +290,10 @@ class Malloy {
276
290
  }
277
291
  }
278
292
  static async *runStream({ connections, preparedResult, sqlStruct, connection, options, }) {
279
- const sqlBlock = sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.structSource.sqlBlock;
280
- if (sqlBlock === undefined && preparedResult === undefined) {
293
+ if (sqlStruct === undefined && preparedResult === undefined) {
281
294
  throw new Error('Internal error: sqlBlock or preparedResult must be provided.');
282
295
  }
283
- const connectionName = (sqlBlock === null || sqlBlock === void 0 ? void 0 : sqlBlock.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
296
+ const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
284
297
  if (connection === undefined) {
285
298
  if (connections === undefined) {
286
299
  throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
@@ -294,11 +307,8 @@ class Malloy {
294
307
  let sql;
295
308
  let resultExplore;
296
309
  if (sqlStruct) {
297
- if (sqlStruct.structRelationship.type !== 'basetable') {
298
- throw new Error("Expected schema's structRelationship type to be 'basetable'.");
299
- }
300
310
  resultExplore = new Explore(sqlStruct);
301
- sql = sqlStruct.structSource.sqlBlock.selectStr;
311
+ sql = sqlStruct.selectStr;
302
312
  }
303
313
  else if (preparedResult !== undefined) {
304
314
  resultExplore = preparedResult.resultExplore;
@@ -314,17 +324,16 @@ class Malloy {
314
324
  }
315
325
  }
316
326
  static async estimateQueryCost({ connections, preparedResult, sqlStruct, }) {
317
- const sqlBlock = sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.structSource.sqlBlock;
318
327
  if (!connections) {
319
328
  throw new Error('Internal Error: Connection or LookupConnection<Connection> must be provided.');
320
329
  }
321
- const connectionName = (sqlBlock === null || sqlBlock === void 0 ? void 0 : sqlBlock.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
330
+ const connectionName = (sqlStruct === null || sqlStruct === void 0 ? void 0 : sqlStruct.connection) || (preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.connectionName);
322
331
  const connection = await connections.lookupConnection(connectionName);
323
- if (sqlBlock) {
324
- return await connection.estimateQueryCost(sqlBlock === null || sqlBlock === void 0 ? void 0 : sqlBlock.selectStr);
332
+ if (sqlStruct) {
333
+ return await connection.estimateQueryCost(sqlStruct.selectStr);
325
334
  }
326
335
  else if (preparedResult) {
327
- return await connection.estimateQueryCost(preparedResult === null || preparedResult === void 0 ? void 0 : preparedResult.sql);
336
+ return await connection.estimateQueryCost(preparedResult.sql);
328
337
  }
329
338
  else {
330
339
  throw new Error('Internal error: sqlStruct or preparedResult must be provided.');
@@ -349,10 +358,9 @@ exports.MalloyError = MalloyError;
349
358
  * A compiled Malloy document.
350
359
  */
351
360
  class Model {
352
- constructor(modelDef, queryList, sqlBlocks, problems, fromSources, referenceAt = () => undefined, importAt = () => undefined) {
361
+ constructor(modelDef, queryList, problems, fromSources, referenceAt = () => undefined, importAt = () => undefined) {
353
362
  this.modelDef = modelDef;
354
363
  this.queryList = queryList;
355
- this.sqlBlocks = sqlBlocks;
356
364
  this.problems = problems;
357
365
  this.fromSources = fromSources;
358
366
  this._referenceAt = referenceAt;
@@ -412,32 +420,6 @@ class Model {
412
420
  }
413
421
  return new PreparedQuery(this.queryList[index], this.modelDef, this.problems);
414
422
  }
415
- /**
416
- * Retrieve a prepared query by the name of a query at the top level of the model.
417
- *
418
- * @param queryName Name of the query to retrieve.
419
- * @return A prepared query.
420
- */
421
- getSQLBlockByName(sqlBlockName) {
422
- const sqlBlock = this.sqlBlocks.find(sqlBlock => sqlBlock.as === sqlBlockName);
423
- if (sqlBlock === undefined) {
424
- throw new Error(`No SQL Block named '${sqlBlockName}'`);
425
- }
426
- return sqlBlock;
427
- }
428
- /**
429
- * Retrieve a prepared query by the name of a query at the top level of the model.
430
- *
431
- * @param index Index of the SQL Block to retrieve.
432
- * @return A prepared query.
433
- */
434
- getSQLBlockByIndex(index) {
435
- const sqlBlock = this.sqlBlocks[index];
436
- if (sqlBlock === undefined) {
437
- throw new Error(`No SQL Block at index ${index}`);
438
- }
439
- return sqlBlock;
440
- }
441
423
  /**
442
424
  * Retrieve a prepared query for the final unnamed query at the top level of a model.
443
425
  *
@@ -465,7 +447,7 @@ class Model {
465
447
  */
466
448
  getExploreByName(name) {
467
449
  const struct = this.modelDef.contents[name];
468
- if (struct.type === 'struct') {
450
+ if ((0, model_1.modelObjIsSource)(struct)) {
469
451
  return new Explore(struct);
470
452
  }
471
453
  throw new Error("'name' is not an explore");
@@ -476,9 +458,8 @@ class Model {
476
458
  * @return An array of `Explore`s contained in the model.
477
459
  */
478
460
  get explores() {
479
- const isStructDef = (object) => object.type === 'struct';
480
461
  return Object.values(this.modelDef.contents)
481
- .filter(isStructDef)
462
+ .filter(model_1.modelObjIsSource)
482
463
  .map(structDef => new Explore(structDef));
483
464
  }
484
465
  /**
@@ -543,7 +524,7 @@ class PreparedQuery {
543
524
  const source = typeof sourceRef === 'string'
544
525
  ? this._modelDef.contents[sourceRef]
545
526
  : sourceRef;
546
- if (source.type !== 'struct') {
527
+ if (!(0, model_1.modelObjIsSource)(source)) {
547
528
  throw new Error('Invalid source for query');
548
529
  }
549
530
  return source.dialect;
@@ -837,7 +818,7 @@ class PreparedResult {
837
818
  if (explore === undefined) {
838
819
  throw new Error('Malformed query result.');
839
820
  }
840
- if (explore.type === 'struct') {
821
+ if ((0, model_1.modelObjIsSource)(explore)) {
841
822
  return new Explore(explore);
842
823
  }
843
824
  throw new Error(`'${name} is not an explore`);
@@ -999,7 +980,13 @@ class Explore extends Entity {
999
980
  return this.sourceExplore;
1000
981
  }
1001
982
  isIntrinsic() {
1002
- return (0, model_1.FieldIsIntrinsic)(this._structDef);
983
+ // Don't have the right discriminator, if this was a field def at some point, the field-defness ahs been lost.
984
+ // A record or an array might be atomic, AND be a structdef, unless they are a dimension (i.e. have a an
985
+ // expression)
986
+ if ((0, model_1.isAtomicFieldType)(this._structDef.type)) {
987
+ return !('e' in this._structDef);
988
+ }
989
+ return false;
1003
990
  }
1004
991
  isExploreField() {
1005
992
  return false;
@@ -1021,9 +1008,13 @@ class Explore extends Entity {
1021
1008
  return this.structDef.as || this.structDef.name;
1022
1009
  }
1023
1010
  getQueryByName(name) {
1011
+ const structRef = this.sourceStructDef;
1012
+ if (!structRef) {
1013
+ throw new Error(`Cannot get query by name from a struct of type ${this.structDef.type}`);
1014
+ }
1024
1015
  const internalQuery = {
1025
1016
  type: 'query',
1026
- structRef: this.structDef,
1017
+ structRef,
1027
1018
  pipeline: [
1028
1019
  {
1029
1020
  type: 'reduce',
@@ -1041,7 +1032,7 @@ class Explore extends Entity {
1041
1032
  };
1042
1033
  }
1043
1034
  getSingleExploreModel() {
1044
- return new Model(this.modelDef, [], [], [], []);
1035
+ return new Model(this.modelDef, [], [], []);
1045
1036
  }
1046
1037
  get fieldMap() {
1047
1038
  var _a;
@@ -1050,7 +1041,7 @@ class Explore extends Entity {
1050
1041
  this._fieldMap = new Map(this.structDef.fields.map(fieldDef => {
1051
1042
  const name = fieldDef.as || fieldDef.name;
1052
1043
  const sourceField = sourceFields.get(fieldDef.name);
1053
- if (fieldDef.type === 'struct') {
1044
+ if ((0, model_1.isJoined)(fieldDef)) {
1054
1045
  return [name, new ExploreField(fieldDef, this, sourceField)];
1055
1046
  }
1056
1047
  else if (fieldDef.type === 'turtle') {
@@ -1097,10 +1088,10 @@ class Explore extends Entity {
1097
1088
  return [...this.fieldMap.values()];
1098
1089
  }
1099
1090
  get allFieldsWithOrder() {
1100
- var _a, _b;
1091
+ var _a, _b, _c;
1101
1092
  if (!this._allFieldsWithOrder) {
1102
1093
  const orderByFields = [
1103
- ...(((_b = (_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.orderBy) === null || _b === void 0 ? void 0 : _b.map(f => {
1094
+ ...(((_c = (_b = (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.resultMetadata) === null || _b === void 0 ? void 0 : _b.orderBy) === null || _c === void 0 ? void 0 : _c.map(f => {
1104
1095
  if (typeof f.field === 'string') {
1105
1096
  const a = {
1106
1097
  field: this.fieldMap.get(f.field),
@@ -1143,44 +1134,38 @@ class Explore extends Entity {
1143
1134
  return this.fieldMap.get(fieldName);
1144
1135
  }
1145
1136
  get primaryKey() {
1146
- return this.structDef.primaryKey;
1137
+ var _a;
1138
+ return (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.primaryKey;
1147
1139
  }
1148
1140
  get parentExplore() {
1149
1141
  return this._parentExplore;
1150
1142
  }
1151
- get sourceRelationship() {
1152
- switch (this.structDef.structRelationship.type) {
1153
- case 'many':
1154
- return SourceRelationship.Many;
1155
- case 'one':
1156
- return SourceRelationship.One;
1157
- case 'cross':
1158
- return SourceRelationship.Cross;
1159
- case 'inline':
1160
- return SourceRelationship.Inline;
1161
- case 'nested':
1162
- return SourceRelationship.Nested;
1163
- case 'basetable':
1164
- return SourceRelationship.BaseTable;
1165
- }
1166
- }
1167
1143
  hasParentExplore() {
1168
1144
  return this instanceof ExploreField;
1169
1145
  }
1170
1146
  // TODO wrapper type for FilterCondition
1171
1147
  get filters() {
1172
1148
  var _a;
1173
- return ((_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.filterList) || [];
1149
+ if ((0, model_1.isSourceDef)(this.structDef)) {
1150
+ return ((_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.filterList) || [];
1151
+ }
1152
+ return [];
1174
1153
  }
1175
1154
  get limit() {
1176
- var _a;
1177
- return (_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.limit;
1155
+ var _a, _b;
1156
+ return (_b = (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.resultMetadata) === null || _b === void 0 ? void 0 : _b.limit;
1178
1157
  }
1179
1158
  get structDef() {
1180
1159
  return this._structDef;
1181
1160
  }
1182
1161
  get queryTimezone() {
1183
- return this.structDef.queryTimezone;
1162
+ var _a;
1163
+ return (_a = this.sourceStructDef) === null || _a === void 0 ? void 0 : _a.queryTimezone;
1164
+ }
1165
+ get sourceStructDef() {
1166
+ if ((0, model_1.isSourceDef)(this.structDef)) {
1167
+ return this.structDef;
1168
+ }
1184
1169
  }
1185
1170
  toJSON() {
1186
1171
  var _a, _b;
@@ -1239,6 +1224,13 @@ class AtomicField extends Entity {
1239
1224
  return AtomicFieldType.NativeUnsupported;
1240
1225
  case 'error':
1241
1226
  return AtomicFieldType.Error;
1227
+ case 'record':
1228
+ case 'array':
1229
+ throw new Error(`MTOY TODO IMPLEMENT Atomic ${this.fieldTypeDef.type}`);
1230
+ default: {
1231
+ const x = this.fieldTypeDef;
1232
+ throw new Error(`Can't make an atomic field from ${x}`);
1233
+ }
1242
1234
  }
1243
1235
  }
1244
1236
  tagParse(spec) {
@@ -1249,7 +1241,7 @@ class AtomicField extends Entity {
1249
1241
  return tags_1.Tag.annotationToTaglines(this.fieldTypeDef.annotation, prefix);
1250
1242
  }
1251
1243
  isIntrinsic() {
1252
- return (0, model_1.FieldIsIntrinsic)(this.fieldTypeDef);
1244
+ return (0, model_1.fieldIsIntrinsic)(this.fieldTypeDef);
1253
1245
  }
1254
1246
  isQueryField() {
1255
1247
  return false;
@@ -1514,19 +1506,16 @@ class ExploreField extends Explore {
1514
1506
  this._parentExplore = parentExplore;
1515
1507
  }
1516
1508
  get joinRelationship() {
1517
- switch (this.structDef.structRelationship.type) {
1518
- case 'one':
1519
- return JoinRelationship.OneToMany;
1520
- case 'many':
1521
- case 'cross':
1522
- return JoinRelationship.ManyToOne;
1523
- case 'inline':
1524
- return JoinRelationship.OneToOne;
1525
- case 'nested':
1526
- return JoinRelationship.ManyToOne;
1527
- default:
1528
- throw new Error('A source field must have a join relationship.');
1509
+ if ((0, model_1.isJoined)(this.structDef)) {
1510
+ switch (this.structDef.join) {
1511
+ case 'one':
1512
+ return JoinRelationship.OneToOne;
1513
+ case 'many':
1514
+ case 'cross':
1515
+ return JoinRelationship.ManyToOne;
1516
+ }
1529
1517
  }
1518
+ throw new Error('A source field must have a join relationship.');
1530
1519
  }
1531
1520
  get isRecord() {
1532
1521
  return this.joinRelationship === JoinRelationship.OneToOne;
@@ -1660,7 +1649,7 @@ class Runtime {
1660
1649
  // be used in tests.
1661
1650
  _loadModelFromModelDef(modelDef, options) {
1662
1651
  return new ModelMaterializer(this, async () => {
1663
- return new Model(modelDef, [], [], [], []);
1652
+ return new Model(modelDef, [], [], []);
1664
1653
  }, options);
1665
1654
  }
1666
1655
  /**
@@ -1697,30 +1686,6 @@ class Runtime {
1697
1686
  loadQueryByName(model, name, options) {
1698
1687
  return this.loadModel(model, options).loadQueryByName(name, options);
1699
1688
  }
1700
- /**
1701
- * Load a SQL block by the URL or contents of a Malloy model document
1702
- * and the name of a query contained in the model.
1703
- *
1704
- * @param model The model URL or contents to load and (eventually) compile to retrieve the requested query.
1705
- * @param name The name of the sql block to use within the model.
1706
- * @return A `SQLBlockMaterializer` capable of materializing the requested query, running it,
1707
- * or loading further related objects.
1708
- */
1709
- loadSQLBlockByName(model, name, options) {
1710
- return this.loadModel(model, options).loadSQLBlockByName(name);
1711
- }
1712
- /**
1713
- * Load a SQL block by the URL or contents of a Malloy model document
1714
- * and the name of a query contained in the model.
1715
- *
1716
- * @param model The model URL or contents to load and (eventually) compile to retrieve the requested query.
1717
- * @param index The index of the SQL block to use within the model. Note: named blocks are indexable, too.
1718
- * @return A `SQLBlockMaterializer` capable of materializing the requested query, running it,
1719
- * or loading further related objects.
1720
- */
1721
- loadSQLBlockByIndex(model, index, options) {
1722
- return this.loadModel(model, options).loadSQLBlockByIndex(index);
1723
- }
1724
1689
  // TODO maybe use overloads for the alternative parameters
1725
1690
  /**
1726
1691
  * Compile a Malloy model by URL or contents.
@@ -1762,28 +1727,6 @@ class Runtime {
1762
1727
  getQueryByName(model, name, options) {
1763
1728
  return this.loadQueryByName(model, name, options).getPreparedQuery();
1764
1729
  }
1765
- /**
1766
- * Get a SQL block by the URL or contents of a Malloy model document
1767
- * and the name of a SQL block contained in the model.
1768
- *
1769
- * @param model The model URL or contents to load and (eventually) compile to retrieve the requested query.
1770
- * @param name The name of the sql block to use within the model.
1771
- * @return A promise of a `CompiledSQLBlock`.
1772
- */
1773
- getSQLBlockByName(model, name, options) {
1774
- return this.loadSQLBlockByName(model, name, options).getSQLBlock();
1775
- }
1776
- /**
1777
- * Get a SQL block by the URL or contents of a Malloy model document
1778
- * and the name of a query contained in the model.
1779
- *
1780
- * @param model The model URL or contents to load and (eventually) compile to retrieve the requested query.
1781
- * @param index The index of the SQL block to use within the model. Note: named blocks are indexable, too.
1782
- * @return A promise of a `SQLBlock`.
1783
- */
1784
- getSQLBlockByIndex(model, index, options) {
1785
- return this.loadSQLBlockByIndex(model, index, options).getSQLBlock();
1786
- }
1787
1730
  }
1788
1731
  exports.Runtime = Runtime;
1789
1732
  class ConnectionRuntime extends Runtime {
@@ -1862,12 +1805,6 @@ class FluentState {
1862
1805
  makePreparedResultMaterializer(materialize) {
1863
1806
  return new PreparedResultMaterializer(this.runtime, materialize);
1864
1807
  }
1865
- makeSQLBlockMaterializer(materialize) {
1866
- return new SQLBlockMaterializer(this.runtime, materialize);
1867
- }
1868
- get eventStream() {
1869
- return this.runtime.eventStream;
1870
- }
1871
1808
  }
1872
1809
  /**
1873
1810
  * An object representing the task of loading a `Model`, capable of
@@ -2013,18 +1950,18 @@ class ModelMaterializer extends FluentState {
2013
1950
  const model = await this.materialize();
2014
1951
  const queryModel = new model_1.QueryModel(model._modelDef, eventStream);
2015
1952
  const schema = model.getExploreByName(sourceName).structDef;
2016
- if (schema.structRelationship.type !== 'basetable') {
2017
- throw new Error("Expected schema's structRelationship type to be 'basetable'.");
1953
+ if (!(0, model_1.isSourceDef)(schema)) {
1954
+ throw new Error('Source to be searched was unexpectedly, not a source');
2018
1955
  }
2019
- const connectionName = schema.structRelationship.connectionName;
1956
+ const connectionName = schema.connection;
2020
1957
  const connection = await this.runtime.connections.lookupConnection(connectionName);
2021
1958
  return await queryModel.searchIndex(connection, sourceName, searchTerm, limit, searchField);
2022
1959
  }
2023
1960
  async searchValueMap(sourceName, limit = 10, options) {
2024
1961
  const model = await this.materialize();
2025
1962
  const schema = model.getExploreByName(sourceName);
2026
- if (schema.structDef.structRelationship.type !== 'basetable') {
2027
- throw new Error("Expected schema's structRelationship type to be 'basetable'.");
1963
+ if (!(0, model_1.isSourceDef)(schema.structDef)) {
1964
+ throw new Error('Source to be searched was unexpectedly, not a source');
2028
1965
  }
2029
1966
  let indexQuery = '{index: *}';
2030
1967
  if (schema.getFieldByNameIfExists('search_index')) {
@@ -2050,32 +1987,6 @@ class ModelMaterializer extends FluentState {
2050
1987
  });
2051
1988
  return result._queryResult.result;
2052
1989
  }
2053
- /**
2054
- * Load a SQL Block by name.
2055
- *
2056
- * @param name The name of the SQL Block to load.
2057
- * @return A `SQLBlockMaterializer` capable of materializing the requested sql block, running it,
2058
- * or loading further related objects.
2059
- */
2060
- loadSQLBlockByName(name) {
2061
- return this.makeSQLBlockMaterializer(async () => {
2062
- return (await this.materialize()).getSQLBlockByName(name);
2063
- });
2064
- }
2065
- /**
2066
- * Load a SQL Block by index.
2067
- *
2068
- * @param index The index of the SQL Block to load. Note: named SQL blocks are indexable, too.
2069
- * @return A `SQLBlockMaterializer` capable of materializing the requested sql block, running it,
2070
- * or loading further related objects.
2071
- *
2072
- * TODO feature-sql-block Should named SQL blocks be indexable? This is not the way unnamed queries work.
2073
- */
2074
- loadSQLBlockByIndex(index) {
2075
- return this.makeSQLBlockMaterializer(async () => {
2076
- return (await this.materialize()).getSQLBlockByIndex(index);
2077
- });
2078
- }
2079
1990
  /**
2080
1991
  * Materialize the final query contained within this loaded `Model`.
2081
1992
  *
@@ -2111,26 +2022,6 @@ class ModelMaterializer extends FluentState {
2111
2022
  getQuery(query, options) {
2112
2023
  return this.loadQuery(query, options).getPreparedQuery();
2113
2024
  }
2114
- /**
2115
- * Get a SQL Block by name.
2116
- *
2117
- * @param name The name of the SQL Block to load.
2118
- * @return A promise of a `SQLBlock`.
2119
- */
2120
- getSQLBlockByName(name) {
2121
- return this.loadSQLBlockByName(name).getSQLBlock();
2122
- }
2123
- /**
2124
- * Get a SQL Block by index.
2125
- *
2126
- * @param index The index of the SQL Block to load. Note: named SQL blocks are indexable, too.
2127
- * @return A promise of a `SQLBlock`.
2128
- *
2129
- * TODO feature-sql-block Should named SQL blocks be indexable? This is not the way unnamed queries work.
2130
- */
2131
- getSQLBlockByIndex(index) {
2132
- return this.loadSQLBlockByIndex(index).getSQLBlock();
2133
- }
2134
2025
  // TODO Consider formalizing this. Perhaps as a `withQuery` method,
2135
2026
  // as well as a `PreparedQuery.fromQueryDefinition` if we choose to expose
2136
2027
  // `InternalQuery` to the world formally. For now, this should only
@@ -2259,6 +2150,9 @@ class QueryMaterializer extends FluentState {
2259
2150
  const preparedResult = await this.getPreparedResult(options);
2260
2151
  return Malloy.estimateQueryCost({ connections, preparedResult });
2261
2152
  }
2153
+ get eventStream() {
2154
+ return this.runtime.eventStream;
2155
+ }
2262
2156
  }
2263
2157
  exports.QueryMaterializer = QueryMaterializer;
2264
2158
  function runSQLOptionsWithAnnotations(preparedResult, givenOptions) {
@@ -2320,58 +2214,6 @@ class PreparedResultMaterializer extends FluentState {
2320
2214
  }
2321
2215
  }
2322
2216
  exports.PreparedResultMaterializer = PreparedResultMaterializer;
2323
- /**
2324
- * An object representing the task of loading a `SQLBlock`, capable of
2325
- * materializing the SQLBlock (via `getSQLBlock()`) or extending the task run
2326
- * the query.
2327
- */
2328
- class SQLBlockMaterializer extends FluentState {
2329
- /**
2330
- * Run this SQL block.
2331
- *
2332
- * @return A promise to the query result data.
2333
- */
2334
- async run(options) {
2335
- const sqlBlock = await this.getSQLBlock();
2336
- const connections = this.runtime.connections;
2337
- return Malloy.run({
2338
- connections,
2339
- sqlStruct: sqlBlock,
2340
- options,
2341
- });
2342
- }
2343
- async *runStream(options) {
2344
- const sqlStruct = await this.getSQLBlock();
2345
- const connections = this.runtime.connections;
2346
- const stream = Malloy.runStream({ connections, sqlStruct, options });
2347
- for await (const row of stream) {
2348
- yield row;
2349
- }
2350
- }
2351
- /**
2352
- * Materialize this loaded SQL block.
2353
- *
2354
- * @return A promise of a SQL block.
2355
- */
2356
- getSQLBlock() {
2357
- return this.materialize();
2358
- }
2359
- /**
2360
- * Materialize the SQL of this loaded SQL block.
2361
- *
2362
- * @return A promise to the SQL string.
2363
- */
2364
- async getSQL() {
2365
- const sqlStruct = await this.getSQLBlock();
2366
- return sqlStruct.structSource.sqlBlock.selectStr;
2367
- }
2368
- async estimateQueryCost() {
2369
- const connections = this.runtime.connections;
2370
- const sqlStruct = await this.getSQLBlock();
2371
- return Malloy.estimateQueryCost({ connections, sqlStruct });
2372
- }
2373
- }
2374
- exports.SQLBlockMaterializer = SQLBlockMaterializer;
2375
2217
  /**
2376
2218
  * An object representing the task of loading an `Explore`, capable of
2377
2219
  * materializing the explore (via `getExplore()`) or extending the task to produce