@malloydata/malloy 0.0.427 → 0.0.429
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/api/foundation/build_targets.d.ts +50 -0
- package/dist/api/foundation/build_targets.js +221 -0
- package/dist/api/foundation/core.d.ts +54 -10
- package/dist/api/foundation/core.js +80 -17
- package/dist/api/foundation/index.d.ts +1 -1
- package/dist/api/foundation/runtime.d.ts +18 -1
- package/dist/api/foundation/runtime.js +35 -0
- package/dist/api/foundation/types.d.ts +93 -6
- package/dist/index.d.ts +1 -1
- package/dist/lang/ast/expressions/apply.d.ts +1 -1
- package/dist/lang/ast/expressions/apply.js +2 -2
- package/dist/lang/ast/expressions/binary-boolean.d.ts +1 -1
- package/dist/lang/ast/expressions/binary-boolean.js +1 -1
- package/dist/lang/ast/expressions/binary-numeric.d.ts +1 -1
- package/dist/lang/ast/expressions/binary-numeric.js +1 -1
- package/dist/lang/ast/expressions/boolean.d.ts +1 -1
- package/dist/lang/ast/expressions/boolean.js +1 -1
- package/dist/lang/ast/expressions/case.d.ts +1 -1
- package/dist/lang/ast/expressions/case.js +1 -1
- package/dist/lang/ast/expressions/constant-expression.d.ts +2 -1
- package/dist/lang/ast/expressions/constant-expression.js +6 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.js +14 -7
- package/dist/lang/ast/expressions/expr-alternation-tree.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-alternation-tree.js +1 -1
- package/dist/lang/ast/expressions/expr-array-literal.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-array-literal.js +1 -1
- package/dist/lang/ast/expressions/expr-cast.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-cast.js +1 -1
- package/dist/lang/ast/expressions/expr-coalesce.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-coalesce.js +1 -1
- package/dist/lang/ast/expressions/expr-compare.d.ts +4 -4
- package/dist/lang/ast/expressions/expr-compare.js +4 -4
- package/dist/lang/ast/expressions/expr-count.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-count.js +1 -1
- package/dist/lang/ast/expressions/expr-filter-expr.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-filter-expr.js +1 -1
- package/dist/lang/ast/expressions/expr-func.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-func.js +1 -1
- package/dist/lang/ast/expressions/expr-given.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-given.js +1 -1
- package/dist/lang/ast/expressions/expr-granular-time.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
- package/dist/lang/ast/expressions/expr-id-reference.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-id-reference.js +1 -1
- package/dist/lang/ast/expressions/expr-minus.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-minus.js +1 -1
- package/dist/lang/ast/expressions/expr-not.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-not.js +1 -1
- package/dist/lang/ast/expressions/expr-now.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-now.js +1 -1
- package/dist/lang/ast/expressions/expr-null.d.ts +3 -3
- package/dist/lang/ast/expressions/expr-null.js +14 -9
- package/dist/lang/ast/expressions/expr-number.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-number.js +1 -1
- package/dist/lang/ast/expressions/expr-parens.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-parens.js +5 -2
- package/dist/lang/ast/expressions/expr-props.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-props.js +1 -1
- package/dist/lang/ast/expressions/expr-record-literal.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-record-literal.js +1 -1
- package/dist/lang/ast/expressions/expr-regex.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-regex.js +1 -1
- package/dist/lang/ast/expressions/expr-string.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-string.js +1 -1
- package/dist/lang/ast/expressions/expr-time-extract.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-time-extract.js +1 -1
- package/dist/lang/ast/expressions/expr-time.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-time.js +1 -1
- package/dist/lang/ast/expressions/expr-ungroup.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-ungroup.js +1 -1
- package/dist/lang/ast/expressions/for-range.d.ts +1 -1
- package/dist/lang/ast/expressions/for-range.js +1 -1
- package/dist/lang/ast/expressions/partial-compare.d.ts +1 -1
- package/dist/lang/ast/expressions/partial-compare.js +1 -1
- package/dist/lang/ast/expressions/pick-when.d.ts +1 -1
- package/dist/lang/ast/expressions/pick-when.js +1 -1
- package/dist/lang/ast/expressions/range.d.ts +1 -1
- package/dist/lang/ast/expressions/range.js +1 -1
- package/dist/lang/ast/expressions/time-literal.d.ts +2 -2
- package/dist/lang/ast/expressions/time-literal.js +2 -2
- package/dist/lang/ast/field-space/dynamic-space.js +20 -3
- package/dist/lang/ast/field-space/parameter-space.d.ts +1 -0
- package/dist/lang/ast/field-space/parameter-space.js +6 -0
- package/dist/lang/ast/field-space/passthrough-space.d.ts +1 -0
- package/dist/lang/ast/field-space/passthrough-space.js +3 -0
- package/dist/lang/ast/field-space/static-space.d.ts +8 -0
- package/dist/lang/ast/field-space/static-space.js +14 -0
- package/dist/lang/ast/query-builders/index-builder.js +1 -1
- package/dist/lang/ast/query-elements/query-arrow.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-arrow.js +10 -4
- package/dist/lang/ast/query-elements/query-base.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-base.js +1 -6
- package/dist/lang/ast/query-elements/query-raw.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-raw.js +4 -2
- package/dist/lang/ast/query-elements/query-reference.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-reference.js +9 -3
- package/dist/lang/ast/query-elements/query-refine.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-refine.js +10 -4
- package/dist/lang/ast/query-properties/drill.d.ts +1 -1
- package/dist/lang/ast/query-properties/drill.js +1 -1
- package/dist/lang/ast/source-elements/query-source.js +1 -1
- package/dist/lang/ast/source-elements/sql-source.js +2 -2
- package/dist/lang/ast/source-query-elements/source-query-element.d.ts +27 -0
- package/dist/lang/ast/source-query-elements/source-query-element.js +33 -0
- package/dist/lang/ast/source-query-elements/sq-arrow.d.ts +2 -0
- package/dist/lang/ast/source-query-elements/sq-arrow.js +12 -6
- package/dist/lang/ast/source-query-elements/sq-refine.d.ts +2 -0
- package/dist/lang/ast/source-query-elements/sq-refine.js +12 -6
- package/dist/lang/ast/source-query-elements/sq-source.d.ts +1 -0
- package/dist/lang/ast/source-query-elements/sq-source.js +6 -3
- package/dist/lang/ast/sql-elements/sql-string.d.ts +1 -1
- package/dist/lang/ast/sql-elements/sql-string.js +25 -5
- package/dist/lang/ast/statements/import-statement.js +7 -10
- package/dist/lang/ast/types/expression-def.d.ts +50 -23
- package/dist/lang/ast/types/expression-def.js +127 -65
- package/dist/lang/ast/types/field-space.d.ts +14 -0
- package/dist/lang/ast/types/field-space.js +36 -0
- package/dist/lang/ast/types/query-element.d.ts +15 -1
- package/dist/lang/parse-log.d.ts +2 -0
- package/dist/lang/test/test-translator.d.ts +17 -0
- package/dist/lang/test/test-translator.js +46 -2
- package/dist/model/malloy_types.d.ts +0 -13
- package/dist/model/malloy_types.js +0 -19
- package/dist/model/persist_utils.d.ts +61 -10
- package/dist/model/persist_utils.js +172 -63
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -21,7 +21,9 @@ class QueryRaw extends malloy_element_1.MalloyElement {
|
|
|
21
21
|
this.source = source;
|
|
22
22
|
this.elementType = 'query-raw';
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
// A raw segment has no query class to decide, so it is never partial and
|
|
25
|
+
// `isPartialOk` has nothing to say here.
|
|
26
|
+
queryComp(isRefOk, _isPartialOk) {
|
|
25
27
|
const invoked = isRefOk
|
|
26
28
|
? this.source.structRef(undefined)
|
|
27
29
|
: { structRef: this.source.getSourceDef(undefined) };
|
|
@@ -40,7 +42,7 @@ class QueryRaw extends malloy_element_1.MalloyElement {
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
query(isRefOk = true) {
|
|
43
|
-
return this.queryComp(isRefOk).query;
|
|
45
|
+
return this.queryComp(isRefOk, false).query;
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
exports.QueryRaw = QueryRaw;
|
|
@@ -12,6 +12,6 @@ export declare class QueryReference extends MalloyElement implements QueryElemen
|
|
|
12
12
|
readonly name: ModelEntryReference;
|
|
13
13
|
elementType: string;
|
|
14
14
|
constructor(name: ModelEntryReference);
|
|
15
|
-
queryComp(isRefOk: boolean): QueryComp;
|
|
15
|
+
queryComp(isRefOk: boolean, isPartialOk: boolean): QueryComp;
|
|
16
16
|
query(isRefOk?: boolean): Query;
|
|
17
17
|
}
|
|
@@ -8,6 +8,7 @@ exports.QueryReference = void 0;
|
|
|
8
8
|
const error_factory_1 = require("../error-factory");
|
|
9
9
|
const malloy_element_1 = require("../types/malloy-element");
|
|
10
10
|
const query_head_struct_1 = require("./query-head-struct");
|
|
11
|
+
const query_utils_1 = require("../query-utils");
|
|
11
12
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
12
13
|
/**
|
|
13
14
|
* A query operation that is just a reference to an existing query.
|
|
@@ -20,7 +21,7 @@ class QueryReference extends malloy_element_1.MalloyElement {
|
|
|
20
21
|
this.name = name;
|
|
21
22
|
this.elementType = 'query-reference';
|
|
22
23
|
}
|
|
23
|
-
queryComp(isRefOk) {
|
|
24
|
+
queryComp(isRefOk, isPartialOk) {
|
|
24
25
|
const headEntry = this.modelEntry(this.name);
|
|
25
26
|
const query = headEntry === null || headEntry === void 0 ? void 0 : headEntry.entry;
|
|
26
27
|
const oops = function () {
|
|
@@ -45,7 +46,12 @@ class QueryReference extends malloy_element_1.MalloyElement {
|
|
|
45
46
|
? query
|
|
46
47
|
: { ...query, structRef: inputStruct };
|
|
47
48
|
return {
|
|
48
|
-
query:
|
|
49
|
+
query: isPartialOk
|
|
50
|
+
? unRefedQuery
|
|
51
|
+
: {
|
|
52
|
+
...unRefedQuery,
|
|
53
|
+
pipeline: (0, query_utils_1.detectAndRemovePartialStages)(unRefedQuery.pipeline, this),
|
|
54
|
+
},
|
|
49
55
|
outputStruct,
|
|
50
56
|
inputStruct,
|
|
51
57
|
};
|
|
@@ -54,7 +60,7 @@ class QueryReference extends malloy_element_1.MalloyElement {
|
|
|
54
60
|
return oops();
|
|
55
61
|
}
|
|
56
62
|
query(isRefOk = true) {
|
|
57
|
-
return this.queryComp(isRefOk).query;
|
|
63
|
+
return this.queryComp(isRefOk, false).query;
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
exports.QueryReference = QueryReference;
|
|
@@ -12,5 +12,5 @@ export declare class QueryRefine extends QueryBase implements QueryElement {
|
|
|
12
12
|
readonly refinement: View;
|
|
13
13
|
elementType: string;
|
|
14
14
|
constructor(base: QueryElement, refinement: View);
|
|
15
|
-
queryComp(isRefOk: boolean): QueryComp;
|
|
15
|
+
queryComp(isRefOk: boolean, isPartialOk: boolean): QueryComp;
|
|
16
16
|
}
|
|
@@ -8,6 +8,7 @@ exports.QueryRefine = void 0;
|
|
|
8
8
|
const static_space_1 = require("../field-space/static-space");
|
|
9
9
|
const query_base_1 = require("./query-base");
|
|
10
10
|
const composite_source_utils_1 = require("../../composite-source-utils");
|
|
11
|
+
const query_utils_1 = require("../query-utils");
|
|
11
12
|
/**
|
|
12
13
|
* A query operation that consists of an exisitng query with refinements.
|
|
13
14
|
*
|
|
@@ -20,8 +21,10 @@ class QueryRefine extends query_base_1.QueryBase {
|
|
|
20
21
|
this.refinement = refinement;
|
|
21
22
|
this.elementType = 'query-refine';
|
|
22
23
|
}
|
|
23
|
-
queryComp(isRefOk) {
|
|
24
|
-
|
|
24
|
+
queryComp(isRefOk, isPartialOk) {
|
|
25
|
+
// The refinement is what decides the query class, so the base is the one
|
|
26
|
+
// place a partial segment is expected rather than an error.
|
|
27
|
+
const q = this.base.queryComp(isRefOk, true);
|
|
25
28
|
const inputFS = new static_space_1.StaticSourceSpace(q.inputStruct, 'public');
|
|
26
29
|
const pipeline = this.refinement.refine(inputFS, q.query.pipeline, undefined);
|
|
27
30
|
const query = {
|
|
@@ -30,12 +33,15 @@ class QueryRefine extends query_base_1.QueryBase {
|
|
|
30
33
|
};
|
|
31
34
|
const compositeResolvedSourceDef = this.resolveCompositeSource(q.inputStruct, pipeline);
|
|
32
35
|
const pipelineWithExpandedFieldUsage = this.expandRefUsage(compositeResolvedSourceDef !== null && compositeResolvedSourceDef !== void 0 ? compositeResolvedSourceDef : q.inputStruct, pipeline);
|
|
36
|
+
const finalPipeline = isPartialOk
|
|
37
|
+
? pipelineWithExpandedFieldUsage
|
|
38
|
+
: (0, query_utils_1.detectAndRemovePartialStages)(pipelineWithExpandedFieldUsage, this);
|
|
33
39
|
return {
|
|
34
40
|
query: {
|
|
35
41
|
...query,
|
|
36
42
|
compositeResolvedSourceDef,
|
|
37
|
-
pipeline:
|
|
38
|
-
givenUsage: (0, composite_source_utils_1.computeQueryGivenUsage)(
|
|
43
|
+
pipeline: finalPipeline,
|
|
44
|
+
givenUsage: (0, composite_source_utils_1.computeQueryGivenUsage)(finalPipeline),
|
|
39
45
|
},
|
|
40
46
|
// TODO bleh
|
|
41
47
|
outputStruct: pipeline[pipeline.length - 1].outputStruct,
|
|
@@ -13,7 +13,7 @@ export declare class DrillField extends ExpressionDef {
|
|
|
13
13
|
readonly typeDesc: TypeDesc;
|
|
14
14
|
elementType: string;
|
|
15
15
|
constructor(expr: Expr, typeDesc: TypeDesc);
|
|
16
|
-
|
|
16
|
+
protected computeExpression(_fs: FieldSpace): ExprValue;
|
|
17
17
|
}
|
|
18
18
|
export declare class Drill extends Filter implements QueryPropertyInterface {
|
|
19
19
|
elementType: string;
|
|
@@ -18,7 +18,7 @@ class QuerySource extends source_1.Source {
|
|
|
18
18
|
return this.withParameters(parameterSpace, undefined);
|
|
19
19
|
}
|
|
20
20
|
withParameters(parameterSpace, pList) {
|
|
21
|
-
const comp = this.query.queryComp(false);
|
|
21
|
+
const comp = this.query.queryComp(false, false);
|
|
22
22
|
const queryStruct = (0, source_def_utils_1.mkQuerySourceDef)(comp.outputStruct, comp.query, `QuerySource-${(0, uuid_1.v4)()}`);
|
|
23
23
|
return {
|
|
24
24
|
...queryStruct,
|
|
@@ -22,7 +22,7 @@ class SQLSource extends source_1.Source {
|
|
|
22
22
|
const partialModel = this.select.containsQueries
|
|
23
23
|
? doc.modelDef()
|
|
24
24
|
: undefined;
|
|
25
|
-
const [valid, phrases] = this.select.sqlPhrases();
|
|
25
|
+
const [valid, phrases] = this.select.sqlPhrases(this.connectionName.refString);
|
|
26
26
|
if (valid) {
|
|
27
27
|
return (0, sql_block_1.getSourceRequest)(phrases, this.connectionName.refString, partialModel);
|
|
28
28
|
}
|
|
@@ -123,7 +123,7 @@ class SQLSource extends source_1.Source {
|
|
|
123
123
|
location: this.location,
|
|
124
124
|
};
|
|
125
125
|
// Use factory to create SQLSourceDef without propagating sourceID/extends
|
|
126
|
-
const [_valid, phrases] = this.select.sqlPhrases();
|
|
126
|
+
const [_valid, phrases] = this.select.sqlPhrases(this.connectionName.refString);
|
|
127
127
|
const selectSegments = this.select.containsQueries ? phrases : undefined;
|
|
128
128
|
const locStruct = (0, source_def_utils_1.mkSQLSourceDef)(baseStruct, lookup.value.selectStr, selectSegments);
|
|
129
129
|
return locStruct;
|
|
@@ -9,10 +9,37 @@ import type { LogMessageOptions, MessageCode, MessageParameterType } from '../..
|
|
|
9
9
|
* a query.
|
|
10
10
|
*/
|
|
11
11
|
export declare abstract class SourceQueryElement extends MalloyElement {
|
|
12
|
+
/** Set once this element has reported why it could not produce a value. */
|
|
12
13
|
errored: boolean;
|
|
13
14
|
getSource(): Source | undefined;
|
|
14
15
|
getQuery(): QueryElement | undefined;
|
|
15
16
|
isSource(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Report the one message which explains why this expression could not be
|
|
19
|
+
* turned into a source or a query.
|
|
20
|
+
*
|
|
21
|
+
* Every element in a source/query expression says something when it fails,
|
|
22
|
+
* so an outer element's generic complaint ("could not get source for
|
|
23
|
+
* query") would stack on top of the specific cause already reported
|
|
24
|
+
* beneath it. The message is therefore logged only when nothing in this
|
|
25
|
+
* subtree has spoken yet, and `errored` is set either way, which is what
|
|
26
|
+
* silences the elements above.
|
|
27
|
+
*
|
|
28
|
+
* This is not protection against logging the same message twice —
|
|
29
|
+
* `MalloyElement.log` already drops a repeat of one message at one
|
|
30
|
+
* location. It is one message per failed expression.
|
|
31
|
+
*
|
|
32
|
+
* The case it does not serve is two unrelated complaints about the same
|
|
33
|
+
* element: a second `sqLog` is dropped. Use `sqClaimError` for those.
|
|
34
|
+
*/
|
|
16
35
|
sqLog<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: LogMessageOptions): T;
|
|
36
|
+
/**
|
|
37
|
+
* Take the one error report this expression is allowed, for an element with
|
|
38
|
+
* more than one complaint to make. False means something below has already
|
|
39
|
+
* spoken. True means the caller owns the report and should `logError` each
|
|
40
|
+
* of its complaints; nothing above will speak after that.
|
|
41
|
+
*/
|
|
42
|
+
sqClaimError(): boolean;
|
|
43
|
+
/** True until this element, or anything below it, has reported a failure. */
|
|
17
44
|
isErrorFree(): boolean;
|
|
18
45
|
}
|
|
@@ -15,6 +15,7 @@ const malloy_element_1 = require("../types/malloy-element");
|
|
|
15
15
|
class SourceQueryElement extends malloy_element_1.MalloyElement {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(...arguments);
|
|
18
|
+
/** Set once this element has reported why it could not produce a value. */
|
|
18
19
|
this.errored = false;
|
|
19
20
|
}
|
|
20
21
|
getSource() {
|
|
@@ -26,6 +27,24 @@ class SourceQueryElement extends malloy_element_1.MalloyElement {
|
|
|
26
27
|
isSource() {
|
|
27
28
|
return false;
|
|
28
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Report the one message which explains why this expression could not be
|
|
32
|
+
* turned into a source or a query.
|
|
33
|
+
*
|
|
34
|
+
* Every element in a source/query expression says something when it fails,
|
|
35
|
+
* so an outer element's generic complaint ("could not get source for
|
|
36
|
+
* query") would stack on top of the specific cause already reported
|
|
37
|
+
* beneath it. The message is therefore logged only when nothing in this
|
|
38
|
+
* subtree has spoken yet, and `errored` is set either way, which is what
|
|
39
|
+
* silences the elements above.
|
|
40
|
+
*
|
|
41
|
+
* This is not protection against logging the same message twice —
|
|
42
|
+
* `MalloyElement.log` already drops a repeat of one message at one
|
|
43
|
+
* location. It is one message per failed expression.
|
|
44
|
+
*
|
|
45
|
+
* The case it does not serve is two unrelated complaints about the same
|
|
46
|
+
* element: a second `sqLog` is dropped. Use `sqClaimError` for those.
|
|
47
|
+
*/
|
|
29
48
|
sqLog(code, parameters, options) {
|
|
30
49
|
if (this.isErrorFree()) {
|
|
31
50
|
this.logError(code, parameters, options);
|
|
@@ -33,6 +52,20 @@ class SourceQueryElement extends malloy_element_1.MalloyElement {
|
|
|
33
52
|
this.errored = true;
|
|
34
53
|
return code;
|
|
35
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Take the one error report this expression is allowed, for an element with
|
|
57
|
+
* more than one complaint to make. False means something below has already
|
|
58
|
+
* spoken. True means the caller owns the report and should `logError` each
|
|
59
|
+
* of its complaints; nothing above will speak after that.
|
|
60
|
+
*/
|
|
61
|
+
sqClaimError() {
|
|
62
|
+
if (!this.isErrorFree()) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
this.errored = true;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/** True until this element, or anything below it, has reported a failure. */
|
|
36
69
|
isErrorFree() {
|
|
37
70
|
if (this.errored) {
|
|
38
71
|
return false;
|
|
@@ -16,6 +16,8 @@ export declare class SQArrow extends SourceQueryElement {
|
|
|
16
16
|
readonly applyTo: SourceQueryElement;
|
|
17
17
|
readonly operation: View;
|
|
18
18
|
elementType: string;
|
|
19
|
+
asQuery?: QueryElement;
|
|
20
|
+
asSource?: Source;
|
|
19
21
|
constructor(applyTo: SourceQueryElement, operation: View);
|
|
20
22
|
getQuery(): QueryElement | undefined;
|
|
21
23
|
getSource(): Source | undefined;
|
|
@@ -26,6 +26,9 @@ class SQArrow extends source_query_element_1.SourceQueryElement {
|
|
|
26
26
|
this.elementType = 'sq-arrow';
|
|
27
27
|
}
|
|
28
28
|
getQuery() {
|
|
29
|
+
if (this.asQuery) {
|
|
30
|
+
return this.asQuery;
|
|
31
|
+
}
|
|
29
32
|
const lhs = this.applyTo.isSource()
|
|
30
33
|
? this.applyTo.getSource()
|
|
31
34
|
: this.applyTo.getQuery();
|
|
@@ -33,19 +36,22 @@ class SQArrow extends source_query_element_1.SourceQueryElement {
|
|
|
33
36
|
this.sqLog('failed-to-compute-arrow-source', 'Could not get LHS of arrow operation');
|
|
34
37
|
return;
|
|
35
38
|
}
|
|
36
|
-
|
|
37
|
-
this.has({ query:
|
|
38
|
-
return
|
|
39
|
+
this.asQuery = new query_arrow_1.QueryArrow(lhs, this.operation);
|
|
40
|
+
this.has({ query: this.asQuery });
|
|
41
|
+
return this.asQuery;
|
|
39
42
|
}
|
|
40
43
|
getSource() {
|
|
44
|
+
if (this.asSource) {
|
|
45
|
+
return this.asSource;
|
|
46
|
+
}
|
|
41
47
|
const query = this.getQuery();
|
|
42
48
|
if (!query) {
|
|
43
49
|
this.sqLog('failed-to-compute-source-from-query', "Couldn't comprehend query well enough to make a source");
|
|
44
50
|
return;
|
|
45
51
|
}
|
|
46
|
-
|
|
47
|
-
this.has({ asSource });
|
|
48
|
-
return asSource;
|
|
52
|
+
this.asSource = new query_source_1.QuerySource(query);
|
|
53
|
+
this.has({ asSource: this.asSource });
|
|
54
|
+
return this.asSource;
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
exports.SQArrow = SQArrow;
|
|
@@ -12,6 +12,8 @@ export declare class SQRefine extends SourceQueryElement {
|
|
|
12
12
|
readonly toRefine: SourceQueryElement;
|
|
13
13
|
readonly refine: View;
|
|
14
14
|
elementType: string;
|
|
15
|
+
asQuery?: QueryRefine;
|
|
16
|
+
asSource?: QuerySource;
|
|
15
17
|
constructor(toRefine: SourceQueryElement, refine: View);
|
|
16
18
|
getQuery(): QueryRefine | undefined;
|
|
17
19
|
getSource(): QuerySource | undefined;
|
|
@@ -23,6 +23,9 @@ class SQRefine extends source_query_element_1.SourceQueryElement {
|
|
|
23
23
|
this.elementType = 'sq-refine';
|
|
24
24
|
}
|
|
25
25
|
getQuery() {
|
|
26
|
+
if (this.asQuery) {
|
|
27
|
+
return this.asQuery;
|
|
28
|
+
}
|
|
26
29
|
if (this.toRefine.isSource()) {
|
|
27
30
|
if (this.toRefine instanceof sq_reference_1.SQReference) {
|
|
28
31
|
this.sqLog('illegal-refinement-of-source', `Cannot add view refinements to '${this.toRefine.ref.refString}' because it is a source`);
|
|
@@ -34,17 +37,20 @@ class SQRefine extends source_query_element_1.SourceQueryElement {
|
|
|
34
37
|
}
|
|
35
38
|
const refinedQuery = this.toRefine.getQuery();
|
|
36
39
|
if (refinedQuery) {
|
|
37
|
-
|
|
38
|
-
this.has({ query:
|
|
39
|
-
return
|
|
40
|
+
this.asQuery = new query_refine_1.QueryRefine(refinedQuery, this.refine);
|
|
41
|
+
this.has({ query: this.asQuery });
|
|
42
|
+
return this.asQuery;
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
getSource() {
|
|
46
|
+
if (this.asSource) {
|
|
47
|
+
return this.asSource;
|
|
48
|
+
}
|
|
43
49
|
const query = this.getQuery();
|
|
44
50
|
if (query) {
|
|
45
|
-
|
|
46
|
-
this.has({ queryAsSource });
|
|
47
|
-
return
|
|
51
|
+
this.asSource = new query_source_1.QuerySource(query);
|
|
52
|
+
this.has({ queryAsSource: this.asSource });
|
|
53
|
+
return this.asSource;
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
}
|
|
@@ -10,6 +10,7 @@ import { QueryRaw } from '../query-elements/query-raw';
|
|
|
10
10
|
export declare class SQSource extends SourceQueryElement {
|
|
11
11
|
readonly theSource: Source;
|
|
12
12
|
elementType: string;
|
|
13
|
+
asQuery?: QueryRaw;
|
|
13
14
|
constructor(theSource: Source);
|
|
14
15
|
isSource(): boolean;
|
|
15
16
|
getSource(): Source;
|
|
@@ -27,10 +27,13 @@ class SQSource extends source_query_element_1.SourceQueryElement {
|
|
|
27
27
|
return this.theSource;
|
|
28
28
|
}
|
|
29
29
|
getQuery() {
|
|
30
|
+
if (this.asQuery) {
|
|
31
|
+
return this.asQuery;
|
|
32
|
+
}
|
|
30
33
|
if (this.theSource instanceof sql_source_1.SQLSource) {
|
|
31
|
-
|
|
32
|
-
this.has({ rawQuery });
|
|
33
|
-
return
|
|
34
|
+
this.asQuery = new query_raw_1.QueryRaw(this.theSource);
|
|
35
|
+
this.has({ rawQuery: this.asQuery });
|
|
36
|
+
return this.asQuery;
|
|
34
37
|
}
|
|
35
38
|
else {
|
|
36
39
|
this.sqLog('invalid-source-as-query', 'This source cannot be used as a query');
|
|
@@ -8,6 +8,6 @@ export declare class SQLString extends MalloyElement {
|
|
|
8
8
|
containsQueries: boolean;
|
|
9
9
|
complete(): void;
|
|
10
10
|
push(el: string | MalloyElement): void;
|
|
11
|
-
sqlPhrases(): [boolean, SQLPhraseSegment[]];
|
|
11
|
+
sqlPhrases(forConnection: string): [boolean, SQLPhraseSegment[]];
|
|
12
12
|
}
|
|
13
13
|
export {};
|
|
@@ -35,7 +35,7 @@ class SQLString extends malloy_element_1.MalloyElement {
|
|
|
35
35
|
el.logError('invalid-sql-source-interpolation', 'This element is not legal inside an SQL string');
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
sqlPhrases() {
|
|
38
|
+
sqlPhrases(forConnection) {
|
|
39
39
|
const ret = [];
|
|
40
40
|
let valid = true;
|
|
41
41
|
for (const el of this.elements) {
|
|
@@ -47,19 +47,39 @@ class SQLString extends malloy_element_1.MalloyElement {
|
|
|
47
47
|
const source = el.getSource();
|
|
48
48
|
if (source) {
|
|
49
49
|
const sourceDef = source.getSourceDef(undefined);
|
|
50
|
-
|
|
50
|
+
const connectionMismatch = sourceDef.connection !== forConnection;
|
|
51
|
+
const persistable = (0, malloy_types_1.isPersistableSourceDef)(sourceDef);
|
|
52
|
+
if (!connectionMismatch && persistable) {
|
|
51
53
|
ret.push(sourceDef);
|
|
52
54
|
continue;
|
|
53
55
|
}
|
|
56
|
+
valid = false;
|
|
57
|
+
// A source can be wrong in both ways at once, and both are worth
|
|
58
|
+
// saying, so claim the report and then say everything.
|
|
59
|
+
if (el.sqClaimError()) {
|
|
60
|
+
if (connectionMismatch) {
|
|
61
|
+
el.logError('sql-source-connection-mismatch', `Source is on connection ${sourceDef.connection}, but this SQL is for ${forConnection}`);
|
|
62
|
+
}
|
|
63
|
+
if (!persistable) {
|
|
64
|
+
el.logError('invalid-sql-source-interpolation', 'Source is not persistable, cannot be used in SQL');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
el.sqLog('failed-to-expand-sql-source', 'Cannot expand into a query');
|
|
70
|
+
valid = false;
|
|
54
71
|
}
|
|
55
|
-
el.sqLog('failed-to-expand-sql-source', 'Cannot expand into a query');
|
|
56
|
-
valid = false;
|
|
57
72
|
}
|
|
58
73
|
else {
|
|
59
74
|
// Not a source - try as a query
|
|
60
75
|
const queryObject = el.getQuery();
|
|
61
76
|
if (queryObject) {
|
|
62
|
-
|
|
77
|
+
const queryComp = queryObject.queryComp(false, false);
|
|
78
|
+
if (queryComp.inputStruct.connection !== forConnection) {
|
|
79
|
+
el.sqLog('sql-source-connection-mismatch', `Query is on connection ${queryComp.inputStruct.connection}, but this SQL is for ${forConnection}`);
|
|
80
|
+
valid = false;
|
|
81
|
+
}
|
|
82
|
+
ret.push(queryComp.query);
|
|
63
83
|
}
|
|
64
84
|
else {
|
|
65
85
|
el.sqLog('failed-to-expand-sql-source', 'Cannot expand into a query');
|
|
@@ -10,13 +10,6 @@ const malloy_types_1 = require("../../../model/malloy_types");
|
|
|
10
10
|
const source_def_utils_1 = require("../../../model/source_def_utils");
|
|
11
11
|
const persist_utils_1 = require("../../../model/persist_utils");
|
|
12
12
|
const utils_1 = require("../../../model/utils");
|
|
13
|
-
/** Walk BuildNode tree and collect all sourceIDs */
|
|
14
|
-
function collectSourceIDs(nodes, into) {
|
|
15
|
-
for (const node of nodes) {
|
|
16
|
-
into.add(node.sourceID);
|
|
17
|
-
collectSourceIDs(node.dependsOn, into);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
13
|
class ImportSourceName extends malloy_element_1.MalloyElement {
|
|
21
14
|
constructor(text) {
|
|
22
15
|
super();
|
|
@@ -160,10 +153,14 @@ class ImportStatement extends malloy_element_1.ListOf {
|
|
|
160
153
|
const importMe = { ...sourceEntry };
|
|
161
154
|
importMe.as = dstName;
|
|
162
155
|
doc.setEntry(dstName, { entry: importMe, exported: false });
|
|
163
|
-
//
|
|
156
|
+
// Every source the walk touched, routes included — not just the
|
|
157
|
+
// persistent ones. A `#@ -persist` wrapper that adds a join is
|
|
158
|
+
// not a table, but it can be the only way to reach the tables
|
|
159
|
+
// under it, and this model has to be able to take the same route.
|
|
164
160
|
if ((0, malloy_types_1.isSourceDef)(importMe) && (0, malloy_types_1.isPersistableSourceDef)(importMe)) {
|
|
165
|
-
const
|
|
166
|
-
|
|
161
|
+
for (const found of (0, persist_utils_1.walkPersistentDependencies)([importMe], importedModel)) {
|
|
162
|
+
neededSourceIDs.add(found.sourceID);
|
|
163
|
+
}
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
}
|
|
@@ -13,20 +13,53 @@ export declare enum ATNodeType {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Root node for any element in an expression. These essentially
|
|
16
|
-
* create a sub-tree in the larger AST.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* create a sub-tree in the larger AST. An ExpressionDef, when
|
|
17
|
+
* given a FieldSpace, can be evaluated to produce an ExprValue
|
|
18
|
+
* which is the IR for an Expr along with its type and other metadata.
|
|
19
19
|
*/
|
|
20
20
|
export declare abstract class ExpressionDef extends MalloyElement {
|
|
21
21
|
abstract elementType: string;
|
|
22
22
|
granular(): boolean;
|
|
23
23
|
/**
|
|
24
|
-
* Returns the "translation" or
|
|
24
|
+
* Returns the "translation" or Expr tree for SQL generation. When asking
|
|
25
25
|
* for a translation you may pass the types you can accept, allowing
|
|
26
26
|
* the translation code a chance to convert to match your expectations
|
|
27
27
|
* @param space Namespace for looking up field references
|
|
28
|
+
*
|
|
29
|
+
* THE RETURNED ExprValue IS SHARED -- TREAT IT AS IMMUTABLE. Asking twice
|
|
30
|
+
* yields the same object, so to derive a value from one, build a new one:
|
|
31
|
+
* `{...operand, type: 'boolean'}` or `computedExprValue({…, from: [operand]})`.
|
|
32
|
+
*
|
|
33
|
+
* DO NOT OVERRIDE THIS. Nodes implement `computeExpression`; an override
|
|
34
|
+
* here bypasses the memo, which for `+`/`-` chains is the difference
|
|
35
|
+
* between linear and exponential compile time.
|
|
28
36
|
*/
|
|
29
|
-
|
|
37
|
+
getExpression(fs: FieldSpace): ExprValue;
|
|
38
|
+
/**
|
|
39
|
+
* The last value this node computed, and what it was computed against.
|
|
40
|
+
* Three states, distinguished by memoGen:
|
|
41
|
+
*
|
|
42
|
+
* memoFs undefined -- nothing computed, or abandoned
|
|
43
|
+
* memoFs set, memoGen undefined -- computing right now, and only that,
|
|
44
|
+
* since abandoning clears memoFs
|
|
45
|
+
* memoFs set, memoGen set -- memoValue is that computation's result
|
|
46
|
+
*
|
|
47
|
+
* Both halves of the stamp are needed: a node can be evaluated under more
|
|
48
|
+
* than one field space -- ConstantExpression evaluates its child against a
|
|
49
|
+
* ConstantFieldSpace whatever it was handed -- and a field space can rebind
|
|
50
|
+
* a name under us.
|
|
51
|
+
*
|
|
52
|
+
* One slot, not a map. A node which alternates between two field spaces
|
|
53
|
+
* simply misses and recomputes, which costs time and never correctness.
|
|
54
|
+
*/
|
|
55
|
+
private memoFs?;
|
|
56
|
+
private memoGen?;
|
|
57
|
+
private memoValue?;
|
|
58
|
+
/**
|
|
59
|
+
* Evaluate this node. Implemented by every expression node; called only
|
|
60
|
+
* by `getExpression` above, never directly.
|
|
61
|
+
*/
|
|
62
|
+
protected abstract computeExpression(fs: FieldSpace): ExprValue;
|
|
30
63
|
legalChildTypes: import("../../..").TypeDesc[];
|
|
31
64
|
/**
|
|
32
65
|
* Some operators want to give the right hand value a chance to
|
|
@@ -45,13 +78,19 @@ export declare abstract class ExpressionDef extends MalloyElement {
|
|
|
45
78
|
typeCheck(eNode: ExpressionDef, eVal: ExprValue): boolean;
|
|
46
79
|
drillExpression(): Malloy.Expression | undefined;
|
|
47
80
|
/**
|
|
48
|
-
* This is the operation which makes partial comparison and value trees work
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* the
|
|
81
|
+
* This is the operation which makes partial comparison and value trees work.
|
|
82
|
+
* `this` is the RIGHT operand; the left arrives here as an argument. All of
|
|
83
|
+
* the magic of malloy expressions eventually flows through here, where an
|
|
84
|
+
* operator is applied to two values -- depending on the operator and the
|
|
85
|
+
* value types that may transform the values or even the operator.
|
|
86
|
+
*
|
|
87
|
+
* Specialized nodes like alternation trees and partial comparisons override
|
|
88
|
+
* this to control how the application gets generated. They are the reason
|
|
89
|
+
* the right operand is in charge: a partial has no bound left operand, and
|
|
90
|
+
* only learns it here.
|
|
52
91
|
* @param fs The symbol table
|
|
53
92
|
* @param op The operator being applied
|
|
54
|
-
* @param
|
|
93
|
+
* @param left The "other" (besides 'this') value
|
|
55
94
|
* @return The translated expression
|
|
56
95
|
*/
|
|
57
96
|
apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef, _warnOnComplexTree?: boolean): ExprValue;
|
|
@@ -69,20 +108,8 @@ export declare class ExprDuration extends ExpressionDef {
|
|
|
69
108
|
legalChildTypes: import("../../..").TypeDesc[];
|
|
70
109
|
constructor(n: ExpressionDef, timeframe: TimestampUnit);
|
|
71
110
|
apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef): ExprValue;
|
|
72
|
-
|
|
111
|
+
protected computeExpression(fs: FieldSpace): ExprValue;
|
|
73
112
|
}
|
|
74
113
|
export type MorphicType = 'date' | 'timestamp';
|
|
75
114
|
export declare function getMorphicValue(mv: ExprValue, mt: MorphicType): ExprValue | undefined;
|
|
76
|
-
/**
|
|
77
|
-
* All of the magic of malloy expressions eventually flows to here,
|
|
78
|
-
* where an operator is applied to two values. Depending on the
|
|
79
|
-
* operator and value types this may involve transformations of
|
|
80
|
-
* the values or even the operator.
|
|
81
|
-
* @param fs FieldSpace for the symbols
|
|
82
|
-
* @param left Left value
|
|
83
|
-
* @param op The operator
|
|
84
|
-
* @param right Right Value
|
|
85
|
-
* @return ExprValue of the expression
|
|
86
|
-
*/
|
|
87
|
-
export declare function applyBinary(fs: FieldSpace, left: ExpressionDef, op: BinaryMalloyOperator, right: ExpressionDef): ExprValue;
|
|
88
115
|
export declare function checkFilterExpression(logTo: MalloyElement, ft: FilterExprType, fexpr: Expr): void;
|