@malloydata/malloy 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lang/ast/ast-expr.d.ts +0 -1
- package/dist/lang/ast/ast-main.d.ts +2 -2
- package/package.json +1 -1
- package/dist/connection_utils.js +0 -56
- package/dist/dialect/dialect.js +0 -77
- package/dist/dialect/dialect_map.js +0 -35
- package/dist/dialect/duckdb.js +0 -347
- package/dist/dialect/index.js +0 -27
- package/dist/dialect/postgres.js +0 -315
- package/dist/dialect/standardsql.js +0 -362
- package/dist/index.js +0 -47
- package/dist/lang/ast/apply-expr.js +0 -231
- package/dist/lang/ast/ast-expr.js +0 -1041
- package/dist/lang/ast/ast-main.js +0 -2087
- package/dist/lang/ast/ast-time-expr.js +0 -549
- package/dist/lang/ast/ast-types.js +0 -215
- package/dist/lang/ast/index.js +0 -34
- package/dist/lang/ast/time-utils.js +0 -94
- package/dist/lang/field-space.js +0 -631
- package/dist/lang/field-utils.js +0 -33
- package/dist/lang/index.js +0 -22
- package/dist/lang/parse-log.js +0 -41
- package/dist/lang/reference-list.js +0 -80
- package/dist/lang/space-field.js +0 -346
- package/dist/lang/test/document-help-context-walker.spec.js +0 -45
- package/dist/lang/test/document-symbol-walker.spec.js +0 -100
- package/dist/lang/test/field-symbols.spec.js +0 -172
- package/dist/lang/test/parse.spec.js +0 -1951
- package/dist/lang/test/test-translator.js +0 -334
- package/dist/lang/zone.js +0 -97
- package/dist/malloy.js +0 -2360
- package/dist/model/index.js +0 -34
- package/dist/model/malloy_query.js +0 -2994
- package/dist/model/malloy_types.js +0 -283
- package/dist/model/sql_block.js +0 -41
- package/dist/model/utils.js +0 -84
- package/dist/runtime_types.js +0 -15
|
@@ -1,2087 +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.FullQuery = 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.Mallobj = exports.isExploreField = exports.Unimplemented = exports.ListOf = exports.MalloyElement = exports.ErrorFactory = void 0;
|
|
27
|
-
exports.SampleProperty = exports.SQLStatement = 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 = void 0;
|
|
28
|
-
/*
|
|
29
|
-
* Copyright 2021 Google LLC
|
|
30
|
-
*
|
|
31
|
-
* This program is free software; you can redistribute it and/or
|
|
32
|
-
* modify it under the terms of the GNU General Public License
|
|
33
|
-
* version 2 as published by the Free Software Foundation.
|
|
34
|
-
*
|
|
35
|
-
* This program is distributed in the hope that it will be useful,
|
|
36
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
37
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
38
|
-
* GNU General Public License for more details.
|
|
39
|
-
*/
|
|
40
|
-
const lodash_1 = require("lodash");
|
|
41
|
-
const model = __importStar(require("../../model/malloy_types"));
|
|
42
|
-
const malloy_query_1 = require("../../model/malloy_query");
|
|
43
|
-
const field_space_1 = require("../field-space");
|
|
44
|
-
const index_1 = require("./index");
|
|
45
|
-
const space_field_1 = require("../space-field");
|
|
46
|
-
const sql_block_1 = require("../../model/sql_block");
|
|
47
|
-
const util_1 = require("util");
|
|
48
|
-
const time_utils_1 = require("./time-utils");
|
|
49
|
-
/*
|
|
50
|
-
** For times when there is a code generation error but your function needs
|
|
51
|
-
** to return some kind of object to type properly, the ErrorFactory is
|
|
52
|
-
** here to help you.
|
|
53
|
-
*/
|
|
54
|
-
const theErrorStruct = {
|
|
55
|
-
type: "struct",
|
|
56
|
-
name: "~malformed~",
|
|
57
|
-
dialect: "~malformed~",
|
|
58
|
-
structSource: { type: "table", tablePath: "//undefined_error_table_path" },
|
|
59
|
-
structRelationship: {
|
|
60
|
-
type: "basetable",
|
|
61
|
-
connectionName: "//undefined_error_connection",
|
|
62
|
-
},
|
|
63
|
-
fields: [],
|
|
64
|
-
};
|
|
65
|
-
class ErrorFactory {
|
|
66
|
-
static get structDef() {
|
|
67
|
-
return { ...theErrorStruct };
|
|
68
|
-
}
|
|
69
|
-
static isErrorStructDef(s) {
|
|
70
|
-
return s.name.includes(theErrorStruct.name);
|
|
71
|
-
}
|
|
72
|
-
static get query() {
|
|
73
|
-
return {
|
|
74
|
-
structRef: ErrorFactory.structDef,
|
|
75
|
-
pipeline: [],
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
static get reduceSegment() {
|
|
79
|
-
return { type: "reduce", fields: [] };
|
|
80
|
-
}
|
|
81
|
-
static get projectSegment() {
|
|
82
|
-
return { type: "project", fields: [] };
|
|
83
|
-
}
|
|
84
|
-
static get indexSegment() {
|
|
85
|
-
return { type: "index", fields: [] };
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
exports.ErrorFactory = ErrorFactory;
|
|
89
|
-
function opOutputStruct(logTo, inputStruct, opDesc) {
|
|
90
|
-
const badModel = ErrorFactory.isErrorStructDef(inputStruct);
|
|
91
|
-
// Don't call into the model code with a broken model
|
|
92
|
-
if (!badModel) {
|
|
93
|
-
try {
|
|
94
|
-
return malloy_query_1.Segment.nextStructDef(inputStruct, opDesc);
|
|
95
|
-
}
|
|
96
|
-
catch (e) {
|
|
97
|
-
logTo.log(`INTERNAL ERROR model/Segment.nextStructDef: ${e.message}\n` +
|
|
98
|
-
`QUERY: ${(0, util_1.inspect)(opDesc, { breakLength: 72, depth: Infinity })}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return { ...ErrorFactory.structDef, dialect: inputStruct.dialect };
|
|
102
|
-
}
|
|
103
|
-
class MalloyElement {
|
|
104
|
-
/**
|
|
105
|
-
* @param kids All children passed to the constructor are not optional
|
|
106
|
-
*/
|
|
107
|
-
constructor(kids) {
|
|
108
|
-
this.children = {};
|
|
109
|
-
this.parent = null;
|
|
110
|
-
this.logged = new Set();
|
|
111
|
-
if (kids) {
|
|
112
|
-
this.has(kids);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Record all elements as children of this element, and mark this
|
|
117
|
-
* element as their parent.
|
|
118
|
-
* @param kids Some of these might be undefined, in which case they are ignored
|
|
119
|
-
*/
|
|
120
|
-
has(kids) {
|
|
121
|
-
for (const kidName in kids) {
|
|
122
|
-
const kidValue = kids[kidName];
|
|
123
|
-
if (kidValue !== undefined) {
|
|
124
|
-
this.children[kidName] = kidValue;
|
|
125
|
-
if (kidValue instanceof MalloyElement) {
|
|
126
|
-
kidValue.parent = this;
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
for (const oneKid of kidValue) {
|
|
130
|
-
oneKid.parent = this;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
get location() {
|
|
137
|
-
if (this.codeLocation) {
|
|
138
|
-
return this.codeLocation;
|
|
139
|
-
}
|
|
140
|
-
if (this.parent) {
|
|
141
|
-
return this.parent.location;
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
url: this.sourceURL,
|
|
145
|
-
range: {
|
|
146
|
-
start: { line: 0, character: 0 },
|
|
147
|
-
end: { line: 0, character: 0 },
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
set location(loc) {
|
|
152
|
-
this.codeLocation = loc;
|
|
153
|
-
}
|
|
154
|
-
namespace() {
|
|
155
|
-
if (this instanceof Document) {
|
|
156
|
-
return this;
|
|
157
|
-
}
|
|
158
|
-
else if (this.parent) {
|
|
159
|
-
return this.parent.namespace();
|
|
160
|
-
}
|
|
161
|
-
throw new Error("INTERNAL ERROR: Translation without document scope");
|
|
162
|
-
}
|
|
163
|
-
modelEntry(reference) {
|
|
164
|
-
var _a;
|
|
165
|
-
const key = reference instanceof ModelEntryReference ? reference.name : reference;
|
|
166
|
-
const result = (_a = this.namespace()) === null || _a === void 0 ? void 0 : _a.getEntry(key);
|
|
167
|
-
if (reference instanceof ModelEntryReference) {
|
|
168
|
-
if ((result === null || result === void 0 ? void 0 : result.entry.type) === "query") {
|
|
169
|
-
this.addReference({
|
|
170
|
-
type: "queryReference",
|
|
171
|
-
text: key,
|
|
172
|
-
definition: result.entry,
|
|
173
|
-
location: reference.location,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
else if ((result === null || result === void 0 ? void 0 : result.entry.type) === "struct") {
|
|
177
|
-
this.addReference({
|
|
178
|
-
type: "exploreReference",
|
|
179
|
-
text: key,
|
|
180
|
-
definition: result.entry,
|
|
181
|
-
location: reference.location,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
else if ((result === null || result === void 0 ? void 0 : result.entry.type) === "sqlBlock") {
|
|
185
|
-
this.addReference({
|
|
186
|
-
type: "sqlBlockReference",
|
|
187
|
-
text: key,
|
|
188
|
-
definition: result.entry,
|
|
189
|
-
location: reference.location,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return result;
|
|
194
|
-
}
|
|
195
|
-
translator() {
|
|
196
|
-
if (this.xlate) {
|
|
197
|
-
return this.xlate;
|
|
198
|
-
}
|
|
199
|
-
if (this.parent) {
|
|
200
|
-
return this.parent.translator();
|
|
201
|
-
}
|
|
202
|
-
return undefined;
|
|
203
|
-
}
|
|
204
|
-
setTranslator(x) {
|
|
205
|
-
this.xlate = x;
|
|
206
|
-
}
|
|
207
|
-
addReference(reference) {
|
|
208
|
-
var _a;
|
|
209
|
-
(_a = this.translator()) === null || _a === void 0 ? void 0 : _a.addReference(reference);
|
|
210
|
-
}
|
|
211
|
-
get sourceURL() {
|
|
212
|
-
const trans = this.translator();
|
|
213
|
-
return (trans === null || trans === void 0 ? void 0 : trans.sourceURL) || "(missing)";
|
|
214
|
-
}
|
|
215
|
-
errorsExist() {
|
|
216
|
-
var _a;
|
|
217
|
-
const logger = (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.root.logger;
|
|
218
|
-
if (logger) {
|
|
219
|
-
return logger.hasErrors();
|
|
220
|
-
}
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
log(message) {
|
|
224
|
-
if (this.codeLocation) {
|
|
225
|
-
/*
|
|
226
|
-
* If this element has a location, then don't report the same
|
|
227
|
-
* error message at the same location more than once
|
|
228
|
-
*/
|
|
229
|
-
if (this.logged.has(message)) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
this.logged.add(message);
|
|
233
|
-
}
|
|
234
|
-
const trans = this.translator();
|
|
235
|
-
const msg = { at: this.location, message };
|
|
236
|
-
const logTo = trans === null || trans === void 0 ? void 0 : trans.root.logger;
|
|
237
|
-
if (logTo) {
|
|
238
|
-
logTo.log(msg);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
throw new Error(`Translation error (without error reporter):\n${JSON.stringify(msg, null, 2)}`);
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Mostly for debugging / testing. A string-y version of this object which
|
|
245
|
-
* is used to ask "are these two AST segments equal". Formatted so that
|
|
246
|
-
* errors would be human readable.
|
|
247
|
-
* @param indent only used for recursion
|
|
248
|
-
*/
|
|
249
|
-
toString() {
|
|
250
|
-
return this.stringify("", 0);
|
|
251
|
-
}
|
|
252
|
-
stringify(prefix, indent) {
|
|
253
|
-
const left = " ".repeat(indent);
|
|
254
|
-
let asString = `${left}${prefix}<${this.elementType}>${this.varInfo()}`;
|
|
255
|
-
for (const kidLabel of Object.keys(this.children)) {
|
|
256
|
-
const kiddle = this.children[kidLabel];
|
|
257
|
-
if (kiddle instanceof MalloyElement) {
|
|
258
|
-
asString += "\n" + kiddle.stringify(`${kidLabel}: `, indent + 2);
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
asString += `\n${left} ${kidLabel}: [`;
|
|
262
|
-
if (kiddle.length > 0) {
|
|
263
|
-
asString +=
|
|
264
|
-
"\n" +
|
|
265
|
-
kiddle.map((k) => k.stringify("", indent + 4)).join("\n") +
|
|
266
|
-
`\n${left} `;
|
|
267
|
-
}
|
|
268
|
-
asString += "]";
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return asString;
|
|
272
|
-
}
|
|
273
|
-
walk(callBack) {
|
|
274
|
-
callBack(this);
|
|
275
|
-
for (const kidLabel of Object.keys(this.children)) {
|
|
276
|
-
const kiddle = this.children[kidLabel];
|
|
277
|
-
if (kiddle instanceof MalloyElement) {
|
|
278
|
-
kiddle.walk(callBack);
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
for (const k of kiddle) {
|
|
282
|
-
k.walk(callBack);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
varInfo() {
|
|
288
|
-
let extra = "";
|
|
289
|
-
for (const [key, value] of Object.entries(this)) {
|
|
290
|
-
if (key !== "elementType") {
|
|
291
|
-
if (typeof value == "boolean") {
|
|
292
|
-
extra += value ? ` ${key}` : ` !${key}`;
|
|
293
|
-
}
|
|
294
|
-
else if (typeof value === "string" || typeof value === "number") {
|
|
295
|
-
extra += ` ${key}=${value}`;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return extra;
|
|
300
|
-
}
|
|
301
|
-
internalError(msg) {
|
|
302
|
-
this.log(`INTERNAL ERROR IN TRANSLATION: ${msg}`);
|
|
303
|
-
return new Error(msg);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
exports.MalloyElement = MalloyElement;
|
|
307
|
-
class ListOf extends MalloyElement {
|
|
308
|
-
constructor(listDesc, elements) {
|
|
309
|
-
super();
|
|
310
|
-
this.elementType = "genericElementList";
|
|
311
|
-
this.elements = elements;
|
|
312
|
-
if (this.elementType === "genericElementList") {
|
|
313
|
-
this.elementType = listDesc;
|
|
314
|
-
}
|
|
315
|
-
this.newContents();
|
|
316
|
-
}
|
|
317
|
-
newContents() {
|
|
318
|
-
this.has({ [this.elementType]: this.elements });
|
|
319
|
-
}
|
|
320
|
-
get list() {
|
|
321
|
-
return this.elements;
|
|
322
|
-
}
|
|
323
|
-
empty() {
|
|
324
|
-
return this.elements.length === 0;
|
|
325
|
-
}
|
|
326
|
-
notEmpty() {
|
|
327
|
-
return this.elements.length > 0;
|
|
328
|
-
}
|
|
329
|
-
push(...el) {
|
|
330
|
-
this.elements.push(...el);
|
|
331
|
-
this.newContents();
|
|
332
|
-
return this.elements;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
exports.ListOf = ListOf;
|
|
336
|
-
class Unimplemented extends MalloyElement {
|
|
337
|
-
constructor() {
|
|
338
|
-
super(...arguments);
|
|
339
|
-
this.elementType = "unimplemented";
|
|
340
|
-
this.reported = false;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
exports.Unimplemented = Unimplemented;
|
|
344
|
-
function getStructFieldDef(s, fn) {
|
|
345
|
-
return s.fields.find((fld) => (fld.as || fld.name) === fn);
|
|
346
|
-
}
|
|
347
|
-
function isFieldDecl(f) {
|
|
348
|
-
return (f instanceof index_1.FieldDeclaration ||
|
|
349
|
-
f instanceof Join ||
|
|
350
|
-
f instanceof TurtleDecl ||
|
|
351
|
-
f instanceof Turtles);
|
|
352
|
-
}
|
|
353
|
-
function isExploreField(f) {
|
|
354
|
-
return isFieldDecl(f) || f instanceof RenameField;
|
|
355
|
-
}
|
|
356
|
-
exports.isExploreField = isExploreField;
|
|
357
|
-
/**
|
|
358
|
-
* A "Mallobj" is a thing which you can run queries against, it has been called
|
|
359
|
-
* an "exploreable", or a "space".
|
|
360
|
-
*/
|
|
361
|
-
class Mallobj extends MalloyElement {
|
|
362
|
-
structRef() {
|
|
363
|
-
return this.structDef();
|
|
364
|
-
}
|
|
365
|
-
withParameters(pList) {
|
|
366
|
-
const before = this.structDef();
|
|
367
|
-
// TODO name collisions are flagged where?
|
|
368
|
-
if (pList) {
|
|
369
|
-
const parameters = { ...(before.parameters || {}) };
|
|
370
|
-
for (const hasP of pList) {
|
|
371
|
-
const pVal = hasP.parameter();
|
|
372
|
-
parameters[pVal.name] = pVal;
|
|
373
|
-
}
|
|
374
|
-
return {
|
|
375
|
-
...before,
|
|
376
|
-
parameters,
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
return before;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
exports.Mallobj = Mallobj;
|
|
383
|
-
class QueryHeadStruct extends Mallobj {
|
|
384
|
-
constructor(fromRef) {
|
|
385
|
-
super();
|
|
386
|
-
this.fromRef = fromRef;
|
|
387
|
-
this.elementType = "internalOnlyQueryHead";
|
|
388
|
-
}
|
|
389
|
-
structRef() {
|
|
390
|
-
return this.fromRef;
|
|
391
|
-
}
|
|
392
|
-
structDef() {
|
|
393
|
-
if (model.refIsStructDef(this.fromRef)) {
|
|
394
|
-
return this.fromRef;
|
|
395
|
-
}
|
|
396
|
-
const ns = new NamedSource(this.fromRef);
|
|
397
|
-
this.has({ exploreReference: ns });
|
|
398
|
-
return ns.structDef();
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
function isDocStatement(e) {
|
|
402
|
-
return e.execute !== undefined;
|
|
403
|
-
}
|
|
404
|
-
exports.isDocStatement = isDocStatement;
|
|
405
|
-
class DefineExplore extends MalloyElement {
|
|
406
|
-
constructor(name, mallobj, exported, params) {
|
|
407
|
-
super({ explore: mallobj });
|
|
408
|
-
this.name = name;
|
|
409
|
-
this.mallobj = mallobj;
|
|
410
|
-
this.exported = exported;
|
|
411
|
-
this.elementType = "defineExplore";
|
|
412
|
-
if (params) {
|
|
413
|
-
this.parameters = [];
|
|
414
|
-
for (const el of params) {
|
|
415
|
-
if (el instanceof HasParameter) {
|
|
416
|
-
this.parameters.push(el);
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
this.log(`Unexpected element type in define statement: ${el.elementType}`);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
this.has({ parameters: this.parameters });
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
execute(doc) {
|
|
426
|
-
if (doc.modelEntry(this.name)) {
|
|
427
|
-
this.log(`Cannot redefine '${this.name}'`);
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
const structDef = this.mallobj.withParameters(this.parameters);
|
|
431
|
-
if (ErrorFactory.isErrorStructDef(structDef)) {
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
doc.setEntry(this.name, {
|
|
435
|
-
entry: {
|
|
436
|
-
...structDef,
|
|
437
|
-
as: this.name,
|
|
438
|
-
location: this.location,
|
|
439
|
-
},
|
|
440
|
-
exported: this.exported,
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
exports.DefineExplore = DefineExplore;
|
|
446
|
-
class DefineSourceList extends ListOf {
|
|
447
|
-
constructor(sourceList) {
|
|
448
|
-
super("defineSources", sourceList);
|
|
449
|
-
this.has({ sourceList });
|
|
450
|
-
}
|
|
451
|
-
execute(doc) {
|
|
452
|
-
for (const dq of this.list) {
|
|
453
|
-
dq.execute(doc);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
exports.DefineSourceList = DefineSourceList;
|
|
458
|
-
/**
|
|
459
|
-
* A Mallobj made from a source and a set of refinements
|
|
460
|
-
*/
|
|
461
|
-
class RefinedExplore extends Mallobj {
|
|
462
|
-
constructor(source, refinement) {
|
|
463
|
-
super({ source, refinement });
|
|
464
|
-
this.source = source;
|
|
465
|
-
this.refinement = refinement;
|
|
466
|
-
this.elementType = "refinedExplore";
|
|
467
|
-
}
|
|
468
|
-
structDef() {
|
|
469
|
-
return this.withParameters([]);
|
|
470
|
-
}
|
|
471
|
-
withParameters(pList) {
|
|
472
|
-
let primaryKey;
|
|
473
|
-
let fieldListEdit;
|
|
474
|
-
const fields = [];
|
|
475
|
-
const filters = [];
|
|
476
|
-
for (const el of this.refinement.list) {
|
|
477
|
-
const errTo = el;
|
|
478
|
-
if (el instanceof PrimaryKey) {
|
|
479
|
-
if (primaryKey) {
|
|
480
|
-
primaryKey.log("Primary key already defined");
|
|
481
|
-
el.log("Primary key redefined");
|
|
482
|
-
}
|
|
483
|
-
primaryKey = el;
|
|
484
|
-
}
|
|
485
|
-
else if (el instanceof FieldListEdit) {
|
|
486
|
-
if (fieldListEdit) {
|
|
487
|
-
fieldListEdit.log("Too many accept/except statements");
|
|
488
|
-
el.log("Too many accept/except statements");
|
|
489
|
-
}
|
|
490
|
-
fieldListEdit = el;
|
|
491
|
-
}
|
|
492
|
-
else if (el instanceof DeclareFields ||
|
|
493
|
-
el instanceof Joins ||
|
|
494
|
-
el instanceof Turtles ||
|
|
495
|
-
el instanceof Renames) {
|
|
496
|
-
fields.push(...el.list);
|
|
497
|
-
}
|
|
498
|
-
else if (el instanceof Filter) {
|
|
499
|
-
filters.push(el);
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
errTo.log(`Unexpected explore property: '${errTo.elementType}'`);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
const from = (0, lodash_1.cloneDeep)(this.source.structDef());
|
|
506
|
-
if (primaryKey) {
|
|
507
|
-
from.primaryKey = primaryKey.field.name;
|
|
508
|
-
}
|
|
509
|
-
const fs = field_space_1.DynamicSpace.filteredFrom(from, fieldListEdit);
|
|
510
|
-
fs.addField(...fields);
|
|
511
|
-
if (pList) {
|
|
512
|
-
fs.addParameters(pList);
|
|
513
|
-
}
|
|
514
|
-
if (primaryKey) {
|
|
515
|
-
const keyDef = primaryKey.field.getField(fs);
|
|
516
|
-
if (keyDef.error) {
|
|
517
|
-
primaryKey.log(keyDef.error);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
const retStruct = fs.structDef();
|
|
521
|
-
const filterList = retStruct.filterList || [];
|
|
522
|
-
let moreFilters = false;
|
|
523
|
-
for (const filter of filters) {
|
|
524
|
-
for (const el of filter.list) {
|
|
525
|
-
const fc = el.filterExpression(fs);
|
|
526
|
-
if (fc.aggregate) {
|
|
527
|
-
el.log("Can't use aggregate computations in top level filters");
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
filterList.push(fc);
|
|
531
|
-
moreFilters = true;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
if (moreFilters) {
|
|
536
|
-
return { ...retStruct, filterList };
|
|
537
|
-
}
|
|
538
|
-
return retStruct;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
exports.RefinedExplore = RefinedExplore;
|
|
542
|
-
class TableSource extends Mallobj {
|
|
543
|
-
constructor(name) {
|
|
544
|
-
super();
|
|
545
|
-
this.name = name;
|
|
546
|
-
this.elementType = "tableSource";
|
|
547
|
-
}
|
|
548
|
-
structDef() {
|
|
549
|
-
var _a;
|
|
550
|
-
const tableDefEntry = (_a = this.translator()) === null || _a === void 0 ? void 0 : _a.root.schemaZone.getEntry(this.name);
|
|
551
|
-
let msg = `Schema read failure for table '${this.name}'`;
|
|
552
|
-
if (tableDefEntry) {
|
|
553
|
-
if (tableDefEntry.status == "present") {
|
|
554
|
-
tableDefEntry.value.location = this.location;
|
|
555
|
-
tableDefEntry.value.fields.forEach((field) => (field.location = this.location));
|
|
556
|
-
return {
|
|
557
|
-
...tableDefEntry.value,
|
|
558
|
-
fields: tableDefEntry.value.fields.map((field) => ({
|
|
559
|
-
...field,
|
|
560
|
-
location: this.location,
|
|
561
|
-
})),
|
|
562
|
-
location: this.location,
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
if (tableDefEntry.status == "error") {
|
|
566
|
-
msg = tableDefEntry.message.includes(this.name)
|
|
567
|
-
? `'Schema error: ${tableDefEntry.message}`
|
|
568
|
-
: `Schema error '${this.name}': ${tableDefEntry.message}`;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
this.log(msg);
|
|
572
|
-
return ErrorFactory.structDef;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
exports.TableSource = TableSource;
|
|
576
|
-
class IsValueBlock extends MalloyElement {
|
|
577
|
-
constructor(isMap) {
|
|
578
|
-
super();
|
|
579
|
-
this.isMap = isMap;
|
|
580
|
-
this.elementType = "isValueBlock";
|
|
581
|
-
this.has(isMap);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
exports.IsValueBlock = IsValueBlock;
|
|
585
|
-
class ModelEntryReference extends MalloyElement {
|
|
586
|
-
constructor(name) {
|
|
587
|
-
super();
|
|
588
|
-
this.name = name;
|
|
589
|
-
this.elementType = "modelEntryReference";
|
|
590
|
-
}
|
|
591
|
-
get refString() {
|
|
592
|
-
return this.name;
|
|
593
|
-
}
|
|
594
|
-
toString() {
|
|
595
|
-
return this.refString;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
exports.ModelEntryReference = ModelEntryReference;
|
|
599
|
-
class NamedSource extends Mallobj {
|
|
600
|
-
constructor(ref, paramValues = {}) {
|
|
601
|
-
super();
|
|
602
|
-
this.ref = ref;
|
|
603
|
-
this.elementType = "namedSource";
|
|
604
|
-
if (paramValues && Object.keys(paramValues).length > 0) {
|
|
605
|
-
this.isBlock = new IsValueBlock(paramValues);
|
|
606
|
-
this.has({ parameterValues: this.isBlock });
|
|
607
|
-
}
|
|
608
|
-
if (ref instanceof ModelEntryReference) {
|
|
609
|
-
this.has({ ref });
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
get refName() {
|
|
613
|
-
return this.ref instanceof ModelEntryReference ? this.ref.name : this.ref;
|
|
614
|
-
}
|
|
615
|
-
structRef() {
|
|
616
|
-
if (this.isBlock) {
|
|
617
|
-
return this.structDef();
|
|
618
|
-
}
|
|
619
|
-
return this.refName;
|
|
620
|
-
}
|
|
621
|
-
modelStruct() {
|
|
622
|
-
var _a;
|
|
623
|
-
const modelEnt = (_a = this.modelEntry(this.ref)) === null || _a === void 0 ? void 0 : _a.entry;
|
|
624
|
-
if (!modelEnt) {
|
|
625
|
-
const undefMsg = `Undefined source '${this.refName}'`;
|
|
626
|
-
(this.ref instanceof ModelEntryReference ? this.ref : this).log(undefMsg);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
if (modelEnt.type === "query") {
|
|
630
|
-
this.log(`Must use 'from()' to explore query '${this.refName}`);
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
else if (modelEnt.type === "sqlBlock") {
|
|
634
|
-
this.log(`Must use 'from_sql()' to explore sql query '${this.refName}`);
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
return { ...modelEnt };
|
|
638
|
-
}
|
|
639
|
-
structDef() {
|
|
640
|
-
/*
|
|
641
|
-
Can't really generate the callback list until after all the
|
|
642
|
-
things before me are translated, and that kinda screws up
|
|
643
|
-
the translation process, so that might be a better place
|
|
644
|
-
to start the next step, because how that gets done might
|
|
645
|
-
make any code I write which ignores the translation problem
|
|
646
|
-
kind of meaningless.
|
|
647
|
-
|
|
648
|
-
Maybe the output of a translation is something which describes
|
|
649
|
-
all the missing data, and then there is a "link" step where you
|
|
650
|
-
can do other translations and link them into a partial translation
|
|
651
|
-
which might result in a full translation.
|
|
652
|
-
*/
|
|
653
|
-
var _a;
|
|
654
|
-
const ret = this.modelStruct();
|
|
655
|
-
if (!ret) {
|
|
656
|
-
const notFound = ErrorFactory.structDef;
|
|
657
|
-
const err = `${this.refName}-undefined`;
|
|
658
|
-
notFound.name = notFound.name + err;
|
|
659
|
-
notFound.dialect = notFound.dialect + err;
|
|
660
|
-
return notFound;
|
|
661
|
-
}
|
|
662
|
-
const declared = { ...ret.parameters } || {};
|
|
663
|
-
const makeWith = ((_a = this.isBlock) === null || _a === void 0 ? void 0 : _a.isMap) || {};
|
|
664
|
-
for (const [pName, pExpr] of Object.entries(makeWith)) {
|
|
665
|
-
const decl = declared[pName];
|
|
666
|
-
// const pVal = pExpr.constantValue();
|
|
667
|
-
if (!decl) {
|
|
668
|
-
this.log(`Value given for undeclared parameter '${pName}`);
|
|
669
|
-
}
|
|
670
|
-
else {
|
|
671
|
-
if (model.isValueParameter(decl)) {
|
|
672
|
-
if (decl.constant) {
|
|
673
|
-
pExpr.log(`Cannot override constant parameter ${pName}`);
|
|
674
|
-
}
|
|
675
|
-
else {
|
|
676
|
-
const pVal = pExpr.constantValue();
|
|
677
|
-
let value = pVal.value;
|
|
678
|
-
if (pVal.dataType !== decl.type) {
|
|
679
|
-
value = (0, time_utils_1.castTo)(decl.type, pVal.value, true);
|
|
680
|
-
}
|
|
681
|
-
decl.value = value;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
// TODO type checking here -- except I am still not sure what
|
|
686
|
-
// datatype half conditions have ..
|
|
687
|
-
decl.condition = pExpr.constantCondition(decl.type).value;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
for (const checkDef in ret.parameters) {
|
|
692
|
-
if (!model.paramHasValue(declared[checkDef])) {
|
|
693
|
-
this.log(`Value not provided for required parameter ${checkDef}`);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
return ret;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
exports.NamedSource = NamedSource;
|
|
700
|
-
class SQLSource extends NamedSource {
|
|
701
|
-
constructor() {
|
|
702
|
-
super(...arguments);
|
|
703
|
-
this.elementType = "sqlSource";
|
|
704
|
-
}
|
|
705
|
-
structRef() {
|
|
706
|
-
return this.structDef();
|
|
707
|
-
}
|
|
708
|
-
modelStruct() {
|
|
709
|
-
var _a, _b;
|
|
710
|
-
const modelEnt = (_a = this.modelEntry(this.ref)) === null || _a === void 0 ? void 0 : _a.entry;
|
|
711
|
-
if (!modelEnt) {
|
|
712
|
-
this.log(`Undefined from_sql source '${this.refName}'`);
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
if (modelEnt.type === "query") {
|
|
716
|
-
this.log(`Cannot use 'from_sql()' to explore query '${this.refName}'`);
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
else if (modelEnt.type === "struct") {
|
|
720
|
-
this.log(`Cannot use 'from_sql()' to explore '${this.refName}'`);
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
const sqlDefEntry = (_b = this.translator()) === null || _b === void 0 ? void 0 : _b.root.sqlQueryZone;
|
|
724
|
-
if (!sqlDefEntry) {
|
|
725
|
-
this.log(`Cant't look up schema for sql block '${this.refName}'`);
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
if (modelEnt.type == "sqlBlock") {
|
|
729
|
-
const key = modelEnt.name;
|
|
730
|
-
const lookup = sqlDefEntry.getEntry(key);
|
|
731
|
-
let msg = `Schema read failure for sql query '${this.refName}'`;
|
|
732
|
-
if (lookup) {
|
|
733
|
-
if (lookup.status == "present") {
|
|
734
|
-
const structDef = lookup.value;
|
|
735
|
-
return {
|
|
736
|
-
...structDef,
|
|
737
|
-
fields: structDef.fields.map((field) => ({
|
|
738
|
-
...field,
|
|
739
|
-
location: modelEnt.location,
|
|
740
|
-
})),
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
if (lookup.status == "error") {
|
|
744
|
-
msg = lookup.message.includes(this.refName)
|
|
745
|
-
? `'Schema error: ${lookup.message}`
|
|
746
|
-
: `Schema error '${this.refName}': ${lookup.message}`;
|
|
747
|
-
}
|
|
748
|
-
this.log(msg);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
this.log(`Mis-typed definition for'${this.refName}'`);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
exports.SQLSource = SQLSource;
|
|
757
|
-
class QuerySource extends Mallobj {
|
|
758
|
-
constructor(query) {
|
|
759
|
-
super({ query });
|
|
760
|
-
this.query = query;
|
|
761
|
-
this.elementType = "querySource";
|
|
762
|
-
}
|
|
763
|
-
structDef() {
|
|
764
|
-
const comp = this.query.queryComp();
|
|
765
|
-
const queryStruct = comp.outputStruct;
|
|
766
|
-
queryStruct.structSource = { type: "query", query: comp.query };
|
|
767
|
-
return queryStruct;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
exports.QuerySource = QuerySource;
|
|
771
|
-
class Join extends MalloyElement {
|
|
772
|
-
}
|
|
773
|
-
exports.Join = Join;
|
|
774
|
-
class KeyJoin extends Join {
|
|
775
|
-
constructor(name, source, keyExpr) {
|
|
776
|
-
super({ name, source, keyExpr });
|
|
777
|
-
this.name = name;
|
|
778
|
-
this.source = source;
|
|
779
|
-
this.keyExpr = keyExpr;
|
|
780
|
-
this.elementType = "joinOnKey";
|
|
781
|
-
}
|
|
782
|
-
structDef() {
|
|
783
|
-
const sourceDef = this.source.structDef();
|
|
784
|
-
const joinStruct = {
|
|
785
|
-
...sourceDef,
|
|
786
|
-
structRelationship: {
|
|
787
|
-
type: "one",
|
|
788
|
-
onExpression: ["('join fixup'='not done yet')"],
|
|
789
|
-
},
|
|
790
|
-
location: this.location,
|
|
791
|
-
};
|
|
792
|
-
if (sourceDef.structSource.type === "query") {
|
|
793
|
-
// the name from query does not need to be preserved
|
|
794
|
-
joinStruct.name = this.name.refString;
|
|
795
|
-
}
|
|
796
|
-
else {
|
|
797
|
-
joinStruct.as = this.name.refString;
|
|
798
|
-
}
|
|
799
|
-
return joinStruct;
|
|
800
|
-
}
|
|
801
|
-
fixupJoinOn(outer, inStruct) {
|
|
802
|
-
const exprX = this.keyExpr.getExpression(outer);
|
|
803
|
-
if (inStruct.primaryKey) {
|
|
804
|
-
const pkey = inStruct.fields.find((f) => (f.as || f.name) === inStruct.primaryKey);
|
|
805
|
-
if (pkey) {
|
|
806
|
-
if (pkey.type === exprX.dataType) {
|
|
807
|
-
inStruct.structRelationship = {
|
|
808
|
-
type: "one",
|
|
809
|
-
onExpression: [
|
|
810
|
-
{ type: "field", path: `${this.name}.${inStruct.primaryKey}` },
|
|
811
|
-
"=",
|
|
812
|
-
...exprX.value,
|
|
813
|
-
],
|
|
814
|
-
};
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
this.log(`join_one: with type mismatch with primary key: ${exprX.dataType}/${pkey.type}`);
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
this.log(`join_one: Primary key '${pkey}' not found in source`);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
else {
|
|
826
|
-
this.log(`join_one: Cannot use with unless source has a primary key`);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
exports.KeyJoin = KeyJoin;
|
|
831
|
-
class ExpressionJoin extends Join {
|
|
832
|
-
constructor(name, source) {
|
|
833
|
-
super({ name, source });
|
|
834
|
-
this.name = name;
|
|
835
|
-
this.source = source;
|
|
836
|
-
this.elementType = "joinOnExpr";
|
|
837
|
-
this.joinType = "one";
|
|
838
|
-
}
|
|
839
|
-
set joinOn(joinExpr) {
|
|
840
|
-
this.expr = joinExpr;
|
|
841
|
-
this.has({ on: joinExpr });
|
|
842
|
-
}
|
|
843
|
-
get joinOn() {
|
|
844
|
-
return this.expr;
|
|
845
|
-
}
|
|
846
|
-
fixupJoinOn(outer, inStruct) {
|
|
847
|
-
if (this.expr == undefined) {
|
|
848
|
-
return;
|
|
849
|
-
}
|
|
850
|
-
const exprX = this.expr.getExpression(outer);
|
|
851
|
-
if (exprX.dataType !== "boolean") {
|
|
852
|
-
this.log("join conditions must be boolean expressions");
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
const joinRel = inStruct.structRelationship;
|
|
856
|
-
if (model.isJoinOn(joinRel)) {
|
|
857
|
-
joinRel.onExpression = (0, index_1.compressExpr)(exprX.value);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
structDef() {
|
|
861
|
-
const sourceDef = this.source.structDef();
|
|
862
|
-
const joinStruct = {
|
|
863
|
-
...sourceDef,
|
|
864
|
-
structRelationship: { type: this.joinType },
|
|
865
|
-
location: this.location,
|
|
866
|
-
};
|
|
867
|
-
if (sourceDef.structSource.type === "query") {
|
|
868
|
-
// the name from query does not need to be preserved
|
|
869
|
-
joinStruct.name = this.name.refString;
|
|
870
|
-
delete joinStruct.as;
|
|
871
|
-
}
|
|
872
|
-
else {
|
|
873
|
-
joinStruct.as = this.name.refString;
|
|
874
|
-
}
|
|
875
|
-
return joinStruct;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
exports.ExpressionJoin = ExpressionJoin;
|
|
879
|
-
class Joins extends ListOf {
|
|
880
|
-
constructor(joins) {
|
|
881
|
-
super("joinList", joins);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
exports.Joins = Joins;
|
|
885
|
-
function isQueryProperty(q) {
|
|
886
|
-
return (q instanceof Ordering ||
|
|
887
|
-
q instanceof Top ||
|
|
888
|
-
q instanceof Limit ||
|
|
889
|
-
q instanceof Filter ||
|
|
890
|
-
q instanceof Index ||
|
|
891
|
-
q instanceof SampleProperty ||
|
|
892
|
-
q instanceof Joins ||
|
|
893
|
-
q instanceof DeclareFields ||
|
|
894
|
-
q instanceof ProjectStatement ||
|
|
895
|
-
q instanceof Aggregate ||
|
|
896
|
-
q instanceof Nests ||
|
|
897
|
-
isNestedQuery(q) ||
|
|
898
|
-
q instanceof GroupBy);
|
|
899
|
-
}
|
|
900
|
-
exports.isQueryProperty = isQueryProperty;
|
|
901
|
-
function isExploreProperty(p) {
|
|
902
|
-
return (p instanceof Filter ||
|
|
903
|
-
p instanceof Joins ||
|
|
904
|
-
p instanceof DeclareFields ||
|
|
905
|
-
p instanceof FieldListEdit ||
|
|
906
|
-
p instanceof Renames ||
|
|
907
|
-
p instanceof PrimaryKey ||
|
|
908
|
-
p instanceof Turtles);
|
|
909
|
-
}
|
|
910
|
-
exports.isExploreProperty = isExploreProperty;
|
|
911
|
-
class ExploreDesc extends ListOf {
|
|
912
|
-
constructor(props) {
|
|
913
|
-
super("exploreDesc", props);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
exports.ExploreDesc = ExploreDesc;
|
|
917
|
-
class FilterElement extends MalloyElement {
|
|
918
|
-
constructor(expr, exprSrc) {
|
|
919
|
-
super({ expr });
|
|
920
|
-
this.expr = expr;
|
|
921
|
-
this.exprSrc = exprSrc;
|
|
922
|
-
this.elementType = "filterElement";
|
|
923
|
-
}
|
|
924
|
-
filterExpression(fs) {
|
|
925
|
-
const exprVal = this.expr.getExpression(fs);
|
|
926
|
-
if (exprVal.dataType !== "boolean") {
|
|
927
|
-
this.expr.log("Filter expression must have boolean value");
|
|
928
|
-
return {
|
|
929
|
-
code: this.exprSrc,
|
|
930
|
-
expression: ["_FILTER_MUST_RETURN_BOOLEAN_"],
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
const exprCond = {
|
|
934
|
-
code: this.exprSrc,
|
|
935
|
-
expression: (0, index_1.compressExpr)(exprVal.value),
|
|
936
|
-
};
|
|
937
|
-
if (exprVal.aggregate) {
|
|
938
|
-
exprCond.aggregate = true;
|
|
939
|
-
}
|
|
940
|
-
return exprCond;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
exports.FilterElement = FilterElement;
|
|
944
|
-
class Filter extends ListOf {
|
|
945
|
-
constructor(elements = []) {
|
|
946
|
-
super("filterElements", elements);
|
|
947
|
-
this.elementType = "filter";
|
|
948
|
-
}
|
|
949
|
-
set having(isHaving) {
|
|
950
|
-
this.elementType = isHaving ? "having" : "where";
|
|
951
|
-
}
|
|
952
|
-
getFilterList(fs) {
|
|
953
|
-
const checked = [];
|
|
954
|
-
for (const oneElement of this.list) {
|
|
955
|
-
const fExpr = oneElement.filterExpression(fs);
|
|
956
|
-
// Aggregates are ALSO checked at SQL generation time, but checking
|
|
957
|
-
// here allows better reflection of errors back to user.
|
|
958
|
-
if (this.havingClause !== undefined) {
|
|
959
|
-
if (this.havingClause) {
|
|
960
|
-
if (!fExpr.aggregate) {
|
|
961
|
-
oneElement.log("Aggregate expression expected in HAVING filter");
|
|
962
|
-
continue;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
else {
|
|
966
|
-
if (fExpr.aggregate) {
|
|
967
|
-
oneElement.log("Aggregate expression not allowed in WHERE");
|
|
968
|
-
continue;
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
checked.push(fExpr);
|
|
973
|
-
}
|
|
974
|
-
return checked;
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
exports.Filter = Filter;
|
|
978
|
-
class DeclareFields extends ListOf {
|
|
979
|
-
constructor(fields, fieldType = "declare") {
|
|
980
|
-
super(fieldType, fields);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
exports.DeclareFields = DeclareFields;
|
|
984
|
-
class Measures extends DeclareFields {
|
|
985
|
-
constructor(measures) {
|
|
986
|
-
super(measures, "measure");
|
|
987
|
-
for (const dim of measures) {
|
|
988
|
-
dim.isMeasure = true;
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
exports.Measures = Measures;
|
|
993
|
-
class Dimensions extends DeclareFields {
|
|
994
|
-
constructor(dimensions) {
|
|
995
|
-
super(dimensions, "dimension");
|
|
996
|
-
for (const dim of dimensions) {
|
|
997
|
-
dim.isMeasure = false;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
exports.Dimensions = Dimensions;
|
|
1002
|
-
class Renames extends ListOf {
|
|
1003
|
-
constructor(renames) {
|
|
1004
|
-
super("renameField", renames);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
exports.Renames = Renames;
|
|
1008
|
-
class FieldName extends MalloyElement {
|
|
1009
|
-
constructor(name) {
|
|
1010
|
-
super();
|
|
1011
|
-
this.name = name;
|
|
1012
|
-
this.elementType = "fieldName";
|
|
1013
|
-
}
|
|
1014
|
-
get refString() {
|
|
1015
|
-
return this.name;
|
|
1016
|
-
}
|
|
1017
|
-
toString() {
|
|
1018
|
-
return this.refString;
|
|
1019
|
-
}
|
|
1020
|
-
getField(fs) {
|
|
1021
|
-
return fs.lookup([this]);
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
exports.FieldName = FieldName;
|
|
1025
|
-
class FieldReference extends ListOf {
|
|
1026
|
-
constructor(names) {
|
|
1027
|
-
super("fieldReference", names);
|
|
1028
|
-
this.elementType = "fieldReference";
|
|
1029
|
-
}
|
|
1030
|
-
get refString() {
|
|
1031
|
-
return this.list.map((n) => n.refString).join(".");
|
|
1032
|
-
}
|
|
1033
|
-
get outputName() {
|
|
1034
|
-
const last = this.list[this.list.length - 1];
|
|
1035
|
-
return last.refString;
|
|
1036
|
-
}
|
|
1037
|
-
get sourceString() {
|
|
1038
|
-
if (this.list.length > 1) {
|
|
1039
|
-
return this.list
|
|
1040
|
-
.slice(0, -1)
|
|
1041
|
-
.map((n) => n.refString)
|
|
1042
|
-
.join(".");
|
|
1043
|
-
}
|
|
1044
|
-
return undefined;
|
|
1045
|
-
}
|
|
1046
|
-
get nameString() {
|
|
1047
|
-
return this.list[this.list.length - 1].refString;
|
|
1048
|
-
}
|
|
1049
|
-
getField(fs) {
|
|
1050
|
-
return fs.lookup(this.list);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
exports.FieldReference = FieldReference;
|
|
1054
|
-
class FieldReferences extends ListOf {
|
|
1055
|
-
constructor(members) {
|
|
1056
|
-
super("fieldReferenceList", members);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
exports.FieldReferences = FieldReferences;
|
|
1060
|
-
function isFieldCollectionMember(el) {
|
|
1061
|
-
return (el instanceof FieldReference ||
|
|
1062
|
-
el instanceof WildcardFieldReference ||
|
|
1063
|
-
el instanceof index_1.FieldDeclaration);
|
|
1064
|
-
}
|
|
1065
|
-
exports.isFieldCollectionMember = isFieldCollectionMember;
|
|
1066
|
-
class ProjectStatement extends ListOf {
|
|
1067
|
-
constructor(members) {
|
|
1068
|
-
super("fieldCollection", members);
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
exports.ProjectStatement = ProjectStatement;
|
|
1072
|
-
class FieldListEdit extends MalloyElement {
|
|
1073
|
-
constructor(edit, refs) {
|
|
1074
|
-
super({ refs });
|
|
1075
|
-
this.edit = edit;
|
|
1076
|
-
this.refs = refs;
|
|
1077
|
-
this.elementType = "fieldListEdit";
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
exports.FieldListEdit = FieldListEdit;
|
|
1081
|
-
class GroupBy extends ListOf {
|
|
1082
|
-
constructor(members) {
|
|
1083
|
-
super("groupBy", members);
|
|
1084
|
-
for (const el of members) {
|
|
1085
|
-
if (el instanceof index_1.FieldDeclaration) {
|
|
1086
|
-
el.isMeasure = false;
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
exports.GroupBy = GroupBy;
|
|
1092
|
-
class Aggregate extends ListOf {
|
|
1093
|
-
constructor(members) {
|
|
1094
|
-
super("aggregate", members);
|
|
1095
|
-
for (const el of members) {
|
|
1096
|
-
if (el instanceof index_1.FieldDeclaration) {
|
|
1097
|
-
el.isMeasure = true;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
exports.Aggregate = Aggregate;
|
|
1103
|
-
class ReduceExecutor {
|
|
1104
|
-
constructor(baseFS) {
|
|
1105
|
-
this.filters = [];
|
|
1106
|
-
this.resultFS = this.getResultSpace(baseFS);
|
|
1107
|
-
this.inputFS = this.resultFS.exprSpace;
|
|
1108
|
-
}
|
|
1109
|
-
getResultSpace(fs) {
|
|
1110
|
-
return new field_space_1.ReduceFieldSpace(fs);
|
|
1111
|
-
}
|
|
1112
|
-
execute(qp) {
|
|
1113
|
-
if (qp instanceof GroupBy ||
|
|
1114
|
-
qp instanceof Aggregate ||
|
|
1115
|
-
qp instanceof Nests) {
|
|
1116
|
-
this.resultFS.addQueryItems(...qp.list);
|
|
1117
|
-
}
|
|
1118
|
-
else if (isNestedQuery(qp)) {
|
|
1119
|
-
this.resultFS.addQueryItems(qp);
|
|
1120
|
-
}
|
|
1121
|
-
else if (qp instanceof Filter) {
|
|
1122
|
-
this.filters.push(...qp.getFilterList(this.inputFS));
|
|
1123
|
-
}
|
|
1124
|
-
else if (qp instanceof Top) {
|
|
1125
|
-
if (this.limit) {
|
|
1126
|
-
qp.log("Query operation already limited");
|
|
1127
|
-
}
|
|
1128
|
-
else {
|
|
1129
|
-
this.limit = qp.limit;
|
|
1130
|
-
}
|
|
1131
|
-
if (qp.by) {
|
|
1132
|
-
if (this.order) {
|
|
1133
|
-
qp.log("Query operation is already sorted");
|
|
1134
|
-
}
|
|
1135
|
-
else {
|
|
1136
|
-
this.order = qp;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
else if (qp instanceof Limit) {
|
|
1141
|
-
if (this.limit) {
|
|
1142
|
-
qp.log("Query operation already limited");
|
|
1143
|
-
}
|
|
1144
|
-
else {
|
|
1145
|
-
this.limit = qp.limit;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
else if (qp instanceof Ordering) {
|
|
1149
|
-
if (this.order) {
|
|
1150
|
-
qp.log("Query operation already sorted");
|
|
1151
|
-
}
|
|
1152
|
-
else {
|
|
1153
|
-
this.order = qp;
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
else if (qp instanceof Joins || qp instanceof DeclareFields) {
|
|
1157
|
-
for (const qel of qp.list) {
|
|
1158
|
-
this.inputFS.extendSource(qel);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
refineFrom(from, to) {
|
|
1163
|
-
if (from && from.type !== "index") {
|
|
1164
|
-
if (!this.order) {
|
|
1165
|
-
if (from.orderBy) {
|
|
1166
|
-
to.orderBy = from.orderBy;
|
|
1167
|
-
}
|
|
1168
|
-
else if (from.by) {
|
|
1169
|
-
to.by = from.by;
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
if (!this.limit && from.limit) {
|
|
1173
|
-
to.limit = from.limit;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
if (this.limit) {
|
|
1177
|
-
to.limit = this.limit;
|
|
1178
|
-
}
|
|
1179
|
-
if (this.order instanceof Top) {
|
|
1180
|
-
const topBy = this.order.getBy(this.inputFS);
|
|
1181
|
-
if (topBy) {
|
|
1182
|
-
to.by = topBy;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
if (this.order instanceof Ordering) {
|
|
1186
|
-
to.orderBy = this.order.getOrderBy(this.inputFS);
|
|
1187
|
-
}
|
|
1188
|
-
const oldFilters = (from === null || from === void 0 ? void 0 : from.filterList) || [];
|
|
1189
|
-
if (this.filters.length > 0 && !oldFilters) {
|
|
1190
|
-
to.filterList = this.filters;
|
|
1191
|
-
}
|
|
1192
|
-
else if (oldFilters) {
|
|
1193
|
-
to.filterList = [...oldFilters, ...this.filters];
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
finalize(fromSeg) {
|
|
1197
|
-
let from;
|
|
1198
|
-
if (fromSeg) {
|
|
1199
|
-
if (model.isReduceSegment(fromSeg)) {
|
|
1200
|
-
from = fromSeg;
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1203
|
-
this.inputFS.result.log(`Can't refine reduce with ${fromSeg.type}`);
|
|
1204
|
-
return ErrorFactory.reduceSegment;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
const reduceSegment = this.resultFS.getQuerySegment(from);
|
|
1208
|
-
this.refineFrom(from, reduceSegment);
|
|
1209
|
-
return reduceSegment;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
class ProjectExecutor extends ReduceExecutor {
|
|
1213
|
-
getResultSpace(fs) {
|
|
1214
|
-
return new field_space_1.ProjectFieldSpace(fs);
|
|
1215
|
-
}
|
|
1216
|
-
execute(qp) {
|
|
1217
|
-
if (qp instanceof ProjectStatement) {
|
|
1218
|
-
this.resultFS.addMembers(qp.list);
|
|
1219
|
-
}
|
|
1220
|
-
else if ((qp instanceof Filter && qp.elementType === "having") ||
|
|
1221
|
-
qp instanceof Measures ||
|
|
1222
|
-
qp instanceof GroupBy) {
|
|
1223
|
-
qp.log("Illegal statement in a project query operation");
|
|
1224
|
-
}
|
|
1225
|
-
else {
|
|
1226
|
-
super.execute(qp);
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
finalize(fromSeg) {
|
|
1230
|
-
let from;
|
|
1231
|
-
if (fromSeg) {
|
|
1232
|
-
if (model.isProjectSegment(fromSeg)) {
|
|
1233
|
-
from = fromSeg;
|
|
1234
|
-
}
|
|
1235
|
-
else {
|
|
1236
|
-
this.resultFS.log(`Can't refine project with ${fromSeg.type}`);
|
|
1237
|
-
return ErrorFactory.projectSegment;
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
const projectSegment = this.resultFS.getQuerySegment(from);
|
|
1241
|
-
this.refineFrom(from, projectSegment);
|
|
1242
|
-
return projectSegment;
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
class IndexExecutor {
|
|
1246
|
-
constructor(inputFS) {
|
|
1247
|
-
this.filters = [];
|
|
1248
|
-
this.resultFS = new field_space_1.IndexFieldSpace(inputFS);
|
|
1249
|
-
this.inputFS = this.resultFS.exprSpace;
|
|
1250
|
-
}
|
|
1251
|
-
execute(qp) {
|
|
1252
|
-
if (qp instanceof Filter) {
|
|
1253
|
-
this.filters.push(...qp.getFilterList(this.inputFS));
|
|
1254
|
-
}
|
|
1255
|
-
else if (qp instanceof Limit) {
|
|
1256
|
-
if (this.limit) {
|
|
1257
|
-
this.limit.log("Ignored, too many limit: statements");
|
|
1258
|
-
}
|
|
1259
|
-
this.limit = qp;
|
|
1260
|
-
}
|
|
1261
|
-
else if (qp instanceof Index) {
|
|
1262
|
-
this.resultFS.addMembers(qp.fields.list);
|
|
1263
|
-
if (qp.weightBy) {
|
|
1264
|
-
if (this.indexOn) {
|
|
1265
|
-
this.indexOn.log("Ignoring previous BY");
|
|
1266
|
-
}
|
|
1267
|
-
this.indexOn = qp.weightBy;
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
else if (qp instanceof SampleProperty) {
|
|
1271
|
-
this.sample = qp.sampling();
|
|
1272
|
-
}
|
|
1273
|
-
else {
|
|
1274
|
-
qp.log("Not legal in an index query operation");
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
finalize(from) {
|
|
1278
|
-
if (from && from.type !== "index") {
|
|
1279
|
-
this.resultFS.log(`Can't refine index with ${from.type}`);
|
|
1280
|
-
return ErrorFactory.indexSegment;
|
|
1281
|
-
}
|
|
1282
|
-
const indexSegment = this.resultFS.getPipeSegment(from);
|
|
1283
|
-
const oldFilters = (from === null || from === void 0 ? void 0 : from.filterList) || [];
|
|
1284
|
-
if (this.filters.length > 0 && !oldFilters) {
|
|
1285
|
-
indexSegment.filterList = this.filters;
|
|
1286
|
-
}
|
|
1287
|
-
else if (oldFilters) {
|
|
1288
|
-
indexSegment.filterList = [...oldFilters, ...this.filters];
|
|
1289
|
-
}
|
|
1290
|
-
if (from === null || from === void 0 ? void 0 : from.limit) {
|
|
1291
|
-
indexSegment.limit = from.limit;
|
|
1292
|
-
}
|
|
1293
|
-
if (this.limit) {
|
|
1294
|
-
indexSegment.limit = this.limit.limit;
|
|
1295
|
-
}
|
|
1296
|
-
if (this.indexOn) {
|
|
1297
|
-
indexSegment.weightMeasure = this.indexOn.refString;
|
|
1298
|
-
}
|
|
1299
|
-
if (from === null || from === void 0 ? void 0 : from.sample) {
|
|
1300
|
-
indexSegment.sample = from.sample;
|
|
1301
|
-
}
|
|
1302
|
-
if (this.sample) {
|
|
1303
|
-
indexSegment.sample = this.sample;
|
|
1304
|
-
}
|
|
1305
|
-
return indexSegment;
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
class QOPDesc extends ListOf {
|
|
1309
|
-
constructor(props) {
|
|
1310
|
-
super("queryOperator", props);
|
|
1311
|
-
this.opType = "grouping";
|
|
1312
|
-
}
|
|
1313
|
-
computeType() {
|
|
1314
|
-
let firstGuess;
|
|
1315
|
-
if (this.refineThis) {
|
|
1316
|
-
if (this.refineThis.type == "reduce") {
|
|
1317
|
-
firstGuess = "grouping";
|
|
1318
|
-
}
|
|
1319
|
-
else {
|
|
1320
|
-
firstGuess = this.refineThis.type;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
let anyGrouping = false;
|
|
1324
|
-
for (const el of this.list) {
|
|
1325
|
-
if (el instanceof Index) {
|
|
1326
|
-
firstGuess || (firstGuess = "index");
|
|
1327
|
-
if (firstGuess !== "index") {
|
|
1328
|
-
el.log(`index: not legal in ${firstGuess} query`);
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
else if (el instanceof Nests ||
|
|
1332
|
-
isNestedQuery(el) ||
|
|
1333
|
-
el instanceof GroupBy) {
|
|
1334
|
-
firstGuess || (firstGuess = "grouping");
|
|
1335
|
-
anyGrouping = true;
|
|
1336
|
-
if (firstGuess === "project" || firstGuess === "index") {
|
|
1337
|
-
el.log(`group_by: not legal in ${firstGuess} query`);
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
else if (el instanceof Aggregate) {
|
|
1341
|
-
firstGuess || (firstGuess = "aggregate");
|
|
1342
|
-
if (firstGuess === "project" || firstGuess === "index") {
|
|
1343
|
-
el.log(`aggregate: not legal in ${firstGuess} query`);
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
else if (el instanceof ProjectStatement) {
|
|
1347
|
-
firstGuess || (firstGuess = "project");
|
|
1348
|
-
if (firstGuess !== "project") {
|
|
1349
|
-
el.log(`project: not legal in ${firstGuess} query`);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
if (firstGuess === "aggregate" && anyGrouping) {
|
|
1354
|
-
firstGuess = "grouping";
|
|
1355
|
-
}
|
|
1356
|
-
if (!firstGuess) {
|
|
1357
|
-
this.log("Can't determine query type (group_by/aggregate/nest,project,index)");
|
|
1358
|
-
}
|
|
1359
|
-
const guessType = firstGuess || "grouping";
|
|
1360
|
-
this.opType = guessType;
|
|
1361
|
-
return guessType;
|
|
1362
|
-
}
|
|
1363
|
-
refineFrom(existing) {
|
|
1364
|
-
this.refineThis = existing;
|
|
1365
|
-
}
|
|
1366
|
-
getExecutor(baseFS) {
|
|
1367
|
-
switch (this.computeType()) {
|
|
1368
|
-
case "aggregate":
|
|
1369
|
-
case "grouping":
|
|
1370
|
-
return new ReduceExecutor(baseFS);
|
|
1371
|
-
case "project":
|
|
1372
|
-
return new ProjectExecutor(baseFS);
|
|
1373
|
-
case "index":
|
|
1374
|
-
return new IndexExecutor(baseFS);
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
getOp(inputFS, forPipeline) {
|
|
1378
|
-
const qex = this.getExecutor(inputFS);
|
|
1379
|
-
if (forPipeline === null || forPipeline === void 0 ? void 0 : forPipeline.nestedInQuerySpace) {
|
|
1380
|
-
qex.inputFS.nestParent = forPipeline.nestedInQuerySpace;
|
|
1381
|
-
}
|
|
1382
|
-
qex.resultFS.astEl = this;
|
|
1383
|
-
for (const qp of this.list) {
|
|
1384
|
-
qex.execute(qp);
|
|
1385
|
-
}
|
|
1386
|
-
const segment = qex.finalize(this.refineThis);
|
|
1387
|
-
return {
|
|
1388
|
-
segment,
|
|
1389
|
-
outputSpace: () => new field_space_1.DynamicSpace(opOutputStruct(this, inputFS.structDef(), segment)),
|
|
1390
|
-
};
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
exports.QOPDesc = QOPDesc;
|
|
1394
|
-
class Document extends MalloyElement {
|
|
1395
|
-
constructor(statements) {
|
|
1396
|
-
super({ statements });
|
|
1397
|
-
this.statements = statements;
|
|
1398
|
-
this.elementType = "document";
|
|
1399
|
-
this.documentModel = {};
|
|
1400
|
-
this.queryList = [];
|
|
1401
|
-
this.sqlBlocks = [];
|
|
1402
|
-
}
|
|
1403
|
-
getModelDef(extendingModelDef) {
|
|
1404
|
-
this.documentModel = {};
|
|
1405
|
-
this.queryList = [];
|
|
1406
|
-
this.sqlBlocks = [];
|
|
1407
|
-
if (extendingModelDef) {
|
|
1408
|
-
for (const inName in extendingModelDef.contents) {
|
|
1409
|
-
const struct = extendingModelDef.contents[inName];
|
|
1410
|
-
if (struct.type == "struct") {
|
|
1411
|
-
const exported = extendingModelDef.exports.includes(inName);
|
|
1412
|
-
this.setEntry(inName, { entry: struct, exported });
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
for (const stmt of this.statements) {
|
|
1417
|
-
if (this.errorsExist()) {
|
|
1418
|
-
// Once errors appear, don't continue executing statements, stops
|
|
1419
|
-
// a number of cascasding errors.
|
|
1420
|
-
break;
|
|
1421
|
-
}
|
|
1422
|
-
stmt.execute(this);
|
|
1423
|
-
}
|
|
1424
|
-
const def = { name: "", exports: [], contents: {} };
|
|
1425
|
-
for (const entry in this.documentModel) {
|
|
1426
|
-
const entryDef = this.documentModel[entry].entry;
|
|
1427
|
-
if (entryDef.type === "struct" || entryDef.type === "query") {
|
|
1428
|
-
if (this.documentModel[entry].exported) {
|
|
1429
|
-
def.exports.push(entry);
|
|
1430
|
-
}
|
|
1431
|
-
def.contents[entry] = (0, lodash_1.cloneDeep)(entryDef);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
return def;
|
|
1435
|
-
}
|
|
1436
|
-
defineSQL(sql, name) {
|
|
1437
|
-
const ret = { ...sql, as: `$${this.sqlBlocks.length}` };
|
|
1438
|
-
if (name) {
|
|
1439
|
-
if (this.getEntry(name)) {
|
|
1440
|
-
return false;
|
|
1441
|
-
}
|
|
1442
|
-
ret.as = name;
|
|
1443
|
-
this.setEntry(name, { entry: ret });
|
|
1444
|
-
}
|
|
1445
|
-
this.sqlBlocks.push(ret);
|
|
1446
|
-
return true;
|
|
1447
|
-
}
|
|
1448
|
-
getEntry(str) {
|
|
1449
|
-
return this.documentModel[str];
|
|
1450
|
-
}
|
|
1451
|
-
setEntry(str, ent) {
|
|
1452
|
-
this.documentModel[str] = ent;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
exports.Document = Document;
|
|
1456
|
-
class PrimaryKey extends MalloyElement {
|
|
1457
|
-
constructor(field) {
|
|
1458
|
-
super({ field });
|
|
1459
|
-
this.field = field;
|
|
1460
|
-
this.elementType = "primary key";
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
exports.PrimaryKey = PrimaryKey;
|
|
1464
|
-
class RenameField extends MalloyElement {
|
|
1465
|
-
constructor(newName, oldName) {
|
|
1466
|
-
super();
|
|
1467
|
-
this.newName = newName;
|
|
1468
|
-
this.oldName = oldName;
|
|
1469
|
-
this.elementType = "renameField";
|
|
1470
|
-
this.has({ oldName });
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
exports.RenameField = RenameField;
|
|
1474
|
-
class WildcardFieldReference extends MalloyElement {
|
|
1475
|
-
constructor(joinPath, star) {
|
|
1476
|
-
super();
|
|
1477
|
-
this.joinPath = joinPath;
|
|
1478
|
-
this.star = star;
|
|
1479
|
-
this.elementType = "wildcardFieldReference";
|
|
1480
|
-
this.has({ joinPath });
|
|
1481
|
-
}
|
|
1482
|
-
getFieldDef() {
|
|
1483
|
-
throw this.internalError("fielddef request from wildcard reference");
|
|
1484
|
-
}
|
|
1485
|
-
get refString() {
|
|
1486
|
-
return this.joinPath
|
|
1487
|
-
? `${this.joinPath.refString}.${this.star}`
|
|
1488
|
-
: this.star;
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
exports.WildcardFieldReference = WildcardFieldReference;
|
|
1492
|
-
class OrderBy extends MalloyElement {
|
|
1493
|
-
constructor(field, dir) {
|
|
1494
|
-
super();
|
|
1495
|
-
this.field = field;
|
|
1496
|
-
this.dir = dir;
|
|
1497
|
-
this.elementType = "orderBy";
|
|
1498
|
-
if (field instanceof FieldName) {
|
|
1499
|
-
this.has({ field });
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
get modelField() {
|
|
1503
|
-
return typeof this.field === "number" ? this.field : this.field.refString;
|
|
1504
|
-
}
|
|
1505
|
-
getOrderBy(_fs) {
|
|
1506
|
-
// TODO jump-to-definition `fs` cannot currently `lookup` fields in the output space
|
|
1507
|
-
// if (this.field instanceof FieldName) {
|
|
1508
|
-
// const entry = this.field.getField(_fs);
|
|
1509
|
-
// if (entry.error) {
|
|
1510
|
-
// this.field.log(entry.error);
|
|
1511
|
-
// }
|
|
1512
|
-
// }
|
|
1513
|
-
const orderElement = { field: this.modelField };
|
|
1514
|
-
if (this.dir) {
|
|
1515
|
-
orderElement.dir = this.dir;
|
|
1516
|
-
}
|
|
1517
|
-
return orderElement;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
exports.OrderBy = OrderBy;
|
|
1521
|
-
class Ordering extends ListOf {
|
|
1522
|
-
constructor(list) {
|
|
1523
|
-
super("ordering", list);
|
|
1524
|
-
}
|
|
1525
|
-
getOrderBy(fs) {
|
|
1526
|
-
return this.list.map((el) => el.getOrderBy(fs));
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
exports.Ordering = Ordering;
|
|
1530
|
-
class Limit extends MalloyElement {
|
|
1531
|
-
constructor(limit) {
|
|
1532
|
-
super();
|
|
1533
|
-
this.limit = limit;
|
|
1534
|
-
this.elementType = "limit";
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
exports.Limit = Limit;
|
|
1538
|
-
class Turtles extends ListOf {
|
|
1539
|
-
constructor(turtles) {
|
|
1540
|
-
super("turtleDeclarationList", turtles);
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
exports.Turtles = Turtles;
|
|
1544
|
-
class Index extends MalloyElement {
|
|
1545
|
-
constructor(fields) {
|
|
1546
|
-
super({ fields });
|
|
1547
|
-
this.fields = fields;
|
|
1548
|
-
this.elementType = "index";
|
|
1549
|
-
}
|
|
1550
|
-
useWeight(fn) {
|
|
1551
|
-
this.has({ weightBy: fn });
|
|
1552
|
-
this.weightBy = fn;
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
exports.Index = Index;
|
|
1556
|
-
function isTurtle(fd) {
|
|
1557
|
-
const ret = fd && typeof fd !== "string" && fd.type === "turtle";
|
|
1558
|
-
return !!ret;
|
|
1559
|
-
}
|
|
1560
|
-
/**
|
|
1561
|
-
* Generic abstract for all pipelines, the first segment might be a reference
|
|
1562
|
-
* to an existing pipeline (query or turtle), and if there is a refinement it
|
|
1563
|
-
* is refers to the first segment of the composed pipeline.
|
|
1564
|
-
*/
|
|
1565
|
-
class PipelineDesc extends MalloyElement {
|
|
1566
|
-
constructor() {
|
|
1567
|
-
super(...arguments);
|
|
1568
|
-
this.elementType = "pipelineDesc";
|
|
1569
|
-
this.qops = [];
|
|
1570
|
-
}
|
|
1571
|
-
refineHead(refinement) {
|
|
1572
|
-
this.headRefinement = refinement;
|
|
1573
|
-
this.has({ headRefinement: refinement });
|
|
1574
|
-
}
|
|
1575
|
-
addSegments(...segDesc) {
|
|
1576
|
-
this.qops.push(...segDesc);
|
|
1577
|
-
this.has({ segments: this.qops });
|
|
1578
|
-
}
|
|
1579
|
-
appendOps(modelPipe, existingEndSpace) {
|
|
1580
|
-
let nextFS = existingEndSpace;
|
|
1581
|
-
let returnPipe;
|
|
1582
|
-
for (const qop of this.qops) {
|
|
1583
|
-
const qopIsNested = modelPipe.length == 0;
|
|
1584
|
-
const next = qop.getOp(nextFS, qopIsNested ? this : null);
|
|
1585
|
-
if (returnPipe == undefined) {
|
|
1586
|
-
returnPipe = [...modelPipe];
|
|
1587
|
-
}
|
|
1588
|
-
returnPipe.push(next.segment);
|
|
1589
|
-
nextFS = next.outputSpace();
|
|
1590
|
-
}
|
|
1591
|
-
return {
|
|
1592
|
-
opList: returnPipe || modelPipe,
|
|
1593
|
-
structDef: nextFS.structDef(),
|
|
1594
|
-
};
|
|
1595
|
-
}
|
|
1596
|
-
refinePipeline(fs, modelPipe) {
|
|
1597
|
-
if (!this.headRefinement) {
|
|
1598
|
-
return modelPipe;
|
|
1599
|
-
}
|
|
1600
|
-
const pipeline = [];
|
|
1601
|
-
if (modelPipe.pipeHead) {
|
|
1602
|
-
const { pipeline: turtlePipe } = this.expandTurtle(modelPipe.pipeHead.name, fs.structDef());
|
|
1603
|
-
pipeline.push(...turtlePipe);
|
|
1604
|
-
}
|
|
1605
|
-
pipeline.push(...modelPipe.pipeline);
|
|
1606
|
-
const firstSeg = pipeline[0];
|
|
1607
|
-
if (firstSeg) {
|
|
1608
|
-
this.headRefinement.refineFrom(firstSeg);
|
|
1609
|
-
}
|
|
1610
|
-
pipeline[0] = this.headRefinement.getOp(fs, this).segment;
|
|
1611
|
-
return { pipeline };
|
|
1612
|
-
}
|
|
1613
|
-
expandTurtle(turtleName, fromStruct) {
|
|
1614
|
-
const turtle = getStructFieldDef(fromStruct, turtleName);
|
|
1615
|
-
if (!turtle) {
|
|
1616
|
-
this.log(`Query '${turtleName}' is not defined in source`);
|
|
1617
|
-
}
|
|
1618
|
-
else if (turtle.type !== "turtle") {
|
|
1619
|
-
this.log(`'${turtleName}' is not a query`);
|
|
1620
|
-
}
|
|
1621
|
-
else {
|
|
1622
|
-
return { pipeline: turtle.pipeline, location: turtle.location };
|
|
1623
|
-
}
|
|
1624
|
-
return { pipeline: [], location: undefined };
|
|
1625
|
-
}
|
|
1626
|
-
getOutputStruct(walkStruct, pipeline) {
|
|
1627
|
-
for (const modelQop of pipeline) {
|
|
1628
|
-
walkStruct = opOutputStruct(this, walkStruct, modelQop);
|
|
1629
|
-
}
|
|
1630
|
-
return walkStruct;
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
class ExistingQuery extends PipelineDesc {
|
|
1634
|
-
set head(head) {
|
|
1635
|
-
this._head = head;
|
|
1636
|
-
this.has({ head });
|
|
1637
|
-
}
|
|
1638
|
-
get head() {
|
|
1639
|
-
return this._head;
|
|
1640
|
-
}
|
|
1641
|
-
queryComp() {
|
|
1642
|
-
if (!this.head) {
|
|
1643
|
-
throw this.internalError("can't make query from nameless query");
|
|
1644
|
-
}
|
|
1645
|
-
const queryEntry = this.modelEntry(this.head);
|
|
1646
|
-
const seedQuery = queryEntry === null || queryEntry === void 0 ? void 0 : queryEntry.entry;
|
|
1647
|
-
const oops = function () {
|
|
1648
|
-
return {
|
|
1649
|
-
outputStruct: ErrorFactory.structDef,
|
|
1650
|
-
query: ErrorFactory.query,
|
|
1651
|
-
};
|
|
1652
|
-
};
|
|
1653
|
-
if (!seedQuery) {
|
|
1654
|
-
this.log(`Reference to undefined query '${this.head}'`);
|
|
1655
|
-
return oops();
|
|
1656
|
-
}
|
|
1657
|
-
if (seedQuery.type !== "query") {
|
|
1658
|
-
this.log(`Illegal reference to '${this.head}', query expected`);
|
|
1659
|
-
return oops();
|
|
1660
|
-
}
|
|
1661
|
-
const queryHead = new QueryHeadStruct(seedQuery.structRef);
|
|
1662
|
-
this.has({ queryHead });
|
|
1663
|
-
const exploreStruct = queryHead.structDef();
|
|
1664
|
-
const exploreFS = new field_space_1.DynamicSpace(exploreStruct);
|
|
1665
|
-
const sourcePipe = this.refinePipeline(exploreFS, seedQuery);
|
|
1666
|
-
const walkStruct = this.getOutputStruct(exploreStruct, sourcePipe.pipeline);
|
|
1667
|
-
const appended = this.appendOps(sourcePipe.pipeline, new field_space_1.DynamicSpace(walkStruct));
|
|
1668
|
-
const destPipe = { ...sourcePipe, pipeline: appended.opList };
|
|
1669
|
-
const query = {
|
|
1670
|
-
type: "query",
|
|
1671
|
-
...destPipe,
|
|
1672
|
-
structRef: queryHead.structRef(),
|
|
1673
|
-
location: this.location,
|
|
1674
|
-
};
|
|
1675
|
-
return { outputStruct: appended.structDef, query };
|
|
1676
|
-
}
|
|
1677
|
-
query() {
|
|
1678
|
-
return this.queryComp().query;
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
exports.ExistingQuery = ExistingQuery;
|
|
1682
|
-
class TurtleHeadedPipe extends PipelineDesc {
|
|
1683
|
-
set turtleName(turtleName) {
|
|
1684
|
-
this._turtleName = turtleName;
|
|
1685
|
-
this.has({ turtleName });
|
|
1686
|
-
}
|
|
1687
|
-
get turtleName() {
|
|
1688
|
-
return this._turtleName;
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
exports.TurtleHeadedPipe = TurtleHeadedPipe;
|
|
1692
|
-
class FullQuery extends TurtleHeadedPipe {
|
|
1693
|
-
constructor(explore) {
|
|
1694
|
-
super({ explore });
|
|
1695
|
-
this.explore = explore;
|
|
1696
|
-
}
|
|
1697
|
-
queryComp() {
|
|
1698
|
-
const structRef = this.explore.structRef();
|
|
1699
|
-
const destQuery = {
|
|
1700
|
-
type: "query",
|
|
1701
|
-
structRef,
|
|
1702
|
-
pipeline: [],
|
|
1703
|
-
location: this.location,
|
|
1704
|
-
};
|
|
1705
|
-
const structDef = model.refIsStructDef(structRef)
|
|
1706
|
-
? structRef
|
|
1707
|
-
: this.explore.structDef();
|
|
1708
|
-
let pipeFs = new field_space_1.DynamicSpace(structDef);
|
|
1709
|
-
if (ErrorFactory.isErrorStructDef(structDef)) {
|
|
1710
|
-
return {
|
|
1711
|
-
outputStruct: structDef,
|
|
1712
|
-
query: {
|
|
1713
|
-
structRef: structRef,
|
|
1714
|
-
pipeline: [],
|
|
1715
|
-
},
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
|
-
if (this.turtleName) {
|
|
1719
|
-
const { error } = this.turtleName.getField(pipeFs);
|
|
1720
|
-
if (error)
|
|
1721
|
-
this.log(error);
|
|
1722
|
-
const name = this.turtleName.refString;
|
|
1723
|
-
const { pipeline, location } = this.expandTurtle(name, structDef);
|
|
1724
|
-
destQuery.location = location;
|
|
1725
|
-
const refined = this.refinePipeline(pipeFs, { pipeline }).pipeline;
|
|
1726
|
-
if (this.headRefinement) {
|
|
1727
|
-
// TODO there is an issue with losing the name of the turtle
|
|
1728
|
-
// which we need to fix, possibly adding a "name:" field to a segment
|
|
1729
|
-
// TODO there was mention of promoting filters to the query
|
|
1730
|
-
destQuery.pipeline = refined;
|
|
1731
|
-
}
|
|
1732
|
-
else {
|
|
1733
|
-
destQuery.pipeHead = { name };
|
|
1734
|
-
}
|
|
1735
|
-
const pipeStruct = this.getOutputStruct(structDef, refined);
|
|
1736
|
-
pipeFs = new field_space_1.DynamicSpace(pipeStruct);
|
|
1737
|
-
}
|
|
1738
|
-
const appended = this.appendOps(destQuery.pipeline, pipeFs);
|
|
1739
|
-
destQuery.pipeline = appended.opList;
|
|
1740
|
-
return { outputStruct: appended.structDef, query: destQuery };
|
|
1741
|
-
}
|
|
1742
|
-
query() {
|
|
1743
|
-
return this.queryComp().query;
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
exports.FullQuery = FullQuery;
|
|
1747
|
-
class TurtleDecl extends TurtleHeadedPipe {
|
|
1748
|
-
constructor(name) {
|
|
1749
|
-
super();
|
|
1750
|
-
this.name = name;
|
|
1751
|
-
}
|
|
1752
|
-
getPipeline(fs) {
|
|
1753
|
-
const modelPipe = { pipeline: [] };
|
|
1754
|
-
if (this.turtleName) {
|
|
1755
|
-
const headEnt = this.turtleName.getField(fs);
|
|
1756
|
-
let reportWrongType = true;
|
|
1757
|
-
if (headEnt.error) {
|
|
1758
|
-
this.log(headEnt.error);
|
|
1759
|
-
reportWrongType = false;
|
|
1760
|
-
}
|
|
1761
|
-
else if (headEnt.found instanceof space_field_1.QueryField) {
|
|
1762
|
-
const headDef = headEnt.found.getQueryFieldDef(fs);
|
|
1763
|
-
if (isTurtle(headDef)) {
|
|
1764
|
-
const newPipe = this.refinePipeline(fs, headDef);
|
|
1765
|
-
modelPipe.pipeline = [...newPipe.pipeline];
|
|
1766
|
-
reportWrongType = false;
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
if (reportWrongType) {
|
|
1770
|
-
this.log(`Expected '${this.turtleName}' to be a query`);
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
else if (this.headRefinement) {
|
|
1774
|
-
throw this.internalError("Can't refine the head of a turtle in its definition");
|
|
1775
|
-
}
|
|
1776
|
-
let appendInput = fs;
|
|
1777
|
-
if (modelPipe.pipeline.length > 0) {
|
|
1778
|
-
let endStruct = appendInput.structDef();
|
|
1779
|
-
for (const existingSeg of modelPipe.pipeline) {
|
|
1780
|
-
endStruct = opOutputStruct(this, endStruct, existingSeg);
|
|
1781
|
-
}
|
|
1782
|
-
appendInput = new field_space_1.DynamicSpace(endStruct);
|
|
1783
|
-
}
|
|
1784
|
-
const appended = this.appendOps(modelPipe.pipeline, appendInput);
|
|
1785
|
-
modelPipe.pipeline = appended.opList;
|
|
1786
|
-
return modelPipe;
|
|
1787
|
-
}
|
|
1788
|
-
getFieldDef(fs, nestParent) {
|
|
1789
|
-
if (nestParent) {
|
|
1790
|
-
this.nestedInQuerySpace = nestParent;
|
|
1791
|
-
}
|
|
1792
|
-
const pipe = this.getPipeline(fs);
|
|
1793
|
-
return {
|
|
1794
|
-
type: "turtle",
|
|
1795
|
-
name: this.name,
|
|
1796
|
-
...pipe,
|
|
1797
|
-
location: this.location,
|
|
1798
|
-
};
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
exports.TurtleDecl = TurtleDecl;
|
|
1802
|
-
class NestReference extends FieldReference {
|
|
1803
|
-
constructor(name) {
|
|
1804
|
-
super([name]);
|
|
1805
|
-
this.name = name;
|
|
1806
|
-
this.elementType = "nestReference";
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
exports.NestReference = NestReference;
|
|
1810
|
-
class NestRefinement extends TurtleDecl {
|
|
1811
|
-
constructor(turtleName) {
|
|
1812
|
-
super(turtleName.refString);
|
|
1813
|
-
this.elementType = "nestRefinement";
|
|
1814
|
-
this.turtleName = turtleName;
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
exports.NestRefinement = NestRefinement;
|
|
1818
|
-
class NestDefinition extends TurtleDecl {
|
|
1819
|
-
constructor(name) {
|
|
1820
|
-
super(name);
|
|
1821
|
-
this.elementType = "nestDefinition";
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
exports.NestDefinition = NestDefinition;
|
|
1825
|
-
function isNestedQuery(me) {
|
|
1826
|
-
return (me instanceof NestRefinement ||
|
|
1827
|
-
me instanceof NestReference ||
|
|
1828
|
-
me instanceof NestDefinition);
|
|
1829
|
-
}
|
|
1830
|
-
exports.isNestedQuery = isNestedQuery;
|
|
1831
|
-
class Nests extends ListOf {
|
|
1832
|
-
constructor(nests) {
|
|
1833
|
-
super("nestedQueries", nests);
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
exports.Nests = Nests;
|
|
1837
|
-
function isQueryElement(e) {
|
|
1838
|
-
return e instanceof FullQuery || e instanceof ExistingQuery;
|
|
1839
|
-
}
|
|
1840
|
-
exports.isQueryElement = isQueryElement;
|
|
1841
|
-
class DefineQueryList extends ListOf {
|
|
1842
|
-
constructor(queryList) {
|
|
1843
|
-
super("defineQueries", queryList);
|
|
1844
|
-
this.has({ queryList });
|
|
1845
|
-
}
|
|
1846
|
-
execute(doc) {
|
|
1847
|
-
for (const dq of this.list) {
|
|
1848
|
-
dq.execute(doc);
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
exports.DefineQueryList = DefineQueryList;
|
|
1853
|
-
class DefineQuery extends MalloyElement {
|
|
1854
|
-
constructor(name, queryDetails) {
|
|
1855
|
-
super({ queryDetails });
|
|
1856
|
-
this.name = name;
|
|
1857
|
-
this.queryDetails = queryDetails;
|
|
1858
|
-
this.elementType = "defineQuery";
|
|
1859
|
-
}
|
|
1860
|
-
execute(doc) {
|
|
1861
|
-
const entry = {
|
|
1862
|
-
...this.queryDetails.query(),
|
|
1863
|
-
type: "query",
|
|
1864
|
-
name: this.name,
|
|
1865
|
-
location: this.location,
|
|
1866
|
-
};
|
|
1867
|
-
const exported = false;
|
|
1868
|
-
doc.setEntry(this.name, { entry, exported });
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
exports.DefineQuery = DefineQuery;
|
|
1872
|
-
class AnonymousQuery extends MalloyElement {
|
|
1873
|
-
constructor(theQuery) {
|
|
1874
|
-
super();
|
|
1875
|
-
this.theQuery = theQuery;
|
|
1876
|
-
this.elementType = "anonymousQuery";
|
|
1877
|
-
this.has({ query: theQuery });
|
|
1878
|
-
}
|
|
1879
|
-
execute(doc) {
|
|
1880
|
-
const modelQuery = this.theQuery.query();
|
|
1881
|
-
doc.queryList.push(modelQuery);
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
exports.AnonymousQuery = AnonymousQuery;
|
|
1885
|
-
class Top extends MalloyElement {
|
|
1886
|
-
constructor(limit, by) {
|
|
1887
|
-
super();
|
|
1888
|
-
this.limit = limit;
|
|
1889
|
-
this.by = by;
|
|
1890
|
-
this.elementType = "top";
|
|
1891
|
-
this.has({ by });
|
|
1892
|
-
}
|
|
1893
|
-
getBy(fs) {
|
|
1894
|
-
if (this.by) {
|
|
1895
|
-
if (this.by instanceof FieldName) {
|
|
1896
|
-
// TODO jump-to-definition `fs` cannot currently `lookup` fields in the output space
|
|
1897
|
-
// const entry = this.by.getField(fs);
|
|
1898
|
-
// if (entry.error) {
|
|
1899
|
-
// this.by.log(entry.error);
|
|
1900
|
-
// }
|
|
1901
|
-
return { by: "name", name: this.by.refString };
|
|
1902
|
-
}
|
|
1903
|
-
else {
|
|
1904
|
-
const byExpr = this.by.getExpression(fs);
|
|
1905
|
-
if (!byExpr.aggregate) {
|
|
1906
|
-
this.log("top by expression must be an aggregate");
|
|
1907
|
-
}
|
|
1908
|
-
return { by: "expression", e: (0, index_1.compressExpr)(byExpr.value) };
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
return undefined;
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
exports.Top = Top;
|
|
1915
|
-
class JSONElement extends MalloyElement {
|
|
1916
|
-
constructor(jsonSrc) {
|
|
1917
|
-
super();
|
|
1918
|
-
this.elementType = "jsonElement";
|
|
1919
|
-
try {
|
|
1920
|
-
this.value = JSON.parse(jsonSrc);
|
|
1921
|
-
}
|
|
1922
|
-
catch (SyntaxError) {
|
|
1923
|
-
this.log("JSON syntax error");
|
|
1924
|
-
this.value = undefined;
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
exports.JSONElement = JSONElement;
|
|
1929
|
-
class JSONStructDef extends Mallobj {
|
|
1930
|
-
constructor(struct) {
|
|
1931
|
-
super();
|
|
1932
|
-
this.struct = struct;
|
|
1933
|
-
this.elementType = "jsonStructDef";
|
|
1934
|
-
}
|
|
1935
|
-
static fromJSON(jsonObj) {
|
|
1936
|
-
const obj = jsonObj.value;
|
|
1937
|
-
if (obj &&
|
|
1938
|
-
obj.type === "struct" &&
|
|
1939
|
-
obj.structRelationship &&
|
|
1940
|
-
obj.structSource) {
|
|
1941
|
-
return new JSONStructDef(obj);
|
|
1942
|
-
}
|
|
1943
|
-
return undefined;
|
|
1944
|
-
}
|
|
1945
|
-
structDef() {
|
|
1946
|
-
return this.struct;
|
|
1947
|
-
}
|
|
1948
|
-
}
|
|
1949
|
-
exports.JSONStructDef = JSONStructDef;
|
|
1950
|
-
class ImportStatement extends MalloyElement {
|
|
1951
|
-
/*
|
|
1952
|
-
* At the time of writng this comment, it is guaranteed that if an AST
|
|
1953
|
-
* node for an import statement is created, the translator has already
|
|
1954
|
-
* succesfully fetched the URL referred to in the statement.
|
|
1955
|
-
*
|
|
1956
|
-
* Error checking code in here is future proofing against a day when
|
|
1957
|
-
* there are other ways to contruct an AST.
|
|
1958
|
-
*/
|
|
1959
|
-
constructor(url, baseURL) {
|
|
1960
|
-
super();
|
|
1961
|
-
this.url = url;
|
|
1962
|
-
this.elementType = "import statement";
|
|
1963
|
-
try {
|
|
1964
|
-
this.fullURL = decodeURI(new URL(url, baseURL).toString());
|
|
1965
|
-
}
|
|
1966
|
-
catch (e) {
|
|
1967
|
-
this.log("Invalid URI in import statement");
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
execute(doc) {
|
|
1971
|
-
const trans = this.translator();
|
|
1972
|
-
if (!trans) {
|
|
1973
|
-
this.log("Cannot import without translation context");
|
|
1974
|
-
}
|
|
1975
|
-
else if (this.fullURL) {
|
|
1976
|
-
const src = trans.root.importZone.getEntry(this.fullURL);
|
|
1977
|
-
if (src.status === "present") {
|
|
1978
|
-
const importStructs = trans.getChildExports(this.fullURL);
|
|
1979
|
-
for (const importing in importStructs) {
|
|
1980
|
-
doc.setEntry(importing, {
|
|
1981
|
-
entry: importStructs[importing],
|
|
1982
|
-
exported: false,
|
|
1983
|
-
});
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
else if (src.status === "error") {
|
|
1987
|
-
this.log(`import failed: '${src.message}'`);
|
|
1988
|
-
}
|
|
1989
|
-
else {
|
|
1990
|
-
this.log(`import failed with status: '${src.status}'`);
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
exports.ImportStatement = ImportStatement;
|
|
1996
|
-
class HasParameter extends MalloyElement {
|
|
1997
|
-
constructor(init) {
|
|
1998
|
-
super();
|
|
1999
|
-
this.elementType = "hasParameter";
|
|
2000
|
-
this.name = init.name;
|
|
2001
|
-
this.isCondition = init.isCondition;
|
|
2002
|
-
if (init.type && model.isAtomicFieldType(init.type)) {
|
|
2003
|
-
this.type = init.type;
|
|
2004
|
-
}
|
|
2005
|
-
if (init.default) {
|
|
2006
|
-
this.default = init.default;
|
|
2007
|
-
this.has({ default: this.default });
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
parameter() {
|
|
2011
|
-
var _a, _b;
|
|
2012
|
-
const name = this.name;
|
|
2013
|
-
const type = this.type || "string";
|
|
2014
|
-
if (this.isCondition) {
|
|
2015
|
-
const cCond = ((_a = this.default) === null || _a === void 0 ? void 0 : _a.constantCondition(type).value) || null;
|
|
2016
|
-
return {
|
|
2017
|
-
type,
|
|
2018
|
-
name,
|
|
2019
|
-
condition: cCond,
|
|
2020
|
-
};
|
|
2021
|
-
}
|
|
2022
|
-
const cVal = ((_b = this.default) === null || _b === void 0 ? void 0 : _b.constantValue().value) || null;
|
|
2023
|
-
return {
|
|
2024
|
-
value: cVal,
|
|
2025
|
-
type,
|
|
2026
|
-
name: this.name,
|
|
2027
|
-
constant: false,
|
|
2028
|
-
};
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
exports.HasParameter = HasParameter;
|
|
2032
|
-
class ConstantParameter extends HasParameter {
|
|
2033
|
-
constructor(name, value) {
|
|
2034
|
-
super({ name, isCondition: false });
|
|
2035
|
-
this.value = value;
|
|
2036
|
-
this.has({ value });
|
|
2037
|
-
}
|
|
2038
|
-
parameter() {
|
|
2039
|
-
const cVal = this.value.constantValue();
|
|
2040
|
-
if (!model.isAtomicFieldType(cVal.dataType)) {
|
|
2041
|
-
this.log(`Unexpected expression type '${cVal.dataType}'`);
|
|
2042
|
-
return {
|
|
2043
|
-
value: ["XXX-type-mismatch-error-XXX"],
|
|
2044
|
-
type: "string",
|
|
2045
|
-
name: this.name,
|
|
2046
|
-
constant: true,
|
|
2047
|
-
};
|
|
2048
|
-
}
|
|
2049
|
-
return {
|
|
2050
|
-
value: cVal.value,
|
|
2051
|
-
type: cVal.dataType,
|
|
2052
|
-
name: this.name,
|
|
2053
|
-
constant: true,
|
|
2054
|
-
};
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
exports.ConstantParameter = ConstantParameter;
|
|
2058
|
-
class SQLStatement extends MalloyElement {
|
|
2059
|
-
constructor(blockReq) {
|
|
2060
|
-
super();
|
|
2061
|
-
this.blockReq = blockReq;
|
|
2062
|
-
this.elementType = "sqlStatement";
|
|
2063
|
-
}
|
|
2064
|
-
sqlBlock() {
|
|
2065
|
-
const sqlBlock = (0, sql_block_1.makeSQLBlock)(this.blockReq);
|
|
2066
|
-
sqlBlock.location = this.location;
|
|
2067
|
-
return sqlBlock;
|
|
2068
|
-
}
|
|
2069
|
-
execute(doc) {
|
|
2070
|
-
if (!doc.defineSQL(this.sqlBlock(), this.is)) {
|
|
2071
|
-
this.log(`${this.is} already defined`);
|
|
2072
|
-
}
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
exports.SQLStatement = SQLStatement;
|
|
2076
|
-
class SampleProperty extends MalloyElement {
|
|
2077
|
-
constructor(sample) {
|
|
2078
|
-
super();
|
|
2079
|
-
this.sample = sample;
|
|
2080
|
-
this.elementType = "sampleProperty";
|
|
2081
|
-
}
|
|
2082
|
-
sampling() {
|
|
2083
|
-
return this.sample;
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
exports.SampleProperty = SampleProperty;
|
|
2087
|
-
//# sourceMappingURL=ast-main.js.map
|