@malloydata/malloy 0.0.294 → 0.0.296
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/dialect/trino/dialect_functions.js +142 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/lang/ast/expressions/expr-granular-time.d.ts +2 -0
- package/dist/lang/ast/expressions/expr-granular-time.js +13 -0
- package/dist/lang/ast/expressions/expr-id-reference.d.ts +2 -0
- package/dist/lang/ast/expressions/expr-id-reference.js +7 -0
- package/dist/lang/ast/field-space/reference-field.js +11 -6
- package/dist/lang/ast/query-items/field-declaration.js +1 -0
- package/dist/lang/ast/query-properties/drill.d.ts +3 -2
- package/dist/lang/ast/query-properties/drill.js +52 -7
- package/dist/lang/ast/query-properties/filters.js +16 -16
- package/dist/lang/ast/types/expression-def.d.ts +2 -0
- package/dist/lang/ast/types/expression-def.js +3 -0
- package/dist/lang/malloy-to-stable-query.js +4 -2
- package/dist/lang/parse-log.d.ts +1 -6
- package/dist/lang/parse-log.js +0 -8
- package/dist/model/composite_source_utils.d.ts +0 -1
- package/dist/model/composite_source_utils.js +93 -61
- package/dist/model/malloy_query.d.ts +5 -2
- package/dist/model/malloy_query.js +26 -22
- package/dist/model/malloy_types.d.ts +8 -6
- package/dist/to_stable.d.ts +13 -1
- package/dist/to_stable.js +188 -41
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -21,13 +21,13 @@ exports.fieldUsageJoinPaths = fieldUsageJoinPaths;
|
|
|
21
21
|
exports.checkRequiredGroupBys = checkRequiredGroupBys;
|
|
22
22
|
exports.pathEq = pathEq;
|
|
23
23
|
exports.pathBegins = pathBegins;
|
|
24
|
-
exports.sortFieldUsageByReferenceLocation = sortFieldUsageByReferenceLocation;
|
|
25
24
|
exports.hasCompositesAnywhere = hasCompositesAnywhere;
|
|
26
25
|
exports.logCompositeError = logCompositeError;
|
|
27
26
|
exports.compileFilterExpression = compileFilterExpression;
|
|
28
27
|
const malloy_filter_1 = require("@malloydata/malloy-filter");
|
|
29
28
|
const malloy_types_1 = require("./malloy_types");
|
|
30
29
|
const utils_1 = require("./utils");
|
|
30
|
+
const utils_2 = require("../lang/utils");
|
|
31
31
|
function _resolveCompositeSources(path, source, rootFields, nests, fieldUsage,
|
|
32
32
|
// for resolving nested composites; the list of sources to try
|
|
33
33
|
sources) {
|
|
@@ -403,27 +403,40 @@ function resolveCompositeSources(source, segment, fieldUsage) {
|
|
|
403
403
|
function fieldUsagePaths(fieldUsage) {
|
|
404
404
|
return fieldUsage.map(u => u.path);
|
|
405
405
|
}
|
|
406
|
-
function
|
|
406
|
+
function dedupPaths(paths) {
|
|
407
407
|
const deduped = [];
|
|
408
|
-
for (const
|
|
409
|
-
if (!deduped.some(p => pathEq(p,
|
|
410
|
-
deduped.push(
|
|
408
|
+
for (const path of paths) {
|
|
409
|
+
if (!deduped.some(p => pathEq(p, path))) {
|
|
410
|
+
deduped.push(path);
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
+
return deduped;
|
|
414
|
+
}
|
|
415
|
+
function formatPaths(paths, combinator = 'and') {
|
|
416
|
+
const deduped = dedupPaths(paths);
|
|
413
417
|
const formattedUsages = deduped.map(fieldUsage => formatFieldUsage(fieldUsage));
|
|
414
|
-
|
|
418
|
+
return commaAndList(formattedUsages, combinator);
|
|
419
|
+
}
|
|
420
|
+
function formatRequiredGroupings(requiredGroupings) {
|
|
421
|
+
return formatPaths(requiredGroupings.map(g => g.path), 'and/or');
|
|
422
|
+
}
|
|
423
|
+
function commaAndList(strs, combinator = 'and') {
|
|
424
|
+
if (strs.length === 0) {
|
|
415
425
|
return '';
|
|
416
426
|
}
|
|
417
|
-
else if (
|
|
418
|
-
return
|
|
427
|
+
else if (strs.length === 1) {
|
|
428
|
+
return strs[0];
|
|
419
429
|
}
|
|
420
|
-
else if (
|
|
421
|
-
return `${
|
|
430
|
+
else if (strs.length === 2) {
|
|
431
|
+
return `${strs[0]} ${combinator} ${strs[1]}`;
|
|
422
432
|
}
|
|
423
433
|
else {
|
|
424
|
-
return `${
|
|
434
|
+
return `${strs.slice(0, -1).join(', ')}, ${combinator} ${strs[strs.length - 1]}`;
|
|
425
435
|
}
|
|
426
436
|
}
|
|
437
|
+
function formatFieldUsages(fieldUsage) {
|
|
438
|
+
return formatPaths(fieldUsage.map(u => u.path));
|
|
439
|
+
}
|
|
427
440
|
function countFieldUsage(fieldUsage) {
|
|
428
441
|
const paths = [];
|
|
429
442
|
for (const usage of fieldUsage) {
|
|
@@ -529,6 +542,7 @@ function requiredGroupBysAt(requiredGroupBys, at) {
|
|
|
529
542
|
return requiredGroupBys;
|
|
530
543
|
return requiredGroupBys === null || requiredGroupBys === void 0 ? void 0 : requiredGroupBys.map(r => ({
|
|
531
544
|
...r,
|
|
545
|
+
fieldUsage: r.fieldUsage ? fieldUsageAt([r.fieldUsage], at)[0] : undefined,
|
|
532
546
|
at,
|
|
533
547
|
}));
|
|
534
548
|
}
|
|
@@ -698,7 +712,7 @@ function expandRefs(nests, fields) {
|
|
|
698
712
|
missingFields.push(field);
|
|
699
713
|
continue;
|
|
700
714
|
}
|
|
701
|
-
requiredGroupBys.push({ path, at: field.at });
|
|
715
|
+
requiredGroupBys.push({ path, at: field.at, fieldUsage: field });
|
|
702
716
|
}
|
|
703
717
|
}
|
|
704
718
|
if (def.ungroupings) {
|
|
@@ -827,8 +841,21 @@ function compareLocations(a, b) {
|
|
|
827
841
|
return 1;
|
|
828
842
|
return 0;
|
|
829
843
|
}
|
|
830
|
-
function
|
|
831
|
-
|
|
844
|
+
function issueLocation(issue) {
|
|
845
|
+
if (issue.type === 'missing-field') {
|
|
846
|
+
return issue.field.at;
|
|
847
|
+
}
|
|
848
|
+
else if (issue.type === 'missing-required-group-by') {
|
|
849
|
+
return issue.requiredGroupBy.at;
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
return issue.firstUsage.at;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
function sortIssuesByReferenceLocation(issues) {
|
|
856
|
+
return issues.sort((a, b) => {
|
|
857
|
+
return compareLocations(issueLocation(a), issueLocation(b));
|
|
858
|
+
});
|
|
832
859
|
}
|
|
833
860
|
function hasCompositesAnywhere(source) {
|
|
834
861
|
if (source.type === 'composite')
|
|
@@ -840,55 +867,60 @@ function hasCompositesAnywhere(source) {
|
|
|
840
867
|
}
|
|
841
868
|
return false;
|
|
842
869
|
}
|
|
870
|
+
function issueFieldUsage(issue) {
|
|
871
|
+
if (issue.type === 'missing-field') {
|
|
872
|
+
return issue.field;
|
|
873
|
+
}
|
|
874
|
+
else if (issue.type === 'missing-required-group-by') {
|
|
875
|
+
return issue.requiredGroupBy.fieldUsage;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
return undefined;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
843
881
|
function logCompositeError(error, logTo) {
|
|
844
882
|
if (error.code === 'no_suitable_composite_source_input') {
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
const joinRef = `\`${issue.path.join('.')}\``;
|
|
887
|
-
logTo.logError('could-not-resolve-composite-source', `Could not resolve composite source: join ${joinRef} could not be resolved in ${source}${requiredFields}`, { at: issue.firstUsage.at });
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
883
|
+
const firstFails = error.data.failures.map(failure => failure.issues[0]);
|
|
884
|
+
const sorted = sortIssuesByReferenceLocation(firstFails);
|
|
885
|
+
const usages = sorted.map(issueFieldUsage);
|
|
886
|
+
const lastIssue = sorted[sorted.length - 1];
|
|
887
|
+
const lastUsage = usages[usages.length - 1];
|
|
888
|
+
const conflictingUsage = firstFails
|
|
889
|
+
.filter(i => i.type === 'missing-field')
|
|
890
|
+
.map(i => i.field);
|
|
891
|
+
const fConflictingUsage = formatFieldUsages(conflictingUsage);
|
|
892
|
+
const dConflictingUsage = conflictingUsage.length > 0
|
|
893
|
+
? `there is no composite input source which defines all of ${fConflictingUsage}`
|
|
894
|
+
: undefined;
|
|
895
|
+
const missingGroupBys = firstFails
|
|
896
|
+
.filter(i => i.type === 'missing-required-group-by')
|
|
897
|
+
.map(i => i.requiredGroupBy);
|
|
898
|
+
const fMissingGroupBys = formatRequiredGroupings(missingGroupBys);
|
|
899
|
+
const dGrouping = 'required group by or single value filter';
|
|
900
|
+
const dMissingGroupBys = missingGroupBys.length > 0
|
|
901
|
+
? `there is a missing ${dGrouping} of ${fMissingGroupBys}`
|
|
902
|
+
: undefined;
|
|
903
|
+
const dConflictingUsageAndMissingGroupBys = conflictingUsage.length > 0 && missingGroupBys.length > 0
|
|
904
|
+
? `there is no composite input source which defines ${fConflictingUsage} without having an unsatisfied ${dGrouping} on ${fMissingGroupBys}`
|
|
905
|
+
: undefined;
|
|
906
|
+
const failedJoins = firstFails
|
|
907
|
+
.filter(i => i.type === 'join-failed')
|
|
908
|
+
.map(i => i.path);
|
|
909
|
+
const uniqueFailedJoins = dedupPaths(failedJoins);
|
|
910
|
+
const joinPlural = uniqueFailedJoins.length > 1 ? 'joins' : 'join';
|
|
911
|
+
const dFailedJoins = failedJoins.length > 0
|
|
912
|
+
? `${joinPlural} ${formatPaths(uniqueFailedJoins)} could not be resolved`
|
|
913
|
+
: undefined;
|
|
914
|
+
const dLastIssue = lastUsage
|
|
915
|
+
? `uses field ${formatFieldUsages([lastUsage])}, resulting in`
|
|
916
|
+
: 'results in';
|
|
917
|
+
const dIssues = dConflictingUsageAndMissingGroupBys
|
|
918
|
+
? commaAndList([dConflictingUsageAndMissingGroupBys, dFailedJoins].filter(utils_2.isNotUndefined))
|
|
919
|
+
: commaAndList([dConflictingUsage, dMissingGroupBys, dFailedJoins].filter(utils_2.isNotUndefined));
|
|
920
|
+
const message = `This operation ${dLastIssue} invalid usage of the composite source, as ${dIssues} (fields required in source: ${formatFieldUsages(error.data.usage)})`;
|
|
921
|
+
logTo.logError('could-not-resolve-composite-source', message, {
|
|
922
|
+
at: issueLocation(lastIssue),
|
|
923
|
+
});
|
|
892
924
|
}
|
|
893
925
|
else {
|
|
894
926
|
logTo.logError('could-not-resolve-composite-source', 'Could not resolve composite source');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
1
2
|
import type { QueryInfo, Dialect, DialectFieldList } from '../dialect';
|
|
2
3
|
import type { AggregateFunctionType, CompiledQuery, Expr, FieldDef, Filtered, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldNode, ParameterNode, PipeSegment, Query, QueryFieldDef, QuerySegment, RefToField, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SegmentFieldDef, StructDef, StructRef, TurtleDef, FunctionOrderBy, Argument, AggregateExpr, FilterCondition, GenericSQLExpr, FieldnameNode, FunctionCallNode, UngroupNode, SourceReferenceNode, SpreadExpr, FilteredExpr, SourceDef, BooleanFieldDef, QueryResultDef, QueryToMaterialize, PrepareResultOptions, CaseExpr, BasicAtomicDef, AtomicFieldDef, FilterMatchExpr } from './malloy_types';
|
|
3
4
|
import type { Connection } from '../connection/types';
|
|
@@ -126,11 +127,12 @@ declare class FieldInstanceField implements FieldInstance {
|
|
|
126
127
|
f: QueryField;
|
|
127
128
|
fieldUsage: FieldUsage;
|
|
128
129
|
parent: FieldInstanceResult;
|
|
130
|
+
readonly drillExpression: Malloy.Expression | undefined;
|
|
129
131
|
type: FieldInstanceType;
|
|
130
132
|
additionalGroupSets: number[];
|
|
131
133
|
analyticalSQL: string | undefined;
|
|
132
134
|
partitionSQL: string | undefined;
|
|
133
|
-
constructor(f: QueryField, fieldUsage: FieldUsage, parent: FieldInstanceResult);
|
|
135
|
+
constructor(f: QueryField, fieldUsage: FieldUsage, parent: FieldInstanceResult, drillExpression: Malloy.Expression | undefined);
|
|
134
136
|
root(): FieldInstanceResultRoot;
|
|
135
137
|
getSQL(): string;
|
|
136
138
|
getAnalyticalSQL(forPartition: boolean): string;
|
|
@@ -161,7 +163,7 @@ declare class FieldInstanceResult implements FieldInstance {
|
|
|
161
163
|
* @returns QueryInfo
|
|
162
164
|
*/
|
|
163
165
|
getQueryInfo(): QueryInfo;
|
|
164
|
-
addField(as: string, field: QueryField, usage: FieldUsage): void;
|
|
166
|
+
addField(as: string, field: QueryField, usage: FieldUsage, drillExpression: Malloy.Expression | undefined): void;
|
|
165
167
|
parentGroupSet(): number;
|
|
166
168
|
add(name: string, f: FieldInstance): void;
|
|
167
169
|
hasField(name: string): boolean;
|
|
@@ -259,6 +261,7 @@ declare class QueryQuery extends QueryField {
|
|
|
259
261
|
addDependantExpr(resultStruct: FieldInstanceResult, context: QueryStruct, e: Expr, joinStack: string[]): void;
|
|
260
262
|
addDependancies(resultStruct: FieldInstanceResult, field: QueryField): void;
|
|
261
263
|
getSegmentFields(resultStruct: FieldInstanceResult): SegmentFieldDef[];
|
|
264
|
+
private getDrillExpression;
|
|
262
265
|
expandFields(resultStruct: FieldInstanceResult): void;
|
|
263
266
|
expandFilters(resultStruct: FieldInstanceResult): void;
|
|
264
267
|
generateSQLFilters(resultStruct: FieldInstanceResult, which: 'where' | 'having'): AndChain;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.QueryModel = exports.Segment = void 0;
|
|
4
|
-
exports.getResultStructDefForView = getResultStructDefForView;
|
|
5
|
-
exports.getResultStructDefForQuery = getResultStructDefForQuery;
|
|
6
2
|
/*
|
|
7
3
|
* Copyright 2023 Google LLC
|
|
8
4
|
*
|
|
@@ -25,6 +21,10 @@ exports.getResultStructDefForQuery = getResultStructDefForQuery;
|
|
|
25
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
26
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
27
23
|
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.QueryModel = exports.Segment = void 0;
|
|
26
|
+
exports.getResultStructDefForView = getResultStructDefForView;
|
|
27
|
+
exports.getResultStructDefForQuery = getResultStructDefForQuery;
|
|
28
28
|
const uuid_1 = require("uuid");
|
|
29
29
|
const dialect_1 = require("../dialect");
|
|
30
30
|
const standardsql_1 = require("../dialect/standardsql/standardsql");
|
|
@@ -1124,10 +1124,11 @@ function sqlSumDistinct(dialect, sqlExp, sqlDistintKey) {
|
|
|
1124
1124
|
return ret;
|
|
1125
1125
|
}
|
|
1126
1126
|
class FieldInstanceField {
|
|
1127
|
-
constructor(f, fieldUsage, parent) {
|
|
1127
|
+
constructor(f, fieldUsage, parent, drillExpression) {
|
|
1128
1128
|
this.f = f;
|
|
1129
1129
|
this.fieldUsage = fieldUsage;
|
|
1130
1130
|
this.parent = parent;
|
|
1131
|
+
this.drillExpression = drillExpression;
|
|
1131
1132
|
this.type = 'field';
|
|
1132
1133
|
this.additionalGroupSets = [];
|
|
1133
1134
|
}
|
|
@@ -1186,7 +1187,7 @@ class FieldInstanceResult {
|
|
|
1186
1187
|
}
|
|
1187
1188
|
return {};
|
|
1188
1189
|
}
|
|
1189
|
-
addField(as, field, usage) {
|
|
1190
|
+
addField(as, field, usage, drillExpression) {
|
|
1190
1191
|
const fi = this.allFields.get(as);
|
|
1191
1192
|
if (fi) {
|
|
1192
1193
|
if (fi.type === 'query') {
|
|
@@ -1203,7 +1204,7 @@ class FieldInstanceResult {
|
|
|
1203
1204
|
}
|
|
1204
1205
|
}
|
|
1205
1206
|
}
|
|
1206
|
-
this.add(as, new FieldInstanceField(field, usage, this));
|
|
1207
|
+
this.add(as, new FieldInstanceField(field, usage, this, drillExpression));
|
|
1207
1208
|
}
|
|
1208
1209
|
parentGroupSet() {
|
|
1209
1210
|
if (this.parent) {
|
|
@@ -1828,10 +1829,16 @@ class QueryQuery extends QueryField {
|
|
|
1828
1829
|
? fs.queryFields
|
|
1829
1830
|
: [];
|
|
1830
1831
|
}
|
|
1832
|
+
getDrillExpression(f) {
|
|
1833
|
+
if ((0, malloy_types_1.isAtomic)(f) || f.type === 'fieldref')
|
|
1834
|
+
return f.drillExpression;
|
|
1835
|
+
return undefined;
|
|
1836
|
+
}
|
|
1831
1837
|
expandFields(resultStruct) {
|
|
1832
1838
|
let resultIndex = 1;
|
|
1833
1839
|
for (const f of this.getSegmentFields(resultStruct)) {
|
|
1834
1840
|
const { as, field } = this.expandField(f);
|
|
1841
|
+
const drillExpression = this.getDrillExpression(f);
|
|
1835
1842
|
if (field instanceof QueryQuery) {
|
|
1836
1843
|
if (this.firstSegment.type === 'project') {
|
|
1837
1844
|
throw new Error(`Nested views cannot be used in select - '${field.fieldDef.name}'`);
|
|
@@ -1844,7 +1851,7 @@ class QueryQuery extends QueryField {
|
|
|
1844
1851
|
resultStruct.addField(as, field, {
|
|
1845
1852
|
resultIndex,
|
|
1846
1853
|
type: 'result',
|
|
1847
|
-
});
|
|
1854
|
+
}, drillExpression);
|
|
1848
1855
|
this.addDependancies(resultStruct, field);
|
|
1849
1856
|
if (isBasicAggregate(field)) {
|
|
1850
1857
|
if (this.firstSegment.type === 'project') {
|
|
@@ -1859,7 +1866,7 @@ class QueryQuery extends QueryField {
|
|
|
1859
1866
|
resultStruct.addField(as, field, {
|
|
1860
1867
|
resultIndex,
|
|
1861
1868
|
type: 'result',
|
|
1862
|
-
});
|
|
1869
|
+
}, drillExpression);
|
|
1863
1870
|
}
|
|
1864
1871
|
// else if (
|
|
1865
1872
|
// this.firstSegment.type === "project" &&
|
|
@@ -1950,11 +1957,13 @@ class QueryQuery extends QueryField {
|
|
|
1950
1957
|
: undefined;
|
|
1951
1958
|
const sourceClasses = [sourceField];
|
|
1952
1959
|
const referenceId = fi.f.referenceId;
|
|
1960
|
+
const drillExpression = fi.drillExpression;
|
|
1953
1961
|
const base = {
|
|
1954
1962
|
sourceField,
|
|
1955
1963
|
sourceExpression,
|
|
1956
1964
|
sourceClasses,
|
|
1957
1965
|
referenceId,
|
|
1966
|
+
drillExpression,
|
|
1958
1967
|
};
|
|
1959
1968
|
if (isBasicCalculation(fi.f)) {
|
|
1960
1969
|
filterList = fi.f.getFilterList();
|
|
@@ -2020,7 +2029,6 @@ class QueryQuery extends QueryField {
|
|
|
2020
2029
|
join: 'many',
|
|
2021
2030
|
name,
|
|
2022
2031
|
resultMetadata,
|
|
2023
|
-
drillView: fi.turtleDef.drillView,
|
|
2024
2032
|
};
|
|
2025
2033
|
fields.push(multiLineNest);
|
|
2026
2034
|
}
|
|
@@ -2031,7 +2039,6 @@ class QueryQuery extends QueryField {
|
|
|
2031
2039
|
join: 'one',
|
|
2032
2040
|
name,
|
|
2033
2041
|
resultMetadata,
|
|
2034
|
-
drillView: fi.turtleDef.drillView,
|
|
2035
2042
|
};
|
|
2036
2043
|
fields.push(oneLineNest);
|
|
2037
2044
|
}
|
|
@@ -2060,12 +2067,10 @@ class QueryQuery extends QueryField {
|
|
|
2060
2067
|
}
|
|
2061
2068
|
const location = fOut.location;
|
|
2062
2069
|
const annotation = fOut.annotation;
|
|
2063
|
-
const drillView = (0, malloy_types_1.isAtomic)(fOut) || (0, malloy_types_1.isTurtle)(fOut) ? fOut.drillView : undefined;
|
|
2064
2070
|
const common = {
|
|
2065
2071
|
resultMetadata,
|
|
2066
2072
|
location,
|
|
2067
2073
|
annotation,
|
|
2068
|
-
drillView,
|
|
2069
2074
|
};
|
|
2070
2075
|
// build out the result fields...
|
|
2071
2076
|
switch (fOut.type) {
|
|
@@ -2835,7 +2840,6 @@ class QueryQuery extends QueryField {
|
|
|
2835
2840
|
type: 'turtle',
|
|
2836
2841
|
name: 'starthere',
|
|
2837
2842
|
pipeline,
|
|
2838
|
-
drillView: fi.turtleDef.drillView,
|
|
2839
2843
|
};
|
|
2840
2844
|
const inputStruct = {
|
|
2841
2845
|
type: 'nest_source',
|
|
@@ -2942,11 +2946,12 @@ class QueryQueryIndexStage extends QueryQuery {
|
|
|
2942
2946
|
this.maxGroupSet = groupIndex;
|
|
2943
2947
|
for (const f of this.firstSegment.indexFields) {
|
|
2944
2948
|
const { as, field } = this.expandField(f);
|
|
2945
|
-
|
|
2949
|
+
const referencePath = f.path;
|
|
2950
|
+
this.indexPaths[as] = referencePath;
|
|
2946
2951
|
resultStruct.addField(as, field, {
|
|
2947
2952
|
resultIndex,
|
|
2948
2953
|
type: 'result',
|
|
2949
|
-
});
|
|
2954
|
+
}, undefined);
|
|
2950
2955
|
if (field instanceof QueryAtomicField) {
|
|
2951
2956
|
this.addDependancies(resultStruct, field);
|
|
2952
2957
|
}
|
|
@@ -2958,7 +2963,7 @@ class QueryQueryIndexStage extends QueryQuery {
|
|
|
2958
2963
|
resultStruct.addField(measure, f, {
|
|
2959
2964
|
resultIndex,
|
|
2960
2965
|
type: 'result',
|
|
2961
|
-
});
|
|
2966
|
+
}, undefined);
|
|
2962
2967
|
this.addDependancies(resultStruct, f);
|
|
2963
2968
|
}
|
|
2964
2969
|
this.expandFilters(resultStruct);
|
|
@@ -3615,20 +3620,20 @@ class QueryStruct {
|
|
|
3615
3620
|
return field;
|
|
3616
3621
|
}
|
|
3617
3622
|
getQueryFieldReference(f) {
|
|
3618
|
-
const { path, annotation,
|
|
3623
|
+
const { path, annotation, drillExpression } = f;
|
|
3619
3624
|
const field = this.getFieldByName(path);
|
|
3620
|
-
if (annotation ||
|
|
3625
|
+
if (annotation || drillExpression) {
|
|
3621
3626
|
if (field.parent === undefined) {
|
|
3622
3627
|
throw new Error('Inconcievable, field reference to orphaned query field');
|
|
3623
3628
|
}
|
|
3624
3629
|
// Made a field object from the source, but the annotations were computed by the compiler
|
|
3625
3630
|
// when it generated the reference, and has both the source and reference annotations included.
|
|
3626
3631
|
if (field instanceof QueryFieldStruct) {
|
|
3627
|
-
const newDef = { ...field.fieldDef, annotation,
|
|
3632
|
+
const newDef = { ...field.fieldDef, annotation, drillExpression };
|
|
3628
3633
|
return new QueryFieldStruct(newDef, undefined, field.parent, {}, field.referenceId);
|
|
3629
3634
|
}
|
|
3630
3635
|
else {
|
|
3631
|
-
const newDef = { ...field.fieldDef, annotation,
|
|
3636
|
+
const newDef = { ...field.fieldDef, annotation, drillExpression };
|
|
3632
3637
|
return field.parent.makeQueryField(newDef, field.referenceId);
|
|
3633
3638
|
}
|
|
3634
3639
|
}
|
|
@@ -3683,7 +3688,6 @@ class QueryStruct {
|
|
|
3683
3688
|
pipeline,
|
|
3684
3689
|
annotation,
|
|
3685
3690
|
location: turtleDef.location,
|
|
3686
|
-
drillView: turtleDef.drillView,
|
|
3687
3691
|
};
|
|
3688
3692
|
return flatTurtleDef;
|
|
3689
3693
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type * as Malloy from '@malloydata/malloy-interfaces';
|
|
2
2
|
/**
|
|
3
3
|
* Field computations are compiled into an expression tree of "Expr"
|
|
4
4
|
* type nodes. Each node is one of these three interfaces. The
|
|
@@ -60,8 +60,8 @@ export interface FilterCondition extends ExprE {
|
|
|
60
60
|
code: string;
|
|
61
61
|
expressionType: ExpressionType;
|
|
62
62
|
fieldUsage?: FieldUsage[];
|
|
63
|
-
|
|
64
|
-
stableFilter?: Filter;
|
|
63
|
+
filterView?: string;
|
|
64
|
+
stableFilter?: Malloy.Filter;
|
|
65
65
|
isSourceFilter?: boolean;
|
|
66
66
|
}
|
|
67
67
|
export interface FilteredExpr extends ExprWithKids {
|
|
@@ -265,6 +265,7 @@ export interface Expression {
|
|
|
265
265
|
fieldUsage?: FieldUsage[];
|
|
266
266
|
expressionType?: ExpressionType;
|
|
267
267
|
code?: string;
|
|
268
|
+
drillExpression?: Malloy.Expression;
|
|
268
269
|
}
|
|
269
270
|
type ConstantExpr = Expr;
|
|
270
271
|
interface ParameterInfo {
|
|
@@ -343,6 +344,7 @@ export interface ResultMetadataDef {
|
|
|
343
344
|
filterList?: FilterCondition[];
|
|
344
345
|
fieldKind: 'measure' | 'dimension' | 'struct';
|
|
345
346
|
referenceId?: string;
|
|
347
|
+
drillExpression?: Malloy.Expression | undefined;
|
|
346
348
|
drillable?: boolean;
|
|
347
349
|
}
|
|
348
350
|
export interface Ordered {
|
|
@@ -389,7 +391,7 @@ export interface FieldBase extends NamedObject, Expression, ResultMetadata {
|
|
|
389
391
|
accessModifier?: NonDefaultAccessModifierLabel | undefined;
|
|
390
392
|
requiresGroupBy?: RequiredGroupBy[];
|
|
391
393
|
ungroupings?: AggregateUngrouping[];
|
|
392
|
-
|
|
394
|
+
drillExpression?: Malloy.Expression | undefined;
|
|
393
395
|
}
|
|
394
396
|
export declare function fieldIsIntrinsic(f: FieldDef): f is AtomicFieldDef;
|
|
395
397
|
export interface StringTypeDef {
|
|
@@ -610,7 +612,6 @@ export interface TurtleDef extends NamedObject, Pipeline {
|
|
|
610
612
|
accessModifier?: NonDefaultAccessModifierLabel | undefined;
|
|
611
613
|
fieldUsage?: FieldUsage[];
|
|
612
614
|
requiredGroupBys?: string[][];
|
|
613
|
-
drillView?: string;
|
|
614
615
|
}
|
|
615
616
|
interface StructDefBase extends HasLocation, NamedObject {
|
|
616
617
|
type: string;
|
|
@@ -684,6 +685,7 @@ export type ExpressionValueType = AtomicFieldType | NonAtomicType;
|
|
|
684
685
|
export type ExpressionValueTypeDef = AtomicTypeDef | NonAtomicTypeDef;
|
|
685
686
|
export type BasicExpressionType = Exclude<ExpressionValueType, JoinElementType | 'turtle'>;
|
|
686
687
|
export interface RequiredGroupBy {
|
|
688
|
+
fieldUsage?: FieldUsage;
|
|
687
689
|
at?: DocumentLocation;
|
|
688
690
|
path: string[];
|
|
689
691
|
}
|
|
@@ -799,7 +801,7 @@ export interface RefToField {
|
|
|
799
801
|
path: string[];
|
|
800
802
|
annotation?: Annotation;
|
|
801
803
|
at?: DocumentLocation;
|
|
802
|
-
|
|
804
|
+
drillExpression?: Malloy.Expression | undefined;
|
|
803
805
|
}
|
|
804
806
|
export type QueryFieldDef = AtomicFieldDef | TurtleDef | RefToField;
|
|
805
807
|
export type TypedDef = AtomicTypeDef | JoinFieldDef | TurtleDef | RefToField | StructDef;
|
package/dist/to_stable.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Malloy from '@malloydata/malloy-interfaces';
|
|
2
2
|
import type { FieldDef, ModelDef, ResultStructMetadataDef, SourceDef } from './model';
|
|
3
3
|
import { Tag } from '@malloydata/malloy-tag';
|
|
4
4
|
export declare function sourceDefToSourceInfo(sourceDef: SourceDef): Malloy.SourceInfo;
|
|
@@ -6,3 +6,15 @@ export declare function modelDefToModelInfo(modelDef: ModelDef): Malloy.ModelInf
|
|
|
6
6
|
export declare function convertFieldInfos(source: SourceDef, fields: FieldDef[]): Malloy.FieldInfo[];
|
|
7
7
|
export declare function writeLiteralToTag(tag: Tag, path: (string | number)[], literal: Malloy.LiteralValue): void;
|
|
8
8
|
export declare function getResultStructMetadataAnnotation(field: SourceDef, resultMetadata: ResultStructMetadataDef): Malloy.Annotation | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Writes a Malloy interface object to a tag at a given path.
|
|
11
|
+
*
|
|
12
|
+
* E.g. `writeMalloyObjectToTag(tag, ['expr'], 'Expression', {kind: 'field_reference', name: 'carrier'})`
|
|
13
|
+
*
|
|
14
|
+
* produces the tag `#(malloy) expr { kind = field_reference name = carrier }`
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeMalloyObjectToTag(tag: Tag, path: (string | number)[], obj: unknown, type: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a Malloy interface object from a tag at a given path; the inverse of `writeMalloyObjectToTag`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractMalloyObjectFromTag(tag: Tag, type: string): unknown;
|