@malloydata/malloy 0.0.391 → 0.0.393
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/asynchronous.js +0 -3
- package/dist/api/foundation/compile.d.ts +1 -1
- package/dist/api/foundation/config.d.ts +80 -8
- package/dist/api/foundation/config.js +151 -69
- package/dist/api/foundation/config_compile.js +27 -35
- package/dist/api/foundation/config_discover.js +5 -9
- package/dist/api/foundation/config_overlays.d.ts +6 -0
- package/dist/api/foundation/config_overlays.js +12 -0
- package/dist/api/foundation/config_resolve.d.ts +4 -1
- package/dist/api/foundation/config_resolve.js +64 -4
- package/dist/api/foundation/core.d.ts +75 -2
- package/dist/api/foundation/core.js +104 -6
- package/dist/api/foundation/index.d.ts +2 -0
- package/dist/api/foundation/readers.js +1 -1
- package/dist/api/foundation/runtime.d.ts +68 -2
- package/dist/api/foundation/runtime.js +212 -10
- package/dist/api/foundation/types.d.ts +2 -1
- package/dist/index.d.ts +3 -1
- package/dist/lang/ast/ast-utils.js +0 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-aggregate-function.js +9 -8
- package/dist/lang/ast/expressions/expr-coalesce.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-coalesce.js +2 -3
- package/dist/lang/ast/expressions/expr-count-distinct.js +1 -1
- package/dist/lang/ast/expressions/expr-count.js +6 -4
- package/dist/lang/ast/expressions/expr-filter-expr.js +0 -1
- package/dist/lang/ast/expressions/expr-func.js +9 -4
- package/dist/lang/ast/expressions/expr-given.d.ts +18 -0
- package/dist/lang/ast/expressions/expr-given.js +69 -0
- package/dist/lang/ast/expressions/expr-granular-time.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-id-reference.js +3 -2
- package/dist/lang/ast/expressions/expr-now.js +0 -1
- package/dist/lang/ast/expressions/expr-props.d.ts +132 -132
- package/dist/lang/ast/expressions/expr-props.js +2 -2
- package/dist/lang/ast/expressions/expr-ungroup.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-ungroup.js +4 -4
- package/dist/lang/ast/expressions/for-range.d.ts +1 -1
- package/dist/lang/ast/expressions/function-ordering.d.ts +1 -1
- package/dist/lang/ast/expressions/function-ordering.js +2 -2
- package/dist/lang/ast/expressions/time-literal.d.ts +3 -3
- package/dist/lang/ast/field-space/include-utils.js +2 -2
- package/dist/lang/ast/field-space/index-field-space.js +18 -23
- package/dist/lang/ast/field-space/passthrough-space.d.ts +1 -1
- package/dist/lang/ast/field-space/query-spaces.d.ts +6 -2
- package/dist/lang/ast/field-space/query-spaces.js +29 -19
- package/dist/lang/ast/field-space/reference-field.js +1 -1
- package/dist/lang/ast/field-space/rename-space-field.d.ts +1 -1
- package/dist/lang/ast/field-space/rename-space-field.js +2 -2
- package/dist/lang/ast/field-space/struct-space-field-base.js +2 -3
- package/dist/lang/ast/index.d.ts +2 -0
- package/dist/lang/ast/index.js +2 -0
- package/dist/lang/ast/query-builders/index-builder.d.ts +1 -1
- package/dist/lang/ast/query-builders/index-builder.js +4 -3
- package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -2
- package/dist/lang/ast/query-builders/reduce-builder.js +4 -5
- package/dist/lang/ast/query-elements/query-arrow.js +3 -2
- package/dist/lang/ast/query-elements/query-base.d.ts +1 -1
- package/dist/lang/ast/query-elements/query-base.js +1 -1
- package/dist/lang/ast/query-elements/query-refine.js +3 -1
- package/dist/lang/ast/query-items/field-declaration.js +2 -2
- package/dist/lang/ast/query-properties/drill.js +6 -6
- package/dist/lang/ast/query-properties/filters.js +2 -2
- package/dist/lang/ast/query-properties/nest.js +3 -3
- package/dist/lang/ast/source-elements/composite-source.js +5 -3
- package/dist/lang/ast/source-elements/named-source.js +4 -0
- package/dist/lang/ast/source-elements/sql-source.js +2 -2
- package/dist/lang/ast/source-elements/table-source.js +3 -1
- package/dist/lang/ast/source-properties/join.js +4 -4
- package/dist/lang/ast/source-query-elements/sq-reference.js +2 -1
- package/dist/lang/ast/statements/define-given.d.ts +23 -0
- package/dist/lang/ast/statements/define-given.js +163 -0
- package/dist/lang/ast/statements/import-statement.js +72 -9
- package/dist/lang/ast/typedesc-utils.d.ts +3 -1
- package/dist/lang/ast/typedesc-utils.js +4 -47
- package/dist/lang/ast/types/expr-value.js +2 -3
- package/dist/lang/ast/types/expression-def.d.ts +2 -2
- package/dist/lang/ast/types/expression-def.js +2 -2
- package/dist/lang/ast/types/malloy-element.d.ts +5 -15
- package/dist/lang/ast/types/malloy-element.js +113 -1
- package/dist/lang/ast/types/space-field.js +7 -9
- package/dist/lang/ast/view-elements/reference-view.js +6 -5
- package/dist/lang/ast/view-elements/refine-utils.js +1 -1
- package/dist/lang/composite-source-utils.d.ts +30 -15
- package/dist/lang/composite-source-utils.js +234 -64
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +171 -169
- package/dist/lang/lib/Malloy/MalloyLexer.js +1194 -1178
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +408 -334
- package/dist/lang/lib/Malloy/MalloyParser.js +3062 -2561
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +68 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +43 -0
- package/dist/lang/malloy-to-ast.d.ts +13 -1
- package/dist/lang/malloy-to-ast.js +90 -11
- package/dist/lang/parse-log.d.ts +8 -0
- package/dist/lang/prettify/filter-type.d.ts +3 -0
- package/dist/lang/prettify/filter-type.js +38 -0
- package/dist/lang/prettify/formatter.js +6 -0
- package/dist/lang/prettify/inline-renderer.js +20 -0
- package/dist/lang/prettify/rules.d.ts +1 -1
- package/dist/lang/prettify/rules.js +1 -0
- package/dist/lang/prettify/sections.js +2 -0
- package/dist/lang/prettify/tokens.js +2 -0
- package/dist/lang/test/expr-to-str.js +2 -0
- package/dist/lang/test/parse-expects.d.ts +1 -0
- package/dist/lang/test/parse-expects.js +27 -10
- package/dist/model/constant_expression_compiler.js +1 -0
- package/dist/model/expression_compiler.d.ts +2 -1
- package/dist/model/expression_compiler.js +41 -1
- package/dist/model/given_binding.d.ts +2 -0
- package/dist/model/given_binding.js +204 -0
- package/dist/model/index.d.ts +1 -1
- package/dist/model/index.js +2 -1
- package/dist/model/malloy_types.d.ts +163 -36
- package/dist/model/malloy_types.js +97 -0
- package/dist/model/query_model_contract.d.ts +2 -1
- package/dist/model/query_model_impl.d.ts +2 -1
- package/dist/model/query_model_impl.js +7 -0
- package/dist/model/query_node.d.ts +2 -1
- package/dist/model/source_def_utils.d.ts +2 -1
- package/dist/model/source_def_utils.js +4 -0
- package/dist/model/utils.d.ts +14 -1
- package/dist/model/utils.js +41 -0
- package/dist/to_stable.js +1 -1
- package/dist/util/closest_match.d.ts +9 -0
- package/dist/util/closest_match.js +47 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -46,7 +46,8 @@ class FluentState {
|
|
|
46
46
|
* An environment for compiling and running Malloy queries.
|
|
47
47
|
*/
|
|
48
48
|
class Runtime {
|
|
49
|
-
constructor({ urlReader, connections, connection, config, buildManifest, eventStream, cacheManager, }) {
|
|
49
|
+
constructor({ urlReader, connections, connection, config, buildManifest, eventStream, cacheManager, givens, }) {
|
|
50
|
+
var _a, _b;
|
|
50
51
|
this.isTestRuntime = false;
|
|
51
52
|
if (config !== undefined) {
|
|
52
53
|
this._config = config;
|
|
@@ -68,6 +69,19 @@ class Runtime {
|
|
|
68
69
|
this._buildManifest = buildManifest;
|
|
69
70
|
this._eventStream = eventStream;
|
|
70
71
|
this._cacheManager = cacheManager;
|
|
72
|
+
if (givens) {
|
|
73
|
+
for (const [name, value] of Object.entries(givens)) {
|
|
74
|
+
if (value === undefined) {
|
|
75
|
+
throw new Error(`Runtime givens.${name}: explicit undefined is not a valid value. ` +
|
|
76
|
+
'Omit the key to defer to declaration default or the file layer; ' +
|
|
77
|
+
'use null for an explicit null value.');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this._constructorGivensMap = givens
|
|
82
|
+
? new Map(Object.entries(givens))
|
|
83
|
+
: new Map();
|
|
84
|
+
this._finalizedGivensSet = new Set((_b = (_a = this._config) === null || _a === void 0 ? void 0 : _a.finalizeGivens) !== null && _b !== void 0 ? _b : []);
|
|
71
85
|
}
|
|
72
86
|
/**
|
|
73
87
|
* @return The `CacheManager` for this runtime instance.
|
|
@@ -93,6 +107,49 @@ class Runtime {
|
|
|
93
107
|
get eventStream() {
|
|
94
108
|
return this._eventStream;
|
|
95
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Constructor-supplied givens, exposed for the materializer's per-query
|
|
112
|
+
* merge. Underscore-prefixed because it's the constructor layer only —
|
|
113
|
+
* use `getGivens()` for the full file+constructor view a caller usually
|
|
114
|
+
* wants.
|
|
115
|
+
*
|
|
116
|
+
* @internal Accessed from QueryMaterializer.
|
|
117
|
+
*/
|
|
118
|
+
get _constructorGivens() {
|
|
119
|
+
return this._constructorGivensMap;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The runtime's effective givens — file (from `config.givensPath`,
|
|
123
|
+
* lazily loaded) merged with the constructor `givens:` option, with
|
|
124
|
+
* the constructor winning per-key. Per-query supply via
|
|
125
|
+
* `.run({ givens: ... })` is *not* included; that's a per-call
|
|
126
|
+
* argument, not runtime state.
|
|
127
|
+
*
|
|
128
|
+
* Async because the file may not yet be loaded; subsequent calls share
|
|
129
|
+
* the cached promise.
|
|
130
|
+
*/
|
|
131
|
+
async getGivens() {
|
|
132
|
+
const file = await this._resolveGivens();
|
|
133
|
+
const merged = new Map();
|
|
134
|
+
if (file) {
|
|
135
|
+
for (const [k, v] of Object.entries(file))
|
|
136
|
+
merged.set(k, v);
|
|
137
|
+
}
|
|
138
|
+
for (const [k, v] of this._constructorGivensMap)
|
|
139
|
+
merged.set(k, v);
|
|
140
|
+
return merged;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Surface names of givens locked at the runtime layer (the resolved set
|
|
144
|
+
* the `config.finalizeGivens` directive produced). Per-query supply for
|
|
145
|
+
* these names throws; `Model.givens` and `PreparedQuery.givens` filter
|
|
146
|
+
* them out so introspection-driven UIs don't render editors for them.
|
|
147
|
+
*
|
|
148
|
+
* @internal Accessed from QueryMaterializer and Model construction.
|
|
149
|
+
*/
|
|
150
|
+
get _finalizedGivens() {
|
|
151
|
+
return this._finalizedGivensSet;
|
|
152
|
+
}
|
|
96
153
|
/**
|
|
97
154
|
* Setter — install an explicit build manifest for persist source
|
|
98
155
|
* substitution. From this point on, compiled queries resolve persist
|
|
@@ -142,14 +199,14 @@ class Runtime {
|
|
|
142
199
|
if (this._buildManifest) {
|
|
143
200
|
return Promise.resolve(this._buildManifest);
|
|
144
201
|
}
|
|
145
|
-
const
|
|
146
|
-
if (!
|
|
202
|
+
const urlStr = (_a = this._config) === null || _a === void 0 ? void 0 : _a.manifestURL;
|
|
203
|
+
if (!urlStr)
|
|
147
204
|
return Promise.resolve(undefined);
|
|
148
205
|
if (!this._resolvedBuildManifestPromise) {
|
|
149
206
|
this._resolvedBuildManifestPromise = (async () => {
|
|
150
207
|
let text;
|
|
151
208
|
try {
|
|
152
|
-
const result = await this._urlReader.readURL(
|
|
209
|
+
const result = await this._urlReader.readURL(new URL(urlStr));
|
|
153
210
|
text = typeof result === 'string' ? result : result.contents;
|
|
154
211
|
}
|
|
155
212
|
catch {
|
|
@@ -173,13 +230,68 @@ class Runtime {
|
|
|
173
230
|
const msg = e instanceof Error ? e.message : String(e);
|
|
174
231
|
return {
|
|
175
232
|
entries: {},
|
|
176
|
-
loadError: `Manifest file at ${
|
|
233
|
+
loadError: `Manifest file at ${urlStr} could not be parsed: ${msg}`,
|
|
177
234
|
};
|
|
178
235
|
}
|
|
179
236
|
})();
|
|
180
237
|
}
|
|
181
238
|
return this._resolvedBuildManifestPromise;
|
|
182
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Resolve the per-runtime givens map from `config.givensURL` (the file
|
|
242
|
+
* `givensPath` points at). Lazy and cached as a Promise — first compile
|
|
243
|
+
* triggers the read, subsequent compiles share the result.
|
|
244
|
+
*
|
|
245
|
+
* Stricter error policy than `_resolveBuildManifest`: a missing file or
|
|
246
|
+
* malformed JSON throws. Per design, the per-runtime givens layer is a
|
|
247
|
+
* configured contract, not an opportunistic read; a misconfigured path
|
|
248
|
+
* should fail loudly at the first compile, not silently degrade.
|
|
249
|
+
*
|
|
250
|
+
* Returns `undefined` only when no `givensURL` is configured.
|
|
251
|
+
*
|
|
252
|
+
* @internal Accessed from QueryMaterializer.
|
|
253
|
+
*/
|
|
254
|
+
_resolveGivens() {
|
|
255
|
+
var _a;
|
|
256
|
+
const urlStr = (_a = this._config) === null || _a === void 0 ? void 0 : _a.givensURL;
|
|
257
|
+
if (!urlStr)
|
|
258
|
+
return Promise.resolve(undefined);
|
|
259
|
+
if (!this._resolvedGivensPromise) {
|
|
260
|
+
this._resolvedGivensPromise = (async () => {
|
|
261
|
+
let text;
|
|
262
|
+
try {
|
|
263
|
+
const result = await this._urlReader.readURL(new URL(urlStr));
|
|
264
|
+
text = typeof result === 'string' ? result : result.contents;
|
|
265
|
+
}
|
|
266
|
+
catch (e) {
|
|
267
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
268
|
+
throw new Error(`givens: failed to read givens file at ${urlStr}: ${msg}`);
|
|
269
|
+
}
|
|
270
|
+
let parsed;
|
|
271
|
+
try {
|
|
272
|
+
parsed = JSON.parse(text);
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
276
|
+
throw new Error(`givens: failed to parse JSON at ${urlStr}: ${msg}`);
|
|
277
|
+
}
|
|
278
|
+
if (!isGivensObject(parsed)) {
|
|
279
|
+
const got = Array.isArray(parsed)
|
|
280
|
+
? 'array'
|
|
281
|
+
: parsed === null
|
|
282
|
+
? 'null'
|
|
283
|
+
: typeof parsed;
|
|
284
|
+
throw new Error(`givens: file at ${urlStr} must be a JSON object of name → value pairs, got ${got}`);
|
|
285
|
+
}
|
|
286
|
+
return parsed;
|
|
287
|
+
})();
|
|
288
|
+
}
|
|
289
|
+
return this._resolvedGivensPromise;
|
|
290
|
+
}
|
|
291
|
+
/** @internal */
|
|
292
|
+
_invalidateGivensCache() {
|
|
293
|
+
this._resolvedGivensPromise = undefined;
|
|
294
|
+
}
|
|
183
295
|
/**
|
|
184
296
|
* The virtual map for virtual source resolution.
|
|
185
297
|
* When set, compiled queries automatically resolve virtual sources
|
|
@@ -244,7 +356,7 @@ class Runtime {
|
|
|
244
356
|
}
|
|
245
357
|
const compilable = source instanceof URL ? { url: source } : { source };
|
|
246
358
|
return new ModelMaterializer(this, async () => {
|
|
247
|
-
|
|
359
|
+
const m = await compile_1.Malloy.compile({
|
|
248
360
|
...compilable,
|
|
249
361
|
urlReader: this.urlReader,
|
|
250
362
|
connections: this.connections,
|
|
@@ -255,15 +367,34 @@ class Runtime {
|
|
|
255
367
|
testEnvironment: options === null || options === void 0 ? void 0 : options.testEnvironment,
|
|
256
368
|
cacheManager: this.cacheManager,
|
|
257
369
|
});
|
|
370
|
+
return this._withRuntimeContext(m);
|
|
258
371
|
}, options);
|
|
259
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Re-wrap a `Model` produced by `Malloy.compile` with this runtime's
|
|
375
|
+
* `RuntimeContext` so context-sensitive Model methods (currently
|
|
376
|
+
* `Model.givens` filtering finalized names; future runtime-aware
|
|
377
|
+
* concerns) work correctly. No-op when there's nothing in the context.
|
|
378
|
+
*
|
|
379
|
+
* @internal Accessed from `ModelMaterializer.extendModel` and Runtime
|
|
380
|
+
* loadModel paths.
|
|
381
|
+
*/
|
|
382
|
+
_withRuntimeContext(m) {
|
|
383
|
+
if (this._finalizedGivensSet.size === 0)
|
|
384
|
+
return m;
|
|
385
|
+
return new core_1.Model(m._modelDef, m.problems, m.fromSources, m.getExistingQueryModel(), {
|
|
386
|
+
finalizedGivens: this._finalizedGivensSet,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
260
389
|
// TODO Consider formalizing this. Perhaps as a `withModel` method,
|
|
261
390
|
// as well as a `Model.fromModelDefinition` if we choose to expose
|
|
262
391
|
// `ModelDef` to the world formally. For now, this should only
|
|
263
392
|
// be used in tests.
|
|
264
393
|
_loadModelFromModelDef(modelDef, options) {
|
|
265
394
|
return new ModelMaterializer(this, async () => {
|
|
266
|
-
return new core_1.Model(modelDef, [], []
|
|
395
|
+
return new core_1.Model(modelDef, [], [], undefined, this._finalizedGivensSet.size > 0
|
|
396
|
+
? { finalizedGivens: this._finalizedGivensSet }
|
|
397
|
+
: undefined);
|
|
267
398
|
}, options);
|
|
268
399
|
}
|
|
269
400
|
/**
|
|
@@ -507,7 +638,7 @@ class ModelMaterializer extends FluentState {
|
|
|
507
638
|
testEnvironment: options === null || options === void 0 ? void 0 : options.testEnvironment,
|
|
508
639
|
...this.compileQueryOptions,
|
|
509
640
|
});
|
|
510
|
-
return queryModel;
|
|
641
|
+
return this.runtime._withRuntimeContext(queryModel);
|
|
511
642
|
}, options);
|
|
512
643
|
}
|
|
513
644
|
async search(sourceName, searchTerm, limit = 1000, searchField = undefined) {
|
|
@@ -691,7 +822,7 @@ class QueryMaterializer extends FluentState {
|
|
|
691
822
|
*/
|
|
692
823
|
loadPreparedResult(options) {
|
|
693
824
|
return this.makePreparedResultMaterializer(async () => {
|
|
694
|
-
var _a, _b;
|
|
825
|
+
var _a, _b, _c;
|
|
695
826
|
const preparedQuery = await this.materialize();
|
|
696
827
|
const mergedOptions = {
|
|
697
828
|
eventStream: this.eventStream,
|
|
@@ -735,7 +866,58 @@ class QueryMaterializer extends FluentState {
|
|
|
735
866
|
}
|
|
736
867
|
// Use virtualMap from options if provided, otherwise fall back to Runtime's.
|
|
737
868
|
const virtualMap = (_b = mergedOptions.virtualMap) !== null && _b !== void 0 ? _b : this.runtime.virtualMap;
|
|
738
|
-
//
|
|
869
|
+
// Per-query supply for a finalized given is rejected at API entry
|
|
870
|
+
// — the finalized-givens set is the runtime's "this can't be
|
|
871
|
+
// overridden by the caller" guarantee. Fail before any IO so misuse
|
|
872
|
+
// is loud.
|
|
873
|
+
const finalizedSet = this.runtime._finalizedGivens;
|
|
874
|
+
if (finalizedSet.size > 0 && mergedOptions.givens) {
|
|
875
|
+
for (const name of Object.keys(mergedOptions.givens)) {
|
|
876
|
+
if (finalizedSet.has(name)) {
|
|
877
|
+
throw new Error(`Cannot supply '${name}' per-query: it is finalized at the runtime layer (config.finalizeGivens).`);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
// Three layers of givens, merged per-key in precedence order:
|
|
882
|
+
// 1. config.givensURL file (lazy + cached)
|
|
883
|
+
// 2. Runtime constructor `givens:` option
|
|
884
|
+
// 3. Per-query supply via `.run({givens: ...})`
|
|
885
|
+
// Higher-numbered layers win on collision. Each layer is optional;
|
|
886
|
+
// the merge collapses to undefined when all three are absent.
|
|
887
|
+
const fileGivens = await this.runtime._resolveGivens();
|
|
888
|
+
const constructorGivens = mapToRecord(this.runtime._constructorGivens);
|
|
889
|
+
const haveAny = fileGivens || constructorGivens || mergedOptions.givens;
|
|
890
|
+
const mergedGivens = haveAny
|
|
891
|
+
? { ...fileGivens, ...constructorGivens, ...mergedOptions.givens }
|
|
892
|
+
: undefined;
|
|
893
|
+
// Query-scoped validation: of the givens THIS query references,
|
|
894
|
+
// any that are finalized must have a value somewhere (file or
|
|
895
|
+
// constructor). One config covers a project; individual files
|
|
896
|
+
// declare overlapping but distinct given sets; an unrelated query
|
|
897
|
+
// shouldn't fail because some other file's given is in the
|
|
898
|
+
// finalize list without a value. The per-query rejection above is
|
|
899
|
+
// the actual security primitive; this check is the sanity net for
|
|
900
|
+
// "you locked it but forgot to supply it."
|
|
901
|
+
const queryGivenUsage = (_c = preparedQuery._query.givenUsage) !== null && _c !== void 0 ? _c : [];
|
|
902
|
+
if (finalizedSet.size > 0 && queryGivenUsage.length > 0) {
|
|
903
|
+
const referencedIds = new Set(queryGivenUsage.map(g => g.id));
|
|
904
|
+
const missing = [];
|
|
905
|
+
for (const [surfaceName, entry] of Object.entries(preparedQuery._modelDef.contents)) {
|
|
906
|
+
if (entry.type !== 'given')
|
|
907
|
+
continue;
|
|
908
|
+
if (!referencedIds.has(entry.id))
|
|
909
|
+
continue;
|
|
910
|
+
if (!finalizedSet.has(surfaceName))
|
|
911
|
+
continue;
|
|
912
|
+
if (mergedGivens && surfaceName in mergedGivens)
|
|
913
|
+
continue;
|
|
914
|
+
missing.push(surfaceName);
|
|
915
|
+
}
|
|
916
|
+
if (missing.length > 0) {
|
|
917
|
+
throw new Error(`Query references finalized given(s) with no resolved value: ${missing.join(', ')}. Each finalized given the query needs must have a value in givensPath or in the Runtime constructor's \`givens\`.`);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
// Build PrepareResultOptions from CompileQueryOptions + connectionDigests.
|
|
739
921
|
const prepareResultOptions = {
|
|
740
922
|
defaultRowLimit: mergedOptions.defaultRowLimit,
|
|
741
923
|
buildManifest,
|
|
@@ -745,6 +927,7 @@ class QueryMaterializer extends FluentState {
|
|
|
745
927
|
return preparedQuery.getPreparedResult({
|
|
746
928
|
...mergedOptions,
|
|
747
929
|
...prepareResultOptions,
|
|
930
|
+
givens: mergedGivens,
|
|
748
931
|
});
|
|
749
932
|
});
|
|
750
933
|
}
|
|
@@ -901,4 +1084,23 @@ function isBuildManifestShape(value) {
|
|
|
901
1084
|
const entries = value.entries;
|
|
902
1085
|
return typeof entries === 'object' && entries !== null;
|
|
903
1086
|
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Shallow shape-check for the givens-values file: must be a non-array
|
|
1089
|
+
* non-null object. Per-value type checking happens later when each
|
|
1090
|
+
* declared given is bound via `resolveSuppliedGivens` — at this layer we
|
|
1091
|
+
* only ensure the top-level shape is a name → value map.
|
|
1092
|
+
*/
|
|
1093
|
+
function isGivensObject(value) {
|
|
1094
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Convert a non-empty `ReadonlyMap` into a plain object for spread-merging
|
|
1098
|
+
* with other given layers. Returns `undefined` for an empty map so the
|
|
1099
|
+
* merge can short-circuit when all layers are absent.
|
|
1100
|
+
*/
|
|
1101
|
+
function mapToRecord(m) {
|
|
1102
|
+
if (m.size === 0)
|
|
1103
|
+
return undefined;
|
|
1104
|
+
return Object.fromEntries(m);
|
|
1105
|
+
}
|
|
904
1106
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EventStream } from '../../runtime_types';
|
|
2
|
-
import type { BuildManifest, VirtualMap } from '../../model';
|
|
2
|
+
import type { BuildManifest, GivenValue, VirtualMap } from '../../model';
|
|
3
3
|
/**
|
|
4
4
|
* An empty BuildManifest with no entries and strict mode off.
|
|
5
5
|
* Use this to explicitly suppress manifest substitution in a query:
|
|
@@ -35,6 +35,7 @@ export interface CompileQueryOptions {
|
|
|
35
35
|
connectionDigests?: Record<string, string>;
|
|
36
36
|
/** Map from connectionName → virtualName → tablePath for virtual source resolution */
|
|
37
37
|
virtualMap?: VirtualMap;
|
|
38
|
+
givens?: Record<string, GivenValue>;
|
|
38
39
|
}
|
|
39
40
|
/**
|
|
40
41
|
* A node in the build graph (recursive DAG structure).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, MySQLDialect, DatabricksDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, } from './dialect';
|
|
2
2
|
export type { DialectFieldList, DialectFunctionOverloadDef, QueryInfo, MalloyStandardFunctionImplementations, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, } from './dialect';
|
|
3
|
-
export type { QueryRecord, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, Argument, Parameter, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryResultDef, QueryRunStats, QueryScalar, NamedQueryDef, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, BasicAtomicTypeDef, BasicAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, RecordDef, RepeatedRecordDef, RecordLiteralNode, StringLiteralNode, ArrayLiteralNode, SourceComponentInfo, DateLiteralNode, TimestampLiteralNode, TimestamptzLiteralNode, TimeLiteralExpr, TypecastExpr, BuildID, BuildManifest, BuildManifestEntry, VirtualMap, } from './model';
|
|
3
|
+
export type { QueryRecord, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType, QueryData, QueryValue, Expr, FilterCondition, Argument, Parameter, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryResultDef, QueryRunStats, QueryScalar, NamedQueryDef, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, BasicAtomicTypeDef, BasicAtomicDef, AtomicTypeDef, AtomicFieldDef, ArrayDef, ArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, RecordDef, RepeatedRecordDef, RecordLiteralNode, StringLiteralNode, ArrayLiteralNode, SourceComponentInfo, DateLiteralNode, TimestampLiteralNode, TimestamptzLiteralNode, TimeLiteralExpr, TypecastExpr, BuildID, BuildManifest, BuildManifestEntry, GivenValue, VirtualMap, } from './model';
|
|
4
4
|
export { isSourceDef, isAtomic, isBasicAtomic, isCompoundArrayData, isJoined, isJoinedSource, isSamplingEnable, isSamplingPercent, isSamplingRows, isRepeatedRecord, isBasicArray, mkArrayDef, mkFieldDef, expressionIsAggregate, expressionIsAnalytic, expressionIsCalculation, expressionIsScalar, expressionIsUngroupedAggregate, indent, composeSQLExpr, isTimestampUnit, isDateUnit, constantExprToSQL, } from './model';
|
|
5
5
|
export { malloyToQuery, MalloyTranslator, } from './lang';
|
|
6
6
|
export type { LogMessage, TranslateResponse } from './lang';
|
|
7
7
|
export { Model, Malloy, Runtime, AtomicFieldType, ConnectionRuntime, SingleConnectionRuntime, EmptyURLReader, InMemoryURLReader, FixedConnectionMap, MalloyError, JoinRelationship, SourceRelationship, DateTimeframe, TimestampTimeframe, PreparedResult, Result, QueryMaterializer, CSVWriter, JSONWriter, Parse, DataWriter, Explore, InMemoryModelCache, CacheManager, Manifest, MalloyConfig, envOverlay, contextOverlay, defaultConfigOverlays, discoverConfig, } from './api/foundation';
|
|
8
8
|
export type { PreparedQuery, Field, AtomicField, ExploreField, QueryField, SortableField, DataArray, DataRecord, DataColumn, DataArrayOrRecord, Loggable, ModelMaterializer, DocumentTablePath, DocumentSymbol, ResultJSON, PreparedResultJSON, PreparedResultMaterializer, ExploreMaterializer, WriteStream, SerializedExplore, ModelCache, CachedModel, DateField, TimestampField, } from './api/foundation';
|
|
9
9
|
export type { Overlay, ConfigOverlays } from './api/foundation';
|
|
10
|
+
export type { FilesystemContext, MalloyConfigOptions } from './api/foundation';
|
|
11
|
+
export type { RuntimeContext } from './api/foundation';
|
|
10
12
|
export type { QueryOptionsReader, RunSQLOptions } from './run_sql_options';
|
|
11
13
|
export type { EventStream, ModelString, ModelURL, QueryString, QueryURL, URLReader, InvalidationKey, } from './runtime_types';
|
|
12
14
|
export type { Connection, ConnectionConfig, ConnectionParameterValue, FetchSchemaOptions, InfoConnection, LookupConnection, PersistSQLResults, PooledConnection, TestableConnection, StreamingConnection, } from './connection/types';
|
|
@@ -10,7 +10,7 @@ export declare abstract class ExprAggregateFunction extends ExpressionDef {
|
|
|
10
10
|
source?: FieldReference;
|
|
11
11
|
expr?: ExpressionDef;
|
|
12
12
|
explicitSource?: boolean;
|
|
13
|
-
legalChildTypes: import("
|
|
13
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
14
14
|
constructor(func: AggregateFunctionType, expr?: ExpressionDef, explicitSource?: boolean);
|
|
15
15
|
abstract returns(fromExpr: ExprValue): ExprValue;
|
|
16
16
|
getExpression(fs: FieldSpace): ExprValue;
|
|
@@ -106,7 +106,11 @@ class ExprAggregateFunction extends expression_def_1.ExpressionDef {
|
|
|
106
106
|
at: this.source.location,
|
|
107
107
|
},
|
|
108
108
|
evalSpace: footType.evalSpace,
|
|
109
|
-
|
|
109
|
+
refSummary: {
|
|
110
|
+
fieldUsage: [
|
|
111
|
+
{ path: this.source.path, at: this.source.location },
|
|
112
|
+
],
|
|
113
|
+
},
|
|
110
114
|
};
|
|
111
115
|
structPath = this.source.path.slice(0, -1);
|
|
112
116
|
// Here we handle a special case where you write `foo.agg()` and `foo` is a
|
|
@@ -178,13 +182,10 @@ class ExprAggregateFunction extends expression_def_1.ExpressionDef {
|
|
|
178
182
|
}
|
|
179
183
|
const returnExpr = this.returns(exprVal);
|
|
180
184
|
if (!this.isSymmetricFunction()) {
|
|
181
|
-
|
|
182
|
-
returnExpr.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
path: structPath || [],
|
|
186
|
-
uniqueKeyRequirement: { isCount: false },
|
|
187
|
-
});
|
|
185
|
+
(0, malloy_types_1.setFieldUsage)(returnExpr, [
|
|
186
|
+
...(0, malloy_types_1.fieldUsageFrom)(returnExpr.refSummary),
|
|
187
|
+
{ path: structPath || [], uniqueKeyRequirement: { isCount: false } },
|
|
188
|
+
]);
|
|
188
189
|
}
|
|
189
190
|
return {
|
|
190
191
|
...returnExpr,
|
|
@@ -5,7 +5,7 @@ export declare class ExprCoalesce extends ExpressionDef {
|
|
|
5
5
|
readonly expr: ExpressionDef;
|
|
6
6
|
readonly altExpr: ExpressionDef;
|
|
7
7
|
elementType: string;
|
|
8
|
-
legalChildTypes: import("
|
|
8
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
9
9
|
constructor(expr: ExpressionDef, altExpr: ExpressionDef);
|
|
10
10
|
getExpression(fs: FieldSpace): ExprValue;
|
|
11
11
|
}
|
|
@@ -57,9 +57,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
57
57
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
58
|
exports.ExprCoalesce = void 0;
|
|
59
59
|
const model_1 = require("../../../model");
|
|
60
|
+
const composite_source_utils_1 = require("../../composite-source-utils");
|
|
60
61
|
const TDU = __importStar(require("../typedesc-utils"));
|
|
61
62
|
const expression_def_1 = require("../types/expression-def");
|
|
62
|
-
const composite_source_utils_1 = require("../../composite-source-utils");
|
|
63
63
|
class ExprCoalesce extends expression_def_1.ExpressionDef {
|
|
64
64
|
constructor(expr, altExpr) {
|
|
65
65
|
super({ expr, altExpr });
|
|
@@ -69,7 +69,6 @@ class ExprCoalesce extends expression_def_1.ExpressionDef {
|
|
|
69
69
|
this.legalChildTypes = TDU.anyAtomicT;
|
|
70
70
|
}
|
|
71
71
|
getExpression(fs) {
|
|
72
|
-
var _a;
|
|
73
72
|
const maybeNull = this.expr.getExpression(fs);
|
|
74
73
|
const whenNull = this.altExpr.getExpression(fs);
|
|
75
74
|
if (maybeNull.type === 'null') {
|
|
@@ -101,7 +100,7 @@ class ExprCoalesce extends expression_def_1.ExpressionDef {
|
|
|
101
100
|
kids: { left: maybeNull.value, right: whenNull.value },
|
|
102
101
|
},
|
|
103
102
|
evalSpace: (0, model_1.mergeEvalSpaces)(maybeNull.evalSpace, whenNull.evalSpace),
|
|
104
|
-
|
|
103
|
+
refSummary: (0, composite_source_utils_1.mergeRefSummaries)(maybeNull.refSummary, whenNull.refSummary),
|
|
105
104
|
};
|
|
106
105
|
}
|
|
107
106
|
}
|
|
@@ -44,7 +44,7 @@ class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
|
|
|
44
44
|
evalSpace: ev.evalSpace,
|
|
45
45
|
expressionType: 'aggregate',
|
|
46
46
|
value: ev.value,
|
|
47
|
-
|
|
47
|
+
refSummary: ev.refSummary,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
getExpression(_fs) {
|
|
@@ -63,9 +63,11 @@ class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
|
|
|
63
63
|
expressionType: 'aggregate',
|
|
64
64
|
value: ret,
|
|
65
65
|
evalSpace: 'output',
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
refSummary: {
|
|
67
|
+
fieldUsage: [
|
|
68
|
+
{ path: ret.structPath || [], uniqueKeyRequirement: { isCount: true } },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
}
|
|
@@ -154,7 +154,9 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
154
154
|
at: this.source.location,
|
|
155
155
|
},
|
|
156
156
|
evalSpace: footType.evalSpace,
|
|
157
|
-
|
|
157
|
+
refSummary: {
|
|
158
|
+
fieldUsage: [{ path: this.source.path, at: this.source.location }],
|
|
159
|
+
},
|
|
158
160
|
};
|
|
159
161
|
structPath = this.source.path.slice(0, -1);
|
|
160
162
|
}
|
|
@@ -357,14 +359,17 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
357
359
|
: 'output';
|
|
358
360
|
const aggregateFunctionUsage = [];
|
|
359
361
|
if (isAsymmetric || isAnalytic) {
|
|
360
|
-
const funcUsage = {
|
|
362
|
+
const funcUsage = {
|
|
363
|
+
path: structPath || [],
|
|
364
|
+
at: this.location,
|
|
365
|
+
};
|
|
361
366
|
if (isAsymmetric)
|
|
362
367
|
funcUsage.uniqueKeyRequirement = { isCount: false };
|
|
363
368
|
if (isAnalytic)
|
|
364
369
|
funcUsage.analyticFunctionUse = true;
|
|
365
370
|
aggregateFunctionUsage.push(funcUsage);
|
|
366
371
|
}
|
|
367
|
-
const
|
|
372
|
+
const refSummary = (0, composite_source_utils_1.mergeRefSummaries)(...argExprs.map(ae => ae.refSummary), (0, malloy_types_1.mkRefSummary)({ fieldUsage: orderByUsage }), (0, malloy_types_1.mkRefSummary)({ fieldUsage: sqlFunctionFieldUsage }), (0, malloy_types_1.mkRefSummary)({ fieldUsage: aggregateFunctionUsage }));
|
|
368
373
|
const ungroupings = argExprs.reduce((ug, a) => { var _a; return (_a = a.ungroupings) !== null && _a !== void 0 ? _a : ug; }, []);
|
|
369
374
|
// TODO consider if I can use `computedExprValue` here...
|
|
370
375
|
// seems like the rules for the evalSpace is a bit different from normal though
|
|
@@ -374,7 +379,7 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
374
379
|
expressionType,
|
|
375
380
|
value: funcCall,
|
|
376
381
|
evalSpace,
|
|
377
|
-
|
|
382
|
+
refSummary,
|
|
378
383
|
ungroupings,
|
|
379
384
|
};
|
|
380
385
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExpressionDef } from '../types/expression-def';
|
|
2
|
+
import type { ExprValue } from '../types/expr-value';
|
|
3
|
+
import type { FieldSpace } from '../types/field-space';
|
|
4
|
+
/**
|
|
5
|
+
* Reference to a given inside an expression: `$NAME`.
|
|
6
|
+
*
|
|
7
|
+
* Resolution bypasses `fs.lookup` (which is source-scoped) and goes
|
|
8
|
+
* straight to the document's given namespace — that lets `$NAME` work
|
|
9
|
+
* even inside a `ConstantFieldSpace`, which is how default values
|
|
10
|
+
* (`given: B :: number is $A + 1`) refuse field references but accept
|
|
11
|
+
* other givens.
|
|
12
|
+
*/
|
|
13
|
+
export declare class GivenReference extends ExpressionDef {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
elementType: string;
|
|
16
|
+
constructor(name: string);
|
|
17
|
+
getExpression(_fs: FieldSpace): ExprValue;
|
|
18
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.GivenReference = void 0;
|
|
8
|
+
const utils_1 = require("../../../model/utils");
|
|
9
|
+
const expression_def_1 = require("../types/expression-def");
|
|
10
|
+
const expr_value_1 = require("../types/expr-value");
|
|
11
|
+
/**
|
|
12
|
+
* Reference to a given inside an expression: `$NAME`.
|
|
13
|
+
*
|
|
14
|
+
* Resolution bypasses `fs.lookup` (which is source-scoped) and goes
|
|
15
|
+
* straight to the document's given namespace — that lets `$NAME` work
|
|
16
|
+
* even inside a `ConstantFieldSpace`, which is how default values
|
|
17
|
+
* (`given: B :: number is $A + 1`) refuse field references but accept
|
|
18
|
+
* other givens.
|
|
19
|
+
*/
|
|
20
|
+
class GivenReference extends expression_def_1.ExpressionDef {
|
|
21
|
+
constructor(name) {
|
|
22
|
+
super();
|
|
23
|
+
this.name = name;
|
|
24
|
+
this.elementType = 'givenReference';
|
|
25
|
+
}
|
|
26
|
+
getExpression(_fs) {
|
|
27
|
+
var _a;
|
|
28
|
+
const doc = this.document();
|
|
29
|
+
const entry = (_a = doc === null || doc === void 0 ? void 0 : doc.getEntry(this.name)) === null || _a === void 0 ? void 0 : _a.entry;
|
|
30
|
+
if (entry === undefined) {
|
|
31
|
+
return this.loggedErrorExpr('given-not-found', `\`$${this.name}\` references a given named \`${this.name}\`, which is not declared in this model`);
|
|
32
|
+
}
|
|
33
|
+
if (entry.type !== 'given') {
|
|
34
|
+
return this.loggedErrorExpr('given-not-found', `\`$${this.name}\` expects a given named \`${this.name}\`, but \`${this.name}\` is a ${entry.type}`);
|
|
35
|
+
}
|
|
36
|
+
const given = doc === null || doc === void 0 ? void 0 : doc.documentGivens.get(entry.id);
|
|
37
|
+
if (given === undefined) {
|
|
38
|
+
return this.loggedErrorExpr('given-not-found', `Internal error: given \`${this.name}\` is in the namespace but has no declaration. Likely a compiler bug.`);
|
|
39
|
+
}
|
|
40
|
+
// Use-site reference. `location` covers `$NAME` at the use site;
|
|
41
|
+
// `definition.location` points at the canonical `given:`
|
|
42
|
+
// declaration (in the same file or in an imported file).
|
|
43
|
+
this.addReference({
|
|
44
|
+
type: 'givenReference',
|
|
45
|
+
text: this.name,
|
|
46
|
+
location: this.location,
|
|
47
|
+
definition: {
|
|
48
|
+
type: (0, utils_1.typeDefToString)(given.type),
|
|
49
|
+
annotation: given.annotation,
|
|
50
|
+
location: given.location,
|
|
51
|
+
defaultText: given.defaultText,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const refNode = {
|
|
55
|
+
node: 'given',
|
|
56
|
+
id: entry.id,
|
|
57
|
+
refName: this.name,
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
...(0, expr_value_1.literalExprValue)({ value: refNode, dataType: given.type }),
|
|
61
|
+
refSummary: {
|
|
62
|
+
fieldUsage: [],
|
|
63
|
+
givenUsage: [{ id: entry.id, at: this.location }],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.GivenReference = GivenReference;
|
|
69
|
+
//# sourceMappingURL=expr-given.js.map
|
|
@@ -16,7 +16,7 @@ export declare class ExprGranularTime extends ExpressionDef {
|
|
|
16
16
|
readonly units: TimestampUnit;
|
|
17
17
|
readonly truncate: boolean;
|
|
18
18
|
elementType: string;
|
|
19
|
-
legalChildTypes: import("
|
|
19
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
20
20
|
constructor(expr: ExpressionDef, units: TimestampUnit, truncate: boolean);
|
|
21
21
|
granular(): boolean;
|
|
22
22
|
drillExpression(): Malloy.Expression | undefined;
|
|
@@ -57,13 +57,14 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
|
|
|
57
57
|
]
|
|
58
58
|
: [];
|
|
59
59
|
const td = def.found.typeDesc();
|
|
60
|
+
const refSummary = (0, malloy_types_1.mkRefSummary)({ fieldUsage: fieldUsage });
|
|
60
61
|
if (def.isOutputField) {
|
|
61
62
|
return {
|
|
62
63
|
...td,
|
|
63
64
|
// TODO what about literal??
|
|
64
65
|
evalSpace: td.evalSpace === 'constant' ? 'constant' : 'output',
|
|
65
66
|
value: { node: 'outputField', name: this.refString },
|
|
66
|
-
|
|
67
|
+
refSummary,
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
const value = {
|
|
@@ -79,7 +80,7 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
|
|
|
79
80
|
...td,
|
|
80
81
|
value,
|
|
81
82
|
evalSpace,
|
|
82
|
-
|
|
83
|
+
refSummary,
|
|
83
84
|
requiresGroupBy: undefined,
|
|
84
85
|
};
|
|
85
86
|
}
|