@malloydata/malloy 0.0.195-dev241003204819 → 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 (146) 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 +111 -269
  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/dist/version.d.ts +1 -0
  143. package/dist/version.js +6 -0
  144. package/package.json +3 -2
  145. package/dist/lang/ast/space-seed.d.ts +0 -16
  146. package/dist/lang/ast/space-seed.js +0 -59
@@ -41,7 +41,7 @@ function identifierNormalize(s) {
41
41
  }
42
42
  function getDialectFieldList(structDef) {
43
43
  const dialectFieldList = [];
44
- for (const f of structDef.fields.filter(malloy_types_1.isPhysical)) {
44
+ for (const f of structDef.fields.filter(malloy_types_1.fieldIsIntrinsic)) {
45
45
  dialectFieldList.push({
46
46
  type: f.type,
47
47
  sqlExpression: (0, malloy_types_1.getIdentifier)(f),
@@ -205,11 +205,8 @@ class GenerateState {
205
205
  }
206
206
  }
207
207
  class QueryNode {
208
- constructor(fieldDef) {
209
- this.fieldDef = fieldDef;
210
- }
211
- getIdentifier() {
212
- return (0, malloy_types_1.getIdentifier)(this.fieldDef);
208
+ constructor(referenceId) {
209
+ this.referenceId = referenceId !== null && referenceId !== void 0 ? referenceId : (0, uuid_1.v4)();
213
210
  }
214
211
  getChildByName(_name) {
215
212
  return undefined;
@@ -217,24 +214,21 @@ class QueryNode {
217
214
  }
218
215
  class QueryField extends QueryNode {
219
216
  constructor(fieldDef, parent, referenceId) {
220
- super(fieldDef);
217
+ super(referenceId);
218
+ this.fieldDef = fieldDef;
221
219
  this.parent = parent;
222
220
  this.fieldDef = fieldDef;
223
- this.referenceId = referenceId !== null && referenceId !== void 0 ? referenceId : (0, uuid_1.v4)();
221
+ }
222
+ getIdentifier() {
223
+ return (0, malloy_types_1.getIdentifier)(this.fieldDef);
224
224
  }
225
225
  uniqueKeyPossibleUse() {
226
226
  return undefined;
227
227
  }
228
228
  getJoinableParent() {
229
- // if it is inline it should always have a parent
230
229
  const parent = this.parent;
231
- if (parent.fieldDef.structRelationship.type === 'inline') {
232
- if (parent) {
233
- return parent.getJoinableParent();
234
- }
235
- else {
236
- throw new Error('Internal Error: inline struct cannot be root');
237
- }
230
+ if (parent.structDef.type === 'record') {
231
+ return parent.getJoinableParent();
238
232
  }
239
233
  return parent;
240
234
  }
@@ -876,19 +870,30 @@ class QueryField extends QueryNode {
876
870
  throw new Error(`Internal Error: Unknown expression node '${expr.node}' ${JSON.stringify(expr, undefined, 2)}`);
877
871
  }
878
872
  }
873
+ isNestedInParent(parentDef) {
874
+ switch (parentDef.type) {
875
+ case 'record':
876
+ case 'array':
877
+ return true;
878
+ return true;
879
+ default:
880
+ return false;
881
+ }
882
+ }
883
+ isArrayElement(parentDef) {
884
+ return (parentDef.type === 'array' &&
885
+ parentDef.elementTypeDef.type !== 'record_element');
886
+ }
879
887
  getExpr() {
880
888
  if ((0, malloy_types_1.hasExpression)(this.fieldDef)) {
881
889
  return this.fieldDef.e;
882
890
  }
891
+ const pType = this.parent.structDef.type;
883
892
  return {
884
893
  node: 'genericSQLExpr',
885
894
  kids: { args: [] },
886
895
  src: [
887
- this.parent.dialect.sqlFieldReference(this.parent.getSQLIdentifier(), this.fieldDef.name, this.fieldDef.type, this.parent.fieldDef.structSource.type === 'nested' ||
888
- this.parent.fieldDef.structSource.type === 'inline' ||
889
- (this.parent.fieldDef.structSource.type === 'sql' &&
890
- this.parent.fieldDef.structSource.method === 'nested'), this.parent.fieldDef.structRelationship.type === 'nested' &&
891
- this.parent.fieldDef.structRelationship.isArray),
896
+ this.parent.dialect.sqlFieldReference(this.parent.getSQLIdentifier(), this.fieldDef.name, this.fieldDef.type, pType === 'record' || pType === 'array' || pType === 'nest_source', (0, malloy_types_1.isScalarArray)(this.parent.structDef)),
892
897
  ],
893
898
  };
894
899
  }
@@ -906,14 +911,20 @@ function isScalarField(f) {
906
911
  return f instanceof QueryAtomicField && !f.isCalculated() && !f.isAggregate();
907
912
  }
908
913
  class QueryAtomicField extends QueryField {
914
+ constructor(fieldDef, parent, refId) {
915
+ super(fieldDef, parent, refId);
916
+ this.fieldDef = fieldDef; // wish I didn't have to do this
917
+ }
909
918
  includeInWildcard() {
910
919
  return true;
911
920
  }
912
921
  isCalculated() {
913
- return (0, malloy_types_1.expressionIsCalculation)(this.fieldDef.expressionType);
922
+ return ((0, malloy_types_1.hasExpression)(this.fieldDef) &&
923
+ (0, malloy_types_1.expressionIsCalculation)(this.fieldDef.expressionType));
914
924
  }
915
925
  isAggregate() {
916
- return (0, malloy_types_1.expressionIsAggregate)(this.fieldDef.expressionType);
926
+ return ((0, malloy_types_1.hasExpression)(this.fieldDef) &&
927
+ (0, malloy_types_1.expressionIsAggregate)(this.fieldDef.expressionType));
917
928
  }
918
929
  getFilterList() {
919
930
  return [];
@@ -933,35 +944,6 @@ class QueryFieldJSON extends QueryAtomicField {
933
944
  }
934
945
  class QueryFieldUnsupported extends QueryAtomicField {
935
946
  }
936
- // in a query a struct can be referenced. The struct will
937
- // emit the primary key field in the actual result set and
938
- // will include the StructDef as a foreign key join in the output
939
- // StructDef.
940
- class QueryFieldStruct extends QueryAtomicField {
941
- constructor(fieldDef, parent, primaryKey) {
942
- super(fieldDef, parent);
943
- this.primaryKey = primaryKey;
944
- }
945
- getName() {
946
- return (0, malloy_types_1.getIdentifier)(this.fieldDef);
947
- }
948
- getAsJoinedStructDef(foreignKeyName) {
949
- return {
950
- ...this.parent.fieldDef,
951
- structRelationship: {
952
- type: 'one',
953
- matrixOperation: 'left',
954
- onExpression: {
955
- node: '=',
956
- kids: {
957
- left: { node: 'field', path: [this.primaryKey] },
958
- right: { node: 'field', path: [foreignKeyName] },
959
- },
960
- },
961
- },
962
- };
963
- }
964
- }
965
947
  class QueryFieldDate extends QueryAtomicField {
966
948
  generateExpression(resultSet) {
967
949
  const fd = this.fieldDef;
@@ -1005,14 +987,14 @@ class QueryFieldDistinctKey extends QueryAtomicField {
1005
987
  const pk = this.parent.getPrimaryKeyField(this.fieldDef);
1006
988
  return pk.generateExpression(resultSet);
1007
989
  }
1008
- else if (this.parent.fieldDef.structSource.type === 'nested') {
990
+ else if (this.parent.structDef.type === 'array') {
1009
991
  const parentKey = (_a = this.parent.parent) === null || _a === void 0 ? void 0 : _a.getDistinctKey().generateExpression(resultSet);
1010
992
  return this.parent.dialect.sqlMakeUnnestKey(parentKey || '', // shouldn't have to do this...
1011
993
  this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), '__row_id', 'string', true, false));
1012
994
  }
1013
995
  else {
1014
996
  // return this.parent.getIdentifier() + "." + "__distinct_key";
1015
- return this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), '__distinct_key', 'string', this.parent.fieldDef.structRelationship.type === 'nested', false);
997
+ return this.parent.dialect.sqlFieldReference(this.parent.getIdentifier(), '__distinct_key', 'string', false, false);
1016
998
  }
1017
999
  }
1018
1000
  includeInWildcard() {
@@ -1257,7 +1239,7 @@ class FieldInstanceResult {
1257
1239
  if (fi instanceof FieldInstanceField) {
1258
1240
  if (fi.fieldUsage.type === 'result') {
1259
1241
  if (fi.f.fieldDef.type === 'turtle' ||
1260
- fi.f.fieldDef.type === 'struct' ||
1242
+ (0, malloy_types_1.isJoined)(fi.f.fieldDef) ||
1261
1243
  (0, malloy_types_1.expressionIsAnalytic)(fi.f.fieldDef.expressionType)) {
1262
1244
  continue;
1263
1245
  }
@@ -1297,12 +1279,12 @@ class FieldInstanceResult {
1297
1279
  parent = this.root().joins.get(parentStruct.getIdentifier());
1298
1280
  }
1299
1281
  // add any dependant joins based on the ON
1300
- const sr = qs.fieldDef.structRelationship;
1301
- if ((0, malloy_types_1.isJoinOn)(sr) &&
1282
+ const sd = qs.structDef;
1283
+ if ((0, malloy_types_1.isJoinedSource)(sd) &&
1302
1284
  qs.parent && // if the join has an ON, it must thave a parent
1303
- sr.onExpression !== undefined &&
1285
+ sd.onExpression &&
1304
1286
  joinStack.indexOf(name) === -1) {
1305
- query.addDependantExpr(this, qs.parent, sr.onExpression, [
1287
+ query.addDependantExpr(this, qs.parent, sd.onExpression, [
1306
1288
  ...joinStack,
1307
1289
  name,
1308
1290
  ]);
@@ -1457,7 +1439,7 @@ class FieldInstanceResultRoot extends FieldInstanceResult {
1457
1439
  if (!j.queryStruct.primaryKey()) {
1458
1440
  j.makeUniqueKey = true;
1459
1441
  }
1460
- if (j.queryStruct.fieldDef.structRelationship.type === 'nested') {
1442
+ if (j.queryStruct.structDef.type === 'array') {
1461
1443
  j = j.parent;
1462
1444
  }
1463
1445
  else {
@@ -1482,54 +1464,50 @@ class JoinInstance {
1482
1464
  }
1483
1465
  // convert the filter list into a list of boolean fields so we can
1484
1466
  // generate dependancies and code for them.
1485
- if (this.queryStruct.fieldDef.filterList) {
1486
- this.joinFilterConditions = [];
1487
- for (const filter of this.queryStruct.fieldDef.filterList) {
1488
- const qf = new QueryFieldBoolean({
1489
- type: 'boolean',
1490
- name: 'ignoreme',
1491
- e: filter.e,
1492
- }, this.queryStruct);
1493
- this.joinFilterConditions.push(qf);
1494
- }
1467
+ const sd = this.queryStruct.structDef;
1468
+ if ((0, malloy_types_1.isSourceDef)(sd) && sd.filterList) {
1469
+ this.joinFilterConditions = sd.filterList.map(filter => new QueryFieldBoolean({
1470
+ type: 'boolean',
1471
+ name: 'ignoreme',
1472
+ e: filter.e,
1473
+ }, this.queryStruct));
1495
1474
  }
1496
1475
  }
1497
1476
  parentRelationship() {
1498
1477
  if (this.queryStruct.parent === undefined) {
1499
1478
  return 'root';
1500
1479
  }
1501
- switch (this.queryStruct.fieldDef.structRelationship.type) {
1502
- case 'one':
1503
- return 'many_to_one';
1504
- case 'cross':
1505
- return 'many_to_many';
1506
- case 'many':
1507
- return 'one_to_many';
1508
- case 'nested':
1509
- return 'one_to_many';
1510
- case 'inline':
1511
- return 'one_to_one';
1512
- default:
1513
- throw new Error(`Internal error unknown relationship type to parent for ${this.queryStruct.fieldDef.name}`);
1480
+ const thisStruct = this.queryStruct.structDef;
1481
+ if ((0, malloy_types_1.isJoined)(thisStruct)) {
1482
+ switch (thisStruct.join) {
1483
+ case 'one':
1484
+ return 'many_to_one';
1485
+ case 'cross':
1486
+ return 'many_to_many';
1487
+ case 'many':
1488
+ return 'one_to_many';
1489
+ }
1514
1490
  }
1491
+ throw new Error(`Internal error unknown relationship type to parent for ${this.queryStruct.structDef.name}`);
1515
1492
  }
1516
1493
  // For now, we force all symmetric calculations for full and right joins
1517
1494
  // because we need distinct keys for COUNT(xx) operations. Don't really need
1518
1495
  // this for sums. This will produce correct results and we can optimize this
1519
1496
  // at some point..
1520
1497
  forceAllSymmetricCalculations() {
1521
- const sr = this.queryStruct.fieldDef.structRelationship;
1522
- if (this.queryStruct.parent === undefined || !(0, malloy_types_1.isJoinOn)(sr)) {
1498
+ if (this.queryStruct.parent === undefined) {
1523
1499
  return false;
1524
1500
  }
1525
- if (sr.matrixOperation === 'right' || sr.matrixOperation === 'full') {
1526
- return true;
1501
+ const thisStruct = this.queryStruct.structDef;
1502
+ if ((0, malloy_types_1.isJoined)(thisStruct)) {
1503
+ return (thisStruct.matrixOperation === 'right' ||
1504
+ thisStruct.matrixOperation === 'full');
1527
1505
  }
1528
1506
  return false;
1529
1507
  }
1530
1508
  // postgres unnest needs to know the names of the physical fields.
1531
1509
  getDialectFieldList() {
1532
- return getDialectFieldList(this.queryStruct.fieldDef);
1510
+ return getDialectFieldList(this.queryStruct.structDef);
1533
1511
  }
1534
1512
  }
1535
1513
  /** nested query */
@@ -1544,7 +1522,7 @@ class Segment {
1544
1522
  static nextStructDef(structDef, segment) {
1545
1523
  const qs = new QueryStruct(structDef, undefined, {
1546
1524
  model: new QueryModel(undefined),
1547
- });
1525
+ }, {});
1548
1526
  const turtleDef = {
1549
1527
  type: 'turtle',
1550
1528
  name: 'ignoreme',
@@ -1574,7 +1552,7 @@ class QueryQuery extends QueryField {
1574
1552
  let parent = parentStruct;
1575
1553
  let turtleWithFilters = parentStruct.applyStructFiltersToTurtleDef(fieldDef);
1576
1554
  const firstStage = turtleWithFilters.pipeline[0];
1577
- const sourceDef = parentStruct.fieldDef;
1555
+ const sourceDef = parentStruct.structDef;
1578
1556
  // if we are generating code
1579
1557
  // and have extended declaration, we need to make a new QueryStruct
1580
1558
  // copy the definitions into a new structdef
@@ -1597,7 +1575,8 @@ class QueryQuery extends QueryField {
1597
1575
  ],
1598
1576
  };
1599
1577
  }
1600
- if (sourceDef.queryTimezone &&
1578
+ if ((0, malloy_types_1.isSourceDef)(sourceDef) &&
1579
+ sourceDef.queryTimezone &&
1601
1580
  (0, malloy_types_1.isQuerySegment)(firstStage) &&
1602
1581
  firstStage.queryTimezone === undefined) {
1603
1582
  firstStage.queryTimezone = sourceDef.queryTimezone;
@@ -1616,8 +1595,7 @@ class QueryQuery extends QueryField {
1616
1595
  }
1617
1596
  }
1618
1597
  inNestedPipeline() {
1619
- return (this.parent.fieldDef.structSource.type === 'sql' &&
1620
- this.parent.fieldDef.structSource.method === 'nested');
1598
+ return this.parent.structDef.type === 'nest_source';
1621
1599
  }
1622
1600
  // get a field ref and expand it.
1623
1601
  expandField(f) {
@@ -1820,11 +1798,14 @@ class QueryQuery extends QueryField {
1820
1798
  getResultMetadata(fi) {
1821
1799
  if (fi instanceof FieldInstanceField) {
1822
1800
  if (fi.fieldUsage.type === 'result') {
1801
+ // const fieldDef = fi.f.fieldDef as AtomicField;
1823
1802
  const fieldDef = fi.f.fieldDef;
1824
1803
  let filterList;
1825
1804
  const sourceField = fi.f.parent.getFullOutputName() +
1826
1805
  (fieldDef.name || fieldDef.as || 'undefined');
1827
- const sourceExpression = fieldDef.code;
1806
+ const sourceExpression = (0, malloy_types_1.hasExpression)(fieldDef)
1807
+ ? fieldDef.code
1808
+ : undefined;
1828
1809
  const sourceClasses = [sourceField];
1829
1810
  const referenceId = fi.f.referenceId;
1830
1811
  const base = {
@@ -1887,24 +1868,34 @@ class QueryQuery extends QueryField {
1887
1868
  const resultMetadata = this.getResultMetadata(fi);
1888
1869
  if (fi instanceof FieldInstanceResult) {
1889
1870
  const { structDef } = this.generateTurtlePipelineSQL(fi, new StageWriter(true, undefined), '<nosource>');
1890
- // LTNOTE: This is probably broken now. Need to look at the last stage
1891
- // to figure out the resulting nested/inline state...
1892
- const resultType = fi.getRepeatedResultType() === 'nested' ? 'nested' : 'inline';
1893
- structDef.name = name;
1894
- structDef.structRelationship = {
1895
- fieldName: name,
1896
- type: resultType,
1897
- isArray: false,
1898
- };
1899
- structDef.structSource = { type: resultType };
1900
- structDef.resultMetadata = resultMetadata;
1901
- fields.push(structDef);
1871
+ if (fi.getRepeatedResultType() === 'nested') {
1872
+ const multiLineNest = {
1873
+ ...structDef,
1874
+ type: 'array',
1875
+ elementTypeDef: { type: 'record_element' },
1876
+ join: 'many',
1877
+ name,
1878
+ resultMetadata,
1879
+ };
1880
+ fields.push(multiLineNest);
1881
+ }
1882
+ else {
1883
+ const oneLineNest = {
1884
+ ...structDef,
1885
+ type: 'record',
1886
+ join: 'one',
1887
+ name,
1888
+ resultMetadata,
1889
+ };
1890
+ fields.push(oneLineNest);
1891
+ }
1902
1892
  }
1903
1893
  else if (fi instanceof FieldInstanceField) {
1904
1894
  if (fi.fieldUsage.type === 'result') {
1905
- if (fi.f instanceof QueryFieldStruct) {
1906
- fields.push(fi.f.getAsJoinedStructDef(name));
1907
- }
1895
+ // mtoy todo -- remember why you commented this out
1896
+ // if (fi.f instanceof QueryFieldStruct) {
1897
+ // fields.push(fi.f.getAsJoinedStructDef(name));
1898
+ // }
1908
1899
  // if there is only one dimension, it is the primaryKey
1909
1900
  // if there are more, primaryKey is undefined.
1910
1901
  if (isScalarField(fi.f)) {
@@ -1931,6 +1922,7 @@ class QueryQuery extends QueryField {
1931
1922
  annotation,
1932
1923
  });
1933
1924
  break;
1925
+ case 'date':
1934
1926
  case 'timestamp': {
1935
1927
  const timeframe = fi.f.fieldDef.timeframe;
1936
1928
  if (timeframe) {
@@ -1954,17 +1946,6 @@ class QueryQuery extends QueryField {
1954
1946
  }
1955
1947
  break;
1956
1948
  }
1957
- case 'date': {
1958
- fields.push({
1959
- name,
1960
- type: fi.f.fieldDef.type,
1961
- timeframe: fi.f.fieldDef.timeframe,
1962
- resultMetadata,
1963
- location,
1964
- annotation,
1965
- });
1966
- break;
1967
- }
1968
1949
  case 'number':
1969
1950
  fields.push({
1970
1951
  name,
@@ -1985,21 +1966,17 @@ class QueryQuery extends QueryField {
1985
1966
  }
1986
1967
  }
1987
1968
  const outputStruct = {
1988
- fields,
1969
+ type: 'query_result',
1989
1970
  name: this.resultStage || 'result',
1990
- dialect: this.parent.dialect.name,
1971
+ fields,
1972
+ dialect: this.parent.structDef.dialect,
1991
1973
  primaryKey,
1992
- structRelationship: {
1993
- type: 'basetable',
1994
- connectionName: this.parent.connectionName,
1995
- },
1996
- structSource: { type: 'query_result' },
1974
+ connection: this.parent.connectionName,
1997
1975
  resultMetadata: this.getResultMetadata(this.rootResult),
1998
- type: 'struct',
1999
1976
  queryTimezone: resultStruct.getQueryInfo().queryTimezone,
2000
1977
  };
2001
- if (this.parent.fieldDef.modelAnnotation) {
2002
- outputStruct.modelAnnotation = this.parent.fieldDef.modelAnnotation;
1978
+ if (this.parent.structDef.modelAnnotation) {
1979
+ outputStruct.modelAnnotation = this.parent.structDef.modelAnnotation;
2003
1980
  }
2004
1981
  return outputStruct;
2005
1982
  }
@@ -2007,14 +1984,12 @@ class QueryQuery extends QueryField {
2007
1984
  var _a;
2008
1985
  let s = '';
2009
1986
  const qs = ji.queryStruct;
2010
- (_a = qs.eventStream) === null || _a === void 0 ? void 0 : _a.emit('join-used', {
2011
- name: qs.fieldDef.as,
2012
- });
1987
+ const qsDef = qs.structDef;
1988
+ (_a = qs.eventStream) === null || _a === void 0 ? void 0 : _a.emit('join-used', { name: (0, malloy_types_1.getIdentifier)(qsDef) });
2013
1989
  qs.maybeEmitParameterizedSourceUsage();
2014
- const structRelationship = qs.fieldDef.structRelationship;
2015
- let structSQL = qs.structSourceSQL(stageWriter);
2016
- if ((0, malloy_types_1.isJoinOn)(structRelationship)) {
2017
- const matrixOperation = structRelationship.matrixOperation.toUpperCase();
1990
+ if ((0, malloy_types_1.isJoinedSource)(qsDef)) {
1991
+ let structSQL = qs.structSourceSQL(stageWriter);
1992
+ const matrixOperation = (qsDef.matrixOperation || 'left').toUpperCase();
2018
1993
  if (ji.makeUniqueKey) {
2019
1994
  const passKeys = this.generateSQLPassthroughKeys(qs);
2020
1995
  structSQL = `(SELECT ${qs.dialect.sqlGenerateUUID()} as ${qs.dialect.sqlMaybeQuoteIdentifier('__distinct_key')}, x.* ${passKeys} FROM ${structSQL} as x)`;
@@ -2023,11 +1998,11 @@ class QueryQuery extends QueryField {
2023
1998
  if (qs.parent === undefined) {
2024
1999
  throw new Error('Expected joined struct to have a parent.');
2025
2000
  }
2026
- if (structRelationship.onExpression) {
2001
+ if (qsDef.onExpression) {
2027
2002
  onCondition = new QueryFieldBoolean({
2028
2003
  type: 'boolean',
2029
2004
  name: 'ignoreme',
2030
- e: structRelationship.onExpression,
2005
+ e: qsDef.onExpression,
2031
2006
  }, qs.parent).generateExpression(this.rootResult);
2032
2007
  }
2033
2008
  else {
@@ -2064,28 +2039,27 @@ class QueryQuery extends QueryField {
2064
2039
  let joins = '';
2065
2040
  for (const childJoin of ji.children) {
2066
2041
  joins += this.generateSQLJoinBlock(stageWriter, childJoin);
2067
- select += `, ${this.parent.dialect.sqlSelectAliasAsStruct(childJoin.alias, getDialectFieldList(childJoin.queryStruct.fieldDef))} AS ${childJoin.alias}`;
2042
+ select += `, ${this.parent.dialect.sqlSelectAliasAsStruct(childJoin.alias, getDialectFieldList(childJoin.queryStruct.structDef))} AS ${childJoin.alias}`;
2068
2043
  }
2069
2044
  select += `\nFROM ${structSQL} AS ${ji.alias}\n${joins}\nWHERE ${conditions === null || conditions === void 0 ? void 0 : conditions.join(' AND ')}\n`;
2070
2045
  s += `${matrixOperation} JOIN (\n${(0, utils_1.indent)(select)}) AS ${ji.alias}\n ON ${onCondition}\n`;
2071
2046
  return s;
2072
2047
  }
2073
2048
  }
2074
- else if (structRelationship.type === 'nested') {
2049
+ else if (qsDef.type === 'array') {
2075
2050
  if (qs.parent === undefined || ji.parent === undefined) {
2076
2051
  throw new Error('Internal Error, nested structure with no parent.');
2077
2052
  }
2078
- const fieldExpression = this.parent.dialect.sqlFieldReference(qs.parent.getSQLIdentifier(), structRelationship.fieldName, 'struct', qs.parent.fieldDef.structRelationship.type === 'nested', this.parent.fieldDef.structRelationship.type === 'nested' &&
2079
- this.parent.fieldDef.structRelationship.isArray);
2053
+ const fieldExpression = this.parent.dialect.sqlFieldReference(qs.parent.getSQLIdentifier(), qsDef.name, 'struct', qs.parent.structDef.type === 'array', (0, malloy_types_1.isScalarArray)(this.parent.structDef));
2080
2054
  // we need to generate primary key. If parent has a primary key combine
2081
2055
  // console.log(ji.alias, fieldExpression, this.inNestedPipeline());
2082
- s += `${this.parent.dialect.sqlUnnestAlias(fieldExpression, ji.alias, ji.getDialectFieldList(), ji.makeUniqueKey, structRelationship.isArray, this.inNestedPipeline())}\n`;
2056
+ s += `${this.parent.dialect.sqlUnnestAlias(fieldExpression, ji.alias, ji.getDialectFieldList(), ji.makeUniqueKey, (0, malloy_types_1.isScalarArray)(qsDef), this.inNestedPipeline())}\n`;
2083
2057
  }
2084
- else if (structRelationship.type === 'inline') {
2085
- throw new Error('Internal Error: inline structs should never appear in join trees');
2058
+ else if (qsDef.type === 'record') {
2059
+ throw new Error('Internal Error: records should never appear in join trees');
2086
2060
  }
2087
2061
  else {
2088
- throw new Error(`Join type not implemented ${JSON.stringify(qs.fieldDef.structRelationship)}`);
2062
+ throw new Error(`Join type not implemented ${qs.structDef.type}`);
2089
2063
  }
2090
2064
  for (const childJoin of ji.children) {
2091
2065
  s += this.generateSQLJoinBlock(stageWriter, childJoin);
@@ -2124,8 +2098,7 @@ class QueryQuery extends QueryField {
2124
2098
  structSQL = stageWriter.addStage(`SELECT * from ${structSQL} as x limit 100000 `);
2125
2099
  }
2126
2100
  }
2127
- const structRelationship = qs.fieldDef.structRelationship;
2128
- if (structRelationship.type === 'basetable') {
2101
+ if ((0, malloy_types_1.isBaseTable)(qs.structDef)) {
2129
2102
  if (ji.makeUniqueKey) {
2130
2103
  const passKeys = this.generateSQLPassthroughKeys(qs);
2131
2104
  structSQL = `(SELECT ${qs.dialect.sqlGenerateUUID()} as ${qs.dialect.sqlMaybeQuoteIdentifier('__distinct_key')}, x.* ${passKeys} FROM ${structSQL} as x)`;
@@ -2460,7 +2433,7 @@ class QueryQuery extends QueryField {
2460
2433
  for (const m of output.groupsAggregated) {
2461
2434
  output.sql[0] += `WHEN group_set=${m.fromGroup} THEN ${m.toGroup} `;
2462
2435
  }
2463
- output.sql[0] += ' ELSE group_set END as group_set';
2436
+ output.sql[0] += 'ELSE group_set END as group_set';
2464
2437
  }
2465
2438
  }
2466
2439
  generateSQLDepthN(depth, stageWriter, stageName) {
@@ -2658,11 +2631,15 @@ class QueryQuery extends QueryField {
2658
2631
  name: 'starthere',
2659
2632
  pipeline,
2660
2633
  };
2661
- structDef.name = this.parent.dialect.sqlUnnestPipelineHead(repeatedResultType === 'inline_all_numbers', sourceSQLExpression);
2662
- structDef.structSource = { type: 'sql', method: 'nested' };
2663
- const qs = new QueryStruct(structDef, undefined, {
2664
- model: this.parent.getModel(),
2665
- }, this.parent.prepareResultOptions);
2634
+ const inputStruct = {
2635
+ type: 'nest_source',
2636
+ name: '~pipe~',
2637
+ pipeSQL: this.parent.dialect.sqlUnnestPipelineHead(repeatedResultType === 'inline_all_numbers', sourceSQLExpression),
2638
+ fields: structDef.fields,
2639
+ connection: structDef.connection,
2640
+ dialect: structDef.dialect,
2641
+ };
2642
+ const qs = new QueryStruct(inputStruct, undefined, { model: this.parent.getModel() }, this.parent.prepareResultOptions);
2666
2643
  const q = QueryQuery.makeQuery(newTurtle, qs, stageWriter, this.isJoinedSubquery);
2667
2644
  pipeOut = q.generateSQLFromPipeline(stageWriter);
2668
2645
  // console.log(stageWriter.generateSQLStages());
@@ -2700,11 +2677,6 @@ class QueryQuery extends QueryField {
2700
2677
  return this.generateSimpleSQL(stageWriter);
2701
2678
  }
2702
2679
  }
2703
- toMalloy() {
2704
- let ret = `EXPLORE ${(0, malloy_types_1.getIdentifier)(this.parent.fieldDef)} | `;
2705
- ret += this.fieldDef.type.toUpperCase() + ' ';
2706
- return ret;
2707
- }
2708
2680
  generateSQLFromPipeline(stageWriter) {
2709
2681
  this.parent.maybeEmitParameterizedSourceUsage();
2710
2682
  this.prepare(stageWriter);
@@ -2715,20 +2687,20 @@ class QueryQuery extends QueryField {
2715
2687
  const pipeline = [...this.fieldDef.pipeline];
2716
2688
  let structDef = {
2717
2689
  ...outputStruct,
2718
- structSource: { type: 'sql', method: 'lastStage' },
2690
+ type: 'finalize',
2719
2691
  };
2720
2692
  pipeline.shift();
2721
2693
  for (const transform of pipeline) {
2722
2694
  const s = new QueryStruct(structDef, undefined, {
2723
2695
  model: this.parent.getModel(),
2724
2696
  }, this.parent.prepareResultOptions);
2725
- const q = QueryQuery.makeQuery({ type: 'turtle', name: 'ignoreme', pipeline: [transform] }, s, stageWriter, this.isJoinedSubquery);
2697
+ const q = QueryQuery.makeQuery({ type: 'turtle', name: '~computeLastStage~', pipeline: [transform] }, s, stageWriter, this.isJoinedSubquery);
2726
2698
  q.prepare(stageWriter);
2727
2699
  lastStageName = q.generateSQL(stageWriter);
2728
2700
  outputStruct = q.getResultStructDef();
2729
2701
  structDef = {
2730
2702
  ...outputStruct,
2731
- structSource: { type: 'sql', method: 'lastStage' },
2703
+ type: 'finalize',
2732
2704
  };
2733
2705
  }
2734
2706
  }
@@ -2869,18 +2841,19 @@ FROM ${resultStage}\n`);
2869
2841
  }
2870
2842
  class QueryQueryRaw extends QueryQuery {
2871
2843
  generateSQL(stageWriter) {
2872
- const ssrc = this.parent.fieldDef.structSource;
2873
- if (ssrc.type !== 'sql' || ssrc.method !== 'subquery') {
2844
+ if (this.parent.structDef.type !== 'sql_select') {
2874
2845
  throw new Error('Invalid struct for QueryQueryRaw, currently only supports SQL');
2875
2846
  }
2876
- const s = ssrc.sqlBlock.selectStr;
2877
- return stageWriter.addStage(s);
2847
+ return stageWriter.addStage(this.parent.structDef.selectStr);
2878
2848
  }
2879
2849
  prepare() {
2880
2850
  // Do nothing!
2881
2851
  }
2882
2852
  getResultStructDef() {
2883
- return this.parent.fieldDef;
2853
+ if (!(0, malloy_types_1.isSourceDef)(this.parent.structDef)) {
2854
+ throw new Error(`Result cannot by type ${this.parent.structDef.type}`);
2855
+ }
2856
+ return this.parent.structDef;
2884
2857
  }
2885
2858
  getResultMetadata(_fi) {
2886
2859
  return undefined;
@@ -2909,9 +2882,9 @@ class QueryQueryIndex extends QueryQuery {
2909
2882
  if (stage === undefined) {
2910
2883
  const f = this.parent.nameMap.get(fref.path[0]);
2911
2884
  if (f instanceof QueryStruct &&
2912
- (f.fieldDef.structRelationship.type === 'many' ||
2913
- f.fieldDef.structRelationship.type === 'nested') &&
2914
- f.fieldDef.fields.length > 1) {
2885
+ (0, malloy_types_1.isJoined)(f.structDef) &&
2886
+ f.structDef.join === 'many' &&
2887
+ f.structDef.fields.length > 1) {
2915
2888
  const toStage = [fref];
2916
2889
  stageMap[stageRoot] = toStage;
2917
2890
  this.stages.push(toStage);
@@ -2962,9 +2935,9 @@ class QueryQueryIndex extends QueryQuery {
2962
2935
  */
2963
2936
  getResultStructDef() {
2964
2937
  const ret = {
2965
- type: 'struct',
2938
+ type: 'query_result',
2966
2939
  name: this.resultStage || 'result',
2967
- dialect: this.parent.fieldDef.dialect,
2940
+ dialect: this.parent.structDef.dialect,
2968
2941
  fields: [
2969
2942
  { type: 'string', name: 'fieldName' },
2970
2943
  { type: 'string', name: 'fieldPath' },
@@ -2972,33 +2945,37 @@ class QueryQueryIndex extends QueryQuery {
2972
2945
  { type: 'string', name: 'fieldType' },
2973
2946
  { type: 'number', name: 'weight', numberType: 'integer' },
2974
2947
  ],
2975
- structRelationship: {
2976
- type: 'basetable',
2977
- connectionName: this.parent.connectionName,
2978
- },
2979
- structSource: { type: 'query_result' },
2948
+ connection: this.parent.connectionName,
2980
2949
  };
2981
- if (this.parent.fieldDef.modelAnnotation) {
2982
- ret.modelAnnotation = this.parent.fieldDef.modelAnnotation;
2950
+ if (this.parent.structDef.modelAnnotation) {
2951
+ ret.modelAnnotation = this.parent.structDef.modelAnnotation;
2983
2952
  }
2984
2953
  return ret;
2985
2954
  }
2986
2955
  }
2987
2956
  /** Structure object as it is used to build a query */
2957
+ /*
2958
+ Sometimes this is built from a field def, as in a join
2959
+
2960
+ But sometimes this is built as the intermediate stage between pipelines
2961
+ and in that case it doesn't have a fieldDef which bugs me because querynode
2962
+ always has a fielddef so i think that is wrong too
2963
+
2964
+ */
2988
2965
  class QueryStruct extends QueryNode {
2989
- constructor(fieldDef, sourceArguments, parent, prepareResultOptions) {
2990
- super(fieldDef);
2966
+ constructor(structDef, sourceArguments, parent, prepareResultOptions, referenceId) {
2967
+ super(referenceId);
2968
+ this.structDef = structDef;
2991
2969
  this.sourceArguments = sourceArguments;
2992
2970
  this.prepareResultOptions = prepareResultOptions;
2993
2971
  this.nameMap = new Map();
2994
2972
  this._arguments = undefined;
2995
- this.stacki = new Error('').stack;
2996
2973
  this.setParent(parent);
2997
2974
  if ('model' in parent) {
2998
2975
  this.model = parent.model;
2999
2976
  this.pathAliasMap = new Map();
3000
- if (fieldDef.structRelationship.type === 'basetable') {
3001
- this.connectionName = fieldDef.structRelationship.connectionName;
2977
+ if ((0, malloy_types_1.isSourceDef)(structDef)) {
2978
+ this.connectionName = structDef.connection;
3002
2979
  }
3003
2980
  else {
3004
2981
  throw new Error('All root StructDefs should be a baseTable');
@@ -3009,22 +2986,22 @@ class QueryStruct extends QueryNode {
3009
2986
  this.pathAliasMap = this.root().pathAliasMap;
3010
2987
  this.connectionName = this.root().connectionName;
3011
2988
  }
3012
- this.fieldDef = fieldDef; // shouldn't have to do this, but
3013
- // type script is missing a beat here.
3014
- this.dialect = (0, dialect_1.getDialect)(this.fieldDef.dialect);
3015
- this.addFieldsFromFieldList(this.fieldDef.fields);
2989
+ this.dialect = (0, dialect_1.getDialect)(structDef.dialect);
2990
+ this.addFieldsFromFieldList(structDef.fields);
3016
2991
  }
3017
2992
  maybeEmitParameterizedSourceUsage() {
3018
2993
  var _a;
3019
- const paramsAndArgs = {
3020
- ...this.fieldDef.parameters,
3021
- ...this.fieldDef.arguments,
3022
- };
3023
- if (Object.values(paramsAndArgs).length === 0)
3024
- return;
3025
- (_a = this.eventStream) === null || _a === void 0 ? void 0 : _a.emit('parameterized-source-compiled', {
3026
- parameters: paramsAndArgs,
3027
- });
2994
+ if ((0, malloy_types_1.isSourceDef)(this.structDef)) {
2995
+ const paramsAndArgs = {
2996
+ ...this.structDef.parameters,
2997
+ ...this.structDef.arguments,
2998
+ };
2999
+ if (Object.values(paramsAndArgs).length === 0)
3000
+ return;
3001
+ (_a = this.eventStream) === null || _a === void 0 ? void 0 : _a.emit('parameterized-source-compiled', {
3002
+ parameters: paramsAndArgs,
3003
+ });
3004
+ }
3028
3005
  }
3029
3006
  resolveParentParameterReferences(param) {
3030
3007
  return {
@@ -3055,39 +3032,33 @@ class QueryStruct extends QueryNode {
3055
3032
  return this._arguments;
3056
3033
  }
3057
3034
  this._arguments = {};
3058
- // First, copy over all parameters, to get default values
3059
- const params = (_a = this.fieldDef.parameters) !== null && _a !== void 0 ? _a : {};
3060
- for (const parameterName in params) {
3061
- this._arguments[parameterName] = params[parameterName];
3062
- }
3063
- // Then, copy over arguments to override default values
3064
- const args = { ...this.fieldDef.arguments, ...this.sourceArguments };
3065
- for (const parameterName in args) {
3066
- const orig = args[parameterName];
3067
- this._arguments[parameterName] =
3068
- this.resolveParentParameterReferences(orig);
3035
+ if ((0, malloy_types_1.isSourceDef)(this.structDef)) {
3036
+ // First, copy over all parameters, to get default values
3037
+ const params = (_a = this.structDef.parameters) !== null && _a !== void 0 ? _a : {};
3038
+ for (const parameterName in params) {
3039
+ this._arguments[parameterName] = params[parameterName];
3040
+ }
3041
+ // Then, copy over arguments to override default values
3042
+ const args = { ...this.structDef.arguments, ...this.sourceArguments };
3043
+ for (const parameterName in args) {
3044
+ const orig = args[parameterName];
3045
+ this._arguments[parameterName] =
3046
+ this.resolveParentParameterReferences(orig);
3047
+ }
3069
3048
  }
3070
3049
  return this._arguments;
3071
3050
  }
3072
3051
  addFieldsFromFieldList(fields) {
3073
3052
  for (const field of fields) {
3074
3053
  const as = (0, malloy_types_1.getIdentifier)(field);
3075
- switch (field.type) {
3076
- case 'struct': {
3077
- this.addFieldToNameMap(as, new QueryStruct(field, undefined, {
3078
- struct: this,
3079
- }, this.prepareResultOptions));
3080
- break;
3081
- }
3082
- // case "reduce" || "project" || "index": {
3083
- case 'turtle': {
3084
- // not sure why we need to cast here...
3085
- this.addFieldToNameMap(as, QueryQuery.makeQuery(field, this, undefined, false));
3086
- break;
3087
- }
3088
- default: {
3089
- this.addFieldToNameMap(as, this.makeQueryField(field));
3090
- }
3054
+ if ((0, malloy_types_1.isJoined)(field)) {
3055
+ this.addFieldToNameMap(as, new QueryStruct(field, undefined, { struct: this }, this.prepareResultOptions));
3056
+ }
3057
+ else if (field.type === 'turtle') {
3058
+ this.addFieldToNameMap(as, QueryQuery.makeQuery(field, this, undefined, false));
3059
+ }
3060
+ else {
3061
+ this.addFieldToNameMap(as, this.makeQueryField(field));
3091
3062
  }
3092
3063
  }
3093
3064
  // if we don't have distinct key yet for this struct, add it.
@@ -3104,7 +3075,7 @@ class QueryStruct extends QueryNode {
3104
3075
  // make a unique alias name
3105
3076
  if (ret === undefined) {
3106
3077
  const aliases = Array.from(this.pathAliasMap.values());
3107
- const base = identifierNormalize((0, malloy_types_1.getIdentifier)(this.fieldDef));
3078
+ const base = identifierNormalize((0, malloy_types_1.getIdentifier)(this.structDef));
3108
3079
  let name = `${base}_0`;
3109
3080
  let n = 1;
3110
3081
  while (aliases.includes(name) && n < 1000) {
@@ -3129,7 +3100,7 @@ class QueryStruct extends QueryNode {
3129
3100
  if (this.unnestWithNumbers() && this.parent !== undefined) {
3130
3101
  const x = this.parent.getSQLIdentifier() +
3131
3102
  '.' +
3132
- (0, malloy_types_1.getIdentifier)(this.fieldDef) +
3103
+ (0, malloy_types_1.getIdentifier)(this.structDef) +
3133
3104
  `[${this.getIdentifier()}.__row_id]`;
3134
3105
  return x;
3135
3106
  }
@@ -3140,12 +3111,12 @@ class QueryStruct extends QueryNode {
3140
3111
  // return the name of the field in SQL
3141
3112
  getIdentifier() {
3142
3113
  // if it is the root table, use provided alias if we have one.
3143
- if (this.fieldDef.structRelationship.type === 'basetable') {
3114
+ if ((0, malloy_types_1.isBaseTable)(this.structDef)) {
3144
3115
  return 'base';
3145
3116
  }
3146
3117
  // if this is an inline object, include the parents alias.
3147
- if (this.fieldDef.structRelationship.type === 'inline' && this.parent) {
3148
- return this.parent.getSQLIdentifier() + '.' + super.getIdentifier();
3118
+ if (this.structDef.type === 'record' && this.parent) {
3119
+ return (this.parent.getSQLIdentifier() + '.' + (0, malloy_types_1.getIdentifier)(this.structDef));
3149
3120
  }
3150
3121
  // we are somewhere in the join tree. Make sure the alias is unique.
3151
3122
  return this.getAliasIdentifier();
@@ -3153,7 +3124,7 @@ class QueryStruct extends QueryNode {
3153
3124
  // return the name of the field in Malloy
3154
3125
  getFullOutputName() {
3155
3126
  if (this.parent) {
3156
- return (this.parent.getFullOutputName() + (0, malloy_types_1.getIdentifier)(this.fieldDef) + '.');
3127
+ return (this.parent.getFullOutputName() + (0, malloy_types_1.getIdentifier)(this.structDef) + '.');
3157
3128
  }
3158
3129
  else {
3159
3130
  return '';
@@ -3168,12 +3139,11 @@ class QueryStruct extends QueryNode {
3168
3139
  throw new Error(`Join ${joinName} not found in result set`);
3169
3140
  }
3170
3141
  unnestWithNumbers() {
3171
- return (this.dialect.unnestWithNumbers &&
3172
- this.fieldDef.structRelationship.type === 'nested');
3142
+ return this.dialect.unnestWithNumbers && this.structDef.type === 'array';
3173
3143
  }
3174
3144
  getJoinableParent() {
3175
3145
  // if it is inline it should always have a parent
3176
- if (this.fieldDef.structRelationship.type === 'inline') {
3146
+ if (this.structDef.type === 'record') {
3177
3147
  if (this.parent) {
3178
3148
  return this.parent.getJoinableParent();
3179
3149
  }
@@ -3205,25 +3175,25 @@ class QueryStruct extends QueryNode {
3205
3175
  * they exist) to the structure.
3206
3176
  */
3207
3177
  resolveQueryFields() {
3208
- if (this.fieldDef.structSource.type === 'query') {
3209
- const structDef = this.model
3210
- .loadQuery(this.fieldDef.structSource.query, undefined, this.prepareResultOptions)
3178
+ if (this.structDef.type === 'query_source') {
3179
+ const resultStruct = this.model
3180
+ .loadQuery(this.structDef.query, undefined, this.prepareResultOptions)
3211
3181
  .structs.pop();
3212
3182
  // should never happen.
3213
- if (!structDef) {
3183
+ if (!resultStruct) {
3214
3184
  throw new Error("Internal Error, query didn't produce a struct");
3215
3185
  }
3216
- const fieldDef = { ...this.fieldDef };
3217
- for (const f of structDef.fields) {
3218
- let as;
3219
- if (!this.nameMap.has((as = (0, malloy_types_1.getIdentifier)(f)))) {
3220
- fieldDef.fields.push(f);
3186
+ const structDef = { ...this.structDef };
3187
+ for (const f of resultStruct.fields) {
3188
+ const as = (0, malloy_types_1.getIdentifier)(f);
3189
+ if (!this.nameMap.has(as)) {
3190
+ structDef.fields.push(f);
3221
3191
  this.nameMap.set(as, this.makeQueryField(f));
3222
3192
  }
3223
3193
  }
3224
- this.fieldDef = fieldDef;
3225
- if (!this.fieldDef.primaryKey && structDef.primaryKey) {
3226
- this.fieldDef.primaryKey = structDef.primaryKey;
3194
+ this.structDef = structDef;
3195
+ if (!this.structDef.primaryKey && resultStruct.primaryKey) {
3196
+ this.structDef.primaryKey = resultStruct.primaryKey;
3227
3197
  }
3228
3198
  }
3229
3199
  for (const [, v] of this.nameMap) {
@@ -3285,53 +3255,37 @@ class QueryStruct extends QueryNode {
3285
3255
  }
3286
3256
  structSourceSQL(stageWriter) {
3287
3257
  var _a, _b;
3288
- switch (this.fieldDef.structSource.type) {
3289
- case 'table': {
3290
- const tablePath = this.fieldDef.structSource.tablePath;
3291
- return this.dialect.quoteTablePath(tablePath);
3292
- }
3293
- case 'sql':
3294
- if (this.fieldDef.structSource.method === 'nested' ||
3295
- this.fieldDef.structSource.method === 'lastStage') {
3296
- return this.fieldDef.name;
3297
- }
3298
- else if (this.fieldDef.structSource.method === 'subquery') {
3299
- return `(${this.fieldDef.structSource.sqlBlock.selectStr})`;
3300
- }
3301
- throw new Error("Internal Error: Unknown structSource type 'sql' method");
3302
- case 'nested':
3303
- // 'name' is always the source field even if has been renamed through
3304
- // 'as'
3305
- return 'UNNEST(this.fieldDef.name)';
3306
- case 'inline':
3307
- return '';
3308
- case 'query': {
3258
+ switch (this.structDef.type) {
3259
+ case 'table':
3260
+ return this.dialect.quoteTablePath(this.structDef.tablePath);
3261
+ case 'finalize':
3262
+ return this.structDef.name;
3263
+ case 'sql_select':
3264
+ return `(${this.structDef.selectStr})`;
3265
+ case 'nest_source':
3266
+ return this.structDef.pipeSQL;
3267
+ case 'query_source': {
3309
3268
  // cache derived table.
3310
3269
  if (((_a = this.prepareResultOptions) === null || _a === void 0 ? void 0 : _a.replaceMaterializedReferences) &&
3311
- (0, utils_2.shouldMaterialize)(this.fieldDef.structSource.query.annotation)) {
3312
- return stageWriter.addMaterializedQuery((0, malloy_types_1.getIdentifier)(this.fieldDef), this.fieldDef.structSource.query, (_b = this.prepareResultOptions) === null || _b === void 0 ? void 0 : _b.materializedTablePrefix);
3270
+ (0, utils_2.shouldMaterialize)(this.structDef.query.annotation)) {
3271
+ return stageWriter.addMaterializedQuery((0, malloy_types_1.getIdentifier)(this.structDef), this.structDef.query, (_b = this.prepareResultOptions) === null || _b === void 0 ? void 0 : _b.materializedTablePrefix);
3313
3272
  }
3314
3273
  else {
3315
3274
  // returns the stage name.
3316
- return this.model.loadQuery(this.fieldDef.structSource.query, stageWriter, this.prepareResultOptions, false, true // this is an intermediate stage.
3275
+ return this.model.loadQuery(this.structDef.query, stageWriter, this.prepareResultOptions, false, true // this is an intermediate stage.
3317
3276
  ).lastStageName;
3318
3277
  }
3319
3278
  }
3320
3279
  default:
3321
- throw new Error(`unknown structSource ${this.fieldDef}`);
3280
+ throw new Error(`Cannot create SQL StageWriter from '${(0, malloy_types_1.getIdentifier)(this.structDef)}' type '${this.structDef.type}`);
3322
3281
  }
3323
3282
  }
3324
3283
  root() {
3325
- if (this.parent === undefined) {
3326
- return this;
3327
- }
3328
- else {
3329
- return this.parent.root();
3330
- }
3284
+ return this.parent ? this.parent.root() : this;
3331
3285
  }
3332
3286
  primaryKey() {
3333
- if (this.fieldDef.primaryKey) {
3334
- return this.getDimensionByName([this.fieldDef.primaryKey]);
3287
+ if ((0, malloy_types_1.isSourceDef)(this.structDef) && this.structDef.primaryKey) {
3288
+ return this.getDimensionByName([this.structDef.primaryKey]);
3335
3289
  }
3336
3290
  else {
3337
3291
  return undefined;
@@ -3356,25 +3310,26 @@ class QueryStruct extends QueryNode {
3356
3310
  getQueryFieldByName(name) {
3357
3311
  const field = this.getFieldByName(name);
3358
3312
  if (field instanceof QueryStruct) {
3359
- throw new Error(`Cannot reference ${name} as a scalar'`);
3313
+ throw new Error(`Cannot reference ${name.join('.')} as a scalar'`);
3360
3314
  }
3361
3315
  return field;
3362
3316
  }
3363
- getQueryFieldReference(name, refAnnoatation) {
3364
- const field = this.getQueryFieldByName(name);
3365
- if (refAnnoatation) {
3366
- // Made the field object from the source, but the annotations were computed by the compiler
3367
- // and have none of the source and reference annotations included, use those.
3317
+ getQueryFieldReference(name, annotation) {
3318
+ const field = this.getFieldByName(name);
3319
+ if (annotation) {
3368
3320
  if (field.parent === undefined) {
3369
- throw new Error('Expected field to have a parent');
3321
+ throw new Error('Unexpected reference to orphaned query field');
3322
+ }
3323
+ // Made a field object from the source, but the annotations were computed by the compiler
3324
+ // when it generated the reference, and has both the source and reference annotations included.
3325
+ if (field instanceof QueryStruct) {
3326
+ const newDef = { ...field.structDef, annotation };
3327
+ return new QueryStruct(newDef, undefined, field.parent, {}, field.referenceId);
3370
3328
  }
3371
- if (!(field instanceof QueryField)) {
3372
- throw new Error('Expected fieldref to reference a QueryField');
3329
+ else {
3330
+ const newDef = { ...field.fieldDef, annotation };
3331
+ return field.parent.makeQueryField(newDef, field.referenceId);
3373
3332
  }
3374
- return field.parent.makeQueryField({
3375
- ...field.fieldDef,
3376
- annotation: refAnnoatation,
3377
- }, field.referenceId);
3378
3333
  }
3379
3334
  return field;
3380
3335
  }
@@ -3383,9 +3338,7 @@ class QueryStruct extends QueryNode {
3383
3338
  if (query instanceof QueryAtomicField) {
3384
3339
  return query;
3385
3340
  }
3386
- else {
3387
- throw new Error(`${name} is not of type a scalar'`);
3388
- }
3341
+ throw new Error(`${name} is not an atomic field? Inconceivable!`);
3389
3342
  }
3390
3343
  /** returns a query object for the given name */
3391
3344
  getDimensionByName(name) {
@@ -3393,9 +3346,7 @@ class QueryStruct extends QueryNode {
3393
3346
  if (query instanceof QueryAtomicField && isScalarField(query)) {
3394
3347
  return query;
3395
3348
  }
3396
- else {
3397
- throw new Error(`${name} is not of type a scalar'`);
3398
- }
3349
+ throw new Error(`${name} is not an atomic scalar field? Inconceivable!`);
3399
3350
  }
3400
3351
  /** returns a query object for the given name */
3401
3352
  getStructByName(name) {
@@ -3408,14 +3359,14 @@ class QueryStruct extends QueryNode {
3408
3359
  }
3409
3360
  }
3410
3361
  getDistinctKey() {
3411
- if (this.fieldDef.structRelationship.type !== 'inline') {
3362
+ if (this.structDef.type !== 'record') {
3412
3363
  return this.getDimensionByName(['__distinct_key']);
3413
3364
  }
3414
3365
  else if (this.parent) {
3415
3366
  return this.parent.getDistinctKey();
3416
3367
  }
3417
3368
  else {
3418
- throw new Error('Internal Error. inline struct can not be top level');
3369
+ throw new Error('Asking a record for a primary key? Inconceivable!');
3419
3370
  }
3420
3371
  }
3421
3372
  applyStructFiltersToTurtleDef(turtleDef) {
@@ -3423,7 +3374,7 @@ class QueryStruct extends QueryNode {
3423
3374
  const annotation = turtleDef.annotation;
3424
3375
  const addedFilters = turtleDef.filterList || [];
3425
3376
  pipeline = structuredClone(pipeline);
3426
- pipeline[0].filterList = addedFilters.concat(pipeline[0].filterList || [], this.fieldDef.filterList || []);
3377
+ pipeline[0].filterList = addedFilters.concat(pipeline[0].filterList || [], (0, malloy_types_1.isSourceDef)(this.structDef) ? this.structDef.filterList || [] : []);
3427
3378
  const flatTurtleDef = {
3428
3379
  type: 'turtle',
3429
3380
  name: turtleDef.name,
@@ -3452,8 +3403,8 @@ class QueryModel {
3452
3403
  this.modelDef = modelDef;
3453
3404
  for (const s of Object.values(this.modelDef.contents)) {
3454
3405
  let qs;
3455
- if (s.type === 'struct') {
3456
- qs = new QueryStruct(s, undefined, { model: this });
3406
+ if ((0, malloy_types_1.modelObjIsSource)(s)) {
3407
+ qs = new QueryStruct(s, undefined, { model: this }, {});
3457
3408
  this.structs.set((0, malloy_types_1.getIdentifier)(s), qs);
3458
3409
  qs.resolveQueryFields();
3459
3410
  }
@@ -3466,31 +3417,23 @@ class QueryModel {
3466
3417
  }
3467
3418
  }
3468
3419
  getStructByName(name) {
3469
- let s;
3470
- if ((s = this.structs.get(name))) {
3420
+ const s = this.structs.get(name);
3421
+ if (s) {
3471
3422
  return s;
3472
3423
  }
3473
- else {
3474
- throw new Error(`Struct ${name} not found in model.`);
3475
- }
3424
+ throw new Error(`Struct ${name} not found in model.`);
3476
3425
  }
3477
3426
  getStructFromRef(structRef, sourceArguments, prepareResultOptions) {
3478
3427
  var _a;
3479
- let structDef;
3428
+ prepareResultOptions !== null && prepareResultOptions !== void 0 ? prepareResultOptions : (prepareResultOptions = {});
3480
3429
  if (typeof structRef === 'string') {
3481
3430
  const ret = this.getStructByName(structRef);
3482
3431
  if (sourceArguments !== undefined) {
3483
- return new QueryStruct(ret.fieldDef, sourceArguments, (_a = ret.parent) !== null && _a !== void 0 ? _a : { model: this }, prepareResultOptions);
3432
+ return new QueryStruct(ret.structDef, sourceArguments, (_a = ret.parent) !== null && _a !== void 0 ? _a : { model: this }, prepareResultOptions);
3484
3433
  }
3485
3434
  return ret;
3486
3435
  }
3487
- else if (structRef.type === 'struct') {
3488
- structDef = structRef;
3489
- }
3490
- else {
3491
- throw new Error('Broken for now');
3492
- }
3493
- return new QueryStruct(structDef, sourceArguments, { model: this }, prepareResultOptions);
3436
+ return new QueryStruct(structRef, sourceArguments, { model: this }, prepareResultOptions);
3494
3437
  }
3495
3438
  loadQuery(query, stageWriter, prepareResultOptions, emitFinalStage = false, isJoinedSubquery = false) {
3496
3439
  const malloy = '';
@@ -3510,7 +3453,7 @@ class QueryModel {
3510
3453
  // for (const f of ret.outputStruct.fields) {
3511
3454
  // fieldNames.push(getIdentifier(f));
3512
3455
  // }
3513
- const fieldNames = (0, malloy_types_1.getPhysicalFields)(ret.outputStruct).map(fieldDef => q.parent.dialect.sqlMaybeQuoteIdentifier(fieldDef.name));
3456
+ const fieldNames = (0, malloy_types_1.getAtomicFields)(ret.outputStruct).map(fieldDef => q.parent.dialect.sqlMaybeQuoteIdentifier(fieldDef.name));
3514
3457
  ret.lastStageName = stageWriter.addStage(q.parent.dialect.sqlFinalStage(ret.lastStageName, fieldNames));
3515
3458
  }
3516
3459
  return {
@@ -3528,11 +3471,7 @@ class QueryModel {
3528
3471
  const ret = m.loadQuery(query, undefined, prepareResultOptions, finalize, false);
3529
3472
  const sourceExplore = typeof query.structRef === 'string'
3530
3473
  ? query.structRef
3531
- : // LTNOTE: the parser needs to capture the query before the |. This will work
3532
- // in most cases but isn't actually complete.
3533
- query.structRef.type === 'struct'
3534
- ? query.structRef.as || query.structRef.name
3535
- : '(need to figure this out)';
3474
+ : query.structRef.as || query.structRef.name;
3536
3475
  // LTNote: I don't understand why this might be here. It should have happened in loadQuery...
3537
3476
  if (finalize && this.dialect.hasFinalStage) {
3538
3477
  ret.lastStageName = ret.stageWriter.addStage(