@malloydata/malloy 0.0.22-dev230119001546 → 0.0.22-dev230119193053

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.
@@ -1,641 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2023 Google LLC
4
- *
5
- * Permission is hereby granted, free of charge, to any person obtaining
6
- * a copy of this software and associated documentation files
7
- * (the "Software"), to deal in the Software without restriction,
8
- * including without limitation the rights to use, copy, modify, merge,
9
- * publish, distribute, sublicense, and/or sell copies of the Software,
10
- * and to permit persons to whom the Software is furnished to do so,
11
- * subject to the following conditions:
12
- *
13
- * The above copyright notice and this permission notice shall be
14
- * included in all copies or substantial portions of the Software.
15
- *
16
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
- */
24
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
- if (k2 === undefined) k2 = k;
26
- var desc = Object.getOwnPropertyDescriptor(m, k);
27
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
- desc = { enumerable: true, get: function() { return m[k]; } };
29
- }
30
- Object.defineProperty(o, k2, desc);
31
- }) : (function(o, m, k, k2) {
32
- if (k2 === undefined) k2 = k;
33
- o[k2] = m[k];
34
- }));
35
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
36
- Object.defineProperty(o, "default", { enumerable: true, value: v });
37
- }) : function(o, v) {
38
- o["default"] = v;
39
- });
40
- var __importStar = (this && this.__importStar) || function (mod) {
41
- if (mod && mod.__esModule) return mod;
42
- var result = {};
43
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
44
- __setModuleDefault(result, mod);
45
- return result;
46
- };
47
- Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.DefSpace = exports.IndexFieldSpace = exports.ProjectFieldSpace = exports.ReduceFieldSpace = exports.ResultSpace = exports.QuerySpace = exports.DynamicSpace = exports.StaticSpace = void 0;
49
- /* eslint-disable no-useless-constructor */
50
- const lodash_1 = require("lodash");
51
- const dialect_1 = require("../dialect");
52
- const model = __importStar(require("../model/malloy_types"));
53
- const ast_1 = require("./ast");
54
- const space_field_1 = require("./space-field");
55
- const field_utils_1 = require("./field-utils");
56
- /**
57
- * The father of all FieldSpaces is a wrapper for a StructDef.
58
- */
59
- class StaticSpace {
60
- constructor(sourceStructDef) {
61
- this.type = "fieldSpace";
62
- this.fromStruct = sourceStructDef;
63
- }
64
- whenComplete(step) {
65
- step();
66
- }
67
- dialectObj() {
68
- try {
69
- return (0, dialect_1.getDialect)(this.fromStruct.dialect);
70
- }
71
- catch {
72
- return undefined;
73
- }
74
- }
75
- fromFieldDef(from) {
76
- if (from.type === "struct") {
77
- return new space_field_1.StructSpaceField(from);
78
- }
79
- else if (model.isTurtleDef(from)) {
80
- return new space_field_1.QueryFieldStruct(this, from);
81
- }
82
- // TODO field has a filter and needs to be a filteredalias
83
- return new space_field_1.ColumnSpaceField(from);
84
- }
85
- get map() {
86
- if (this.memoMap === undefined) {
87
- this.memoMap = {};
88
- for (const f of this.fromStruct.fields) {
89
- const name = f.as || f.name;
90
- this.memoMap[name] = this.fromFieldDef(f);
91
- }
92
- if (this.fromStruct.parameters) {
93
- for (const [paramName, paramDef] of Object.entries(this.fromStruct.parameters)) {
94
- if (this.memoMap[paramName]) {
95
- throw new Error(`In struct '${this.fromStruct.as || this.fromStruct.name}': ` +
96
- ` : Field and parameter name conflict '${paramName}`);
97
- }
98
- this.memoMap[paramName] = new space_field_1.DefinedParameter(paramDef);
99
- }
100
- }
101
- }
102
- return this.memoMap;
103
- }
104
- dropEntries() {
105
- this.memoMap = {};
106
- }
107
- dropEntry(name) {
108
- delete this.map[name];
109
- }
110
- entry(name) {
111
- return this.map[name];
112
- }
113
- setEntry(name, value) {
114
- this.map[name] = value;
115
- }
116
- entries() {
117
- return Object.entries(this.map);
118
- }
119
- structDef() {
120
- return this.fromStruct;
121
- }
122
- emptyStructDef() {
123
- return { ...this.fromStruct, fields: [] };
124
- }
125
- lookup(path) {
126
- const head = path[0];
127
- const rest = path.slice(1);
128
- const found = this.entry(head.refString);
129
- if (!found) {
130
- return { error: `'${head}' is not defined`, found };
131
- }
132
- if (found instanceof space_field_1.SpaceField) {
133
- /*
134
- * TODO cache defs, post the addReference call to whenComplete
135
- *
136
- * In the cleanup phase of query space construction, it may check
137
- * the output space for ungrouping variables. However if an
138
- * ungrouping variable is a measure, the field expression value
139
- * needed to get the definition needs to be computed in the
140
- * input space of the query. There is a test which failed which
141
- * caused this code to be here, but this is really a bandaid.
142
- *
143
- * Some re-work of how to get the definition of a SpaceField
144
- * no matter what it is contained in needs to be thought out.
145
- *
146
- * ... or this check would look at the finalized output of
147
- * the namespace and not re-compile ...
148
- */
149
- const definition = found.fieldDef();
150
- if (definition) {
151
- head.addReference({
152
- type: found instanceof space_field_1.StructSpaceField
153
- ? "joinReference"
154
- : "fieldReference",
155
- definition,
156
- location: head.location,
157
- text: head.refString,
158
- });
159
- }
160
- }
161
- if (rest.length) {
162
- if (found instanceof space_field_1.StructSpaceField) {
163
- return found.fieldSpace.lookup(rest);
164
- }
165
- return {
166
- error: `'${head}' cannot contain a '${rest[0]}'`,
167
- found: undefined,
168
- };
169
- }
170
- return { found, error: undefined };
171
- }
172
- }
173
- exports.StaticSpace = StaticSpace;
174
- function isFieldSpace(x) {
175
- return x.type == "fieldSpace";
176
- }
177
- /**
178
- * Based on how things are constructed, the starting field space
179
- * can either be another field space or an existing structdef.
180
- * Using a SpaceSeed allows a class to accept either one
181
- * and use either version at some future time.
182
- */
183
- class SpaceSeed {
184
- constructor(sourceSpec) {
185
- this.sourceSpec = sourceSpec;
186
- this.spaceSpec = sourceSpec;
187
- }
188
- get structDef() {
189
- if (isFieldSpace(this.spaceSpec)) {
190
- if (!this.asStruct) {
191
- this.asStruct = this.spaceSpec.structDef();
192
- }
193
- return this.asStruct;
194
- }
195
- return this.spaceSpec;
196
- }
197
- get fieldSpace() {
198
- if (isFieldSpace(this.spaceSpec)) {
199
- return this.spaceSpec;
200
- }
201
- if (!this.asFS) {
202
- this.asFS = new StaticSpace(this.spaceSpec);
203
- }
204
- return this.asFS;
205
- }
206
- }
207
- /**
208
- * A FieldSpace which may undergo modification
209
- */
210
- class DynamicSpace extends StaticSpace {
211
- constructor(extending) {
212
- const source = new SpaceSeed(extending);
213
- super((0, lodash_1.cloneDeep)(source.structDef));
214
- this.completions = [];
215
- this.complete = false;
216
- this.final = undefined;
217
- this.source = source;
218
- }
219
- /**
220
- * Factory for DynamicSpace when there are accept/except edits
221
- * @param from A structdef which seeds this space
222
- * @param choose A accept/except edit of the "from" fields
223
- */
224
- static filteredFrom(from, choose) {
225
- const edited = new DynamicSpace(from);
226
- if (choose) {
227
- const names = choose.refs.list;
228
- const oldMap = edited.entries();
229
- edited.dropEntries();
230
- for (const [symbol, value] of oldMap) {
231
- const included = !!names.find((f) => f.refString === symbol);
232
- const accepting = choose.edit === "accept";
233
- if (included === accepting) {
234
- edited.setEntry(symbol, value);
235
- }
236
- }
237
- }
238
- return edited;
239
- }
240
- whenComplete(finalizeStep) {
241
- if (this.complete) {
242
- finalizeStep();
243
- }
244
- else {
245
- this.completions.push(finalizeStep);
246
- }
247
- }
248
- isComplete() {
249
- this.complete = true;
250
- for (const step of this.completions) {
251
- step();
252
- }
253
- this.completions = [];
254
- }
255
- setEntry(name, value) {
256
- if (this.final) {
257
- throw new Error("Space already final");
258
- }
259
- super.setEntry(name, value);
260
- }
261
- addParameters(params) {
262
- for (const oneP of params) {
263
- this.setEntry(oneP.name, new space_field_1.AbstractParameter(oneP));
264
- }
265
- return this;
266
- }
267
- newEntry(name, astEl, entry) {
268
- if (this.entry(name)) {
269
- astEl.log(`Cannot redefine '${name}'`);
270
- return;
271
- }
272
- this.setEntry(name, entry);
273
- }
274
- addField(...defs) {
275
- for (const def of defs) {
276
- // TODO express the "three fields kinds" in a typesafe way
277
- // one of three kinds of fields are legal in an explore: expressions ...
278
- const elseLog = def.log;
279
- const elseType = def.elementType;
280
- if (def instanceof ast_1.FieldDeclaration) {
281
- const exprField = new space_field_1.ExpressionFieldFromAst(this, def);
282
- this.newEntry(exprField.name, def, exprField);
283
- // querry (turtle) fields
284
- }
285
- else if (def instanceof ast_1.TurtleDecl) {
286
- const name = def.name;
287
- this.newEntry(name, def, new space_field_1.QueryFieldAST(this, def, name));
288
- }
289
- else if (def instanceof ast_1.RenameField) {
290
- if (def.oldName.refString === def.newName) {
291
- def.log("Can't rename field to itself");
292
- continue;
293
- }
294
- const oldValue = def.oldName.getField(this);
295
- if (oldValue.found) {
296
- if (oldValue.found instanceof space_field_1.SpaceField) {
297
- this.setEntry(def.newName, new space_field_1.RenameSpaceField(oldValue.found, def.newName, def.location));
298
- this.dropEntry(def.oldName.refString);
299
- }
300
- else {
301
- def.log(`'${def.oldName}' cannot be renamed`);
302
- }
303
- }
304
- else {
305
- def.log(`Can't rename '${def.oldName}', no such field`);
306
- }
307
- }
308
- else if (def instanceof ast_1.Join) {
309
- this.newEntry(def.name.refString, def, new space_field_1.JoinSpaceField(this, def));
310
- }
311
- else {
312
- elseLog(`Internal error: Expected expression, query, or rename, got '${elseType}'`);
313
- }
314
- }
315
- }
316
- addFieldDef(fd) {
317
- this.setEntry((0, field_utils_1.nameOf)(fd), this.fromFieldDef(fd));
318
- }
319
- structDef() {
320
- const parameters = this.fromStruct.parameters || {};
321
- if (this.final === undefined) {
322
- this.final = {
323
- ...this.fromStruct,
324
- fields: [],
325
- };
326
- // Need to process the entities in specific order
327
- const fields = [];
328
- const joins = [];
329
- const turtles = [];
330
- const fixupJoins = [];
331
- for (const [name, spaceEntry] of this.entries()) {
332
- if (spaceEntry instanceof space_field_1.StructSpaceField) {
333
- joins.push([name, spaceEntry]);
334
- }
335
- else if (spaceEntry instanceof space_field_1.QueryField) {
336
- turtles.push([name, spaceEntry]);
337
- }
338
- else if (spaceEntry instanceof space_field_1.SpaceField) {
339
- fields.push([name, spaceEntry]);
340
- }
341
- else if (spaceEntry instanceof space_field_1.SpaceParam) {
342
- parameters[name] = spaceEntry.parameter();
343
- }
344
- }
345
- const reorderFields = [...fields, ...joins, ...turtles];
346
- for (const [fieldName, field] of reorderFields) {
347
- if (field instanceof space_field_1.JoinSpaceField) {
348
- const joinStruct = field.join.structDef();
349
- if (!ast_1.ErrorFactory.isErrorStructDef(joinStruct)) {
350
- this.final.fields.push(joinStruct);
351
- fixupJoins.push([field.join, joinStruct]);
352
- }
353
- }
354
- else {
355
- const fieldDef = field.fieldDef();
356
- if (fieldDef) {
357
- this.final.fields.push(fieldDef);
358
- }
359
- else {
360
- throw new Error(`'${fieldName}' doesn't have a FieldDef`);
361
- }
362
- }
363
- }
364
- if (Object.entries(parameters).length > 0) {
365
- this.final.parameters = parameters;
366
- }
367
- // If we have join expressions, we need to now go back and fill them in
368
- for (const [join, missingOn] of fixupJoins) {
369
- join.fixupJoinOn(this, missingOn);
370
- }
371
- }
372
- this.isComplete();
373
- return this.final;
374
- }
375
- }
376
- exports.DynamicSpace = DynamicSpace;
377
- /**
378
- * Unlike a source, which is a refinement of a namespace, a query
379
- * is creating a new unrelated namespace. The query starts with a
380
- * source, which it might modify. This set of fields used to resolve
381
- * expressions in the query is called the "input space". There is a
382
- * specialized QuerySpace for each type of query operation.
383
- *
384
- * The query output is managed by an instance of ResultSpace.
385
- */
386
- class QuerySpace extends DynamicSpace {
387
- constructor(input, result) {
388
- const inputSpace = new SpaceSeed(input);
389
- super(inputSpace.structDef);
390
- this.result = result;
391
- this.extendList = [];
392
- }
393
- extendSource(extendField) {
394
- this.addField(extendField);
395
- if (extendField instanceof ast_1.Join) {
396
- this.extendList.push(extendField.name.refString);
397
- }
398
- else {
399
- this.extendList.push(extendField.defineName);
400
- }
401
- }
402
- }
403
- exports.QuerySpace = QuerySpace;
404
- class ResultSpace extends DynamicSpace {
405
- constructor(queryInputSpace) {
406
- super(queryInputSpace.emptyStructDef());
407
- this.queryInputSpace = queryInputSpace;
408
- this.exprSpace = new QuerySpace(queryInputSpace, this);
409
- }
410
- log(s) {
411
- if (this.astEl) {
412
- this.astEl.log(s);
413
- }
414
- }
415
- addMembers(members) {
416
- for (const member of members) {
417
- if (member instanceof ast_1.FieldReference) {
418
- this.addReference(member);
419
- }
420
- else if (member instanceof ast_1.WildcardFieldReference) {
421
- this.addWild(member);
422
- }
423
- else {
424
- this.addField(member);
425
- }
426
- }
427
- }
428
- addReference(ref) {
429
- const refName = ref.outputName;
430
- if (this.entry(refName)) {
431
- ref.log(`Output already has a field named '${refName}'`);
432
- }
433
- else {
434
- this.setEntry(refName, new space_field_1.ReferenceField(ref));
435
- }
436
- }
437
- addWild(wild) {
438
- this.setEntry(wild.refString, new space_field_1.WildSpaceField(wild.refString));
439
- }
440
- /**
441
- * Check for the definition of an ungrouping reference in the result space,
442
- * or in the case of an exclude reference, if this query is nested
443
- * in another query, in the result space of a query that this query
444
- * is nested inside of.
445
- */
446
- checkUngroup(fn, isExclude) {
447
- if (!this.entry(fn.refString)) {
448
- if (isExclude && this.exprSpace.nestParent) {
449
- const parent = this.exprSpace.nestParent;
450
- parent.whenComplete(() => {
451
- parent.result.checkUngroup(fn, isExclude);
452
- });
453
- }
454
- else {
455
- const uName = isExclude ? "exclude()" : "all()";
456
- fn.log(`${uName} '${fn.refString}' is missing from query output`);
457
- }
458
- }
459
- }
460
- addQueryItems(...qiList) {
461
- for (const qi of qiList) {
462
- if (qi instanceof ast_1.FieldReference || qi instanceof ast_1.NestReference) {
463
- this.addReference(qi);
464
- }
465
- else if (qi instanceof ast_1.FieldDeclaration) {
466
- this.addField(qi);
467
- }
468
- else if ((0, ast_1.isNestedQuery)(qi)) {
469
- const qf = new space_field_1.QueryFieldAST(this, qi, qi.name);
470
- qf.nestParent = this.exprSpace;
471
- this.setEntry(qi.name, qf);
472
- }
473
- else {
474
- // Compiler will error if we don't handle all cases
475
- const _itemNotHandled = qi;
476
- }
477
- }
478
- }
479
- canContain(_qd) {
480
- return true;
481
- }
482
- queryFieldDefs() {
483
- const fields = [];
484
- for (const [name, field] of this.entries()) {
485
- if (field instanceof space_field_1.SpaceField) {
486
- const fieldQueryDef = field.getQueryFieldDef(this.exprSpace);
487
- if (fieldQueryDef) {
488
- if (this.canContain(fieldQueryDef)) {
489
- fields.push(fieldQueryDef);
490
- }
491
- else {
492
- this.log(`'${name}' not legal in ${this.segmentType}`);
493
- }
494
- }
495
- else {
496
- throw new Error(`'${name}' does not have a QueryFieldDef`);
497
- }
498
- }
499
- }
500
- this.isComplete();
501
- return fields;
502
- }
503
- getQuerySegment(rf) {
504
- const p = this.getPipeSegment(rf);
505
- if (model.isQuerySegment(p)) {
506
- return p;
507
- }
508
- throw new Error("TODO NOT POSSIBLE");
509
- }
510
- getPipeSegment(refineFrom) {
511
- if (this.segmentType == "index") {
512
- // TODO ... should make this go away
513
- throw new Error("INDEX FIELD PIPE SEGMENT MIS HANDLED");
514
- }
515
- if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
516
- for (const xField of refineFrom.extendSource) {
517
- this.exprSpace.addFieldDef(xField);
518
- }
519
- }
520
- const segment = {
521
- type: this.segmentType,
522
- fields: this.queryFieldDefs(),
523
- };
524
- segment.fields = (0, field_utils_1.mergeFields)(refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.fields, segment.fields);
525
- if (refineFrom === null || refineFrom === void 0 ? void 0 : refineFrom.extendSource) {
526
- segment.extendSource = refineFrom.extendSource;
527
- }
528
- if (this.exprSpace.extendList.length > 0) {
529
- const newExtends = [];
530
- const extendedStruct = this.exprSpace.structDef();
531
- for (const extendName of this.exprSpace.extendList) {
532
- const extendEnt = extendedStruct.fields.find((f) => (0, field_utils_1.nameOf)(f) == extendName);
533
- if (extendEnt) {
534
- newExtends.push(extendEnt);
535
- }
536
- }
537
- segment.extendSource = (0, field_utils_1.mergeFields)(segment.extendSource, newExtends);
538
- }
539
- this.isComplete();
540
- return segment;
541
- }
542
- }
543
- exports.ResultSpace = ResultSpace;
544
- /**
545
- * Reduce and project queries use a "QuerySpace"
546
- */
547
- class ReduceFieldSpace extends ResultSpace {
548
- constructor() {
549
- super(...arguments);
550
- this.segmentType = "reduce";
551
- }
552
- }
553
- exports.ReduceFieldSpace = ReduceFieldSpace;
554
- class ProjectFieldSpace extends ResultSpace {
555
- constructor() {
556
- super(...arguments);
557
- this.segmentType = "project";
558
- }
559
- canContain(qd) {
560
- if (typeof qd !== "string") {
561
- if (model.isFilteredAliasedName(qd)) {
562
- return true;
563
- }
564
- if (qd.type === "turtle") {
565
- this.log("Cannot nest queries in project");
566
- return false;
567
- }
568
- if (model.expressionIsAggregate(qd.expressionType)) {
569
- this.log("Cannot add aggregate measures to project");
570
- return false;
571
- }
572
- }
573
- return true;
574
- }
575
- }
576
- exports.ProjectFieldSpace = ProjectFieldSpace;
577
- class IndexFieldSpace extends ResultSpace {
578
- constructor() {
579
- super(...arguments);
580
- this.segmentType = "index";
581
- this.fieldList = new Set();
582
- }
583
- addReference(ref) {
584
- if (ref.getField(this.exprSpace).found) {
585
- this.fieldList.add(ref.refString);
586
- }
587
- }
588
- addWild(wild) {
589
- this.fieldList.add(wild.refString);
590
- }
591
- getPipeSegment(refineIndex) {
592
- if (refineIndex && refineIndex.fields) {
593
- for (const exists of refineIndex.fields) {
594
- if (typeof exists == "string") {
595
- this.fieldList.add(exists);
596
- }
597
- }
598
- }
599
- this.isComplete();
600
- return {
601
- type: "index",
602
- fields: Array.from(this.fieldList.values()),
603
- };
604
- }
605
- }
606
- exports.IndexFieldSpace = IndexFieldSpace;
607
- /**
608
- * Used to detect references to fields in the statement which defines them
609
- */
610
- class DefSpace {
611
- constructor(realFS, circular) {
612
- this.realFS = realFS;
613
- this.circular = circular;
614
- this.type = "fieldSpace";
615
- this.foundCircle = false;
616
- }
617
- structDef() {
618
- return this.realFS.structDef();
619
- }
620
- emptyStructDef() {
621
- return this.realFS.emptyStructDef();
622
- }
623
- lookup(symbol) {
624
- if (symbol[0] && symbol[0].refString === this.circular.defineName) {
625
- this.foundCircle = true;
626
- return {
627
- error: `Circular reference to '${this.circular.defineName}' in definition`,
628
- found: undefined,
629
- };
630
- }
631
- return this.realFS.lookup(symbol);
632
- }
633
- dialectObj() {
634
- return this.realFS.dialectObj();
635
- }
636
- whenComplete(step) {
637
- this.realFS.whenComplete(step);
638
- }
639
- }
640
- exports.DefSpace = DefSpace;
641
- //# sourceMappingURL=field-space.js.map