@malloydata/malloy 0.0.22-dev230126015148 → 0.0.22-dev230206094309

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/package.json +2 -2
  2. package/dist/connection_utils.d.ts +0 -1
  3. package/dist/connection_utils.js +0 -66
  4. package/dist/dialect/dialect.d.ts +0 -66
  5. package/dist/dialect/dialect.js +0 -85
  6. package/dist/dialect/dialect_map.d.ts +0 -3
  7. package/dist/dialect/dialect_map.js +0 -45
  8. package/dist/dialect/duckdb.d.ts +0 -52
  9. package/dist/dialect/duckdb.js +0 -364
  10. package/dist/dialect/index.d.ts +0 -6
  11. package/dist/dialect/index.js +0 -37
  12. package/dist/dialect/postgres.d.ts +0 -52
  13. package/dist/dialect/postgres.js +0 -330
  14. package/dist/dialect/standardsql.d.ts +0 -49
  15. package/dist/dialect/standardsql.js +0 -381
  16. package/dist/index.d.ts +0 -10
  17. package/dist/index.js +0 -59
  18. package/dist/lang/ast/apply-expr.d.ts +0 -3
  19. package/dist/lang/ast/apply-expr.js +0 -34
  20. package/dist/lang/ast/ast-expr.d.ts +0 -206
  21. package/dist/lang/ast/ast-expr.js +0 -781
  22. package/dist/lang/ast/ast-main.d.ts +0 -915
  23. package/dist/lang/ast/ast-main.js +0 -3672
  24. package/dist/lang/ast/ast-time-expr.d.ts +0 -69
  25. package/dist/lang/ast/ast-time-expr.js +0 -389
  26. package/dist/lang/ast/ast-types.d.ts +0 -83
  27. package/dist/lang/ast/ast-types.js +0 -225
  28. package/dist/lang/ast/index.d.ts +0 -5
  29. package/dist/lang/ast/index.js +0 -44
  30. package/dist/lang/ast/time-utils.d.ts +0 -9
  31. package/dist/lang/ast/time-utils.js +0 -104
  32. package/dist/lang/field-utils.d.ts +0 -5
  33. package/dist/lang/field-utils.js +0 -43
  34. package/dist/lang/index.d.ts +0 -9
  35. package/dist/lang/index.js +0 -32
  36. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +0 -165
  37. package/dist/lang/lib/Malloy/MalloyLexer.js +0 -1232
  38. package/dist/lang/lib/Malloy/MalloyParser.d.ts +0 -1947
  39. package/dist/lang/lib/Malloy/MalloyParser.js +0 -11909
  40. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +0 -2022
  41. package/dist/lang/lib/Malloy/MalloyParserListener.js +0 -4
  42. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +0 -1274
  43. package/dist/lang/lib/Malloy/MalloyParserVisitor.js +0 -4
  44. package/dist/lang/parse-log.d.ts +0 -27
  45. package/dist/lang/parse-log.js +0 -51
  46. package/dist/lang/parse-malloy.d.ts +0 -236
  47. package/dist/lang/parse-malloy.js +0 -746
  48. package/dist/lang/parse-to-ast.d.ts +0 -155
  49. package/dist/lang/parse-to-ast.js +0 -990
  50. package/dist/lang/parse-tree-walkers/document-completion-walker.d.ts +0 -10
  51. package/dist/lang/parse-tree-walkers/document-completion-walker.js +0 -148
  52. package/dist/lang/parse-tree-walkers/document-help-context-walker.d.ts +0 -9
  53. package/dist/lang/parse-tree-walkers/document-help-context-walker.js +0 -107
  54. package/dist/lang/parse-tree-walkers/document-highlight-walker.d.ts +0 -83
  55. package/dist/lang/parse-tree-walkers/document-highlight-walker.js +0 -385
  56. package/dist/lang/parse-tree-walkers/document-symbol-walker.d.ts +0 -11
  57. package/dist/lang/parse-tree-walkers/document-symbol-walker.js +0 -182
  58. package/dist/lang/parse-tree-walkers/explore-query-walker.d.ts +0 -34
  59. package/dist/lang/parse-tree-walkers/explore-query-walker.js +0 -74
  60. package/dist/lang/parse-tree-walkers/find-external-references.d.ts +0 -11
  61. package/dist/lang/parse-tree-walkers/find-external-references.js +0 -61
  62. package/dist/lang/reference-list.d.ts +0 -10
  63. package/dist/lang/reference-list.js +0 -90
  64. package/dist/lang/space-field.d.ts +0 -17
  65. package/dist/lang/space-field.js +0 -127
  66. package/dist/lang/test/document-help-context-walker.spec.d.ts +0 -1
  67. package/dist/lang/test/document-help-context-walker.spec.js +0 -55
  68. package/dist/lang/test/document-symbol-walker.spec.d.ts +0 -1
  69. package/dist/lang/test/document-symbol-walker.spec.js +0 -110
  70. package/dist/lang/test/field-symbols.spec.d.ts +0 -1
  71. package/dist/lang/test/field-symbols.spec.js +0 -180
  72. package/dist/lang/test/parse.spec.d.ts +0 -14
  73. package/dist/lang/test/parse.spec.js +0 -2134
  74. package/dist/lang/test/test-translator.d.ts +0 -38
  75. package/dist/lang/test/test-translator.js +0 -344
  76. package/dist/lang/zone.d.ts +0 -57
  77. package/dist/lang/zone.js +0 -107
  78. package/dist/malloy.d.ts +0 -1146
  79. package/dist/malloy.js +0 -2413
  80. package/dist/model/index.d.ts +0 -2
  81. package/dist/model/index.js +0 -45
  82. package/dist/model/malloy_query.d.ts +0 -351
  83. package/dist/model/malloy_query.js +0 -3174
  84. package/dist/model/malloy_types.d.ts +0 -551
  85. package/dist/model/malloy_types.js +0 -378
  86. package/dist/model/sql_block.d.ts +0 -7
  87. package/dist/model/sql_block.js +0 -56
  88. package/dist/model/utils.d.ts +0 -22
  89. package/dist/model/utils.js +0 -102
  90. package/dist/run_sql_options.d.ts +0 -3
  91. package/dist/run_sql_options.js +0 -25
  92. package/dist/runtime_types.d.ts +0 -105
  93. package/dist/runtime_types.js +0 -25
@@ -1,3672 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.TurtleHeadedPipe = exports.ExistingQuery = exports.Index = exports.Turtles = exports.Limit = exports.Ordering = exports.OrderBy = exports.WildcardFieldReference = exports.RenameField = exports.PrimaryKey = exports.Document = exports.QOPDesc = exports.Aggregate = exports.GroupBy = exports.FieldListEdit = exports.ProjectStatement = exports.isFieldCollectionMember = exports.FieldReferences = exports.FieldReference = exports.FieldName = exports.Renames = exports.Dimensions = exports.Measures = exports.DeclareFields = exports.Filter = exports.FilterElement = exports.ExploreDesc = exports.isExploreProperty = exports.isQueryProperty = exports.Joins = exports.ExpressionJoin = exports.KeyJoin = exports.Join = exports.QuerySource = exports.SQLSource = exports.NamedSource = exports.ModelEntryReference = exports.IsValueBlock = exports.TableSource = exports.RefinedExplore = exports.DefineSourceList = exports.DefineExplore = exports.isDocStatement = exports.RunList = exports.Mallobj = exports.isExploreField = exports.Unimplemented = exports.ListOf = exports.MalloyElement = exports.ErrorFactory = void 0;
27
- exports.RenameSpaceField = exports.QueryFieldAST = exports.ExpressionFieldFromAst = exports.AbstractParameter = exports.SpaceSeed = exports.DefinedParameter = exports.SpaceParam = exports.ColumnSpaceField = exports.QueryFieldStruct = exports.QueryField = exports.StructSpaceField = exports.SpaceField = exports.SpaceEntry = exports.ProjectFieldSpace = exports.ReduceFieldSpace = exports.ResultSpace = exports.DynamicSpace = exports.StaticSpace = exports.DefSpace = exports.Range = exports.ExprTime = exports.ExprDuration = exports.TypeMistmatch = exports.ExprGranularTime = exports.ExprCompare = exports.BinaryBoolean = exports.applyBinary = exports.FieldDeclaration = exports.ConstantSubExpression = exports.ExpressionDef = exports.SampleProperty = exports.SQLStatement = exports.SQLString = exports.ConstantParameter = exports.HasParameter = exports.ImportStatement = exports.JSONStructDef = exports.JSONElement = exports.Top = exports.AnonymousQuery = exports.DefineQuery = exports.DefineQueryList = exports.isQueryElement = exports.Nests = exports.isNestedQuery = exports.NestDefinition = exports.NestRefinement = exports.NestReference = exports.TurtleDecl = exports.FullQuery = void 0;
28
- exports.IndexFieldSpace = exports.WildSpaceField = exports.ReferenceField = exports.QuerySpace = exports.JoinSpaceField = void 0;
29
- /*
30
- * Copyright 2023 Google LLC
31
- *
32
- * Permission is hereby granted, free of charge, to any person obtaining
33
- * a copy of this software and associated documentation files
34
- * (the "Software"), to deal in the Software without restriction,
35
- * including without limitation the rights to use, copy, modify, merge,
36
- * publish, distribute, sublicense, and/or sell copies of the Software,
37
- * and to permit persons to whom the Software is furnished to do so,
38
- * subject to the following conditions:
39
- *
40
- * The above copyright notice and this permission notice shall be
41
- * included in all copies or substantial portions of the Software.
42
- *
43
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
44
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
47
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
48
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
49
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50
- */
51
- const lodash_1 = require("lodash");
52
- const model = __importStar(require("../../model/malloy_types"));
53
- const dialect_map_1 = require("../../dialect/dialect_map");
54
- const malloy_types_1 = require("../../model/malloy_types");
55
- const malloy_query_1 = require("../../model/malloy_query");
56
- const ast_types_1 = require("./ast-types");
57
- const sql_block_1 = require("../../model/sql_block");
58
- const util_1 = require("util");
59
- const time_utils_1 = require("./time-utils");
60
- const apply_expr_1 = require("./apply-expr");
61
- const field_utils_1 = require("../field-utils");
62
- /*
63
- ** For times when there is a code generation error but your function needs
64
- ** to return some kind of object to type properly, the ErrorFactory is
65
- ** here to help you.
66
- */
67
- const theErrorStruct = {
68
- type: "struct",
69
- name: "~malformed~",
70
- dialect: "~malformed~",
71
- structSource: { type: "table", tablePath: "//undefined_error_table_path" },
72
- structRelationship: {
73
- type: "basetable",
74
- connectionName: "//undefined_error_connection",
75
- },
76
- fields: [],
77
- };
78
- class ErrorFactory {
79
- static get structDef() {
80
- return { ...theErrorStruct };
81
- }
82
- static isErrorStructDef(s) {
83
- return s.name.includes(theErrorStruct.name);
84
- }
85
- static get query() {
86
- return {
87
- structRef: ErrorFactory.structDef,
88
- pipeline: [],
89
- };
90
- }
91
- static get reduceSegment() {
92
- return { type: "reduce", fields: [] };
93
- }
94
- static get projectSegment() {
95
- return { type: "project", fields: [] };
96
- }
97
- static get indexSegment() {
98
- return { type: "index", fields: [] };
99
- }
100
- }
101
- exports.ErrorFactory = ErrorFactory;
102
- function opOutputStruct(logTo, inputStruct, opDesc) {
103
- const badModel = ErrorFactory.isErrorStructDef(inputStruct);
104
- // Don't call into the model code with a broken model
105
- if (!badModel) {
106
- try {
107
- return malloy_query_1.Segment.nextStructDef(inputStruct, opDesc);
108
- }
109
- catch (e) {
110
- logTo.log(`INTERNAL ERROR model/Segment.nextStructDef: ${e.message}\n` +
111
- `QUERY: ${(0, util_1.inspect)(opDesc, { breakLength: 72, depth: Infinity })}`);
112
- }
113
- }
114
- return { ...ErrorFactory.structDef, dialect: inputStruct.dialect };
115
- }
116
- class MalloyElement {
117
- /**
118
- * @param kids All children passed to the constructor are not optional
119
- */
120
- constructor(kids) {
121
- this.children = {};
122
- this.parent = null;
123
- this.logged = new Set();
124
- if (kids) {
125
- this.has(kids);
126
- }
127
- }
128
- /**
129
- * Record all elements as children of this element, and mark this
130
- * element as their parent.
131
- * @param kids Some of these might be undefined, in which case they are ignored
132
- */
133
- has(kids) {
134
- for (const kidName in kids) {
135
- const kidValue = kids[kidName];
136
- if (kidValue !== undefined) {
137
- this.children[kidName] = kidValue;
138
- if (kidValue instanceof MalloyElement) {
139
- kidValue.parent = this;
140
- }
141
- else {
142
- for (const oneKid of kidValue) {
143
- oneKid.parent = this;
144
- }
145
- }
146
- }
147
- }
148
- }
149
- get location() {
150
- if (this.codeLocation) {
151
- return this.codeLocation;
152
- }
153
- if (this.parent) {
154
- return this.parent.location;
155
- }
156
- return {
157
- url: this.sourceURL,
158
- range: {
159
- start: { line: 0, character: 0 },
160
- end: { line: 0, character: 0 },
161
- },
162
- };
163
- }
164
- set location(loc) {
165
- this.codeLocation = loc;
166
- }
167
- namespace() {
168
- if (this instanceof Document) {
169
- return this;
170
- }
171
- else if (this.parent) {
172
- return this.parent.namespace();
173
- }
174
- throw new Error("INTERNAL ERROR: Translation without document scope");
175
- }
176
- modelEntry(reference) {
177
- var _a;
178
- const key = reference instanceof ModelEntryReference ? reference.name : reference;
179
- const result = (_a = this.namespace()) === null || _a === void 0 ? void 0 : _a.getEntry(key);
180
- if (reference instanceof ModelEntryReference) {
181
- if ((result === null || result === void 0 ? void 0 : result.entry.type) === "query") {
182
- this.addReference({
183
- type: "queryReference",
184
- text: key,
185
- definition: result.entry,
186
- location: reference.location,
187
- });
188
- }
189
- else if ((result === null || result === void 0 ? void 0 : result.entry.type) === "struct") {
190
- if (model.isSQLBlock(result.entry)) {
191
- this.addReference({
192
- type: "sqlBlockReference",
193
- text: key,
194
- definition: result.entry,
195
- location: reference.location,
196
- });
197
- }
198
- else {
199
- this.addReference({
200
- type: "exploreReference",
201
- text: key,
202
- definition: result.entry,
203
- location: reference.location,
204
- });
205
- }
206
- }
207
- }
208
- return result;
209
- }
210
- translator() {
211
- if (this.xlate) {
212
- return this.xlate;
213
- }
214
- if (this.parent) {
215
- return this.parent.translator();
216
- }
217
- return undefined;
218
- }
219
- setTranslator(x) {
220
- this.xlate = x;
221
- }
222
- addReference(reference) {
223
- var _a;
224
- (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.addReference(reference);
225
- }
226
- get sourceURL() {
227
- const trans = this.translator();
228
- return (trans === null || trans === void 0 ? void 0 : trans.sourceURL) || "(missing)";
229
- }
230
- errorsExist() {
231
- var _a;
232
- const logger = (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.root.logger;
233
- if (logger) {
234
- return logger.hasErrors();
235
- }
236
- return true;
237
- }
238
- log(message) {
239
- if (this.codeLocation) {
240
- /*
241
- * If this element has a location, then don't report the same
242
- * error message at the same location more than once
243
- */
244
- if (this.logged.has(message)) {
245
- return;
246
- }
247
- this.logged.add(message);
248
- }
249
- const trans = this.translator();
250
- const msg = { at: this.location, message };
251
- const logTo = trans === null || trans === void 0 ? void 0 : trans.root.logger;
252
- if (logTo) {
253
- logTo.log(msg);
254
- return;
255
- }
256
- throw new Error(`Translation error (without error reporter):\n${JSON.stringify(msg, null, 2)}`);
257
- }
258
- /**
259
- * Mostly for debugging / testing. A string-y version of this object which
260
- * is used to ask "are these two AST segments equal". Formatted so that
261
- * errors would be human readable.
262
- * @param indent only used for recursion
263
- */
264
- toString() {
265
- return this.stringify("", 0);
266
- }
267
- stringify(prefix, indent) {
268
- const left = " ".repeat(indent);
269
- let asString = `${left}${prefix}<${this.elementType}>${this.varInfo()}`;
270
- for (const kidLabel of Object.keys(this.children)) {
271
- const kiddle = this.children[kidLabel];
272
- if (kiddle instanceof MalloyElement) {
273
- asString += "\n" + kiddle.stringify(`${kidLabel}: `, indent + 2);
274
- }
275
- else {
276
- asString += `\n${left} ${kidLabel}: [`;
277
- if (kiddle.length > 0) {
278
- asString +=
279
- "\n" +
280
- kiddle.map((k) => k.stringify("", indent + 4)).join("\n") +
281
- `\n${left} `;
282
- }
283
- asString += "]";
284
- }
285
- }
286
- return asString;
287
- }
288
- walk(callBack) {
289
- callBack(this);
290
- for (const kidLabel of Object.keys(this.children)) {
291
- const kiddle = this.children[kidLabel];
292
- if (kiddle instanceof MalloyElement) {
293
- kiddle.walk(callBack);
294
- }
295
- else {
296
- for (const k of kiddle) {
297
- k.walk(callBack);
298
- }
299
- }
300
- }
301
- }
302
- varInfo() {
303
- let extra = "";
304
- for (const [key, value] of Object.entries(this)) {
305
- if (key !== "elementType") {
306
- if (typeof value == "boolean") {
307
- extra += value ? ` ${key}` : ` !${key}`;
308
- }
309
- else if (typeof value === "string" || typeof value === "number") {
310
- extra += ` ${key}=${value}`;
311
- }
312
- }
313
- }
314
- return extra;
315
- }
316
- internalError(msg) {
317
- this.log(`INTERNAL ERROR IN TRANSLATION: ${msg}`);
318
- return new Error(msg);
319
- }
320
- }
321
- exports.MalloyElement = MalloyElement;
322
- class ListOf extends MalloyElement {
323
- constructor(listDesc, elements) {
324
- super();
325
- this.elementType = "genericElementList";
326
- this.elements = elements;
327
- if (this.elementType === "genericElementList") {
328
- this.elementType = listDesc;
329
- }
330
- this.newContents();
331
- }
332
- newContents() {
333
- this.has({ [this.elementType]: this.elements });
334
- }
335
- get list() {
336
- return this.elements;
337
- }
338
- empty() {
339
- return this.elements.length === 0;
340
- }
341
- notEmpty() {
342
- return this.elements.length > 0;
343
- }
344
- push(...el) {
345
- this.elements.push(...el);
346
- this.newContents();
347
- return this.elements;
348
- }
349
- }
350
- exports.ListOf = ListOf;
351
- class Unimplemented extends MalloyElement {
352
- constructor() {
353
- super(...arguments);
354
- this.elementType = "unimplemented";
355
- this.reported = false;
356
- }
357
- }
358
- exports.Unimplemented = Unimplemented;
359
- function getStructFieldDef(s, fn) {
360
- return s.fields.find((fld) => (fld.as || fld.name) === fn);
361
- }
362
- function isFieldDecl(f) {
363
- return (f instanceof FieldDeclaration ||
364
- f instanceof Join ||
365
- f instanceof TurtleDecl ||
366
- f instanceof Turtles);
367
- }
368
- function isExploreField(f) {
369
- return isFieldDecl(f) || f instanceof RenameField;
370
- }
371
- exports.isExploreField = isExploreField;
372
- /**
373
- * A "Mallobj" is a thing which you can run queries against, it has been called
374
- * an "exploreable", or a "space".
375
- */
376
- class Mallobj extends MalloyElement {
377
- structRef() {
378
- return this.structDef();
379
- }
380
- withParameters(pList) {
381
- const before = this.structDef();
382
- // TODO name collisions are flagged where?
383
- if (pList) {
384
- const parameters = { ...(before.parameters || {}) };
385
- for (const hasP of pList) {
386
- const pVal = hasP.parameter();
387
- parameters[pVal.name] = pVal;
388
- }
389
- return {
390
- ...before,
391
- parameters,
392
- };
393
- }
394
- return before;
395
- }
396
- }
397
- exports.Mallobj = Mallobj;
398
- class QueryHeadStruct extends Mallobj {
399
- constructor(fromRef) {
400
- super();
401
- this.fromRef = fromRef;
402
- this.elementType = "internalOnlyQueryHead";
403
- }
404
- structRef() {
405
- return this.fromRef;
406
- }
407
- structDef() {
408
- if (model.refIsStructDef(this.fromRef)) {
409
- return this.fromRef;
410
- }
411
- const ns = new NamedSource(this.fromRef);
412
- this.has({ exploreReference: ns });
413
- return ns.structDef();
414
- }
415
- }
416
- class RunList extends ListOf {
417
- constructor() {
418
- super(...arguments);
419
- this.execCursor = 0;
420
- }
421
- executeList(doc) {
422
- while (this.execCursor < this.elements.length) {
423
- if (doc.errorsExist()) {
424
- // This stops cascading errors
425
- return;
426
- }
427
- const el = this.elements[this.execCursor];
428
- if (isDocStatement(el)) {
429
- const resp = el.execute(doc);
430
- if (resp) {
431
- return resp;
432
- }
433
- this.execCursor += 1;
434
- }
435
- }
436
- return undefined;
437
- }
438
- }
439
- exports.RunList = RunList;
440
- function isDocStatement(e) {
441
- return e.execute !== undefined;
442
- }
443
- exports.isDocStatement = isDocStatement;
444
- class DefineExplore extends MalloyElement {
445
- constructor(name, mallobj, exported, params) {
446
- super({ explore: mallobj });
447
- this.name = name;
448
- this.mallobj = mallobj;
449
- this.exported = exported;
450
- this.elementType = "defineExplore";
451
- if (params) {
452
- this.parameters = [];
453
- for (const el of params) {
454
- if (el instanceof HasParameter) {
455
- this.parameters.push(el);
456
- }
457
- else {
458
- this.log(`Unexpected element type in define statement: ${el.elementType}`);
459
- }
460
- }
461
- this.has({ parameters: this.parameters });
462
- }
463
- }
464
- execute(doc) {
465
- if (doc.modelEntry(this.name)) {
466
- this.log(`Cannot redefine '${this.name}'`);
467
- }
468
- else {
469
- const structDef = this.mallobj.withParameters(this.parameters);
470
- if (ErrorFactory.isErrorStructDef(structDef)) {
471
- return;
472
- }
473
- doc.setEntry(this.name, {
474
- entry: {
475
- ...structDef,
476
- as: this.name,
477
- location: this.location,
478
- },
479
- exported: this.exported,
480
- });
481
- }
482
- }
483
- }
484
- exports.DefineExplore = DefineExplore;
485
- class DefineSourceList extends RunList {
486
- constructor(sourceList) {
487
- super("defineSources", sourceList);
488
- }
489
- execute(doc) {
490
- return this.executeList(doc);
491
- }
492
- }
493
- exports.DefineSourceList = DefineSourceList;
494
- /**
495
- * A Mallobj made from a source and a set of refinements
496
- */
497
- class RefinedExplore extends Mallobj {
498
- constructor(source, refinement) {
499
- super({ source, refinement });
500
- this.source = source;
501
- this.refinement = refinement;
502
- this.elementType = "refinedExplore";
503
- }
504
- structDef() {
505
- return this.withParameters([]);
506
- }
507
- withParameters(pList) {
508
- let primaryKey;
509
- let fieldListEdit;
510
- const fields = [];
511
- const filters = [];
512
- for (const el of this.refinement.list) {
513
- const errTo = el;
514
- if (el instanceof PrimaryKey) {
515
- if (primaryKey) {
516
- primaryKey.log("Primary key already defined");
517
- el.log("Primary key redefined");
518
- }
519
- primaryKey = el;
520
- }
521
- else if (el instanceof FieldListEdit) {
522
- if (fieldListEdit) {
523
- fieldListEdit.log("Too many accept/except statements");
524
- el.log("Too many accept/except statements");
525
- }
526
- fieldListEdit = el;
527
- }
528
- else if (el instanceof DeclareFields ||
529
- el instanceof Joins ||
530
- el instanceof Turtles ||
531
- el instanceof Renames) {
532
- fields.push(...el.list);
533
- }
534
- else if (el instanceof Filter) {
535
- filters.push(el);
536
- }
537
- else {
538
- errTo.log(`Unexpected explore property: '${errTo.elementType}'`);
539
- }
540
- }
541
- const from = (0, lodash_1.cloneDeep)(this.source.structDef());
542
- if (primaryKey) {
543
- from.primaryKey = primaryKey.field.name;
544
- }
545
- const fs = DynamicSpace.filteredFrom(from, fieldListEdit);
546
- fs.addField(...fields);
547
- if (pList) {
548
- fs.addParameters(pList);
549
- }
550
- if (primaryKey) {
551
- const keyDef = primaryKey.field.getField(fs);
552
- if (keyDef.error) {
553
- primaryKey.log(keyDef.error);
554
- }
555
- }
556
- const retStruct = fs.structDef();
557
- const filterList = retStruct.filterList || [];
558
- let moreFilters = false;
559
- for (const filter of filters) {
560
- for (const el of filter.list) {
561
- const fc = el.filterExpression(fs);
562
- if (model.expressionIsCalculation(fc.expressionType)) {
563
- el.log("Can't use aggregate computations in top level filters");
564
- }
565
- else {
566
- filterList.push(fc);
567
- moreFilters = true;
568
- }
569
- }
570
- }
571
- if (moreFilters) {
572
- return { ...retStruct, filterList };
573
- }
574
- return retStruct;
575
- }
576
- }
577
- exports.RefinedExplore = RefinedExplore;
578
- class TableSource extends Mallobj {
579
- constructor(name) {
580
- super();
581
- this.name = name;
582
- this.elementType = "tableSource";
583
- }
584
- structDef() {
585
- var _a;
586
- const tableDefEntry = (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.root.schemaZone.getEntry(this.name);
587
- let msg = `Schema read failure for table '${this.name}'`;
588
- if (tableDefEntry) {
589
- if (tableDefEntry.status == "present") {
590
- tableDefEntry.value.location = this.location;
591
- tableDefEntry.value.fields.forEach((field) => (field.location = this.location));
592
- return {
593
- ...tableDefEntry.value,
594
- fields: tableDefEntry.value.fields.map((field) => ({
595
- ...field,
596
- location: this.location,
597
- })),
598
- location: this.location,
599
- };
600
- }
601
- if (tableDefEntry.status == "error") {
602
- msg = tableDefEntry.message;
603
- }
604
- }
605
- this.log(msg);
606
- return ErrorFactory.structDef;
607
- }
608
- }
609
- exports.TableSource = TableSource;
610
- class IsValueBlock extends MalloyElement {
611
- constructor(isMap) {
612
- super();
613
- this.isMap = isMap;
614
- this.elementType = "isValueBlock";
615
- this.has(isMap);
616
- }
617
- }
618
- exports.IsValueBlock = IsValueBlock;
619
- class ModelEntryReference extends MalloyElement {
620
- constructor(name) {
621
- super();
622
- this.name = name;
623
- this.elementType = "modelEntryReference";
624
- }
625
- get refString() {
626
- return this.name;
627
- }
628
- toString() {
629
- return this.refString;
630
- }
631
- }
632
- exports.ModelEntryReference = ModelEntryReference;
633
- class NamedSource extends Mallobj {
634
- constructor(ref, paramValues = {}) {
635
- super();
636
- this.ref = ref;
637
- this.elementType = "namedSource";
638
- if (paramValues && Object.keys(paramValues).length > 0) {
639
- this.isBlock = new IsValueBlock(paramValues);
640
- this.has({ parameterValues: this.isBlock });
641
- }
642
- if (ref instanceof ModelEntryReference) {
643
- this.has({ ref });
644
- }
645
- }
646
- get refName() {
647
- return this.ref instanceof ModelEntryReference ? this.ref.name : this.ref;
648
- }
649
- structRef() {
650
- if (this.isBlock) {
651
- return this.structDef();
652
- }
653
- const modelEnt = this.modelEntry(this.ref);
654
- if (modelEnt && !modelEnt.exported) {
655
- // If we are not exporting the referenced structdef, don't
656
- // use the reference
657
- return this.structDef();
658
- }
659
- return this.refName;
660
- }
661
- modelStruct() {
662
- const modelEnt = this.modelEntry(this.ref);
663
- const entry = modelEnt === null || modelEnt === void 0 ? void 0 : modelEnt.entry;
664
- if (!entry) {
665
- const undefMsg = `Undefined source '${this.refName}'`;
666
- (this.ref instanceof ModelEntryReference ? this.ref : this).log(undefMsg);
667
- return;
668
- }
669
- if (entry.type === "query") {
670
- this.log(`Must use 'from()' for query source '${this.refName}`);
671
- return;
672
- }
673
- else if (modelEnt.sqlType) {
674
- this.log(`Must use 'from_sql()' for sql source '${this.refName}`);
675
- return;
676
- }
677
- return { ...entry };
678
- }
679
- structDef() {
680
- /*
681
- Can't really generate the callback list until after all the
682
- things before me are translated, and that kinda screws up
683
- the translation process, so that might be a better place
684
- to start the next step, because how that gets done might
685
- make any code I write which ignores the translation problem
686
- kind of meaningless.
687
-
688
- Maybe the output of a translation is something which describes
689
- all the missing data, and then there is a "link" step where you
690
- can do other translations and link them into a partial translation
691
- which might result in a full translation.
692
- */
693
- var _a;
694
- const ret = this.modelStruct();
695
- if (!ret) {
696
- const notFound = ErrorFactory.structDef;
697
- const err = `${this.refName}-undefined`;
698
- notFound.name = notFound.name + err;
699
- notFound.dialect = notFound.dialect + err;
700
- return notFound;
701
- }
702
- const declared = { ...ret.parameters } || {};
703
- const makeWith = ((_a = this.isBlock) === null || _a === void 0 ? void 0 : _a.isMap) || {};
704
- for (const [pName, pExpr] of Object.entries(makeWith)) {
705
- const decl = declared[pName];
706
- // const pVal = pExpr.constantValue();
707
- if (!decl) {
708
- this.log(`Value given for undeclared parameter '${pName}`);
709
- }
710
- else {
711
- if (model.isValueParameter(decl)) {
712
- if (decl.constant) {
713
- pExpr.log(`Cannot override constant parameter ${pName}`);
714
- }
715
- else {
716
- const pVal = pExpr.constantValue();
717
- let value = pVal.value;
718
- if (pVal.dataType !== decl.type) {
719
- value = (0, time_utils_1.castTo)(decl.type, pVal.value, true);
720
- }
721
- decl.value = value;
722
- }
723
- }
724
- else {
725
- // TODO type checking here -- except I am still not sure what
726
- // datatype half conditions have ..
727
- decl.condition = pExpr.constantCondition(decl.type).value;
728
- }
729
- }
730
- }
731
- for (const checkDef in ret.parameters) {
732
- if (!model.paramHasValue(declared[checkDef])) {
733
- this.log(`Value not provided for required parameter ${checkDef}`);
734
- }
735
- }
736
- return ret;
737
- }
738
- }
739
- exports.NamedSource = NamedSource;
740
- class SQLSource extends NamedSource {
741
- constructor() {
742
- super(...arguments);
743
- this.elementType = "sqlSource";
744
- }
745
- structRef() {
746
- return this.structDef();
747
- }
748
- modelStruct() {
749
- const modelEnt = this.modelEntry(this.ref);
750
- const entry = modelEnt === null || modelEnt === void 0 ? void 0 : modelEnt.entry;
751
- if (!entry) {
752
- this.log(`Undefined from_sql source '${this.refName}'`);
753
- return;
754
- }
755
- if (entry.type === "query") {
756
- this.log(`Cannot use 'from_sql()' to explore query '${this.refName}'`);
757
- return;
758
- }
759
- else if (!modelEnt.sqlType) {
760
- this.log(`Cannot use 'from_sql()' to explore '${this.refName}'`);
761
- return;
762
- }
763
- return entry;
764
- }
765
- }
766
- exports.SQLSource = SQLSource;
767
- class QuerySource extends Mallobj {
768
- constructor(query) {
769
- super({ query });
770
- this.query = query;
771
- this.elementType = "querySource";
772
- }
773
- structDef() {
774
- const comp = this.query.queryComp();
775
- const queryStruct = comp.outputStruct;
776
- queryStruct.structSource = { type: "query", query: comp.query };
777
- return queryStruct;
778
- }
779
- }
780
- exports.QuerySource = QuerySource;
781
- class Join extends MalloyElement {
782
- }
783
- exports.Join = Join;
784
- class KeyJoin extends Join {
785
- constructor(name, source, keyExpr) {
786
- super({ name, source, keyExpr });
787
- this.name = name;
788
- this.source = source;
789
- this.keyExpr = keyExpr;
790
- this.elementType = "joinOnKey";
791
- }
792
- structDef() {
793
- const sourceDef = this.source.structDef();
794
- const joinStruct = {
795
- ...sourceDef,
796
- structRelationship: {
797
- type: "one",
798
- onExpression: ["('join fixup'='not done yet')"],
799
- },
800
- location: this.location,
801
- };
802
- if (sourceDef.structSource.type === "query") {
803
- // the name from query does not need to be preserved
804
- joinStruct.name = this.name.refString;
805
- }
806
- else {
807
- joinStruct.as = this.name.refString;
808
- }
809
- return joinStruct;
810
- }
811
- fixupJoinOn(outer, inStruct) {
812
- const exprX = this.keyExpr.getExpression(outer);
813
- if (inStruct.primaryKey) {
814
- const pkey = inStruct.fields.find((f) => (f.as || f.name) === inStruct.primaryKey);
815
- if (pkey) {
816
- if (pkey.type === exprX.dataType) {
817
- inStruct.structRelationship = {
818
- type: "one",
819
- onExpression: [
820
- { type: "field", path: `${this.name}.${inStruct.primaryKey}` },
821
- "=",
822
- ...exprX.value,
823
- ],
824
- };
825
- return;
826
- }
827
- else {
828
- this.log(`join_one: with type mismatch with primary key: ${exprX.dataType}/${pkey.type}`);
829
- }
830
- }
831
- else {
832
- this.log(`join_one: Primary key '${pkey}' not found in source`);
833
- }
834
- }
835
- else {
836
- this.log(`join_one: Cannot use with unless source has a primary key`);
837
- }
838
- }
839
- }
840
- exports.KeyJoin = KeyJoin;
841
- class ExpressionJoin extends Join {
842
- constructor(name, source) {
843
- super({ name, source });
844
- this.name = name;
845
- this.source = source;
846
- this.elementType = "joinOnExpr";
847
- this.joinType = "one";
848
- }
849
- set joinOn(joinExpr) {
850
- this.expr = joinExpr;
851
- this.has({ on: joinExpr });
852
- }
853
- get joinOn() {
854
- return this.expr;
855
- }
856
- fixupJoinOn(outer, inStruct) {
857
- if (this.expr == undefined) {
858
- return;
859
- }
860
- const exprX = this.expr.getExpression(outer);
861
- if (exprX.dataType !== "boolean") {
862
- this.log("join conditions must be boolean expressions");
863
- return;
864
- }
865
- const joinRel = inStruct.structRelationship;
866
- if (model.isJoinOn(joinRel)) {
867
- joinRel.onExpression = (0, ast_types_1.compressExpr)(exprX.value);
868
- }
869
- }
870
- structDef() {
871
- const sourceDef = this.source.structDef();
872
- const joinStruct = {
873
- ...sourceDef,
874
- structRelationship: { type: this.joinType },
875
- location: this.location,
876
- };
877
- if (sourceDef.structSource.type === "query") {
878
- // the name from query does not need to be preserved
879
- joinStruct.name = this.name.refString;
880
- delete joinStruct.as;
881
- }
882
- else {
883
- joinStruct.as = this.name.refString;
884
- }
885
- return joinStruct;
886
- }
887
- }
888
- exports.ExpressionJoin = ExpressionJoin;
889
- class Joins extends ListOf {
890
- constructor(joins) {
891
- super("joinList", joins);
892
- }
893
- }
894
- exports.Joins = Joins;
895
- function isQueryProperty(q) {
896
- return (q instanceof Ordering ||
897
- q instanceof Top ||
898
- q instanceof Limit ||
899
- q instanceof Filter ||
900
- q instanceof Index ||
901
- q instanceof SampleProperty ||
902
- q instanceof Joins ||
903
- q instanceof DeclareFields ||
904
- q instanceof ProjectStatement ||
905
- q instanceof Aggregate ||
906
- q instanceof Nests ||
907
- isNestedQuery(q) ||
908
- q instanceof GroupBy);
909
- }
910
- exports.isQueryProperty = isQueryProperty;
911
- function isExploreProperty(p) {
912
- return (p instanceof Filter ||
913
- p instanceof Joins ||
914
- p instanceof DeclareFields ||
915
- p instanceof FieldListEdit ||
916
- p instanceof Renames ||
917
- p instanceof PrimaryKey ||
918
- p instanceof Turtles);
919
- }
920
- exports.isExploreProperty = isExploreProperty;
921
- class ExploreDesc extends ListOf {
922
- constructor(props) {
923
- super("exploreDesc", props);
924
- }
925
- }
926
- exports.ExploreDesc = ExploreDesc;
927
- class FilterElement extends MalloyElement {
928
- constructor(expr, exprSrc) {
929
- super({ expr });
930
- this.expr = expr;
931
- this.exprSrc = exprSrc;
932
- this.elementType = "filterElement";
933
- }
934
- filterExpression(fs) {
935
- const exprVal = this.expr.getExpression(fs);
936
- if (exprVal.dataType !== "boolean") {
937
- this.expr.log("Filter expression must have boolean value");
938
- return {
939
- code: this.exprSrc,
940
- expression: ["_FILTER_MUST_RETURN_BOOLEAN_"],
941
- expressionType: "scalar",
942
- };
943
- }
944
- const exprCond = {
945
- code: this.exprSrc,
946
- expression: (0, ast_types_1.compressExpr)(exprVal.value),
947
- expressionType: exprVal.expressionType,
948
- };
949
- return exprCond;
950
- }
951
- }
952
- exports.FilterElement = FilterElement;
953
- class Filter extends ListOf {
954
- constructor(elements = []) {
955
- super("filterElements", elements);
956
- this.elementType = "filter";
957
- }
958
- set having(isHaving) {
959
- this.elementType = isHaving ? "having" : "where";
960
- }
961
- getFilterList(fs) {
962
- const checked = [];
963
- for (const oneElement of this.list) {
964
- const fExpr = oneElement.filterExpression(fs);
965
- // Aggregates are ALSO checked at SQL generation time, but checking
966
- // here allows better reflection of errors back to user.
967
- if (this.havingClause !== undefined) {
968
- if (this.havingClause) {
969
- if (model.expressionIsCalculation(fExpr.expressionType)) {
970
- oneElement.log("Aggregate or Analytical expression expected in HAVING filter");
971
- continue;
972
- }
973
- }
974
- else {
975
- if (fExpr.expressionType !== "scalar") {
976
- oneElement.log("Aggregate or Analytical expressions not allowed in WHERE");
977
- continue;
978
- }
979
- }
980
- }
981
- checked.push(fExpr);
982
- }
983
- return checked;
984
- }
985
- }
986
- exports.Filter = Filter;
987
- class DeclareFields extends ListOf {
988
- constructor(fields, fieldType = "declare") {
989
- super(fieldType, fields);
990
- }
991
- }
992
- exports.DeclareFields = DeclareFields;
993
- class Measures extends DeclareFields {
994
- constructor(measures) {
995
- super(measures, "measure");
996
- for (const dim of measures) {
997
- dim.isMeasure = true;
998
- }
999
- }
1000
- }
1001
- exports.Measures = Measures;
1002
- class Dimensions extends DeclareFields {
1003
- constructor(dimensions) {
1004
- super(dimensions, "dimension");
1005
- for (const dim of dimensions) {
1006
- dim.isMeasure = false;
1007
- }
1008
- }
1009
- }
1010
- exports.Dimensions = Dimensions;
1011
- class Renames extends ListOf {
1012
- constructor(renames) {
1013
- super("renameField", renames);
1014
- }
1015
- }
1016
- exports.Renames = Renames;
1017
- class FieldName extends MalloyElement {
1018
- constructor(name) {
1019
- super();
1020
- this.name = name;
1021
- this.elementType = "fieldName";
1022
- }
1023
- get refString() {
1024
- return this.name;
1025
- }
1026
- toString() {
1027
- return this.refString;
1028
- }
1029
- getField(fs) {
1030
- return fs.lookup([this]);
1031
- }
1032
- }
1033
- exports.FieldName = FieldName;
1034
- class FieldReference extends ListOf {
1035
- constructor(names) {
1036
- super("fieldReference", names);
1037
- this.elementType = "fieldReference";
1038
- }
1039
- get refString() {
1040
- return this.list.map((n) => n.refString).join(".");
1041
- }
1042
- get outputName() {
1043
- const last = this.list[this.list.length - 1];
1044
- return last.refString;
1045
- }
1046
- get sourceString() {
1047
- if (this.list.length > 1) {
1048
- return this.list
1049
- .slice(0, -1)
1050
- .map((n) => n.refString)
1051
- .join(".");
1052
- }
1053
- return undefined;
1054
- }
1055
- get nameString() {
1056
- return this.list[this.list.length - 1].refString;
1057
- }
1058
- getField(fs) {
1059
- return fs.lookup(this.list);
1060
- }
1061
- }
1062
- exports.FieldReference = FieldReference;
1063
- class FieldReferences extends ListOf {
1064
- constructor(members) {
1065
- super("fieldReferenceList", members);
1066
- }
1067
- }
1068
- exports.FieldReferences = FieldReferences;
1069
- function isFieldCollectionMember(el) {
1070
- return (el instanceof FieldReference ||
1071
- el instanceof WildcardFieldReference ||
1072
- el instanceof FieldDeclaration);
1073
- }
1074
- exports.isFieldCollectionMember = isFieldCollectionMember;
1075
- class ProjectStatement extends ListOf {
1076
- constructor(members) {
1077
- super("fieldCollection", members);
1078
- }
1079
- }
1080
- exports.ProjectStatement = ProjectStatement;
1081
- class FieldListEdit extends MalloyElement {
1082
- constructor(edit, refs) {
1083
- super({ refs });
1084
- this.edit = edit;
1085
- this.refs = refs;
1086
- this.elementType = "fieldListEdit";
1087
- }
1088
- }
1089
- exports.FieldListEdit = FieldListEdit;
1090
- class GroupBy extends ListOf {
1091
- constructor(members) {
1092
- super("groupBy", members);
1093
- for (const el of members) {
1094
- if (el instanceof FieldDeclaration) {
1095
- el.isMeasure = false;
1096
- }
1097
- }
1098
- }
1099
- }
1100
- exports.GroupBy = GroupBy;
1101
- class Aggregate extends ListOf {
1102
- constructor(members) {
1103
- super("aggregate", members);
1104
- for (const el of members) {
1105
- if (el instanceof FieldDeclaration) {
1106
- el.isMeasure = true;
1107
- }
1108
- }
1109
- }
1110
- }
1111
- exports.Aggregate = Aggregate;
1112
- class ReduceExecutor {
1113
- constructor(baseFS) {
1114
- this.filters = [];
1115
- this.resultFS = this.getResultSpace(baseFS);
1116
- this.inputFS = this.resultFS.exprSpace;
1117
- }
1118
- getResultSpace(fs) {
1119
- return new ReduceFieldSpace(fs);
1120
- }
1121
- execute(qp) {
1122
- if (qp instanceof GroupBy ||
1123
- qp instanceof Aggregate ||
1124
- qp instanceof Nests) {
1125
- this.resultFS.addQueryItems(...qp.list);
1126
- }
1127
- else if (isNestedQuery(qp)) {
1128
- this.resultFS.addQueryItems(qp);
1129
- }
1130
- else if (qp instanceof Filter) {
1131
- this.filters.push(...qp.getFilterList(this.inputFS));
1132
- }
1133
- else if (qp instanceof Top) {
1134
- if (this.limit) {
1135
- qp.log("Query operation already limited");
1136
- }
1137
- else {
1138
- this.limit = qp.limit;
1139
- }
1140
- if (qp.by) {
1141
- if (this.order) {
1142
- qp.log("Query operation is already sorted");
1143
- }
1144
- else {
1145
- this.order = qp;
1146
- }
1147
- }
1148
- }
1149
- else if (qp instanceof Limit) {
1150
- if (this.limit) {
1151
- qp.log("Query operation already limited");
1152
- }
1153
- else {
1154
- this.limit = qp.limit;
1155
- }
1156
- }
1157
- else if (qp instanceof Ordering) {
1158
- if (this.order) {
1159
- qp.log("Query operation already sorted");
1160
- }
1161
- else {
1162
- this.order = qp;
1163
- }
1164
- }
1165
- else if (qp instanceof Joins || qp instanceof DeclareFields) {
1166
- for (const qel of qp.list) {
1167
- this.inputFS.extendSource(qel);
1168
- }
1169
- }
1170
- }
1171
- refineFrom(from, to) {
1172
- if (from && from.type !== "index") {
1173
- if (!this.order) {
1174
- if (from.orderBy) {
1175
- to.orderBy = from.orderBy;
1176
- }
1177
- else if (from.by) {
1178
- to.by = from.by;
1179
- }
1180
- }
1181
- if (!this.limit && from.limit) {
1182
- to.limit = from.limit;
1183
- }
1184
- }
1185
- if (this.limit) {
1186
- to.limit = this.limit;
1187
- }
1188
- if (this.order instanceof Top) {
1189
- const topBy = this.order.getBy(this.inputFS);
1190
- if (topBy) {
1191
- to.by = topBy;
1192
- }
1193
- }
1194
- if (this.order instanceof Ordering) {
1195
- to.orderBy = this.order.getOrderBy(this.inputFS);
1196
- }
1197
- const oldFilters = (from === null || from === void 0 ? void 0 : from.filterList) || [];
1198
- if (this.filters.length > 0 && !oldFilters) {
1199
- to.filterList = this.filters;
1200
- }
1201
- else if (oldFilters) {
1202
- to.filterList = [...oldFilters, ...this.filters];
1203
- }
1204
- }
1205
- finalize(fromSeg) {
1206
- let from;
1207
- if (fromSeg) {
1208
- if (model.isReduceSegment(fromSeg)) {
1209
- from = fromSeg;
1210
- }
1211
- else {
1212
- this.inputFS.result.log(`Can't refine reduce with ${fromSeg.type}`);
1213
- return ErrorFactory.reduceSegment;
1214
- }
1215
- }
1216
- const reduceSegment = this.resultFS.getQuerySegment(from);
1217
- this.refineFrom(from, reduceSegment);
1218
- return reduceSegment;
1219
- }
1220
- }
1221
- class ProjectExecutor extends ReduceExecutor {
1222
- getResultSpace(fs) {
1223
- return new ProjectFieldSpace(fs);
1224
- }
1225
- execute(qp) {
1226
- if (qp instanceof ProjectStatement) {
1227
- this.resultFS.addMembers(qp.list);
1228
- }
1229
- else if ((qp instanceof Filter && qp.elementType === "having") ||
1230
- qp instanceof Measures ||
1231
- qp instanceof GroupBy) {
1232
- qp.log("Illegal statement in a project query operation");
1233
- }
1234
- else {
1235
- super.execute(qp);
1236
- }
1237
- }
1238
- finalize(fromSeg) {
1239
- let from;
1240
- if (fromSeg) {
1241
- if (model.isProjectSegment(fromSeg)) {
1242
- from = fromSeg;
1243
- }
1244
- else {
1245
- this.resultFS.log(`Can't refine project with ${fromSeg.type}`);
1246
- return ErrorFactory.projectSegment;
1247
- }
1248
- }
1249
- const projectSegment = this.resultFS.getQuerySegment(from);
1250
- this.refineFrom(from, projectSegment);
1251
- return projectSegment;
1252
- }
1253
- }
1254
- class IndexExecutor {
1255
- constructor(inputFS) {
1256
- this.filters = [];
1257
- this.resultFS = new IndexFieldSpace(inputFS);
1258
- this.inputFS = this.resultFS.exprSpace;
1259
- }
1260
- execute(qp) {
1261
- if (qp instanceof Filter) {
1262
- this.filters.push(...qp.getFilterList(this.inputFS));
1263
- }
1264
- else if (qp instanceof Limit) {
1265
- if (this.limit) {
1266
- this.limit.log("Ignored, too many limit: statements");
1267
- }
1268
- this.limit = qp;
1269
- }
1270
- else if (qp instanceof Index) {
1271
- this.resultFS.addMembers(qp.fields.list);
1272
- if (qp.weightBy) {
1273
- if (this.indexOn) {
1274
- this.indexOn.log("Ignoring previous BY");
1275
- }
1276
- this.indexOn = qp.weightBy;
1277
- }
1278
- }
1279
- else if (qp instanceof SampleProperty) {
1280
- this.sample = qp.sampling();
1281
- }
1282
- else {
1283
- qp.log("Not legal in an index query operation");
1284
- }
1285
- }
1286
- finalize(from) {
1287
- if (from && from.type !== "index") {
1288
- this.resultFS.log(`Can't refine index with ${from.type}`);
1289
- return ErrorFactory.indexSegment;
1290
- }
1291
- const indexSegment = this.resultFS.getPipeSegment(from);
1292
- const oldFilters = (from === null || from === void 0 ? void 0 : from.filterList) || [];
1293
- if (this.filters.length > 0 && !oldFilters) {
1294
- indexSegment.filterList = this.filters;
1295
- }
1296
- else if (oldFilters) {
1297
- indexSegment.filterList = [...oldFilters, ...this.filters];
1298
- }
1299
- if (from === null || from === void 0 ? void 0 : from.limit) {
1300
- indexSegment.limit = from.limit;
1301
- }
1302
- if (this.limit) {
1303
- indexSegment.limit = this.limit.limit;
1304
- }
1305
- if (this.indexOn) {
1306
- indexSegment.weightMeasure = this.indexOn.refString;
1307
- }
1308
- if (from === null || from === void 0 ? void 0 : from.sample) {
1309
- indexSegment.sample = from.sample;
1310
- }
1311
- if (this.sample) {
1312
- indexSegment.sample = this.sample;
1313
- }
1314
- return indexSegment;
1315
- }
1316
- }
1317
- class QOPDesc extends ListOf {
1318
- constructor(props) {
1319
- super("queryOperator", props);
1320
- this.opType = "grouping";
1321
- }
1322
- computeType() {
1323
- let firstGuess;
1324
- if (this.refineThis) {
1325
- if (this.refineThis.type == "reduce") {
1326
- firstGuess = "grouping";
1327
- }
1328
- else {
1329
- firstGuess = this.refineThis.type;
1330
- }
1331
- }
1332
- let anyGrouping = false;
1333
- for (const el of this.list) {
1334
- if (el instanceof Index) {
1335
- firstGuess || (firstGuess = "index");
1336
- if (firstGuess !== "index") {
1337
- el.log(`index: not legal in ${firstGuess} query`);
1338
- }
1339
- }
1340
- else if (el instanceof Nests ||
1341
- isNestedQuery(el) ||
1342
- el instanceof GroupBy) {
1343
- firstGuess || (firstGuess = "grouping");
1344
- anyGrouping = true;
1345
- if (firstGuess === "project" || firstGuess === "index") {
1346
- el.log(`group_by: not legal in ${firstGuess} query`);
1347
- }
1348
- }
1349
- else if (el instanceof Aggregate) {
1350
- firstGuess || (firstGuess = "aggregate");
1351
- if (firstGuess === "project" || firstGuess === "index") {
1352
- el.log(`aggregate: not legal in ${firstGuess} query`);
1353
- }
1354
- }
1355
- else if (el instanceof ProjectStatement) {
1356
- firstGuess || (firstGuess = "project");
1357
- if (firstGuess !== "project") {
1358
- el.log(`project: not legal in ${firstGuess} query`);
1359
- }
1360
- }
1361
- }
1362
- if (firstGuess === "aggregate" && anyGrouping) {
1363
- firstGuess = "grouping";
1364
- }
1365
- if (!firstGuess) {
1366
- this.log("Can't determine query type (group_by/aggregate/nest,project,index)");
1367
- }
1368
- const guessType = firstGuess || "grouping";
1369
- this.opType = guessType;
1370
- return guessType;
1371
- }
1372
- refineFrom(existing) {
1373
- this.refineThis = existing;
1374
- }
1375
- getExecutor(baseFS) {
1376
- switch (this.computeType()) {
1377
- case "aggregate":
1378
- case "grouping":
1379
- return new ReduceExecutor(baseFS);
1380
- case "project":
1381
- return new ProjectExecutor(baseFS);
1382
- case "index":
1383
- return new IndexExecutor(baseFS);
1384
- }
1385
- }
1386
- getOp(inputFS, forPipeline) {
1387
- const qex = this.getExecutor(inputFS);
1388
- if (forPipeline === null || forPipeline === void 0 ? void 0 : forPipeline.nestedInQuerySpace) {
1389
- qex.inputFS.nestParent = forPipeline.nestedInQuerySpace;
1390
- }
1391
- qex.resultFS.astEl = this;
1392
- for (const qp of this.list) {
1393
- qex.execute(qp);
1394
- }
1395
- const segment = qex.finalize(this.refineThis);
1396
- return {
1397
- segment,
1398
- outputSpace: () => new DynamicSpace(opOutputStruct(this, inputFS.structDef(), segment)),
1399
- };
1400
- }
1401
- }
1402
- exports.QOPDesc = QOPDesc;
1403
- /**
1404
- * The Document class is a little weird because we might need to bounce back
1405
- * to the requestor, which might be on the other side of a wire, to get
1406
- * back some schema information. The intended translation of a Document
1407
- * is to call initModelDef(), and then to call modelDataRequest() until it
1408
- * returns undefined. At any time you can call modelDef to get the model
1409
- * as it exists so far, but the translation is not complete until
1410
- * modelDataRequest() returns undefined;
1411
- *
1412
- * TODO probably modelRequest should be the method and you call it
1413
- * until it returns a model with no additional data needed ...
1414
- * that can be tomorrow
1415
- */
1416
- class Document extends MalloyElement {
1417
- constructor(statements) {
1418
- super();
1419
- this.elementType = "document";
1420
- this.documentModel = {};
1421
- this.queryList = [];
1422
- this.sqlBlocks = [];
1423
- this.didInitModel = false;
1424
- this.statements = new RunList("topLevelStatements", statements);
1425
- this.has({ statements });
1426
- }
1427
- initModelDef(extendingModelDef) {
1428
- if (this.didInitModel) {
1429
- return;
1430
- }
1431
- this.documentModel = {};
1432
- this.queryList = [];
1433
- this.sqlBlocks = [];
1434
- if (extendingModelDef) {
1435
- for (const inName in extendingModelDef.contents) {
1436
- const struct = extendingModelDef.contents[inName];
1437
- if (struct.type == "struct") {
1438
- const exported = extendingModelDef.exports.includes(inName);
1439
- this.setEntry(inName, { entry: struct, exported });
1440
- }
1441
- }
1442
- }
1443
- this.didInitModel = true;
1444
- }
1445
- compile() {
1446
- const needs = this.statements.executeList(this);
1447
- const ret = {
1448
- modelDef: this.modelDef(),
1449
- queryList: this.queryList,
1450
- sqlBlocks: this.sqlBlocks,
1451
- needs,
1452
- };
1453
- return ret;
1454
- }
1455
- modelDef() {
1456
- const def = { name: "", exports: [], contents: {} };
1457
- for (const entry in this.documentModel) {
1458
- const entryDef = this.documentModel[entry].entry;
1459
- if (entryDef.type === "struct" || entryDef.type === "query") {
1460
- if (this.documentModel[entry].exported) {
1461
- def.exports.push(entry);
1462
- }
1463
- def.contents[entry] = (0, lodash_1.cloneDeep)(entryDef);
1464
- }
1465
- }
1466
- return def;
1467
- }
1468
- defineSQL(sql, name) {
1469
- const ret = { ...sql, as: `$${this.sqlBlocks.length}` };
1470
- if (name) {
1471
- if (this.getEntry(name)) {
1472
- return false;
1473
- }
1474
- ret.as = name;
1475
- this.setEntry(name, { entry: ret, sqlType: true });
1476
- }
1477
- this.sqlBlocks.push(ret);
1478
- return true;
1479
- }
1480
- getEntry(str) {
1481
- return this.documentModel[str];
1482
- }
1483
- setEntry(str, ent) {
1484
- this.documentModel[str] = ent;
1485
- }
1486
- }
1487
- exports.Document = Document;
1488
- class PrimaryKey extends MalloyElement {
1489
- constructor(field) {
1490
- super({ field });
1491
- this.field = field;
1492
- this.elementType = "primary key";
1493
- }
1494
- }
1495
- exports.PrimaryKey = PrimaryKey;
1496
- class RenameField extends MalloyElement {
1497
- constructor(newName, oldName) {
1498
- super();
1499
- this.newName = newName;
1500
- this.oldName = oldName;
1501
- this.elementType = "renameField";
1502
- this.has({ oldName });
1503
- }
1504
- }
1505
- exports.RenameField = RenameField;
1506
- class WildcardFieldReference extends MalloyElement {
1507
- constructor(joinPath, star) {
1508
- super();
1509
- this.joinPath = joinPath;
1510
- this.star = star;
1511
- this.elementType = "wildcardFieldReference";
1512
- this.has({ joinPath });
1513
- }
1514
- getFieldDef() {
1515
- throw this.internalError("fielddef request from wildcard reference");
1516
- }
1517
- get refString() {
1518
- return this.joinPath
1519
- ? `${this.joinPath.refString}.${this.star}`
1520
- : this.star;
1521
- }
1522
- }
1523
- exports.WildcardFieldReference = WildcardFieldReference;
1524
- class OrderBy extends MalloyElement {
1525
- constructor(field, dir) {
1526
- super();
1527
- this.field = field;
1528
- this.dir = dir;
1529
- this.elementType = "orderBy";
1530
- if (field instanceof FieldName) {
1531
- this.has({ field });
1532
- }
1533
- }
1534
- get modelField() {
1535
- return typeof this.field === "number" ? this.field : this.field.refString;
1536
- }
1537
- getOrderBy(_fs) {
1538
- // TODO jump-to-definition `fs` cannot currently `lookup` fields in the output space
1539
- // if (this.field instanceof FieldName) {
1540
- // const entry = this.field.getField(_fs);
1541
- // if (entry.error) {
1542
- // this.field.log(entry.error);
1543
- // }
1544
- // }
1545
- const orderElement = { field: this.modelField };
1546
- if (this.dir) {
1547
- orderElement.dir = this.dir;
1548
- }
1549
- return orderElement;
1550
- }
1551
- }
1552
- exports.OrderBy = OrderBy;
1553
- class Ordering extends ListOf {
1554
- constructor(list) {
1555
- super("ordering", list);
1556
- }
1557
- getOrderBy(fs) {
1558
- return this.list.map((el) => el.getOrderBy(fs));
1559
- }
1560
- }
1561
- exports.Ordering = Ordering;
1562
- class Limit extends MalloyElement {
1563
- constructor(limit) {
1564
- super();
1565
- this.limit = limit;
1566
- this.elementType = "limit";
1567
- }
1568
- }
1569
- exports.Limit = Limit;
1570
- class Turtles extends ListOf {
1571
- constructor(turtles) {
1572
- super("turtleDeclarationList", turtles);
1573
- }
1574
- }
1575
- exports.Turtles = Turtles;
1576
- class Index extends MalloyElement {
1577
- constructor(fields) {
1578
- super({ fields });
1579
- this.fields = fields;
1580
- this.elementType = "index";
1581
- }
1582
- useWeight(fn) {
1583
- this.has({ weightBy: fn });
1584
- this.weightBy = fn;
1585
- }
1586
- }
1587
- exports.Index = Index;
1588
- function isTurtle(fd) {
1589
- const ret = fd && typeof fd !== "string" && fd.type === "turtle";
1590
- return !!ret;
1591
- }
1592
- /**
1593
- * Generic abstract for all pipelines, the first segment might be a reference
1594
- * to an existing pipeline (query or turtle), and if there is a refinement it
1595
- * is refers to the first segment of the composed pipeline.
1596
- */
1597
- class PipelineDesc extends MalloyElement {
1598
- constructor() {
1599
- super(...arguments);
1600
- this.elementType = "pipelineDesc";
1601
- this.qops = [];
1602
- }
1603
- refineHead(refinement) {
1604
- this.headRefinement = refinement;
1605
- this.has({ headRefinement: refinement });
1606
- }
1607
- addSegments(...segDesc) {
1608
- this.qops.push(...segDesc);
1609
- this.has({ segments: this.qops });
1610
- }
1611
- appendOps(modelPipe, existingEndSpace) {
1612
- let nextFS = existingEndSpace;
1613
- let returnPipe;
1614
- for (const qop of this.qops) {
1615
- const qopIsNested = modelPipe.length == 0;
1616
- const next = qop.getOp(nextFS, qopIsNested ? this : null);
1617
- if (returnPipe == undefined) {
1618
- returnPipe = [...modelPipe];
1619
- }
1620
- returnPipe.push(next.segment);
1621
- nextFS = next.outputSpace();
1622
- }
1623
- return {
1624
- opList: returnPipe || modelPipe,
1625
- structDef: nextFS.structDef(),
1626
- };
1627
- }
1628
- refinePipeline(fs, modelPipe) {
1629
- if (!this.headRefinement) {
1630
- return modelPipe;
1631
- }
1632
- const pipeline = [];
1633
- if (modelPipe.pipeHead) {
1634
- const { pipeline: turtlePipe } = this.expandTurtle(modelPipe.pipeHead.name, fs.structDef());
1635
- pipeline.push(...turtlePipe);
1636
- }
1637
- pipeline.push(...modelPipe.pipeline);
1638
- const firstSeg = pipeline[0];
1639
- if (firstSeg) {
1640
- this.headRefinement.refineFrom(firstSeg);
1641
- }
1642
- pipeline[0] = this.headRefinement.getOp(fs, this).segment;
1643
- return { pipeline };
1644
- }
1645
- expandTurtle(turtleName, fromStruct) {
1646
- const turtle = getStructFieldDef(fromStruct, turtleName);
1647
- if (!turtle) {
1648
- this.log(`Query '${turtleName}' is not defined in source`);
1649
- }
1650
- else if (turtle.type !== "turtle") {
1651
- this.log(`'${turtleName}' is not a query`);
1652
- }
1653
- else {
1654
- return { pipeline: turtle.pipeline, location: turtle.location };
1655
- }
1656
- return { pipeline: [], location: undefined };
1657
- }
1658
- getOutputStruct(walkStruct, pipeline) {
1659
- for (const modelQop of pipeline) {
1660
- walkStruct = opOutputStruct(this, walkStruct, modelQop);
1661
- }
1662
- return walkStruct;
1663
- }
1664
- }
1665
- class ExistingQuery extends PipelineDesc {
1666
- set head(head) {
1667
- this._head = head;
1668
- this.has({ head });
1669
- }
1670
- get head() {
1671
- return this._head;
1672
- }
1673
- queryComp() {
1674
- if (!this.head) {
1675
- throw this.internalError("can't make query from nameless query");
1676
- }
1677
- const queryEntry = this.modelEntry(this.head);
1678
- const seedQuery = queryEntry === null || queryEntry === void 0 ? void 0 : queryEntry.entry;
1679
- const oops = function () {
1680
- return {
1681
- outputStruct: ErrorFactory.structDef,
1682
- query: ErrorFactory.query,
1683
- };
1684
- };
1685
- if (!seedQuery) {
1686
- this.log(`Reference to undefined query '${this.head}'`);
1687
- return oops();
1688
- }
1689
- if (seedQuery.type !== "query") {
1690
- this.log(`Illegal reference to '${this.head}', query expected`);
1691
- return oops();
1692
- }
1693
- const queryHead = new QueryHeadStruct(seedQuery.structRef);
1694
- this.has({ queryHead });
1695
- const exploreStruct = queryHead.structDef();
1696
- const exploreFS = new DynamicSpace(exploreStruct);
1697
- const sourcePipe = this.refinePipeline(exploreFS, seedQuery);
1698
- const walkStruct = this.getOutputStruct(exploreStruct, sourcePipe.pipeline);
1699
- const appended = this.appendOps(sourcePipe.pipeline, new DynamicSpace(walkStruct));
1700
- const destPipe = { ...sourcePipe, pipeline: appended.opList };
1701
- const query = {
1702
- type: "query",
1703
- ...destPipe,
1704
- structRef: queryHead.structRef(),
1705
- location: this.location,
1706
- };
1707
- return { outputStruct: appended.structDef, query };
1708
- }
1709
- query() {
1710
- return this.queryComp().query;
1711
- }
1712
- }
1713
- exports.ExistingQuery = ExistingQuery;
1714
- class TurtleHeadedPipe extends PipelineDesc {
1715
- set turtleName(turtleName) {
1716
- this._turtleName = turtleName;
1717
- this.has({ turtleName });
1718
- }
1719
- get turtleName() {
1720
- return this._turtleName;
1721
- }
1722
- }
1723
- exports.TurtleHeadedPipe = TurtleHeadedPipe;
1724
- class FullQuery extends TurtleHeadedPipe {
1725
- constructor(explore) {
1726
- super({ explore });
1727
- this.explore = explore;
1728
- }
1729
- queryComp() {
1730
- const structRef = this.explore.structRef();
1731
- const destQuery = {
1732
- type: "query",
1733
- structRef,
1734
- pipeline: [],
1735
- location: this.location,
1736
- };
1737
- const structDef = model.refIsStructDef(structRef)
1738
- ? structRef
1739
- : this.explore.structDef();
1740
- let pipeFs = new DynamicSpace(structDef);
1741
- if (ErrorFactory.isErrorStructDef(structDef)) {
1742
- return {
1743
- outputStruct: structDef,
1744
- query: {
1745
- structRef: structRef,
1746
- pipeline: [],
1747
- },
1748
- };
1749
- }
1750
- if (this.turtleName) {
1751
- const { error } = this.turtleName.getField(pipeFs);
1752
- if (error)
1753
- this.log(error);
1754
- const name = this.turtleName.refString;
1755
- const { pipeline, location } = this.expandTurtle(name, structDef);
1756
- destQuery.location = location;
1757
- const refined = this.refinePipeline(pipeFs, { pipeline }).pipeline;
1758
- if (this.headRefinement) {
1759
- // TODO there is an issue with losing the name of the turtle
1760
- // which we need to fix, possibly adding a "name:" field to a segment
1761
- // TODO there was mention of promoting filters to the query
1762
- destQuery.pipeline = refined;
1763
- }
1764
- else {
1765
- destQuery.pipeHead = { name };
1766
- }
1767
- const pipeStruct = this.getOutputStruct(structDef, refined);
1768
- pipeFs = new DynamicSpace(pipeStruct);
1769
- }
1770
- const appended = this.appendOps(destQuery.pipeline, pipeFs);
1771
- destQuery.pipeline = appended.opList;
1772
- return { outputStruct: appended.structDef, query: destQuery };
1773
- }
1774
- query() {
1775
- return this.queryComp().query;
1776
- }
1777
- }
1778
- exports.FullQuery = FullQuery;
1779
- class TurtleDecl extends TurtleHeadedPipe {
1780
- constructor(name) {
1781
- super();
1782
- this.name = name;
1783
- }
1784
- getPipeline(fs) {
1785
- const modelPipe = { pipeline: [] };
1786
- if (this.turtleName) {
1787
- const headEnt = this.turtleName.getField(fs);
1788
- let reportWrongType = true;
1789
- if (headEnt.error) {
1790
- this.log(headEnt.error);
1791
- reportWrongType = false;
1792
- }
1793
- else if (headEnt.found instanceof QueryField) {
1794
- const headDef = headEnt.found.getQueryFieldDef(fs);
1795
- if (isTurtle(headDef)) {
1796
- const newPipe = this.refinePipeline(fs, headDef);
1797
- modelPipe.pipeline = [...newPipe.pipeline];
1798
- reportWrongType = false;
1799
- }
1800
- }
1801
- if (reportWrongType) {
1802
- this.log(`Expected '${this.turtleName}' to be a query`);
1803
- }
1804
- }
1805
- else if (this.headRefinement) {
1806
- throw this.internalError("Can't refine the head of a turtle in its definition");
1807
- }
1808
- let appendInput = fs;
1809
- if (modelPipe.pipeline.length > 0) {
1810
- let endStruct = appendInput.structDef();
1811
- for (const existingSeg of modelPipe.pipeline) {
1812
- endStruct = opOutputStruct(this, endStruct, existingSeg);
1813
- }
1814
- appendInput = new DynamicSpace(endStruct);
1815
- }
1816
- const appended = this.appendOps(modelPipe.pipeline, appendInput);
1817
- modelPipe.pipeline = appended.opList;
1818
- return modelPipe;
1819
- }
1820
- getFieldDef(fs, nestParent) {
1821
- if (nestParent) {
1822
- this.nestedInQuerySpace = nestParent;
1823
- }
1824
- const pipe = this.getPipeline(fs);
1825
- return {
1826
- type: "turtle",
1827
- name: this.name,
1828
- ...pipe,
1829
- location: this.location,
1830
- };
1831
- }
1832
- }
1833
- exports.TurtleDecl = TurtleDecl;
1834
- class NestReference extends FieldReference {
1835
- constructor(name) {
1836
- super([name]);
1837
- this.name = name;
1838
- this.elementType = "nestReference";
1839
- }
1840
- }
1841
- exports.NestReference = NestReference;
1842
- class NestRefinement extends TurtleDecl {
1843
- constructor(turtleName) {
1844
- super(turtleName.refString);
1845
- this.elementType = "nestRefinement";
1846
- this.turtleName = turtleName;
1847
- }
1848
- }
1849
- exports.NestRefinement = NestRefinement;
1850
- class NestDefinition extends TurtleDecl {
1851
- constructor(name) {
1852
- super(name);
1853
- this.elementType = "nestDefinition";
1854
- }
1855
- }
1856
- exports.NestDefinition = NestDefinition;
1857
- function isNestedQuery(me) {
1858
- return (me instanceof NestRefinement ||
1859
- me instanceof NestReference ||
1860
- me instanceof NestDefinition);
1861
- }
1862
- exports.isNestedQuery = isNestedQuery;
1863
- class Nests extends ListOf {
1864
- constructor(nests) {
1865
- super("nestedQueries", nests);
1866
- }
1867
- }
1868
- exports.Nests = Nests;
1869
- function isQueryElement(e) {
1870
- return e instanceof FullQuery || e instanceof ExistingQuery;
1871
- }
1872
- exports.isQueryElement = isQueryElement;
1873
- class DefineQueryList extends RunList {
1874
- constructor(queryList) {
1875
- super("defineQueries", queryList);
1876
- }
1877
- execute(doc) {
1878
- return this.executeList(doc);
1879
- }
1880
- }
1881
- exports.DefineQueryList = DefineQueryList;
1882
- class DefineQuery extends MalloyElement {
1883
- constructor(name, queryDetails) {
1884
- super({ queryDetails });
1885
- this.name = name;
1886
- this.queryDetails = queryDetails;
1887
- this.elementType = "defineQuery";
1888
- }
1889
- execute(doc) {
1890
- const entry = {
1891
- ...this.queryDetails.query(),
1892
- type: "query",
1893
- name: this.name,
1894
- location: this.location,
1895
- };
1896
- const exported = false;
1897
- doc.setEntry(this.name, { entry, exported });
1898
- return undefined;
1899
- }
1900
- }
1901
- exports.DefineQuery = DefineQuery;
1902
- class AnonymousQuery extends MalloyElement {
1903
- constructor(theQuery) {
1904
- super();
1905
- this.theQuery = theQuery;
1906
- this.elementType = "anonymousQuery";
1907
- this.has({ query: theQuery });
1908
- }
1909
- execute(doc) {
1910
- const modelQuery = this.theQuery.query();
1911
- doc.queryList.push(modelQuery);
1912
- return undefined;
1913
- }
1914
- }
1915
- exports.AnonymousQuery = AnonymousQuery;
1916
- class Top extends MalloyElement {
1917
- constructor(limit, by) {
1918
- super();
1919
- this.limit = limit;
1920
- this.by = by;
1921
- this.elementType = "top";
1922
- this.has({ by });
1923
- }
1924
- getBy(fs) {
1925
- if (this.by) {
1926
- if (this.by instanceof FieldName) {
1927
- // TODO jump-to-definition `fs` cannot currently `lookup` fields in the output space
1928
- // const entry = this.by.getField(fs);
1929
- // if (entry.error) {
1930
- // this.by.log(entry.error);
1931
- // }
1932
- return { by: "name", name: this.by.refString };
1933
- }
1934
- else {
1935
- const byExpr = this.by.getExpression(fs);
1936
- if (model.expressionIsAggregate(byExpr.expressionType)) {
1937
- this.log("top by expression must be an aggregate");
1938
- }
1939
- return { by: "expression", e: (0, ast_types_1.compressExpr)(byExpr.value) };
1940
- }
1941
- }
1942
- return undefined;
1943
- }
1944
- }
1945
- exports.Top = Top;
1946
- class JSONElement extends MalloyElement {
1947
- constructor(jsonSrc) {
1948
- super();
1949
- this.elementType = "jsonElement";
1950
- try {
1951
- this.value = JSON.parse(jsonSrc);
1952
- }
1953
- catch (SyntaxError) {
1954
- this.log("JSON syntax error");
1955
- this.value = undefined;
1956
- }
1957
- }
1958
- }
1959
- exports.JSONElement = JSONElement;
1960
- class JSONStructDef extends Mallobj {
1961
- constructor(struct) {
1962
- super();
1963
- this.struct = struct;
1964
- this.elementType = "jsonStructDef";
1965
- }
1966
- static fromJSON(jsonObj) {
1967
- const obj = jsonObj.value;
1968
- if (obj &&
1969
- obj.type === "struct" &&
1970
- obj.structRelationship &&
1971
- obj.structSource) {
1972
- return new JSONStructDef(obj);
1973
- }
1974
- return undefined;
1975
- }
1976
- structDef() {
1977
- return this.struct;
1978
- }
1979
- }
1980
- exports.JSONStructDef = JSONStructDef;
1981
- class ImportStatement extends MalloyElement {
1982
- /*
1983
- * At the time of writng this comment, it is guaranteed that if an AST
1984
- * node for an import statement is created, the translator has already
1985
- * succesfully fetched the URL referred to in the statement.
1986
- *
1987
- * Error checking code in here is future proofing against a day when
1988
- * there are other ways to contruct an AST.
1989
- */
1990
- constructor(url, baseURL) {
1991
- super();
1992
- this.url = url;
1993
- this.elementType = "import statement";
1994
- try {
1995
- this.fullURL = decodeURI(new URL(url, baseURL).toString());
1996
- }
1997
- catch (e) {
1998
- this.log("Invalid URI in import statement");
1999
- }
2000
- }
2001
- execute(doc) {
2002
- const trans = this.translator();
2003
- if (!trans) {
2004
- this.log("Cannot import without translation context");
2005
- }
2006
- else if (this.fullURL) {
2007
- const src = trans.root.importZone.getEntry(this.fullURL);
2008
- if (src.status === "present") {
2009
- const childNeeds = trans.childRequest(this.fullURL);
2010
- if (childNeeds) {
2011
- return childNeeds;
2012
- }
2013
- const importStructs = trans.getChildExports(this.fullURL);
2014
- for (const importing in importStructs) {
2015
- doc.setEntry(importing, {
2016
- entry: importStructs[importing],
2017
- exported: false,
2018
- });
2019
- }
2020
- }
2021
- else if (src.status === "error") {
2022
- this.log(`import failed: '${src.message}'`);
2023
- }
2024
- else {
2025
- this.log(`import failed with status: '${src.status}'`);
2026
- }
2027
- }
2028
- return undefined;
2029
- }
2030
- }
2031
- exports.ImportStatement = ImportStatement;
2032
- class HasParameter extends MalloyElement {
2033
- constructor(init) {
2034
- super();
2035
- this.elementType = "hasParameter";
2036
- this.name = init.name;
2037
- this.isCondition = init.isCondition;
2038
- if (init.type && model.isAtomicFieldType(init.type)) {
2039
- this.type = init.type;
2040
- }
2041
- if (init.default) {
2042
- this.default = init.default;
2043
- this.has({ default: this.default });
2044
- }
2045
- }
2046
- parameter() {
2047
- var _a, _b;
2048
- const name = this.name;
2049
- const type = this.type || "string";
2050
- if (this.isCondition) {
2051
- const cCond = ((_a = this.default) === null || _a === void 0 ? void 0 : _a.constantCondition(type).value) || null;
2052
- return {
2053
- type,
2054
- name,
2055
- condition: cCond,
2056
- };
2057
- }
2058
- const cVal = ((_b = this.default) === null || _b === void 0 ? void 0 : _b.constantValue().value) || null;
2059
- return {
2060
- value: cVal,
2061
- type,
2062
- name: this.name,
2063
- constant: false,
2064
- };
2065
- }
2066
- }
2067
- exports.HasParameter = HasParameter;
2068
- class ConstantParameter extends HasParameter {
2069
- constructor(name, value) {
2070
- super({ name, isCondition: false });
2071
- this.value = value;
2072
- this.has({ value });
2073
- }
2074
- parameter() {
2075
- const cVal = this.value.constantValue();
2076
- if (!model.isAtomicFieldType(cVal.dataType)) {
2077
- this.log(`Unexpected expression type '${cVal.dataType}'`);
2078
- return {
2079
- value: ["XXX-type-mismatch-error-XXX"],
2080
- type: "string",
2081
- name: this.name,
2082
- constant: true,
2083
- };
2084
- }
2085
- return {
2086
- value: cVal.value,
2087
- type: cVal.dataType,
2088
- name: this.name,
2089
- constant: true,
2090
- };
2091
- }
2092
- }
2093
- exports.ConstantParameter = ConstantParameter;
2094
- class SQLString extends MalloyElement {
2095
- constructor() {
2096
- super(...arguments);
2097
- this.elementType = "sqlString";
2098
- this.elements = [];
2099
- this.containsQueries = false;
2100
- }
2101
- push(el) {
2102
- if (typeof el == "string") {
2103
- if (el.length > 0) {
2104
- this.elements.push(el);
2105
- }
2106
- }
2107
- else if (isQueryElement(el)) {
2108
- this.elements.push(el);
2109
- this.containsQueries = true;
2110
- el.parent = this;
2111
- }
2112
- else {
2113
- el.log("This element is not legal inside an SQL string");
2114
- }
2115
- }
2116
- sqlPhrases() {
2117
- return this.elements.map((el) => {
2118
- if (typeof el == "string") {
2119
- return { sql: el };
2120
- }
2121
- return el.query();
2122
- });
2123
- }
2124
- }
2125
- exports.SQLString = SQLString;
2126
- class SQLStatement extends MalloyElement {
2127
- constructor(select) {
2128
- super();
2129
- this.select = select;
2130
- this.elementType = "sqlStatement";
2131
- this.has({ select });
2132
- }
2133
- sqlBlock() {
2134
- if (!this.requestBlock) {
2135
- this.requestBlock = (0, sql_block_1.makeSQLBlock)(this.select.sqlPhrases(), this.connection);
2136
- }
2137
- return this.requestBlock;
2138
- }
2139
- /**
2140
- * This is the one statement which pauses execution. First time through
2141
- * it will generate a schema request, next time through it will either
2142
- * record the error or record the schema.
2143
- */
2144
- execute(doc) {
2145
- var _a;
2146
- const sqlDefEntry = (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.root.sqlQueryZone;
2147
- if (!sqlDefEntry) {
2148
- this.log("Cant't look up schema for sql block");
2149
- return;
2150
- }
2151
- const sql = this.sqlBlock();
2152
- sqlDefEntry.reference(sql.name, this.location);
2153
- const lookup = sqlDefEntry.getEntry(sql.name);
2154
- if (lookup.status == "error") {
2155
- const msgLines = lookup.message.split(/\r?\n/);
2156
- this.select.log("Invalid SQL, " + msgLines.join("\n "));
2157
- return undefined;
2158
- }
2159
- if (lookup.status == "present") {
2160
- const location = this.select.location;
2161
- const locStruct = {
2162
- ...lookup.value,
2163
- fields: lookup.value.fields.map((f) => ({ ...f, location })),
2164
- location: this.location,
2165
- };
2166
- if (this.is && !doc.defineSQL(locStruct, this.is)) {
2167
- this.log(`'${this.is}' already defined`);
2168
- }
2169
- return undefined;
2170
- }
2171
- return {
2172
- compileSQL: sql,
2173
- partialModel: this.select.containsQueries ? doc.modelDef() : undefined,
2174
- };
2175
- }
2176
- }
2177
- exports.SQLStatement = SQLStatement;
2178
- class SampleProperty extends MalloyElement {
2179
- constructor(sample) {
2180
- super();
2181
- this.sample = sample;
2182
- this.elementType = "sampleProperty";
2183
- }
2184
- sampling() {
2185
- return this.sample;
2186
- }
2187
- }
2188
- exports.SampleProperty = SampleProperty;
2189
- /**
2190
- * Root node for any element in an expression. These essentially
2191
- * create a sub-tree in the larger AST. Expression nodes know
2192
- * how to write themselves as SQL (or rather, generate the
2193
- * template for SQL required by the query writer)
2194
- */
2195
- class ExpressionDef extends MalloyElement {
2196
- constructor() {
2197
- super(...arguments);
2198
- this.legalChildTypes = ast_types_1.FT.anyAtomicT;
2199
- }
2200
- granular() {
2201
- return false;
2202
- }
2203
- /**
2204
- * Some operators want to give the right hand value a chance to
2205
- * rewrite itself. This requests a translation for a rewrite,
2206
- * or returns undefined if that request should be denied.
2207
- * @param fs FieldSpace
2208
- * @returns Translated expression or undefined
2209
- */
2210
- requestExpression(fs) {
2211
- return this.getExpression(fs);
2212
- }
2213
- defaultFieldName() {
2214
- return undefined;
2215
- }
2216
- /**
2217
- * Check an expression for type compatibility
2218
- * @param _eNode currently unused, will be used to get error location
2219
- * @param eVal ...list of expressions that must match legalChildTypes
2220
- */
2221
- typeCheck(eNode, eVal) {
2222
- if (!ast_types_1.FT.in(eVal, this.legalChildTypes)) {
2223
- eNode.log(`'${this.elementType}' Can't use type ${ast_types_1.FT.inspect(eVal)}`);
2224
- return false;
2225
- }
2226
- return true;
2227
- }
2228
- /**
2229
- * This is the operation which makes partial comparison and value trees work
2230
- * The default implemention merely constructs LEFT OP RIGHT, but specialized
2231
- * nodes like alternation trees or or partial comparison can control how
2232
- * the appplication gets generated
2233
- * @param fs The symbol table
2234
- * @param op The operator being applied
2235
- * @param expr The "other" (besdies 'this') value
2236
- * @returns The translated expression
2237
- */
2238
- apply(fs, op, left) {
2239
- return applyBinary(fs, left, op, this);
2240
- }
2241
- }
2242
- exports.ExpressionDef = ExpressionDef;
2243
- class ConstantSubExpression extends ExpressionDef {
2244
- constructor(expr) {
2245
- super({ expr });
2246
- this.expr = expr;
2247
- this.elementType = "constantExpression";
2248
- }
2249
- getExpression(_fs) {
2250
- return this.constantValue();
2251
- }
2252
- get constantFs() {
2253
- if (!this.cfs) {
2254
- this.cfs = new ConstantFieldSpace();
2255
- }
2256
- return this.cfs;
2257
- }
2258
- constantValue() {
2259
- return this.expr.getExpression(this.constantFs);
2260
- }
2261
- constantCondition(type) {
2262
- const compareAndContrast = new ExprCompare(new DollarReference(type), "=", this.expr);
2263
- const application = compareAndContrast.getExpression(this.constantFs);
2264
- return { ...application, value: (0, ast_types_1.compressExpr)(application.value) };
2265
- }
2266
- apply(fs, op, expr) {
2267
- return this.expr.apply(fs, op, expr);
2268
- }
2269
- requestExpression(fs) {
2270
- return this.expr.requestExpression(fs);
2271
- }
2272
- }
2273
- exports.ConstantSubExpression = ConstantSubExpression;
2274
- class DollarReference extends ExpressionDef {
2275
- constructor(refType) {
2276
- super();
2277
- this.refType = refType;
2278
- this.elementType = "$";
2279
- }
2280
- getExpression(_fs) {
2281
- return {
2282
- dataType: this.refType,
2283
- value: [{ type: "applyVal" }],
2284
- expressionType: "scalar",
2285
- };
2286
- }
2287
- }
2288
- class ConstantFieldSpace {
2289
- constructor() {
2290
- this.type = "fieldSpace";
2291
- }
2292
- structDef() {
2293
- throw new Error("ConstantFieldSpace cannot generate a structDef");
2294
- }
2295
- emptyStructDef() {
2296
- throw new Error("ConstantFieldSpace cannot generate a structDef");
2297
- }
2298
- lookup(_name) {
2299
- return {
2300
- error: "Only constants allowed in parameter expressions",
2301
- found: undefined,
2302
- };
2303
- }
2304
- dialectObj() {
2305
- return undefined;
2306
- }
2307
- whenComplete(step) {
2308
- step();
2309
- }
2310
- }
2311
- class FieldDeclaration extends MalloyElement {
2312
- constructor(expr, defineName, exprSrc) {
2313
- super({ expr });
2314
- this.expr = expr;
2315
- this.defineName = defineName;
2316
- this.exprSrc = exprSrc;
2317
- this.elementType = "fieldDeclaration";
2318
- }
2319
- fieldDef(fs, exprName) {
2320
- /*
2321
- * In an explore we cannot reference the thing we are defining, you need
2322
- * to use rename. In a query, the output space is a new thing, and expressions
2323
- * can reference the outer value in order to make a value with the new name,
2324
- * and it feels wrong that this is HERE and not somehow in the QueryOperation.
2325
- * For now, this stops the stack overflow, and passes all tests, but I think
2326
- * a refactor of QueryFieldSpace might someday be the place where this should
2327
- * happen.
2328
- */
2329
- return this.queryFieldDef(new DefSpace(fs, this), exprName);
2330
- }
2331
- queryFieldDef(exprFS, exprName) {
2332
- let exprValue;
2333
- try {
2334
- exprValue = this.expr.getExpression(exprFS);
2335
- }
2336
- catch (error) {
2337
- this.log(`Cannot define '${exprName}', ${error.message}`);
2338
- return {
2339
- name: `error_defining_${exprName}`,
2340
- type: "string",
2341
- };
2342
- }
2343
- const compressValue = (0, ast_types_1.compressExpr)(exprValue.value);
2344
- const retType = exprValue.dataType;
2345
- if ((0, malloy_types_1.isAtomicFieldType)(retType)) {
2346
- const template = {
2347
- name: exprName,
2348
- type: retType,
2349
- location: this.location,
2350
- };
2351
- if (compressValue.length > 0) {
2352
- template.e = compressValue;
2353
- }
2354
- if (exprValue.expressionType) {
2355
- template.expressionType = exprValue.expressionType;
2356
- }
2357
- if (this.exprSrc) {
2358
- template.code = this.exprSrc;
2359
- }
2360
- // TODO this should work for dates too
2361
- if ((0, ast_types_1.isGranularResult)(exprValue) && template.type === "timestamp") {
2362
- template.timeframe = exprValue.timeframe;
2363
- }
2364
- return template;
2365
- }
2366
- const circularDef = exprFS instanceof DefSpace && exprFS.foundCircle;
2367
- if (!circularDef) {
2368
- if (exprValue.dataType == "unknown") {
2369
- this.log(`Cannot define '${exprName}', value has unknown type`);
2370
- }
2371
- else {
2372
- const badType = ast_types_1.FT.inspect(exprValue);
2373
- this.log(`Cannot define '${exprName}', unexpected type: ${badType}`);
2374
- }
2375
- }
2376
- return {
2377
- name: `error_defining_${exprName}`,
2378
- type: "string",
2379
- };
2380
- }
2381
- }
2382
- exports.FieldDeclaration = FieldDeclaration;
2383
- /**
2384
- * All of the magic of malloy expressions eventually flows to here,
2385
- * where an operator is applied to two values. Depending on the
2386
- * operator and value types this may involve transformations of
2387
- * the values or even the operator.
2388
- * @param fs FieldSpace for the symbols
2389
- * @param left Left value
2390
- * @param op The operator
2391
- * @param right Right Value
2392
- * @returns ExprValue of the expression
2393
- */
2394
- function applyBinary(fs, left, op, right) {
2395
- if ((0, ast_types_1.isEquality)(op)) {
2396
- return equality(fs, left, op, right);
2397
- }
2398
- if ((0, ast_types_1.isComparison)(op)) {
2399
- return compare(fs, left, op, right);
2400
- }
2401
- if (oneOf(op, "+", "-")) {
2402
- return delta(fs, left, op, right);
2403
- }
2404
- if (oneOf(op, "*", "%")) {
2405
- return numeric(fs, left, op, right);
2406
- }
2407
- if (oneOf(op, "/")) {
2408
- const num = left.getExpression(fs);
2409
- const denom = right.getExpression(fs);
2410
- if (num.dataType != "number") {
2411
- left.log("Numerator for division must be a number");
2412
- }
2413
- else if (denom.dataType != "number") {
2414
- right.log("Denominator for division must be a number");
2415
- }
2416
- else {
2417
- const div = {
2418
- type: "dialect",
2419
- function: "div",
2420
- numerator: num.value,
2421
- denominator: denom.value,
2422
- };
2423
- return {
2424
- dataType: "number",
2425
- expressionType: (0, malloy_types_1.maxExpressionType)(num.expressionType, denom.expressionType),
2426
- value: [div],
2427
- };
2428
- }
2429
- return (0, ast_types_1.errorFor)("divide type mismatch");
2430
- }
2431
- left.log(`Canot use ${op} operator here`);
2432
- return (0, ast_types_1.errorFor)("applybinary bad operator");
2433
- }
2434
- exports.applyBinary = applyBinary;
2435
- class BinaryBoolean extends ExpressionDef {
2436
- constructor(left, op, right) {
2437
- super({ left, right });
2438
- this.left = left;
2439
- this.op = op;
2440
- this.right = right;
2441
- this.elementType = "abstract boolean binary";
2442
- this.legalChildTypes = [ast_types_1.FT.boolT];
2443
- }
2444
- getExpression(fs) {
2445
- const left = this.left.getExpression(fs);
2446
- const right = this.right.getExpression(fs);
2447
- if (this.typeCheck(this.left, left) && this.typeCheck(this.right, right)) {
2448
- return {
2449
- dataType: "boolean",
2450
- expressionType: (0, malloy_types_1.maxExpressionType)(left.expressionType, right.expressionType),
2451
- value: (0, ast_types_1.compose)(left.value, this.op, right.value),
2452
- };
2453
- }
2454
- return (0, ast_types_1.errorFor)("logial required boolean");
2455
- }
2456
- }
2457
- exports.BinaryBoolean = BinaryBoolean;
2458
- class ExprCompare extends BinaryBoolean {
2459
- constructor(left, op, right) {
2460
- super(left, op, right);
2461
- this.elementType = "a<=>b";
2462
- this.legalChildTypes = compareTypes[op];
2463
- }
2464
- getExpression(fs) {
2465
- if (!this.right.granular()) {
2466
- const rhs = this.right.requestExpression(fs);
2467
- if (rhs && (0, ast_types_1.isGranularResult)(rhs)) {
2468
- const newRight = new ExprGranularTime(this.right, rhs.timeframe, false);
2469
- return newRight.apply(fs, this.op, this.left);
2470
- }
2471
- }
2472
- return this.right.apply(fs, this.op, this.left);
2473
- }
2474
- }
2475
- exports.ExprCompare = ExprCompare;
2476
- function equality(fs, left, op, right) {
2477
- const lhs = left.getExpression(fs);
2478
- const rhs = right.getExpression(fs);
2479
- let value = timeCompare(lhs, op, rhs) || (0, ast_types_1.compose)(lhs.value, op, rhs.value);
2480
- if (lhs.dataType != "unknown" && rhs.dataType != "unknown") {
2481
- switch (op) {
2482
- case "~":
2483
- case "!~": {
2484
- if (lhs.dataType === "string" && rhs.dataType === "string") {
2485
- value = (0, ast_types_1.compose)(lhs.value, "LIKE", rhs.value);
2486
- }
2487
- else {
2488
- const regexCmp = regexEqual(lhs, rhs);
2489
- if (regexCmp === undefined) {
2490
- throw new TypeMistmatch("Incompatible types for match('~') operator");
2491
- }
2492
- value = regexCmp;
2493
- }
2494
- value = (0, apply_expr_1.nullsafeNot)(value, op);
2495
- break;
2496
- }
2497
- case "=":
2498
- case "!=": {
2499
- const nullCmp = nullCompare(lhs, op, rhs);
2500
- if (nullCmp) {
2501
- value = nullCmp;
2502
- }
2503
- else {
2504
- value = (0, apply_expr_1.nullsafeNot)(regexEqual(lhs, rhs) || (0, ast_types_1.compose)(lhs.value, "=", rhs.value), op);
2505
- }
2506
- break;
2507
- }
2508
- }
2509
- }
2510
- return {
2511
- dataType: "boolean",
2512
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType),
2513
- value,
2514
- };
2515
- }
2516
- function compare(fs, left, op, right) {
2517
- const lhs = left.getExpression(fs);
2518
- const rhs = right.getExpression(fs);
2519
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
2520
- const value = timeCompare(lhs, op, rhs) || (0, ast_types_1.compose)(lhs.value, op, rhs.value);
2521
- return {
2522
- dataType: "boolean",
2523
- expressionType,
2524
- value: value,
2525
- };
2526
- }
2527
- function oneOf(op, ...operators) {
2528
- return operators.includes(op);
2529
- }
2530
- function delta(fs, left, op, right) {
2531
- const lhs = left.getExpression(fs);
2532
- const rhs = right.getExpression(fs);
2533
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType)) {
2534
- let duration = right;
2535
- if (rhs.dataType !== "duration") {
2536
- if ((0, ast_types_1.isGranularResult)(lhs)) {
2537
- duration = new ExprDuration(right, lhs.timeframe);
2538
- }
2539
- else if (lhs.dataType === "date") {
2540
- duration = new ExprDuration(right, "day");
2541
- }
2542
- else {
2543
- left.log(`Can not offset time by '${rhs.dataType}'`);
2544
- return (0, ast_types_1.errorFor)(`time plus ${rhs.dataType}`);
2545
- }
2546
- }
2547
- return duration.apply(fs, op, left);
2548
- }
2549
- return numeric(fs, left, op, right);
2550
- }
2551
- function numeric(fs, left, op, right) {
2552
- const lhs = left.getExpression(fs);
2553
- const rhs = right.getExpression(fs);
2554
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
2555
- if (allAre("number", lhs, rhs)) {
2556
- return {
2557
- dataType: "number",
2558
- expressionType,
2559
- value: (0, ast_types_1.compose)(lhs.value, op, rhs.value),
2560
- };
2561
- }
2562
- left.log(`Non numeric('${lhs.dataType},${rhs.dataType}') value with '${op}'`);
2563
- return (0, ast_types_1.errorFor)("numbers required");
2564
- }
2565
- const compareTypes = {
2566
- "~": [ast_types_1.FT.stringT],
2567
- "!~": [ast_types_1.FT.stringT],
2568
- "<": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2569
- "<=": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2570
- "=": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2571
- "!=": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2572
- ">=": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2573
- ">": [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT],
2574
- };
2575
- /**
2576
- * GranularTime is a moment in time which ALSO has a "granularity"
2577
- * commonly this are created by applying ".datePart" to an expression
2578
- * 1) They have a value, which is the moment in time
2579
- * 2) When used in a comparison, they act like a range, for the
2580
- * duration of 1 unit of granularity
2581
- */
2582
- class ExprGranularTime extends ExpressionDef {
2583
- constructor(expr, units, truncate) {
2584
- super({ expr });
2585
- this.expr = expr;
2586
- this.units = units;
2587
- this.truncate = truncate;
2588
- this.elementType = "granularTime";
2589
- this.legalChildTypes = [ast_types_1.FT.timestampT, ast_types_1.FT.dateT];
2590
- }
2591
- granular() {
2592
- return true;
2593
- }
2594
- getExpression(fs) {
2595
- const timeframe = this.units;
2596
- const exprVal = this.expr.getExpression(fs);
2597
- if ((0, malloy_types_1.isTimeFieldType)(exprVal.dataType)) {
2598
- const tsVal = {
2599
- ...exprVal,
2600
- dataType: exprVal.dataType,
2601
- timeframe: timeframe,
2602
- };
2603
- if (this.truncate) {
2604
- tsVal.value = [
2605
- {
2606
- type: "dialect",
2607
- function: "trunc",
2608
- expr: { value: exprVal.value, valueType: exprVal.dataType },
2609
- units: timeframe,
2610
- },
2611
- ];
2612
- }
2613
- return tsVal;
2614
- }
2615
- this.log(`Cannot do time truncation on type '${exprVal.dataType}'`);
2616
- return (0, ast_types_1.errorFor)(`granularity typecheck`);
2617
- }
2618
- apply(fs, op, left) {
2619
- const rangeType = this.getExpression(fs).dataType;
2620
- const _valueType = left.getExpression(fs).dataType;
2621
- const granularityType = (0, malloy_types_1.isDateUnit)(this.units) ? "date" : "timestamp";
2622
- if (rangeType == "date" && granularityType == "date") {
2623
- return this.dateRange(fs, op, left);
2624
- }
2625
- return this.timestampRange(fs, op, left);
2626
- /*
2627
- write tests for each of these cases ....
2628
-
2629
- vt rt gt use
2630
- dt dt dt dateRange
2631
- dt dt ts == or timeStampRange
2632
- dt ts dt timestampRange
2633
- dt ts ts timeStampRange
2634
-
2635
- ts ts ts timestampRange
2636
- ts ts dt timestampRange
2637
- ts dt ts timestampRange
2638
- ts dt dt either
2639
-
2640
- */
2641
- }
2642
- timestampRange(fs, op, expr) {
2643
- const begin = this.getExpression(fs);
2644
- const beginTime = ExprTime.fromValue("timestamp", begin);
2645
- const endTime = new ExprTime("timestamp", (0, time_utils_1.timeOffset)("timestamp", begin.value, "+", (0, malloy_types_1.mkExpr) `1`, this.units), begin.expressionType);
2646
- const range = new Range(beginTime, endTime);
2647
- return range.apply(fs, op, expr);
2648
- }
2649
- dateRange(fs, op, expr) {
2650
- const begin = this.getExpression(fs);
2651
- const beginTime = new ExprTime("date", begin.value, begin.expressionType);
2652
- const endAt = (0, time_utils_1.timeOffset)("date", begin.value, "+", ["1"], this.units);
2653
- const end = new ExprTime("date", endAt, begin.expressionType);
2654
- const range = new Range(beginTime, end);
2655
- return range.apply(fs, op, expr);
2656
- }
2657
- }
2658
- exports.ExprGranularTime = ExprGranularTime;
2659
- function timeCompare(lhs, op, rhs) {
2660
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType) && (0, malloy_types_1.isTimeFieldType)(rhs.dataType)) {
2661
- if (lhs.dataType !== rhs.dataType) {
2662
- let lval = lhs.value;
2663
- let rval = rhs.value;
2664
- if (lhs.dataType === "timestamp") {
2665
- lval = (0, time_utils_1.castTimestampToDate)(lval);
2666
- }
2667
- else {
2668
- rval = (0, time_utils_1.castTimestampToDate)(rval);
2669
- }
2670
- return (0, ast_types_1.compose)(lval, op, rval);
2671
- }
2672
- }
2673
- return undefined;
2674
- }
2675
- function regexEqual(left, right) {
2676
- if (left.dataType === "string") {
2677
- if (right.dataType === "regular expression") {
2678
- return [
2679
- {
2680
- type: "dialect",
2681
- function: "regexpMatch",
2682
- expr: left.value,
2683
- regexp: right.value[0].replace(/^r'/, "'"),
2684
- },
2685
- ];
2686
- }
2687
- }
2688
- else if (right.dataType === "string") {
2689
- if (left.dataType === "regular expression") {
2690
- return [
2691
- {
2692
- type: "dialect",
2693
- function: "regexpMatch",
2694
- expr: right.value,
2695
- regexp: left.value[0].replace(/^r'/, "'"),
2696
- },
2697
- ];
2698
- }
2699
- }
2700
- return undefined;
2701
- }
2702
- class TypeMistmatch extends Error {
2703
- }
2704
- exports.TypeMistmatch = TypeMistmatch;
2705
- function nullCompare(left, op, right) {
2706
- const not = op === "!=" || op === "!~";
2707
- if (left.dataType === "null" || right.dataType === "null") {
2708
- const maybeNot = not ? " NOT" : "";
2709
- if (left.dataType !== "null") {
2710
- return [...left.value, ` IS${maybeNot} NULL`];
2711
- }
2712
- if (right.dataType !== "null") {
2713
- return [...right.value, `IS${maybeNot} NULL`];
2714
- }
2715
- return [not ? "false" : "true"];
2716
- }
2717
- return undefined;
2718
- }
2719
- class ExprDuration extends ExpressionDef {
2720
- constructor(n, timeframe) {
2721
- super({ n });
2722
- this.n = n;
2723
- this.timeframe = timeframe;
2724
- this.elementType = "duration";
2725
- this.legalChildTypes = [ast_types_1.FT.timestampT, ast_types_1.FT.dateT];
2726
- }
2727
- apply(fs, op, left) {
2728
- const lhs = left.getExpression(fs);
2729
- this.typeCheck(this, lhs);
2730
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType) && (op === "+" || op === "-")) {
2731
- const num = this.n.getExpression(fs);
2732
- if (!ast_types_1.FT.typeEq(num, ast_types_1.FT.numberT)) {
2733
- this.log(`Duration units needs number not '${num.dataType}`);
2734
- return (0, ast_types_1.errorFor)("illegal unit expression");
2735
- }
2736
- let resultGranularity;
2737
- // Only allow the output of this to be granular if the
2738
- // granularities match, this is still an area where
2739
- // more thought is required.
2740
- if ((0, ast_types_1.isGranularResult)(lhs) && lhs.timeframe == this.timeframe) {
2741
- resultGranularity = lhs.timeframe;
2742
- }
2743
- if (lhs.dataType === "timestamp") {
2744
- const result = (0, time_utils_1.timeOffset)("timestamp", lhs.value, op, num.value, this.timeframe);
2745
- return (0, time_utils_1.timeResult)({
2746
- dataType: "timestamp",
2747
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, num.expressionType),
2748
- value: result,
2749
- }, resultGranularity);
2750
- }
2751
- return (0, time_utils_1.timeResult)({
2752
- dataType: "date",
2753
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, num.expressionType),
2754
- value: (0, time_utils_1.timeOffset)("date", lhs.value, op, num.value, this.timeframe),
2755
- }, resultGranularity);
2756
- }
2757
- return super.apply(fs, op, left);
2758
- }
2759
- getExpression(_fs) {
2760
- return {
2761
- dataType: "duration",
2762
- expressionType: "scalar",
2763
- value: ["__ERROR_DURATION_IS_NOT_A_VALUE__"],
2764
- };
2765
- }
2766
- }
2767
- exports.ExprDuration = ExprDuration;
2768
- function allAre(oneType, ...values) {
2769
- for (const v of values) {
2770
- if (v.dataType !== oneType) {
2771
- return false;
2772
- }
2773
- }
2774
- return true;
2775
- }
2776
- class ExprTime extends ExpressionDef {
2777
- constructor(timeType, value, expressionType = "scalar") {
2778
- super();
2779
- this.elementType = "timestampOrDate";
2780
- this.elementType = timeType;
2781
- this.translationValue = {
2782
- dataType: timeType,
2783
- expressionType,
2784
- value: typeof value === "string" ? [value] : value,
2785
- };
2786
- }
2787
- getExpression(_fs) {
2788
- return this.translationValue;
2789
- }
2790
- static fromValue(timeType, expr) {
2791
- let value = expr.value;
2792
- if (timeType != expr.dataType) {
2793
- const toTs = {
2794
- type: "dialect",
2795
- function: "cast",
2796
- safe: false,
2797
- dstType: timeType,
2798
- expr: expr.value,
2799
- };
2800
- if ((0, malloy_types_1.isTimeFieldType)(expr.dataType)) {
2801
- toTs.srcType = expr.dataType;
2802
- }
2803
- value = (0, ast_types_1.compressExpr)([toTs]);
2804
- }
2805
- return new ExprTime(timeType, value, expr.expressionType);
2806
- }
2807
- }
2808
- exports.ExprTime = ExprTime;
2809
- class Range extends ExpressionDef {
2810
- constructor(first, last) {
2811
- super({ first, last });
2812
- this.first = first;
2813
- this.last = last;
2814
- this.elementType = "range";
2815
- }
2816
- apply(fs, op, expr) {
2817
- switch (op) {
2818
- case "=":
2819
- case "!=": {
2820
- const op1 = op === "=" ? ">=" : "<";
2821
- const op2 = op === "=" ? "and" : "or";
2822
- const op3 = op === "=" ? "<" : ">=";
2823
- const fromValue = this.first.apply(fs, op1, expr);
2824
- const toValue = this.last.apply(fs, op3, expr);
2825
- return {
2826
- dataType: "boolean",
2827
- expressionType: (0, malloy_types_1.maxExpressionType)(fromValue.expressionType, toValue.expressionType),
2828
- value: (0, ast_types_1.compose)(fromValue.value, op2, toValue.value),
2829
- };
2830
- }
2831
- /**
2832
- * This is a little surprising, but is actually how you comapre a
2833
- * value to a range ...
2834
- *
2835
- * val > begin to end val >= end
2836
- * val >= begin to end val >= begin
2837
- * val < begin to end val < begin
2838
- * val <= begin to end val < end
2839
- */
2840
- case ">":
2841
- return this.last.apply(fs, ">=", expr);
2842
- case ">=":
2843
- return this.first.apply(fs, ">=", expr);
2844
- case "<":
2845
- return this.first.apply(fs, "<", expr);
2846
- case "<=":
2847
- return this.last.apply(fs, "<", expr);
2848
- }
2849
- throw new Error("mysterious error in range computation");
2850
- }
2851
- requestExpression(_fs) {
2852
- return undefined;
2853
- }
2854
- getExpression(_fs) {
2855
- return (0, ast_types_1.errorFor)("a range is not a value");
2856
- }
2857
- }
2858
- exports.Range = Range;
2859
- /**
2860
- * Used to detect references to fields in the statement which defines them
2861
- */
2862
- class DefSpace {
2863
- constructor(realFS, circular) {
2864
- this.realFS = realFS;
2865
- this.circular = circular;
2866
- this.type = "fieldSpace";
2867
- this.foundCircle = false;
2868
- }
2869
- structDef() {
2870
- return this.realFS.structDef();
2871
- }
2872
- emptyStructDef() {
2873
- return this.realFS.emptyStructDef();
2874
- }
2875
- lookup(symbol) {
2876
- if (symbol[0] && symbol[0].refString === this.circular.defineName) {
2877
- this.foundCircle = true;
2878
- return {
2879
- error: `Circular reference to '${this.circular.defineName}' in definition`,
2880
- found: undefined,
2881
- };
2882
- }
2883
- return this.realFS.lookup(symbol);
2884
- }
2885
- dialectObj() {
2886
- return this.realFS.dialectObj();
2887
- }
2888
- whenComplete(step) {
2889
- this.realFS.whenComplete(step);
2890
- }
2891
- }
2892
- exports.DefSpace = DefSpace;
2893
- class StaticSpace {
2894
- constructor(sourceStructDef) {
2895
- this.type = "fieldSpace";
2896
- this.fromStruct = sourceStructDef;
2897
- }
2898
- whenComplete(step) {
2899
- step();
2900
- }
2901
- dialectObj() {
2902
- try {
2903
- return (0, dialect_map_1.getDialect)(this.fromStruct.dialect);
2904
- }
2905
- catch {
2906
- return undefined;
2907
- }
2908
- }
2909
- fromFieldDef(from) {
2910
- if (from.type === "struct") {
2911
- return new StructSpaceField(from);
2912
- }
2913
- else if (model.isTurtleDef(from)) {
2914
- return new QueryFieldStruct(this, from);
2915
- }
2916
- // TODO field has a filter and needs to be a filteredalias
2917
- return new ColumnSpaceField(from);
2918
- }
2919
- get map() {
2920
- if (this.memoMap === undefined) {
2921
- this.memoMap = {};
2922
- for (const f of this.fromStruct.fields) {
2923
- const name = f.as || f.name;
2924
- this.memoMap[name] = this.fromFieldDef(f);
2925
- }
2926
- if (this.fromStruct.parameters) {
2927
- for (const [paramName, paramDef] of Object.entries(this.fromStruct.parameters)) {
2928
- if (this.memoMap[paramName]) {
2929
- throw new Error(`In struct '${this.fromStruct.as || this.fromStruct.name}': ` +
2930
- ` : Field and parameter name conflict '${paramName}`);
2931
- }
2932
- this.memoMap[paramName] = new DefinedParameter(paramDef);
2933
- }
2934
- }
2935
- }
2936
- return this.memoMap;
2937
- }
2938
- dropEntries() {
2939
- this.memoMap = {};
2940
- }
2941
- dropEntry(name) {
2942
- delete this.map[name];
2943
- }
2944
- entry(name) {
2945
- return this.map[name];
2946
- }
2947
- setEntry(name, value) {
2948
- this.map[name] = value;
2949
- }
2950
- entries() {
2951
- return Object.entries(this.map);
2952
- }
2953
- structDef() {
2954
- return this.fromStruct;
2955
- }
2956
- emptyStructDef() {
2957
- return { ...this.fromStruct, fields: [] };
2958
- }
2959
- lookup(path) {
2960
- const head = path[0];
2961
- const rest = path.slice(1);
2962
- const found = this.entry(head.refString);
2963
- if (!found) {
2964
- return { error: `'${head}' is not defined`, found };
2965
- }
2966
- if (found instanceof SpaceField) {
2967
- /*
2968
- * TODO cache defs, post the addReference call to whenComplete
2969
- *
2970
- * In the cleanup phase of query space construction, it may check
2971
- * the output space for ungrouping variables. However if an
2972
- * ungrouping variable is a measure, the field expression value
2973
- * needed to get the definition needs to be computed in the
2974
- * input space of the query. There is a test which failed which
2975
- * caused this code to be here, but this is really a bandaid.
2976
- *
2977
- * Some re-work of how to get the definition of a SpaceField
2978
- * no matter what it is contained in needs to be thought out.
2979
- *
2980
- * ... or this check would look at the finalized output of
2981
- * the namespace and not re-compile ...
2982
- */
2983
- const definition = found.fieldDef();
2984
- if (definition) {
2985
- head.addReference({
2986
- type: found instanceof StructSpaceField
2987
- ? "joinReference"
2988
- : "fieldReference",
2989
- definition,
2990
- location: head.location,
2991
- text: head.refString,
2992
- });
2993
- }
2994
- }
2995
- if (rest.length) {
2996
- if (found instanceof StructSpaceField) {
2997
- return found.fieldSpace.lookup(rest);
2998
- }
2999
- return {
3000
- error: `'${head}' cannot contain a '${rest[0]}'`,
3001
- found: undefined,
3002
- };
3003
- }
3004
- return { found, error: undefined };
3005
- }
3006
- }
3007
- exports.StaticSpace = StaticSpace;
3008
- /**
3009
- * A FieldSpace which may undergo modification
3010
- */
3011
- class DynamicSpace extends StaticSpace {
3012
- constructor(extending) {
3013
- const source = new SpaceSeed(extending);
3014
- super((0, lodash_1.cloneDeep)(source.structDef));
3015
- this.completions = [];
3016
- this.complete = false;
3017
- this.final = undefined;
3018
- this.source = source;
3019
- }
3020
- /**
3021
- * Factory for DynamicSpace when there are accept/except edits
3022
- * @param from A structdef which seeds this space
3023
- * @param choose A accept/except edit of the "from" fields
3024
- */
3025
- static filteredFrom(from, choose) {
3026
- const edited = new DynamicSpace(from);
3027
- if (choose) {
3028
- const names = choose.refs.list;
3029
- const oldMap = edited.entries();
3030
- edited.dropEntries();
3031
- for (const [symbol, value] of oldMap) {
3032
- const included = !!names.find((f) => f.refString === symbol);
3033
- const accepting = choose.edit === "accept";
3034
- if (included === accepting) {
3035
- edited.setEntry(symbol, value);
3036
- }
3037
- }
3038
- }
3039
- return edited;
3040
- }
3041
- whenComplete(finalizeStep) {
3042
- if (this.complete) {
3043
- finalizeStep();
3044
- }
3045
- else {
3046
- this.completions.push(finalizeStep);
3047
- }
3048
- }
3049
- isComplete() {
3050
- this.complete = true;
3051
- for (const step of this.completions) {
3052
- step();
3053
- }
3054
- this.completions = [];
3055
- }
3056
- setEntry(name, value) {
3057
- if (this.final) {
3058
- throw new Error("Space already final");
3059
- }
3060
- super.setEntry(name, value);
3061
- }
3062
- addParameters(params) {
3063
- for (const oneP of params) {
3064
- this.setEntry(oneP.name, new AbstractParameter(oneP));
3065
- }
3066
- return this;
3067
- }
3068
- newEntry(name, astEl, entry) {
3069
- if (this.entry(name)) {
3070
- astEl.log(`Cannot redefine '${name}'`);
3071
- return;
3072
- }
3073
- this.setEntry(name, entry);
3074
- }
3075
- addField(...defs) {
3076
- for (const def of defs) {
3077
- // TODO express the "three fields kinds" in a typesafe way
3078
- // one of three kinds of fields are legal in an explore: expressions ...
3079
- const elseLog = def.log;
3080
- const elseType = def.elementType;
3081
- if (def instanceof FieldDeclaration) {
3082
- const exprField = new ExpressionFieldFromAst(this, def);
3083
- this.newEntry(exprField.name, def, exprField);
3084
- // querry (turtle) fields
3085
- }
3086
- else if (def instanceof TurtleDecl) {
3087
- const name = def.name;
3088
- this.newEntry(name, def, new QueryFieldAST(this, def, name));
3089
- }
3090
- else if (def instanceof RenameField) {
3091
- if (def.oldName.refString === def.newName) {
3092
- def.log("Can't rename field to itself");
3093
- continue;
3094
- }
3095
- const oldValue = def.oldName.getField(this);
3096
- if (oldValue.found) {
3097
- if (oldValue.found instanceof SpaceField) {
3098
- this.setEntry(def.newName, new RenameSpaceField(oldValue.found, def.newName, def.location));
3099
- this.dropEntry(def.oldName.refString);
3100
- }
3101
- else {
3102
- def.log(`'${def.oldName}' cannot be renamed`);
3103
- }
3104
- }
3105
- else {
3106
- def.log(`Can't rename '${def.oldName}', no such field`);
3107
- }
3108
- }
3109
- else if (def instanceof Join) {
3110
- this.newEntry(def.name.refString, def, new JoinSpaceField(this, def));
3111
- }
3112
- else {
3113
- elseLog(`Internal error: Expected expression, query, or rename, got '${elseType}'`);
3114
- }
3115
- }
3116
- }
3117
- addFieldDef(fd) {
3118
- this.setEntry((0, field_utils_1.nameOf)(fd), this.fromFieldDef(fd));
3119
- }
3120
- structDef() {
3121
- const parameters = this.fromStruct.parameters || {};
3122
- if (this.final === undefined) {
3123
- this.final = {
3124
- ...this.fromStruct,
3125
- fields: [],
3126
- };
3127
- // Need to process the entities in specific order
3128
- const fields = [];
3129
- const joins = [];
3130
- const turtles = [];
3131
- const fixupJoins = [];
3132
- for (const [name, spaceEntry] of this.entries()) {
3133
- if (spaceEntry instanceof StructSpaceField) {
3134
- joins.push([name, spaceEntry]);
3135
- }
3136
- else if (spaceEntry instanceof QueryField) {
3137
- turtles.push([name, spaceEntry]);
3138
- }
3139
- else if (spaceEntry instanceof SpaceField) {
3140
- fields.push([name, spaceEntry]);
3141
- }
3142
- else if (spaceEntry instanceof SpaceParam) {
3143
- parameters[name] = spaceEntry.parameter();
3144
- }
3145
- }
3146
- const reorderFields = [...fields, ...joins, ...turtles];
3147
- for (const [fieldName, field] of reorderFields) {
3148
- if (field instanceof JoinSpaceField) {
3149
- const joinStruct = field.join.structDef();
3150
- if (!ErrorFactory.isErrorStructDef(joinStruct)) {
3151
- this.final.fields.push(joinStruct);
3152
- fixupJoins.push([field.join, joinStruct]);
3153
- }
3154
- }
3155
- else {
3156
- const fieldDef = field.fieldDef();
3157
- if (fieldDef) {
3158
- this.final.fields.push(fieldDef);
3159
- }
3160
- else {
3161
- throw new Error(`'${fieldName}' doesn't have a FieldDef`);
3162
- }
3163
- }
3164
- }
3165
- if (Object.entries(parameters).length > 0) {
3166
- this.final.parameters = parameters;
3167
- }
3168
- // If we have join expressions, we need to now go back and fill them in
3169
- for (const [join, missingOn] of fixupJoins) {
3170
- join.fixupJoinOn(this, missingOn);
3171
- }
3172
- }
3173
- this.isComplete();
3174
- return this.final;
3175
- }
3176
- }
3177
- exports.DynamicSpace = DynamicSpace;
3178
- class ResultSpace extends DynamicSpace {
3179
- constructor(queryInputSpace) {
3180
- super(queryInputSpace.emptyStructDef());
3181
- this.queryInputSpace = queryInputSpace;
3182
- this.exprSpace = new QuerySpace(queryInputSpace, this);
3183
- }
3184
- log(s) {
3185
- if (this.astEl) {
3186
- this.astEl.log(s);
3187
- }
3188
- }
3189
- addMembers(members) {
3190
- for (const member of members) {
3191
- if (member instanceof FieldReference) {
3192
- this.addReference(member);
3193
- }
3194
- else if (member instanceof WildcardFieldReference) {
3195
- this.addWild(member);
3196
- }
3197
- else {
3198
- this.addField(member);
3199
- }
3200
- }
3201
- }
3202
- addReference(ref) {
3203
- const refName = ref.outputName;
3204
- if (this.entry(refName)) {
3205
- ref.log(`Output already has a field named '${refName}'`);
3206
- }
3207
- else {
3208
- this.setEntry(refName, new ReferenceField(ref));
3209
- }
3210
- }
3211
- addWild(wild) {
3212
- this.setEntry(wild.refString, new WildSpaceField(wild.refString));
3213
- }
3214
- /**
3215
- * Check for the definition of an ungrouping reference in the result space,
3216
- * or in the case of an exclude reference, if this query is nested
3217
- * in another query, in the result space of a query that this query
3218
- * is nested inside of.
3219
- */
3220
- checkUngroup(fn, isExclude) {
3221
- if (!this.entry(fn.refString)) {
3222
- if (isExclude && this.exprSpace.nestParent) {
3223
- const parent = this.exprSpace.nestParent;
3224
- parent.whenComplete(() => {
3225
- parent.result.checkUngroup(fn, isExclude);
3226
- });
3227
- }
3228
- else {
3229
- const uName = isExclude ? "exclude()" : "all()";
3230
- fn.log(`${uName} '${fn.refString}' is missing from query output`);
3231
- }
3232
- }
3233
- }
3234
- addQueryItems(...qiList) {
3235
- for (const qi of qiList) {
3236
- if (qi instanceof FieldReference || qi instanceof NestReference) {
3237
- this.addReference(qi);
3238
- }
3239
- else if (qi instanceof FieldDeclaration) {
3240
- this.addField(qi);
3241
- }
3242
- else if (isNestedQuery(qi)) {
3243
- const qf = new QueryFieldAST(this, qi, qi.name);
3244
- qf.nestParent = this.exprSpace;
3245
- this.setEntry(qi.name, qf);
3246
- }
3247
- else {
3248
- // Compiler will error if we don't handle all cases
3249
- const _itemNotHandled = qi;
3250
- }
3251
- }
3252
- }
3253
- canContain(_qd) {
3254
- return true;
3255
- }
3256
- queryFieldDefs() {
3257
- const fields = [];
3258
- for (const [name, field] of this.entries()) {
3259
- if (field instanceof SpaceField) {
3260
- const fieldQueryDef = field.getQueryFieldDef(this.exprSpace);
3261
- if (fieldQueryDef) {
3262
- if (this.canContain(fieldQueryDef)) {
3263
- fields.push(fieldQueryDef);
3264
- }
3265
- else {
3266
- this.log(`'${name}' not legal in ${this.segmentType}`);
3267
- }
3268
- }
3269
- else {
3270
- throw new Error(`'${name}' does not have a QueryFieldDef`);
3271
- }
3272
- }
3273
- }
3274
- this.isComplete();
3275
- return fields;
3276
- }
3277
- getQuerySegment(rf) {
3278
- const p = this.getPipeSegment(rf);
3279
- if (model.isQuerySegment(p)) {
3280
- return p;
3281
- }
3282
- throw new Error("TODO NOT POSSIBLE");
3283
- }
3284
- getPipeSegment(refineFrom) {
3285
- if (this.segmentType == "index") {
3286
- // TODO ... should make this go away
3287
- throw new Error("INDEX FIELD PIPE SEGMENT MIS HANDLED");
3288
- }
3289
- if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
3290
- for (const xField of refineFrom.extendSource) {
3291
- this.exprSpace.addFieldDef(xField);
3292
- }
3293
- }
3294
- const segment = {
3295
- type: this.segmentType,
3296
- fields: this.queryFieldDefs(),
3297
- };
3298
- segment.fields = (0, field_utils_1.mergeFields)(refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.fields, segment.fields);
3299
- if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
3300
- segment.extendSource = refineFrom.extendSource;
3301
- }
3302
- if (this.exprSpace.extendList.length > 0) {
3303
- const newExtends = [];
3304
- const extendedStruct = this.exprSpace.structDef();
3305
- for (const extendName of this.exprSpace.extendList) {
3306
- const extendEnt = extendedStruct.fields.find((f) => (0, field_utils_1.nameOf)(f) == extendName);
3307
- if (extendEnt) {
3308
- newExtends.push(extendEnt);
3309
- }
3310
- }
3311
- segment.extendSource = (0, field_utils_1.mergeFields)(segment.extendSource, newExtends);
3312
- }
3313
- this.isComplete();
3314
- return segment;
3315
- }
3316
- }
3317
- exports.ResultSpace = ResultSpace;
3318
- /**
3319
- * Reduce and project queries use a "QuerySpace"
3320
- */
3321
- class ReduceFieldSpace extends ResultSpace {
3322
- constructor() {
3323
- super(...arguments);
3324
- this.segmentType = "reduce";
3325
- }
3326
- }
3327
- exports.ReduceFieldSpace = ReduceFieldSpace;
3328
- class ProjectFieldSpace extends ResultSpace {
3329
- constructor() {
3330
- super(...arguments);
3331
- this.segmentType = "project";
3332
- }
3333
- canContain(qd) {
3334
- if (typeof qd !== "string") {
3335
- if (model.isFilteredAliasedName(qd)) {
3336
- return true;
3337
- }
3338
- if (qd.type === "turtle") {
3339
- this.log("Cannot nest queries in project");
3340
- return false;
3341
- }
3342
- if (model.expressionIsAggregate(qd.expressionType)) {
3343
- this.log("Cannot add aggregate measures to project");
3344
- return false;
3345
- }
3346
- }
3347
- return true;
3348
- }
3349
- }
3350
- exports.ProjectFieldSpace = ProjectFieldSpace;
3351
- class SpaceEntry {
3352
- }
3353
- exports.SpaceEntry = SpaceEntry;
3354
- class SpaceField extends SpaceEntry {
3355
- constructor() {
3356
- super(...arguments);
3357
- this.refType = "field";
3358
- }
3359
- fieldTypeFromFieldDef(def) {
3360
- const ref = { type: def.type };
3361
- if (model.isFieldTypeDef(def) && def.expressionType) {
3362
- ref.expressionType = def.expressionType;
3363
- }
3364
- return ref;
3365
- }
3366
- getQueryFieldDef(_fs) {
3367
- return undefined;
3368
- }
3369
- fieldDef() {
3370
- return undefined;
3371
- }
3372
- }
3373
- exports.SpaceField = SpaceField;
3374
- class StructSpaceField extends SpaceField {
3375
- constructor(sourceDef) {
3376
- super();
3377
- this.sourceDef = sourceDef;
3378
- }
3379
- get fieldSpace() {
3380
- if (!this.space) {
3381
- this.space = new StaticSpace(this.sourceDef);
3382
- }
3383
- return this.space;
3384
- }
3385
- fieldDef() {
3386
- return this.sourceDef;
3387
- }
3388
- type() {
3389
- return { type: "struct" };
3390
- }
3391
- }
3392
- exports.StructSpaceField = StructSpaceField;
3393
- class QueryField extends SpaceField {
3394
- constructor(inSpace) {
3395
- super();
3396
- this.inSpace = inSpace;
3397
- }
3398
- type() {
3399
- return { type: "turtle" };
3400
- }
3401
- }
3402
- exports.QueryField = QueryField;
3403
- class QueryFieldStruct extends QueryField {
3404
- constructor(fs, turtleDef) {
3405
- super(fs);
3406
- this.turtleDef = turtleDef;
3407
- }
3408
- rename(name) {
3409
- this.turtleDef = {
3410
- ...this.turtleDef,
3411
- as: name,
3412
- };
3413
- }
3414
- fieldDef() {
3415
- return this.turtleDef;
3416
- }
3417
- getQueryFieldDef(_fs) {
3418
- return this.fieldDef();
3419
- }
3420
- }
3421
- exports.QueryFieldStruct = QueryFieldStruct;
3422
- class ColumnSpaceField extends SpaceField {
3423
- constructor(def) {
3424
- super();
3425
- this.def = def;
3426
- }
3427
- fieldDef() {
3428
- return this.def;
3429
- }
3430
- type() {
3431
- return this.fieldTypeFromFieldDef(this.def);
3432
- }
3433
- }
3434
- exports.ColumnSpaceField = ColumnSpaceField;
3435
- class SpaceParam extends SpaceEntry {
3436
- constructor() {
3437
- super(...arguments);
3438
- this.refType = "parameter";
3439
- }
3440
- }
3441
- exports.SpaceParam = SpaceParam;
3442
- class DefinedParameter extends SpaceParam {
3443
- constructor(paramDef) {
3444
- super();
3445
- this.paramDef = paramDef;
3446
- }
3447
- parameter() {
3448
- return this.paramDef;
3449
- }
3450
- type() {
3451
- return { type: this.paramDef.type };
3452
- }
3453
- }
3454
- exports.DefinedParameter = DefinedParameter;
3455
- /**
3456
- * Based on how things are constructed, the starting field space
3457
- * can either be another field space or an existing structdef.
3458
- * Using a SpaceSeed allows a class to accept either one
3459
- * and use either version at some future time.
3460
- */
3461
- class SpaceSeed {
3462
- constructor(sourceSpec) {
3463
- this.sourceSpec = sourceSpec;
3464
- this.spaceSpec = sourceSpec;
3465
- }
3466
- get structDef() {
3467
- if (isFieldSpace(this.spaceSpec)) {
3468
- if (!this.asStruct) {
3469
- this.asStruct = this.spaceSpec.structDef();
3470
- }
3471
- return this.asStruct;
3472
- }
3473
- return this.spaceSpec;
3474
- }
3475
- get fieldSpace() {
3476
- if (isFieldSpace(this.spaceSpec)) {
3477
- return this.spaceSpec;
3478
- }
3479
- if (!this.asFS) {
3480
- this.asFS = new StaticSpace(this.spaceSpec);
3481
- }
3482
- return this.asFS;
3483
- }
3484
- }
3485
- exports.SpaceSeed = SpaceSeed;
3486
- function isFieldSpace(x) {
3487
- return x.type == "fieldSpace";
3488
- }
3489
- class AbstractParameter extends SpaceParam {
3490
- constructor(astParam) {
3491
- super();
3492
- this.astParam = astParam;
3493
- }
3494
- parameter() {
3495
- return this.astParam.parameter();
3496
- }
3497
- type() {
3498
- const type = this.astParam.type || "unknown";
3499
- return { type };
3500
- }
3501
- }
3502
- exports.AbstractParameter = AbstractParameter;
3503
- class ExpressionFieldFromAst extends SpaceField {
3504
- constructor(space, exprDef) {
3505
- super();
3506
- this.space = space;
3507
- this.exprDef = exprDef;
3508
- this.fieldName = exprDef.defineName;
3509
- }
3510
- get name() {
3511
- return this.fieldName;
3512
- }
3513
- fieldDef() {
3514
- const def = this.exprDef.fieldDef(this.space, this.name);
3515
- this.defType = this.fieldTypeFromFieldDef(def);
3516
- return def;
3517
- }
3518
- getQueryFieldDef(fs) {
3519
- const def = this.exprDef.queryFieldDef(fs, this.name);
3520
- this.defType = this.fieldTypeFromFieldDef(def);
3521
- return def;
3522
- }
3523
- type() {
3524
- if (this.defType) {
3525
- return this.defType;
3526
- }
3527
- return this.fieldTypeFromFieldDef(this.fieldDef());
3528
- }
3529
- }
3530
- exports.ExpressionFieldFromAst = ExpressionFieldFromAst;
3531
- class QueryFieldAST extends QueryField {
3532
- constructor(fs, turtle, name) {
3533
- super(fs);
3534
- this.turtle = turtle;
3535
- this.name = name;
3536
- }
3537
- getQueryFieldDef(fs) {
3538
- const def = this.turtle.getFieldDef(fs, this.nestParent);
3539
- if (this.renameAs) {
3540
- def.as = this.renameAs;
3541
- }
3542
- return def;
3543
- }
3544
- fieldDef() {
3545
- const def = this.turtle.getFieldDef(this.inSpace, this.nestParent);
3546
- if (this.renameAs) {
3547
- def.as = this.renameAs;
3548
- }
3549
- return def;
3550
- }
3551
- }
3552
- exports.QueryFieldAST = QueryFieldAST;
3553
- class RenameSpaceField extends SpaceField {
3554
- constructor(otherField, newName, location) {
3555
- super();
3556
- this.otherField = otherField;
3557
- this.newName = newName;
3558
- this.location = location;
3559
- }
3560
- fieldDef() {
3561
- const renamedFieldRaw = this.otherField.fieldDef();
3562
- if (renamedFieldRaw === undefined) {
3563
- return undefined;
3564
- }
3565
- return {
3566
- ...renamedFieldRaw,
3567
- as: this.newName,
3568
- location: this.location,
3569
- };
3570
- }
3571
- type() {
3572
- return this.otherField.type();
3573
- }
3574
- }
3575
- exports.RenameSpaceField = RenameSpaceField;
3576
- class JoinSpaceField extends StructSpaceField {
3577
- constructor(intoFS, join) {
3578
- super(join.structDef());
3579
- this.intoFS = intoFS;
3580
- this.join = join;
3581
- }
3582
- }
3583
- exports.JoinSpaceField = JoinSpaceField;
3584
- /**
3585
- * Unlike a source, which is a refinement of a namespace, a query
3586
- * is creating a new unrelated namespace. The query starts with a
3587
- * source, which it might modify. This set of fields used to resolve
3588
- * expressions in the query is called the "input space". There is a
3589
- * specialized QuerySpace for each type of query operation.
3590
- *
3591
- * The query output is managed by an instance of ResultSpace.
3592
- */
3593
- class QuerySpace extends DynamicSpace {
3594
- constructor(input, result) {
3595
- const inputSpace = new SpaceSeed(input);
3596
- super(inputSpace.structDef);
3597
- this.result = result;
3598
- this.extendList = [];
3599
- }
3600
- extendSource(extendField) {
3601
- this.addField(extendField);
3602
- if (extendField instanceof Join) {
3603
- this.extendList.push(extendField.name.refString);
3604
- }
3605
- else {
3606
- this.extendList.push(extendField.defineName);
3607
- }
3608
- }
3609
- }
3610
- exports.QuerySpace = QuerySpace;
3611
- class ReferenceField extends SpaceField {
3612
- constructor(fieldRef) {
3613
- super();
3614
- this.fieldRef = fieldRef;
3615
- }
3616
- getQueryFieldDef(fs) {
3617
- // Lookup string and generate error if it isn't defined.
3618
- const check = this.fieldRef.getField(fs);
3619
- if (check.error) {
3620
- this.fieldRef.log(check.error);
3621
- }
3622
- return this.fieldRef.refString;
3623
- }
3624
- type() {
3625
- return { type: "unknown" };
3626
- }
3627
- }
3628
- exports.ReferenceField = ReferenceField;
3629
- class WildSpaceField extends SpaceField {
3630
- constructor(wildText) {
3631
- super();
3632
- this.wildText = wildText;
3633
- }
3634
- type() {
3635
- throw new Error("should never ask a wild field for its type");
3636
- }
3637
- getQueryFieldDef(_fs) {
3638
- return this.wildText;
3639
- }
3640
- }
3641
- exports.WildSpaceField = WildSpaceField;
3642
- class IndexFieldSpace extends ResultSpace {
3643
- constructor() {
3644
- super(...arguments);
3645
- this.segmentType = "index";
3646
- this.fieldList = new Set();
3647
- }
3648
- addReference(ref) {
3649
- if (ref.getField(this.exprSpace).found) {
3650
- this.fieldList.add(ref.refString);
3651
- }
3652
- }
3653
- addWild(wild) {
3654
- this.fieldList.add(wild.refString);
3655
- }
3656
- getPipeSegment(refineIndex) {
3657
- if (refineIndex && refineIndex.fields) {
3658
- for (const exists of refineIndex.fields) {
3659
- if (typeof exists == "string") {
3660
- this.fieldList.add(exists);
3661
- }
3662
- }
3663
- }
3664
- this.isComplete();
3665
- return {
3666
- type: "index",
3667
- fields: Array.from(this.fieldList.values()),
3668
- };
3669
- }
3670
- }
3671
- exports.IndexFieldSpace = IndexFieldSpace;
3672
- //# sourceMappingURL=ast-main.js.map