@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.
- package/dist/connection/base_connection.d.ts +21 -7
- package/dist/connection/base_connection.js +62 -0
- package/dist/connection/types.d.ts +5 -5
- package/dist/dialect/dialect.d.ts +5 -3
- package/dist/dialect/dialect.js +15 -0
- package/dist/dialect/duckdb/duckdb.d.ts +3 -3
- package/dist/dialect/duckdb/duckdb.js +8 -3
- package/dist/dialect/postgres/postgres.d.ts +3 -3
- package/dist/dialect/postgres/postgres.js +5 -2
- package/dist/dialect/snowflake/snowflake.d.ts +3 -3
- package/dist/dialect/snowflake/snowflake.js +4 -1
- package/dist/dialect/standardsql/standardsql.d.ts +3 -3
- package/dist/dialect/standardsql/standardsql.js +5 -2
- package/dist/dialect/trino/trino.d.ts +3 -3
- package/dist/dialect/trino/trino.js +35 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -2
- package/dist/lang/ast/error-factory.d.ts +4 -3
- package/dist/lang/ast/error-factory.js +27 -17
- package/dist/lang/ast/expressions/constant-expression.d.ts +1 -0
- package/dist/lang/ast/expressions/constant-expression.js +3 -0
- package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +3 -7
- package/dist/lang/ast/expressions/expr-aggregate-function.js +50 -54
- package/dist/lang/ast/expressions/expr-cast.js +2 -4
- package/dist/lang/ast/expressions/expr-func.js +1 -1
- package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
- package/dist/lang/ast/expressions/expr-record-literal.d.ts +16 -0
- package/dist/lang/ast/expressions/expr-record-literal.js +57 -0
- package/dist/lang/ast/expressions/expr-time-extract.js +3 -3
- package/dist/lang/ast/expressions/expr-time.d.ts +3 -3
- package/dist/lang/ast/expressions/expr-time.js +1 -1
- package/dist/lang/ast/expressions/time-literal.d.ts +6 -6
- package/dist/lang/ast/expressions/time-literal.js +1 -1
- package/dist/lang/ast/field-space/column-space-field.d.ts +6 -5
- package/dist/lang/ast/field-space/column-space-field.js +7 -4
- package/dist/lang/ast/field-space/dynamic-space.d.ts +8 -6
- package/dist/lang/ast/field-space/dynamic-space.js +35 -11
- package/dist/lang/ast/field-space/index-field-space.js +6 -3
- package/dist/lang/ast/field-space/ir-view-field.d.ts +1 -0
- package/dist/lang/ast/field-space/ir-view-field.js +3 -1
- package/dist/lang/ast/field-space/join-space-field.d.ts +2 -2
- package/dist/lang/ast/field-space/join-space-field.js +2 -2
- package/dist/lang/ast/field-space/parameter-space.d.ts +1 -0
- package/dist/lang/ast/field-space/parameter-space.js +4 -1
- package/dist/lang/ast/field-space/query-input-space.d.ts +4 -4
- package/dist/lang/ast/field-space/query-input-space.js +3 -5
- package/dist/lang/ast/field-space/query-spaces.d.ts +4 -4
- package/dist/lang/ast/field-space/query-spaces.js +1 -1
- package/dist/lang/ast/field-space/reference-field.js +10 -8
- package/dist/lang/ast/field-space/refined-space.d.ts +2 -2
- package/dist/lang/ast/field-space/static-space.d.ts +14 -5
- package/dist/lang/ast/field-space/static-space.js +45 -20
- package/dist/lang/ast/field-space/struct-space-field-base.d.ts +6 -5
- package/dist/lang/ast/field-space/struct-space-field-base.js +12 -4
- package/dist/lang/ast/index.d.ts +2 -1
- package/dist/lang/ast/index.js +2 -1
- package/dist/lang/ast/query-builders/index-builder.d.ts +2 -2
- package/dist/lang/ast/query-builders/project-builder.d.ts +2 -2
- package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -2
- package/dist/lang/ast/query-elements/query-arrow.js +2 -2
- package/dist/lang/ast/query-elements/query-head-struct.d.ts +2 -2
- package/dist/lang/ast/query-elements/query-head-struct.js +2 -2
- package/dist/lang/ast/query-elements/query-raw.js +2 -2
- package/dist/lang/ast/query-elements/query-reference.js +1 -1
- package/dist/lang/ast/query-items/field-declaration.d.ts +8 -6
- package/dist/lang/ast/query-items/field-declaration.js +66 -24
- package/dist/lang/ast/query-properties/qop-desc.d.ts +2 -2
- package/dist/lang/ast/query-properties/qop-desc.js +1 -1
- package/dist/lang/ast/source-elements/named-source.d.ts +4 -4
- package/dist/lang/ast/source-elements/named-source.js +16 -8
- package/dist/lang/ast/source-elements/query-source.d.ts +3 -3
- package/dist/lang/ast/source-elements/query-source.js +5 -2
- package/dist/lang/ast/source-elements/refined-source.d.ts +3 -3
- package/dist/lang/ast/source-elements/refined-source.js +4 -4
- package/dist/lang/ast/source-elements/source.d.ts +2 -2
- package/dist/lang/ast/source-elements/source.js +2 -2
- package/dist/lang/ast/source-elements/sql-source.d.ts +4 -4
- package/dist/lang/ast/source-elements/sql-source.js +6 -6
- package/dist/lang/ast/source-elements/table-source.d.ts +2 -2
- package/dist/lang/ast/source-elements/table-source.js +1 -1
- package/dist/lang/ast/source-properties/{joins.d.ts → join.d.ts} +11 -14
- package/dist/lang/ast/source-properties/{joins.js → join.js} +35 -52
- package/dist/lang/ast/source-query-elements/sq-reference.js +6 -5
- package/dist/lang/ast/sql-elements/sql-string.d.ts +2 -2
- package/dist/lang/ast/statements/define-source.js +1 -1
- package/dist/lang/ast/struct-utils.d.ts +3 -3
- package/dist/lang/ast/struct-utils.js +12 -3
- package/dist/lang/ast/time-utils.d.ts +3 -3
- package/dist/lang/ast/types/document-compile-result.d.ts +2 -2
- package/dist/lang/ast/types/expression-def.js +4 -4
- package/dist/lang/ast/types/field-space.d.ts +8 -3
- package/dist/lang/ast/types/lookup-result.d.ts +8 -5
- package/dist/lang/ast/types/malloy-element.d.ts +3 -3
- package/dist/lang/ast/types/malloy-element.js +10 -21
- package/dist/lang/ast/types/op-desc.d.ts +2 -2
- package/dist/lang/ast/types/pipeline-comp.d.ts +2 -2
- package/dist/lang/ast/types/query-comp.d.ts +3 -3
- package/dist/lang/ast/types/query-extend-property.d.ts +1 -2
- package/dist/lang/ast/types/query-extend-property.js +4 -2
- package/dist/lang/ast/types/source-property.d.ts +2 -2
- package/dist/lang/ast/types/source-property.js +2 -2
- package/dist/lang/ast/types/space-field.d.ts +10 -3
- package/dist/lang/ast/types/space-field.js +11 -2
- package/dist/lang/ast/types/time-result.d.ts +2 -2
- package/dist/lang/ast/view-elements/qop-desc-view.d.ts +3 -3
- package/dist/lang/ast/view-elements/qop-desc-view.js +1 -1
- package/dist/lang/ast/view-elements/reference-view.d.ts +4 -4
- package/dist/lang/ast/view-elements/reference-view.js +2 -6
- package/dist/lang/ast/view-elements/view-refine.d.ts +2 -2
- package/dist/lang/index.d.ts +1 -1
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +54 -21
- package/dist/lang/lib/Malloy/MalloyParser.js +1647 -1457
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +57 -9
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +35 -5
- package/dist/lang/malloy-to-ast.d.ts +4 -4
- package/dist/lang/malloy-to-ast.js +32 -4
- package/dist/lang/parse-log.d.ts +5 -9
- package/dist/lang/parse-malloy.d.ts +10 -10
- package/dist/lang/parse-malloy.js +2 -1
- package/dist/lang/test/annotation.spec.js +7 -1
- package/dist/lang/test/field-symbols.spec.js +21 -25
- package/dist/lang/test/imports.spec.js +12 -10
- package/dist/lang/test/lenses.spec.js +2 -2
- package/dist/lang/test/model_serialization.spec.d.ts +4 -4
- package/dist/lang/test/model_serialization.spec.js +19 -31
- package/dist/lang/test/parse.spec.js +3 -4
- package/dist/lang/test/query.spec.js +3 -2
- package/dist/lang/test/source.spec.js +7 -0
- package/dist/lang/test/sql-block.spec.js +8 -19
- package/dist/lang/test/test-translator.d.ts +4 -4
- package/dist/lang/test/test-translator.js +53 -61
- package/dist/lang/translate-response.d.ts +3 -3
- package/dist/malloy.d.ts +31 -149
- package/dist/malloy.js +109 -267
- package/dist/model/malloy_query.d.ts +25 -23
- package/dist/model/malloy_query.js +262 -323
- package/dist/model/malloy_types.d.ts +145 -155
- package/dist/model/malloy_types.js +81 -84
- package/dist/model/sql_block.d.ts +4 -4
- package/dist/model/sql_block.js +9 -12
- package/dist/tags.js +2 -2
- package/package.json +1 -1
- package/dist/lang/ast/space-seed.d.ts +0 -16
- 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.
|
|
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(
|
|
209
|
-
this.
|
|
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(
|
|
217
|
+
super(referenceId);
|
|
218
|
+
this.fieldDef = fieldDef;
|
|
221
219
|
this.parent = parent;
|
|
222
220
|
this.fieldDef = fieldDef;
|
|
223
|
-
|
|
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.
|
|
232
|
-
|
|
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,
|
|
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.
|
|
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.
|
|
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.
|
|
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',
|
|
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
|
|
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
|
|
1301
|
-
if ((0, malloy_types_1.
|
|
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
|
-
|
|
1285
|
+
sd.onExpression &&
|
|
1304
1286
|
joinStack.indexOf(name) === -1) {
|
|
1305
|
-
query.addDependantExpr(this, qs.parent,
|
|
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.
|
|
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
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
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
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1526
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
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
|
-
|
|
1906
|
-
|
|
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
|
-
|
|
1969
|
+
type: 'query_result',
|
|
1989
1970
|
name: this.resultStage || 'result',
|
|
1990
|
-
|
|
1971
|
+
fields,
|
|
1972
|
+
dialect: this.parent.structDef.dialect,
|
|
1991
1973
|
primaryKey,
|
|
1992
|
-
|
|
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.
|
|
2002
|
-
outputStruct.modelAnnotation = this.parent.
|
|
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
|
-
|
|
2011
|
-
|
|
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
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
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 (
|
|
2001
|
+
if (qsDef.onExpression) {
|
|
2027
2002
|
onCondition = new QueryFieldBoolean({
|
|
2028
2003
|
type: 'boolean',
|
|
2029
2004
|
name: 'ignoreme',
|
|
2030
|
-
e:
|
|
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.
|
|
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 (
|
|
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(),
|
|
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,
|
|
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 (
|
|
2085
|
-
throw new Error('Internal Error:
|
|
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 ${
|
|
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
|
-
|
|
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] += '
|
|
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
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
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
|
-
|
|
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: '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
2913
|
-
|
|
2914
|
-
f.
|
|
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: '
|
|
2938
|
+
type: 'query_result',
|
|
2966
2939
|
name: this.resultStage || 'result',
|
|
2967
|
-
dialect: this.parent.
|
|
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
|
-
|
|
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.
|
|
2982
|
-
ret.modelAnnotation = this.parent.
|
|
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(
|
|
2990
|
-
super(
|
|
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 (
|
|
3001
|
-
this.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.
|
|
3013
|
-
|
|
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
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
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
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
const
|
|
3067
|
-
|
|
3068
|
-
this.
|
|
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
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
3148
|
-
return this.parent.getSQLIdentifier() + '.' +
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
3209
|
-
const
|
|
3210
|
-
.loadQuery(this.
|
|
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 (!
|
|
3183
|
+
if (!resultStruct) {
|
|
3214
3184
|
throw new Error("Internal Error, query didn't produce a struct");
|
|
3215
3185
|
}
|
|
3216
|
-
const
|
|
3217
|
-
for (const f of
|
|
3218
|
-
|
|
3219
|
-
if (!this.nameMap.has(
|
|
3220
|
-
|
|
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.
|
|
3225
|
-
if (!this.
|
|
3226
|
-
this.
|
|
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.
|
|
3289
|
-
case 'table':
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
case '
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
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.
|
|
3312
|
-
return stageWriter.addMaterializedQuery((0, malloy_types_1.getIdentifier)(this.
|
|
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.
|
|
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(`
|
|
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
|
-
|
|
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.
|
|
3334
|
-
return this.getDimensionByName([this.
|
|
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,
|
|
3364
|
-
const field = this.
|
|
3365
|
-
if (
|
|
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('
|
|
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
|
-
|
|
3372
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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('
|
|
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.
|
|
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 (
|
|
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
|
-
|
|
3470
|
-
if (
|
|
3420
|
+
const s = this.structs.get(name);
|
|
3421
|
+
if (s) {
|
|
3471
3422
|
return s;
|
|
3472
3423
|
}
|
|
3473
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
:
|
|
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(
|