@malloydata/malloy 0.0.1
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/README.md +39 -0
- package/dist/connection_utils.d.ts +1 -0
- package/dist/connection_utils.js +56 -0
- package/dist/dialect/dialect-map.d.ts +3 -0
- package/dist/dialect/dialect-map.js +33 -0
- package/dist/dialect/dialect.d.ts +64 -0
- package/dist/dialect/dialect.js +64 -0
- package/dist/dialect/dialect_map.d.ts +3 -0
- package/dist/dialect/dialect_map.js +35 -0
- package/dist/dialect/duckdb.d.ts +49 -0
- package/dist/dialect/duckdb.js +349 -0
- package/dist/dialect/index.d.ts +6 -0
- package/dist/dialect/index.js +27 -0
- package/dist/dialect/postgres.d.ts +49 -0
- package/dist/dialect/postgres.js +308 -0
- package/dist/dialect/standardsql.d.ts +46 -0
- package/dist/dialect/standardsql.js +361 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +47 -0
- package/dist/lang/ast/apply-expr.d.ts +16 -0
- package/dist/lang/ast/apply-expr.js +215 -0
- package/dist/lang/ast/ast-expr.d.ts +291 -0
- package/dist/lang/ast/ast-expr.js +1056 -0
- package/dist/lang/ast/ast-main.d.ts +480 -0
- package/dist/lang/ast/ast-main.js +2096 -0
- package/dist/lang/ast/ast-time-expr.d.ts +109 -0
- package/dist/lang/ast/ast-time-expr.js +550 -0
- package/dist/lang/ast/ast-types.d.ts +83 -0
- package/dist/lang/ast/ast-types.js +215 -0
- package/dist/lang/ast/index.d.ts +5 -0
- package/dist/lang/ast/index.js +34 -0
- package/dist/lang/ast/time-utils.d.ts +8 -0
- package/dist/lang/ast/time-utils.js +83 -0
- package/dist/lang/field-space.d.ts +157 -0
- package/dist/lang/field-space.js +651 -0
- package/dist/lang/field-utils.d.ts +5 -0
- package/dist/lang/field-utils.js +33 -0
- package/dist/lang/index.d.ts +9 -0
- package/dist/lang/index.js +22 -0
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +156 -0
- package/dist/lang/lib/Malloy/MalloyLexer.js +1163 -0
- package/dist/lang/lib/Malloy/MalloyListener.d.ts +2026 -0
- package/dist/lang/lib/Malloy/MalloyListener.js +4 -0
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +1920 -0
- package/dist/lang/lib/Malloy/MalloyParser.js +11790 -0
- package/dist/lang/lib/Malloy/MalloyVisitor.d.ts +1276 -0
- package/dist/lang/lib/Malloy/MalloyVisitor.js +4 -0
- package/dist/lang/parse-log.d.ts +27 -0
- package/dist/lang/parse-log.js +41 -0
- package/dist/lang/parse-malloy.d.ts +245 -0
- package/dist/lang/parse-malloy.js +729 -0
- package/dist/lang/parse-to-ast.d.ts +156 -0
- package/dist/lang/parse-to-ast.js +945 -0
- package/dist/lang/parse-tree-walkers/document-completion-walker.d.ts +10 -0
- package/dist/lang/parse-tree-walkers/document-completion-walker.js +136 -0
- package/dist/lang/parse-tree-walkers/document-help-context-walker.d.ts +9 -0
- package/dist/lang/parse-tree-walkers/document-help-context-walker.js +97 -0
- package/dist/lang/parse-tree-walkers/document-highlight-walker.d.ts +83 -0
- package/dist/lang/parse-tree-walkers/document-highlight-walker.js +375 -0
- package/dist/lang/parse-tree-walkers/document-symbol-walker.d.ts +11 -0
- package/dist/lang/parse-tree-walkers/document-symbol-walker.js +172 -0
- package/dist/lang/parse-tree-walkers/explore-query-walker.d.ts +34 -0
- package/dist/lang/parse-tree-walkers/explore-query-walker.js +64 -0
- package/dist/lang/parse-tree-walkers/find-external-references.d.ts +11 -0
- package/dist/lang/parse-tree-walkers/find-external-references.js +51 -0
- package/dist/lang/reference-list.d.ts +10 -0
- package/dist/lang/reference-list.js +80 -0
- package/dist/lang/space-field.d.ts +119 -0
- package/dist/lang/space-field.js +339 -0
- package/dist/lang/test/document-help-context-walker.spec.d.ts +1 -0
- package/dist/lang/test/document-help-context-walker.spec.js +45 -0
- package/dist/lang/test/document-symbol-walker.spec.d.ts +1 -0
- package/dist/lang/test/document-symbol-walker.spec.js +100 -0
- package/dist/lang/test/field-symbols.spec.d.ts +1 -0
- package/dist/lang/test/field-symbols.spec.js +172 -0
- package/dist/lang/test/parse.spec.d.ts +12 -0
- package/dist/lang/test/parse.spec.js +1936 -0
- package/dist/lang/test/test-translator.d.ts +38 -0
- package/dist/lang/test/test-translator.js +334 -0
- package/dist/lang/zone.d.ts +57 -0
- package/dist/lang/zone.js +97 -0
- package/dist/malloy.d.ts +1134 -0
- package/dist/malloy.js +2354 -0
- package/dist/model/index.d.ts +2 -0
- package/dist/model/index.js +34 -0
- package/dist/model/malloy-query.d.ts +313 -0
- package/dist/model/malloy-query.js +2603 -0
- package/dist/model/malloy-types.d.ts +404 -0
- package/dist/model/malloy-types.js +242 -0
- package/dist/model/malloy_query.d.ts +353 -0
- package/dist/model/malloy_query.js +2990 -0
- package/dist/model/malloy_types.d.ts +502 -0
- package/dist/model/malloy_types.js +283 -0
- package/dist/model/sql-block.d.ts +11 -0
- package/dist/model/sql-block.js +38 -0
- package/dist/model/sql_block.d.ts +11 -0
- package/dist/model/sql_block.js +41 -0
- package/dist/model/utils.d.ts +21 -0
- package/dist/model/utils.js +84 -0
- package/dist/runtime-types.d.ts +116 -0
- package/dist/runtime-types.js +40 -0
- package/dist/runtime_types.d.ts +119 -0
- package/dist/runtime_types.js +15 -0
- package/package.json +36 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2021 Google LLC
|
|
4
|
+
*
|
|
5
|
+
* This program is free software; you can redistribute it and/or
|
|
6
|
+
* modify it under the terms of the GNU General Public License
|
|
7
|
+
* version 2 as published by the Free Software Foundation.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU General Public License for more details.
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.fsPair = exports.DefSpace = exports.IndexFieldSpace = exports.ProjectFieldSpace = exports.ReduceFieldSpace = exports.QuerySpace = exports.QueryOperationSpace = exports.DynamicSpace = exports.StaticSpace = void 0;
|
|
39
|
+
/* eslint-disable no-useless-constructor */
|
|
40
|
+
const lodash_1 = require("lodash");
|
|
41
|
+
const dialect_1 = require("../dialect");
|
|
42
|
+
const model = __importStar(require("../model/malloy_types"));
|
|
43
|
+
const ast_1 = require("./ast");
|
|
44
|
+
const space_field_1 = require("./space-field");
|
|
45
|
+
const field_utils_1 = require("./field-utils");
|
|
46
|
+
/**
|
|
47
|
+
* The father of all FieldSpaces is a wrapper for a StructDef.
|
|
48
|
+
*/
|
|
49
|
+
class StaticSpace {
|
|
50
|
+
constructor(sourceStructDef) {
|
|
51
|
+
this.type = "fieldSpace";
|
|
52
|
+
this.fromStruct = sourceStructDef;
|
|
53
|
+
}
|
|
54
|
+
whenComplete(step) {
|
|
55
|
+
step();
|
|
56
|
+
}
|
|
57
|
+
getDialect() {
|
|
58
|
+
return (0, dialect_1.getDialect)(this.fromStruct.dialect);
|
|
59
|
+
}
|
|
60
|
+
fromFieldDef(from) {
|
|
61
|
+
if (from.type === "struct") {
|
|
62
|
+
return new space_field_1.StructSpaceField(from);
|
|
63
|
+
}
|
|
64
|
+
else if (model.isTurtleDef(from)) {
|
|
65
|
+
return new space_field_1.QueryFieldStruct(this, from);
|
|
66
|
+
}
|
|
67
|
+
// TODO field has a filter and needs to be a filteredalias
|
|
68
|
+
return new space_field_1.ColumnSpaceField(from);
|
|
69
|
+
}
|
|
70
|
+
get map() {
|
|
71
|
+
if (this.memoMap === undefined) {
|
|
72
|
+
this.memoMap = {};
|
|
73
|
+
for (const f of this.fromStruct.fields) {
|
|
74
|
+
const name = f.as || f.name;
|
|
75
|
+
this.memoMap[name] = this.fromFieldDef(f);
|
|
76
|
+
}
|
|
77
|
+
if (this.fromStruct.parameters) {
|
|
78
|
+
for (const [paramName, paramDef] of Object.entries(this.fromStruct.parameters)) {
|
|
79
|
+
if (this.memoMap[paramName]) {
|
|
80
|
+
throw new Error(`In struct '${this.fromStruct.as || this.fromStruct.name}': ` +
|
|
81
|
+
` : Field and parameter name conflict '${paramName}`);
|
|
82
|
+
}
|
|
83
|
+
this.memoMap[paramName] = new space_field_1.DefinedParameter(paramDef);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return this.memoMap;
|
|
88
|
+
}
|
|
89
|
+
dropEntries() {
|
|
90
|
+
this.memoMap = {};
|
|
91
|
+
}
|
|
92
|
+
dropEntry(name) {
|
|
93
|
+
delete this.map[name];
|
|
94
|
+
}
|
|
95
|
+
entry(name) {
|
|
96
|
+
return this.map[name];
|
|
97
|
+
}
|
|
98
|
+
setEntry(name, value) {
|
|
99
|
+
this.map[name] = value;
|
|
100
|
+
}
|
|
101
|
+
entries() {
|
|
102
|
+
return Object.entries(this.map);
|
|
103
|
+
}
|
|
104
|
+
structDef() {
|
|
105
|
+
return this.fromStruct;
|
|
106
|
+
}
|
|
107
|
+
emptyStructDef() {
|
|
108
|
+
return { ...this.fromStruct, fields: [] };
|
|
109
|
+
}
|
|
110
|
+
lookup(path) {
|
|
111
|
+
const head = path[0];
|
|
112
|
+
const rest = path.slice(1);
|
|
113
|
+
const found = this.entry(head.refString);
|
|
114
|
+
if (!found) {
|
|
115
|
+
return { error: `'${head}' is not defined`, found };
|
|
116
|
+
}
|
|
117
|
+
if (found instanceof space_field_1.SpaceField) {
|
|
118
|
+
/*
|
|
119
|
+
* In the cleanup phase of query space construction, it may check
|
|
120
|
+
* the output space for ungrouping variables. However if an
|
|
121
|
+
* ungrouping variable is a measure, the field expression value
|
|
122
|
+
* needed to get the definition needs to be computed in the
|
|
123
|
+
* input space of the query. There is a test which failed which
|
|
124
|
+
* caused this code to be here, but this is really a bandaid.
|
|
125
|
+
*
|
|
126
|
+
* Some re-work of how to get the definition of a SpaceField
|
|
127
|
+
* no matter what it is contained in needs to be thought out.
|
|
128
|
+
*
|
|
129
|
+
* ... or this check would look at the finalized output of
|
|
130
|
+
* the namespace and not re-compile ...
|
|
131
|
+
*/
|
|
132
|
+
let definition = undefined;
|
|
133
|
+
if (this instanceof QuerySpace) {
|
|
134
|
+
const qfd = found.getQueryFieldDef(this.qfs());
|
|
135
|
+
if (qfd &&
|
|
136
|
+
typeof qfd != "string" &&
|
|
137
|
+
!model.isFilteredAliasedName(qfd)) {
|
|
138
|
+
definition = qfd;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
definition = found.fieldDef();
|
|
143
|
+
}
|
|
144
|
+
if (definition) {
|
|
145
|
+
head.addReference({
|
|
146
|
+
type: found instanceof space_field_1.StructSpaceField
|
|
147
|
+
? "joinReference"
|
|
148
|
+
: "fieldReference",
|
|
149
|
+
definition,
|
|
150
|
+
location: head.location,
|
|
151
|
+
text: head.refString,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (rest.length) {
|
|
156
|
+
if (found instanceof space_field_1.StructSpaceField) {
|
|
157
|
+
return found.fieldSpace.lookup(rest);
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
error: `'${head}' cannot contain a '${rest[0]}'`,
|
|
161
|
+
found: undefined,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { found, error: undefined };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.StaticSpace = StaticSpace;
|
|
168
|
+
function isFieldSpace(x) {
|
|
169
|
+
return x.type == "fieldSpace";
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Based on how things are constructed, the starting field space
|
|
173
|
+
* can either be another field space or an existing structdef.
|
|
174
|
+
* Using a SourceSpace allows a class to accept either one
|
|
175
|
+
* and use either version at some future time.
|
|
176
|
+
*/
|
|
177
|
+
class SourceSpace {
|
|
178
|
+
constructor(sourceSpec) {
|
|
179
|
+
this.sourceSpec = sourceSpec;
|
|
180
|
+
this.spaceSpec = sourceSpec;
|
|
181
|
+
}
|
|
182
|
+
get structDef() {
|
|
183
|
+
if (isFieldSpace(this.spaceSpec)) {
|
|
184
|
+
if (!this.asStruct) {
|
|
185
|
+
this.asStruct = this.spaceSpec.structDef();
|
|
186
|
+
}
|
|
187
|
+
return this.asStruct;
|
|
188
|
+
}
|
|
189
|
+
return this.spaceSpec;
|
|
190
|
+
}
|
|
191
|
+
get fieldSpace() {
|
|
192
|
+
if (isFieldSpace(this.spaceSpec)) {
|
|
193
|
+
return this.spaceSpec;
|
|
194
|
+
}
|
|
195
|
+
if (!this.asFS) {
|
|
196
|
+
this.asFS = new StaticSpace(this.spaceSpec);
|
|
197
|
+
}
|
|
198
|
+
return this.asFS;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* A FieldSpace which may undergo modification
|
|
203
|
+
*/
|
|
204
|
+
class DynamicSpace extends StaticSpace {
|
|
205
|
+
constructor(extending) {
|
|
206
|
+
const source = new SourceSpace(extending);
|
|
207
|
+
super((0, lodash_1.cloneDeep)(source.structDef));
|
|
208
|
+
this.completions = [];
|
|
209
|
+
this.complete = false;
|
|
210
|
+
this.final = undefined;
|
|
211
|
+
this.source = source;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Factory for DynamicSpace when there are accept/except edits
|
|
215
|
+
* @param from A structdef which seeds this space
|
|
216
|
+
* @param choose A accept/except edit of the "from" fields
|
|
217
|
+
*/
|
|
218
|
+
static filteredFrom(from, choose) {
|
|
219
|
+
const edited = new DynamicSpace(from);
|
|
220
|
+
if (choose) {
|
|
221
|
+
const names = choose.refs.list;
|
|
222
|
+
const oldMap = edited.entries();
|
|
223
|
+
edited.dropEntries();
|
|
224
|
+
for (const [symbol, value] of oldMap) {
|
|
225
|
+
const included = !!names.find((f) => f.refString === symbol);
|
|
226
|
+
const accepting = choose.edit === "accept";
|
|
227
|
+
if (included === accepting) {
|
|
228
|
+
edited.setEntry(symbol, value);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return edited;
|
|
233
|
+
}
|
|
234
|
+
whenComplete(finalizeStep) {
|
|
235
|
+
if (this.complete) {
|
|
236
|
+
finalizeStep();
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
this.completions.push(finalizeStep);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
isComplete() {
|
|
243
|
+
this.complete = true;
|
|
244
|
+
for (const step of this.completions) {
|
|
245
|
+
step();
|
|
246
|
+
}
|
|
247
|
+
this.completions = [];
|
|
248
|
+
}
|
|
249
|
+
setEntry(name, value) {
|
|
250
|
+
if (this.final) {
|
|
251
|
+
throw new Error("Space already final");
|
|
252
|
+
}
|
|
253
|
+
super.setEntry(name, value);
|
|
254
|
+
}
|
|
255
|
+
addParameters(params) {
|
|
256
|
+
for (const oneP of params) {
|
|
257
|
+
this.setEntry(oneP.name, new space_field_1.AbstractParameter(oneP));
|
|
258
|
+
}
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
newEntry(name, astEl, entry) {
|
|
262
|
+
if (this.entry(name)) {
|
|
263
|
+
astEl.log(`Cannot redefine '${name}'`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
this.setEntry(name, entry);
|
|
267
|
+
}
|
|
268
|
+
addField(...defs) {
|
|
269
|
+
for (const def of defs) {
|
|
270
|
+
// TODO express the "three fields kinds" in a typesafe way
|
|
271
|
+
// one of three kinds of fields are legal in an explore: expressions ...
|
|
272
|
+
const elseLog = def.log;
|
|
273
|
+
const elseType = def.elementType;
|
|
274
|
+
if (def instanceof ast_1.FieldDeclaration) {
|
|
275
|
+
const exprField = new space_field_1.ExpressionFieldFromAst(this, def);
|
|
276
|
+
this.newEntry(exprField.name, def, exprField);
|
|
277
|
+
// querry (turtle) fields
|
|
278
|
+
}
|
|
279
|
+
else if (def instanceof ast_1.TurtleDecl) {
|
|
280
|
+
const name = def.name;
|
|
281
|
+
this.newEntry(name, def, new space_field_1.QueryFieldAST(this, def, name));
|
|
282
|
+
}
|
|
283
|
+
else if (def instanceof ast_1.RenameField) {
|
|
284
|
+
if (def.oldName.refString === def.newName) {
|
|
285
|
+
def.log("Can't rename field to itself");
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const oldValue = def.oldName.getField(fsPair(this));
|
|
289
|
+
if (oldValue.found) {
|
|
290
|
+
if (oldValue.found instanceof space_field_1.SpaceField) {
|
|
291
|
+
this.setEntry(def.newName, new space_field_1.RenameSpaceField(oldValue.found, def.newName, def.location));
|
|
292
|
+
this.dropEntry(def.oldName.refString);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
def.log(`'${def.oldName}' cannot be renamed`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
def.log(`Can't rename '${def.oldName}', no such field`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (def instanceof ast_1.Join) {
|
|
303
|
+
this.newEntry(def.name.refString, def, new space_field_1.JoinSpaceField(this, def));
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
elseLog(`Internal error: Expected expression, query, or rename, got '${elseType}'`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
addFieldDef(fd) {
|
|
311
|
+
this.setEntry((0, field_utils_1.nameOf)(fd), this.fromFieldDef(fd));
|
|
312
|
+
}
|
|
313
|
+
structDef() {
|
|
314
|
+
const parameters = this.fromStruct.parameters || {};
|
|
315
|
+
if (this.final === undefined) {
|
|
316
|
+
this.final = {
|
|
317
|
+
...this.fromStruct,
|
|
318
|
+
fields: [],
|
|
319
|
+
};
|
|
320
|
+
// Need to process the entities in specific order
|
|
321
|
+
const fields = [];
|
|
322
|
+
const joins = [];
|
|
323
|
+
const turtles = [];
|
|
324
|
+
const fixupJoins = [];
|
|
325
|
+
for (const [name, spaceEntry] of this.entries()) {
|
|
326
|
+
if (spaceEntry instanceof space_field_1.StructSpaceField) {
|
|
327
|
+
joins.push([name, spaceEntry]);
|
|
328
|
+
}
|
|
329
|
+
else if (spaceEntry instanceof space_field_1.QueryField) {
|
|
330
|
+
turtles.push([name, spaceEntry]);
|
|
331
|
+
}
|
|
332
|
+
else if (spaceEntry instanceof space_field_1.SpaceField) {
|
|
333
|
+
fields.push([name, spaceEntry]);
|
|
334
|
+
}
|
|
335
|
+
else if (spaceEntry instanceof space_field_1.SpaceParam) {
|
|
336
|
+
parameters[name] = spaceEntry.parameter();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const reorderFields = [...fields, ...joins, ...turtles];
|
|
340
|
+
for (const [fieldName, field] of reorderFields) {
|
|
341
|
+
if (field instanceof space_field_1.JoinSpaceField) {
|
|
342
|
+
const joinStruct = field.join.structDef();
|
|
343
|
+
if (!ast_1.ErrorFactory.isErrorStructDef(joinStruct)) {
|
|
344
|
+
this.final.fields.push(joinStruct);
|
|
345
|
+
fixupJoins.push([field.join, joinStruct]);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const fieldDef = field.fieldDef();
|
|
350
|
+
if (fieldDef) {
|
|
351
|
+
this.final.fields.push(fieldDef);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
throw new Error(`'${fieldName}' doesn't have a FieldDef`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (Object.entries(parameters).length > 0) {
|
|
359
|
+
this.final.parameters = parameters;
|
|
360
|
+
}
|
|
361
|
+
// If we have join expressions, we need to now go back and fill them in
|
|
362
|
+
for (const [join, missingOn] of fixupJoins) {
|
|
363
|
+
join.fixupJoinOn(fsPair(this), missingOn);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
this.isComplete();
|
|
367
|
+
return this.final;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
exports.DynamicSpace = DynamicSpace;
|
|
371
|
+
/**
|
|
372
|
+
* A namespace for Query operations. The have an input and an
|
|
373
|
+
* output set of fields.
|
|
374
|
+
*/
|
|
375
|
+
class QueryOperationSpace extends DynamicSpace {
|
|
376
|
+
constructor(input) {
|
|
377
|
+
const inputSpace = new SourceSpace(input);
|
|
378
|
+
super({ ...inputSpace.structDef, fields: [] });
|
|
379
|
+
this.queryInput = inputSpace;
|
|
380
|
+
}
|
|
381
|
+
inputFS() {
|
|
382
|
+
return this.queryInput.fieldSpace;
|
|
383
|
+
}
|
|
384
|
+
structDef() {
|
|
385
|
+
// Actually since we have the input structdef and the fields, this feels
|
|
386
|
+
// like it could return the output structdef of the query op ... except
|
|
387
|
+
// the pipeline code merges refinements in before asking for the output
|
|
388
|
+
// struct, and that would require a call back here somehow to get the
|
|
389
|
+
// pre-refinement fields ... I think possibly this is always a
|
|
390
|
+
// runtime error
|
|
391
|
+
throw new Error("StructDef requested from QueryOperationSpace");
|
|
392
|
+
}
|
|
393
|
+
addMembers(members) {
|
|
394
|
+
for (const member of members) {
|
|
395
|
+
if (member instanceof ast_1.FieldReference) {
|
|
396
|
+
this.addReference(member);
|
|
397
|
+
}
|
|
398
|
+
else if (member instanceof ast_1.WildcardFieldReference) {
|
|
399
|
+
this.addWild(member);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
this.addField(member);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
addReference(ref) {
|
|
407
|
+
const refName = ref.outputName;
|
|
408
|
+
if (this.entry(refName)) {
|
|
409
|
+
ref.log(`Output already has a field named '${refName}'`);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
this.setEntry(refName, new space_field_1.ReferenceField(ref));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
addWild(wild) {
|
|
416
|
+
this.setEntry(wild.refString, new space_field_1.WildSpaceField(wild.refString));
|
|
417
|
+
}
|
|
418
|
+
log(s) {
|
|
419
|
+
if (this.astEl) {
|
|
420
|
+
this.astEl.log(s);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
exports.QueryOperationSpace = QueryOperationSpace;
|
|
425
|
+
/**
|
|
426
|
+
* Reduce and project queries use a "QuerySpace"
|
|
427
|
+
*/
|
|
428
|
+
class QuerySpace extends QueryOperationSpace {
|
|
429
|
+
constructor() {
|
|
430
|
+
super(...arguments);
|
|
431
|
+
this.extendedFields = [];
|
|
432
|
+
}
|
|
433
|
+
extendSource(extendField) {
|
|
434
|
+
this.extendedFields.push(extendField instanceof ast_1.Join
|
|
435
|
+
? extendField.name.refString
|
|
436
|
+
: extendField.defineName);
|
|
437
|
+
this.extendInto().addField(extendField);
|
|
438
|
+
}
|
|
439
|
+
inputFS() {
|
|
440
|
+
if (this.extendedInput) {
|
|
441
|
+
return this.extendedInput;
|
|
442
|
+
}
|
|
443
|
+
return this.queryInput.fieldSpace;
|
|
444
|
+
}
|
|
445
|
+
qfs() {
|
|
446
|
+
return {
|
|
447
|
+
in: this.inputFS(),
|
|
448
|
+
out: this,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
checkUngroup(fn, isExclude) {
|
|
452
|
+
if (this.lookup([fn]).error) {
|
|
453
|
+
if (isExclude && this.nestParent) {
|
|
454
|
+
const parent = this.nestParent;
|
|
455
|
+
parent.whenComplete(() => {
|
|
456
|
+
parent.checkUngroup(fn, isExclude);
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
const uName = isExclude ? "exclude()" : "all()";
|
|
461
|
+
fn.log(`${uName} '${fn.refString}' is missing from query output`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
extendInto() {
|
|
466
|
+
if (!this.extendedInput) {
|
|
467
|
+
this.extendedInput = new DynamicSpace(this.queryInput.sourceSpec);
|
|
468
|
+
}
|
|
469
|
+
return this.extendedInput;
|
|
470
|
+
}
|
|
471
|
+
getPipeSegment(refineFrom) {
|
|
472
|
+
const reduceOrProject = this.segType;
|
|
473
|
+
if (reduceOrProject === "index") {
|
|
474
|
+
throw new Error("IndexSegment getPipeSegment should not call super");
|
|
475
|
+
}
|
|
476
|
+
if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
|
|
477
|
+
for (const xField of refineFrom.extendSource) {
|
|
478
|
+
this.extendInto().addFieldDef(xField);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const segment = {
|
|
482
|
+
type: reduceOrProject,
|
|
483
|
+
fields: this.queryFieldDefs(),
|
|
484
|
+
};
|
|
485
|
+
segment.fields = (0, field_utils_1.mergeFields)(refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.fields, segment.fields);
|
|
486
|
+
if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
|
|
487
|
+
segment.extendSource = refineFrom.extendSource;
|
|
488
|
+
}
|
|
489
|
+
if (this.extendedInput) {
|
|
490
|
+
const newExtends = [];
|
|
491
|
+
// have to get the whole structdef because we need all the join
|
|
492
|
+
// resolution to happen and that only happens at the completion
|
|
493
|
+
// of the structdef generation.
|
|
494
|
+
const extendedStruct = this.extendedInput.structDef();
|
|
495
|
+
for (const extendName of this.extendedFields) {
|
|
496
|
+
const extendEnt = extendedStruct.fields.find((f) => (0, field_utils_1.nameOf)(f) == extendName);
|
|
497
|
+
if (extendEnt) {
|
|
498
|
+
newExtends.push(extendEnt);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
segment.extendSource = (0, field_utils_1.mergeFields)(segment.extendSource, newExtends);
|
|
502
|
+
}
|
|
503
|
+
return segment;
|
|
504
|
+
}
|
|
505
|
+
addQueryItems(...qiList) {
|
|
506
|
+
for (const qi of qiList) {
|
|
507
|
+
if (qi instanceof ast_1.FieldReference || qi instanceof ast_1.NestReference) {
|
|
508
|
+
this.addReference(qi);
|
|
509
|
+
}
|
|
510
|
+
else if (qi instanceof ast_1.FieldDeclaration) {
|
|
511
|
+
this.addField(qi);
|
|
512
|
+
}
|
|
513
|
+
else if ((0, ast_1.isNestedQuery)(qi)) {
|
|
514
|
+
const qf = new space_field_1.QueryFieldAST(this.inputFS(), qi, qi.name);
|
|
515
|
+
qf.nestParent = this;
|
|
516
|
+
this.setEntry(qi.name, qf);
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
// Compiler will error if we don't handle all cases
|
|
520
|
+
const _itemNotHandled = qi;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
canContain(_qd) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
queryFieldDefs() {
|
|
528
|
+
const fields = [];
|
|
529
|
+
for (const [name, field] of this.entries()) {
|
|
530
|
+
if (field instanceof space_field_1.SpaceField) {
|
|
531
|
+
const fieldQueryDef = field.getQueryFieldDef(this.qfs());
|
|
532
|
+
if (fieldQueryDef) {
|
|
533
|
+
if (this.canContain(fieldQueryDef)) {
|
|
534
|
+
fields.push(fieldQueryDef);
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
this.log(`'${name}' not legal in ${this.segType}`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
throw new Error(`'${name}' does not have a QueryFieldDef`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
this.isComplete();
|
|
546
|
+
return fields;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
exports.QuerySpace = QuerySpace;
|
|
550
|
+
class ReduceFieldSpace extends QuerySpace {
|
|
551
|
+
constructor() {
|
|
552
|
+
super(...arguments);
|
|
553
|
+
this.segType = "reduce";
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
exports.ReduceFieldSpace = ReduceFieldSpace;
|
|
557
|
+
class ProjectFieldSpace extends QuerySpace {
|
|
558
|
+
constructor() {
|
|
559
|
+
super(...arguments);
|
|
560
|
+
this.segType = "project";
|
|
561
|
+
}
|
|
562
|
+
canContain(qd) {
|
|
563
|
+
if (typeof qd !== "string") {
|
|
564
|
+
if (model.isFilteredAliasedName(qd)) {
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
if (qd.type === "turtle") {
|
|
568
|
+
this.log("Cannot nest queries in project");
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
if (qd.aggregate) {
|
|
572
|
+
this.log("Cannot add aggregate measures to project");
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
exports.ProjectFieldSpace = ProjectFieldSpace;
|
|
580
|
+
class IndexFieldSpace extends QueryOperationSpace {
|
|
581
|
+
constructor() {
|
|
582
|
+
super(...arguments);
|
|
583
|
+
this.segType = "index";
|
|
584
|
+
this.fieldList = new Set();
|
|
585
|
+
}
|
|
586
|
+
addReference(ref) {
|
|
587
|
+
if (ref.getField(this.inputFS()).found) {
|
|
588
|
+
this.fieldList.add(ref.refString);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
addWild(wild) {
|
|
592
|
+
this.fieldList.add(wild.refString);
|
|
593
|
+
}
|
|
594
|
+
getPipeSegment(refineIndex) {
|
|
595
|
+
if (refineIndex && refineIndex.fields) {
|
|
596
|
+
for (const exists of refineIndex.fields) {
|
|
597
|
+
if (typeof exists == "string") {
|
|
598
|
+
this.fieldList.add(exists);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
this.isComplete();
|
|
603
|
+
return {
|
|
604
|
+
type: "index",
|
|
605
|
+
fields: Array.from(this.fieldList.values()),
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
exports.IndexFieldSpace = IndexFieldSpace;
|
|
610
|
+
/**
|
|
611
|
+
* Used to detect references to fields in the statement which defines them
|
|
612
|
+
*/
|
|
613
|
+
class DefSpace {
|
|
614
|
+
constructor(realFS, circular) {
|
|
615
|
+
this.realFS = realFS;
|
|
616
|
+
this.circular = circular;
|
|
617
|
+
this.type = "fieldSpace";
|
|
618
|
+
this.foundCircle = false;
|
|
619
|
+
}
|
|
620
|
+
structDef() {
|
|
621
|
+
return this.realFS.structDef();
|
|
622
|
+
}
|
|
623
|
+
emptyStructDef() {
|
|
624
|
+
return this.realFS.emptyStructDef();
|
|
625
|
+
}
|
|
626
|
+
lookup(symbol) {
|
|
627
|
+
if (symbol[0] && symbol[0].refString === this.circular.defineName) {
|
|
628
|
+
this.foundCircle = true;
|
|
629
|
+
return {
|
|
630
|
+
error: `Circular reference to '${this.circular.defineName}' in definition`,
|
|
631
|
+
found: undefined,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
return this.realFS.lookup(symbol);
|
|
635
|
+
}
|
|
636
|
+
getDialect() {
|
|
637
|
+
return this.realFS.getDialect();
|
|
638
|
+
}
|
|
639
|
+
whenComplete(step) {
|
|
640
|
+
this.realFS.whenComplete(step);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
exports.DefSpace = DefSpace;
|
|
644
|
+
function fsPair(inFS, outFS) {
|
|
645
|
+
return {
|
|
646
|
+
in: inFS,
|
|
647
|
+
out: outFS || inFS,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
exports.fsPair = fsPair;
|
|
651
|
+
//# sourceMappingURL=field-space.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { QueryFieldDef, FieldDef } from "../model/malloy_types";
|
|
2
|
+
declare type Field = QueryFieldDef | FieldDef;
|
|
3
|
+
export declare function nameOf(qfd: Field): string;
|
|
4
|
+
export declare function mergeFields<T extends Field>(older: T[] | undefined, newer: T[]): T[];
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2021 Google LLC
|
|
4
|
+
*
|
|
5
|
+
* This program is free software; you can redistribute it and/or
|
|
6
|
+
* modify it under the terms of the GNU General Public License
|
|
7
|
+
* version 2 as published by the Free Software Foundation.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU General Public License for more details.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.mergeFields = exports.nameOf = void 0;
|
|
16
|
+
function nameOf(qfd) {
|
|
17
|
+
if (typeof qfd == "string") {
|
|
18
|
+
return qfd;
|
|
19
|
+
}
|
|
20
|
+
return qfd.as || qfd.name;
|
|
21
|
+
}
|
|
22
|
+
exports.nameOf = nameOf;
|
|
23
|
+
function mergeFields(older, newer) {
|
|
24
|
+
if (older == undefined) {
|
|
25
|
+
return newer;
|
|
26
|
+
}
|
|
27
|
+
const redefined = new Set(newer.map((f) => nameOf(f)));
|
|
28
|
+
const merged = older.filter((f) => !redefined.has(nameOf(f)));
|
|
29
|
+
merged.push(...newer);
|
|
30
|
+
return merged;
|
|
31
|
+
}
|
|
32
|
+
exports.mergeFields = mergeFields;
|
|
33
|
+
//# sourceMappingURL=field-utils.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { MalloyTranslator } from "./parse-malloy";
|
|
2
|
+
export type { TranslateResponse, UpdateData, SchemaData, URLData, SQLStructData, } from "./parse-malloy";
|
|
3
|
+
export { exploreQueryWalkerBuilder } from "./parse-tree-walkers/explore-query-walker";
|
|
4
|
+
export type { ExploreClauseRef } from "./parse-tree-walkers/explore-query-walker";
|
|
5
|
+
export { HighlightType } from "./parse-tree-walkers/document-highlight-walker";
|
|
6
|
+
export type { DocumentHighlight } from "./parse-tree-walkers/document-highlight-walker";
|
|
7
|
+
export type { DocumentSymbol } from "./parse-tree-walkers/document-symbol-walker";
|
|
8
|
+
export type { DocumentCompletion } from "./parse-tree-walkers/document-completion-walker";
|
|
9
|
+
export type { LogMessage } from "./parse-log";
|