@malloydata/malloy-query-builder 0.0.237-dev250225144145

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/DEVELOPING.md ADDED
@@ -0,0 +1,27 @@
1
+ ## Things Flow converter does not support
2
+
3
+ Constructor types:
4
+
5
+ ```ts
6
+ type NodeConstructor<T extends Node> = new (...args: any[]) => T;
7
+ ```
8
+
9
+ Computed signature names, including ones for basic symbols like `Symbol.iterator`:
10
+
11
+ ```ts
12
+ *[Symbol.iterator](): Generator<N, void, unknown> {
13
+ for (let i = 0; i < this.length; i++) {
14
+ yield this.index(i);
15
+ }
16
+ }
17
+ ```
18
+
19
+ Instead, name it something concrete, like `iter()`. Which is annoying because then you can't iterate on it directly.
20
+
21
+ ```ts
22
+ *iter(): Generator<N, void, unknown> {
23
+ for (let i = 0; i < this.length; i++) {
24
+ yield this.index(i);
25
+ }
26
+ }
27
+ ```
package/README.md ADDED
@@ -0,0 +1,437 @@
1
+
2
+ # Malloy Query AST
3
+
4
+ Get started with the {@link ASTQuery} class.
5
+
6
+ ## Serialize itself to a Malloy Query string
7
+
8
+ {@link ASTQuery.toMalloy}
9
+
10
+ ```ts
11
+ query.setSource('flights');
12
+ query.setView('by_carrier');
13
+ query.toMalloy();
14
+ ```
15
+ ```
16
+ run: flights -> by_carrier
17
+ ```
18
+
19
+ ## Provide an interface to walk the tree
20
+
21
+ This is for the Explorer, e.g., to create the query summary UI
22
+
23
+ ## To the empty query, add a starting point which is either a new literal view or a view reference which can later be refined
24
+
25
+ {@link ASTQuery.getOrAddDefaultSegment}
26
+
27
+ ```ts
28
+ query.setSource('flights');
29
+ query.getOrAddDefaultSegment().addGroupBy("carrier");
30
+ ```
31
+ ```
32
+ run: flights -> { group_by: carrier }
33
+ ```
34
+
35
+ {@link ASTQuery.setViewToEmptySegment}
36
+
37
+ ```ts
38
+ query.setSource('flights');
39
+ query.setViewToEmptySegment().addGroupBy("carrier");
40
+ ```
41
+ ```
42
+ run: flights -> { group_by: carrier }
43
+ ```
44
+
45
+ {@link ASTQuery.setView}
46
+
47
+ ```ts
48
+ query.setSource('flights');
49
+ query.setView('by_carrier');
50
+ ```
51
+ ```
52
+ run: flights -> by_carrier
53
+ ```
54
+
55
+ ## Determine if the query can be run
56
+
57
+ {@link ASTSegmentViewDefinition.isRunnable}
58
+
59
+ ```
60
+ run: flights -> { }
61
+ ```
62
+ ```ts
63
+ query.isRunnable() // false
64
+ ```
65
+
66
+ ## Add a new field to a particular literal view
67
+
68
+ {@link ASTSegmentViewDefinition.addGroupBy}
69
+ {@link ASTSegmentViewDefinition.addAggregate}
70
+ {@link ASTSegmentViewDefinition.addNest}
71
+
72
+ ```ts
73
+ const segment = query.getOrAddDefaultSegment();
74
+ segment.addGroupBy('carrier');
75
+ segment.addAggregate('flight_count');
76
+ segment.addNest('by_origin');
77
+ ```
78
+ ```
79
+ run: flights -> {
80
+ group_by: carrier
81
+ aggregate: flight_count
82
+ nest: by_origin
83
+ }
84
+ ```
85
+
86
+ ## A field reference
87
+ ## A time truncation of a field reference
88
+
89
+ {@link ASTSegmentViewDefinition.addDateGroupBy}
90
+ {@link ASTSegmentViewDefinition.addTimestampGroupBy}
91
+
92
+ ```ts
93
+ const segment = query.getOrAddDefaultSegment();
94
+ segment.addTimestampGroupBy('dep_time', 'month');
95
+ ```
96
+ ```
97
+ run: flights -> {
98
+ group_by: dep_time.month
99
+ }
100
+ ```
101
+
102
+ ## A measure reference with filters
103
+
104
+ ## Rename/delete a field
105
+
106
+ {@link ASTGroupByViewOperation.delete}
107
+ {@link ASTAggregateViewOperation.delete}
108
+ {@link ASTNestViewOperation.delete}
109
+ {@link ASTGroupByViewOperation.rename}
110
+ {@link ASTAggregateViewOperation.rename}
111
+ {@link ASTNestViewOperation.rename}
112
+
113
+ ```
114
+ run: flights -> {
115
+ group_by: carrier
116
+ aggregate: flight_count
117
+ }
118
+ ```
119
+ ```ts
120
+ groupBy.delete();
121
+ aggregate.rename("flight_count_2");
122
+ ```
123
+ ```
124
+ run: flights -> { aggregate: flight_count_2 is flight_count }
125
+ ```
126
+
127
+ ## Check if a field is present
128
+
129
+ {@link ASTSegmentViewDefinition.hasField}
130
+
131
+ ```ts
132
+ query.getOrAddDefaultSegment().hasField('carrier');
133
+ ```
134
+
135
+ ## Add/edit/delete order by
136
+
137
+ {@link ASTOrderByViewOperation.delete}
138
+
139
+ ```
140
+ run: flights -> {
141
+ group_by: carrier
142
+ order_by: carrier desc
143
+ }
144
+ ```
145
+ ```ts
146
+ orderBy.delete();
147
+ ```
148
+ ```
149
+ run: flights -> { group_by: carrier }
150
+ ```
151
+
152
+ {@link ASTOrderByViewOperation.setField}
153
+
154
+ ```
155
+ run: flights -> {
156
+ group_by:
157
+ carrier
158
+ flight_count
159
+ order_by: carrier desc
160
+ }
161
+ ```
162
+ ```ts
163
+ orderBy.setField("flight_count");
164
+ ```
165
+ ```
166
+ run: flights -> {
167
+ group_by:
168
+ carrier
169
+ flight_count
170
+ order_by: flight_count desc
171
+ }
172
+ ```
173
+
174
+ {@link ASTOrderByViewOperation.setDirection}
175
+
176
+ ```
177
+ run: flights -> {
178
+ group_by: carrier
179
+ order_by: carrier desc
180
+ }
181
+ ```
182
+ ```ts
183
+ orderBy.setDirection(Malloy.OrderByDirection.ASC);
184
+ ```
185
+ ```
186
+ run: flights -> {
187
+ group_by: carrier
188
+ order_by: flight_count asc
189
+ }
190
+ ```
191
+
192
+ ## Add/edit/delete filter
193
+
194
+ * {@link ASTSegmentViewDefinition.addWhere}
195
+ * {@link ASTFilterWithFilterString.setFilterString}
196
+ * {@link ASTFilterWithFilterString.setFilter}
197
+ * {@link ASTFilterWithFilterString.getFilter}
198
+ * {@link ASTWhereViewOperation.delete}
199
+ * {@link ASTWhere.delete}
200
+
201
+ ```ts
202
+ query.getOrAddDefaultSegment().addWhere("carrier", "WN, AA");
203
+ ```
204
+ ```
205
+ run: flights -> { where: carrier ~ f`WN, AA` }
206
+ ```
207
+
208
+ ## Add/edit/delete limit
209
+
210
+ * {@link ASTSegmentViewDefinition.setLimit}
211
+ * {@link ASTLimitViewOperation.delete}
212
+
213
+ ```ts
214
+ query.getOrAddDefaultSegment().setLimit(10);
215
+ ```
216
+ ```
217
+ run: flights -> { limit: 10 }
218
+ ```
219
+
220
+ ## Create new nest with name
221
+
222
+ {@link ASTSegmentViewDefinition.addEmptyNest}
223
+
224
+
225
+ ```ts
226
+ query.getOrAddDefaultSegment().addEmptyNest("by_origin");
227
+ ```
228
+ ```
229
+ run: flights -> { nest: by_origin is { } }
230
+ ```
231
+
232
+ ## Reorder fields
233
+ ## To a particular nesting level (literal view or view + refinements), reorder fields
234
+
235
+ ## For a particular literal view, list the fields which can be added
236
+
237
+ {@link ASTSegmentViewDefinition.getInputSchema}
238
+
239
+ ```ts
240
+ query.getOrAddDefaultSegment().getInputSchema();
241
+ ```
242
+ ```
243
+ {
244
+ fields: [
245
+ { kind: "measure", name: "flight_count", type: { kind: "string_type" }}
246
+ ...
247
+ ]
248
+ }
249
+ ```
250
+
251
+ ## To a particular view reference, add a new literal view as a refinement
252
+
253
+ {@link IASTViewDefinition.addEmptyRefinement}
254
+
255
+
256
+ ```ts
257
+ const view = query.setView("by_carrier");
258
+ const segment = view.addEmptyRefinement();
259
+ segment.setLimit(10);
260
+ ```
261
+ ```
262
+ run: flights -> by_carrier + { limit: 10 }
263
+ ```
264
+
265
+ ## To a particular view reference, add a new view reference as a refinement
266
+
267
+ {@link IASTViewDefinition.addViewRefinement}
268
+
269
+ ```ts
270
+ const view = query.setView("by_carrier");
271
+ view.addViewRefinement("top10");
272
+ ```
273
+ ```
274
+ run: flights -> by_carrier + top10
275
+ ```
276
+
277
+ ## To a particular view (literal or reference), specify the order of fields by way of adding/editing an annotation
278
+
279
+ {@link ASTQuery.reorderFields}
280
+ {@link ASTView.reorderFields}
281
+
282
+ If the view or query is a simple segment, it will automatically reorder the clauses.
283
+
284
+ ```
285
+ run: flights -> {
286
+ group_by: carrier
287
+ aggregate: flight_count
288
+ }
289
+ ```
290
+ ```ts
291
+ query.reorderFields(['flight_count', 'carrier']);
292
+ ```
293
+ ```
294
+ run: flights -> {
295
+ aggregate: flight_count
296
+ group_by: carrier
297
+ }
298
+ ```
299
+
300
+ Otherwise, it will add an annotation:
301
+
302
+ ```
303
+ run: flights -> by_carrier
304
+ ```
305
+ ```ts
306
+ query.reorderFields(['flight_count', 'carrier']);
307
+ ```
308
+ ```
309
+ # field_order = [flight_count, carrier]
310
+ run: flights -> by_carrier
311
+ ```
312
+
313
+ ## To a particular aggregate field in the query, add/edit/delete filter
314
+
315
+ * {@link ASTAggregateViewOperation.addWhere}
316
+ * {@link ASTFilterWithFilterString.setFilter}
317
+ * {@link ASTWhere.delete}
318
+
319
+ ```ts
320
+ query.getOrAddDefaultSegment().addAggregate('flight_count').addWhere('carrier', 'WN, AA');
321
+ ```
322
+ ```
323
+ run: flights -> { aggregate: flight_count { where: carrier ~ f`WN, AA`} }
324
+ ```
325
+
326
+ ## Specify or remove source parameter value
327
+
328
+ {@link ASTSourceReference.setParameter}
329
+
330
+ ```ts
331
+ query.source.setParameter("param", 1);
332
+ ```
333
+ ```
334
+ run: flights(param is 1) ->
335
+ ```
336
+
337
+ ## List parameters of the source and whether they are required
338
+
339
+ {@link ASTSourceReference.getSourceParameters}
340
+
341
+ ```ts
342
+ query.definition.asArrowQueryDefinition().source.getSourceParameters();
343
+ ```
344
+
345
+ ## To a particular field in the query (including nests), add/edit/delete annotation
346
+
347
+ {@link IASTAnnotatable.setTagProperty}
348
+ {@link IASTAnnotatable.removeTagProperty}
349
+
350
+ ```ts
351
+ query
352
+ .getOrAddDefaultSegment()
353
+ .addGroupBy('carrier');
354
+ .setTagProperty(['a', 'b', 'c'], 10);
355
+ ```
356
+ ```
357
+ run: flights -> {
358
+ # a.b.c = 10
359
+ group_by: carrier
360
+ }
361
+ ```
362
+
363
+ ```ts
364
+ // Assume that 'by_carrier' has, in the model, a tag "bar_chart"
365
+ query
366
+ .getOrAddDefaultSegment()
367
+ .addNest('by_carrier');
368
+ .removeTagProperty(['bar_chart']);
369
+ ```
370
+ ```
371
+ run: flights -> {
372
+ # -bar_chart
373
+ nest: by_carrier
374
+ }
375
+ ```
376
+
377
+ ## To a particular field, ask which annotations come from the input field vs in the query itself
378
+
379
+ {@link IASTAnnotatable.getIntrinsicTag}
380
+ {@link IASTAnnotatable.getInheritedTag}
381
+
382
+ ```ts
383
+ query
384
+ .getOrAddDefaultSegment()
385
+ .addGroupBy('carrier');
386
+ .getIntrinsicTag()
387
+ .has('some_tag');
388
+ query
389
+ .getOrAddDefaultSegment()
390
+ .addGroupBy('carrier');
391
+ .getInheritedTag()
392
+ .has('some_tag');
393
+ ```
394
+
395
+ ## To the query itself, add/edit/delete annotation
396
+
397
+ ```ts
398
+ query.setTagProperty(['bar_chart']);
399
+ query.setSource('flights');
400
+ query.setView('by_carrier');
401
+ ```
402
+ ```
403
+ # bar_chart
404
+ run: flights -> by_carrier
405
+ ```
406
+
407
+ ## After any operation of a QueryBuilder, perform a partial validation of the query
408
+ This is only ever a partial validation: cube resolution, aggregate validation, and expression validation (and possibly other validation) must happen in the translator, and will not be replicated in the QueryBuilder
409
+ We will do as much validation as we can do, but it is possible some queries will only generate errors when you do a full translation (probably when you run it)
410
+ ## Given a filter string and a field type, parse it into a StableFilterDef
411
+ ## Given a StableFilterDef, serialize it into a filter string
412
+ ## Automatically determine where in a literal view is most appropriate to place a new field
413
+
414
+ This happens automatically when you call {@link ASTSegmentViewDefinition.addGroupBy}, {@link ASTSegmentViewDefinition.addAggregate}, {@link ASTSegmentViewDefinition.addNest}, {@link ASTSegmentViewDefinition.addWhere}, {@link ASTSegmentViewDefinition.addOrderBy}, {@link ASTSegmentViewDefinition.setLimit}, etc..
415
+
416
+ ## Finding the default place in the tree to put a new field
417
+
418
+ {@link ASTQuery.getOrAddDefaultSegment}
419
+
420
+ ```ts
421
+ query.setSource('flights');
422
+ query.getOrAddDefaultSegment().addGroupBy("carrier");
423
+ ```
424
+ ```
425
+ run: flights -> { group_by: carrier }
426
+ ```
427
+
428
+ ```
429
+ run: flights -> by_carrier
430
+ ```
431
+ ```ts
432
+ query.setSource('flights');
433
+ query.getOrAddDefaultSegment().setLimit(10);
434
+ ```
435
+ ```
436
+ run: flights -> by_carrier + { limit: 10 }
437
+ ```
@@ -0,0 +1,26 @@
1
+ import * as Malloy from '@malloydata/malloy-interfaces';
2
+ declare global {
3
+ namespace jest {
4
+ interface Matchers<R> {
5
+ /**
6
+ * expect(q => q.getOrCreateDefaultSegment().addGroupBy('carrier')).toModifyQuery({
7
+ * from: ...,
8
+ * to: ...,
9
+ * malloy: 'run: flights -> { group_by: carrier }'
10
+ * });
11
+ */
12
+ toModifyQuery(exp: {
13
+ model: Malloy.ModelInfo;
14
+ from: Malloy.Query;
15
+ to: Malloy.Query;
16
+ malloy: string;
17
+ }): R;
18
+ toModifyQuery(exp: {
19
+ source: Malloy.SourceInfo;
20
+ from: Malloy.Query;
21
+ to: Malloy.Query;
22
+ malloy: string;
23
+ }): R;
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const query_ast_1 = require("./query-ast");
10
+ expect.extend({
11
+ toModifyQuery(f, { model, source, from, to, malloy, }) {
12
+ const clone = JSON.parse(JSON.stringify(from));
13
+ const q = model
14
+ ? new query_ast_1.ASTQuery({ model, query: from })
15
+ : source
16
+ ? new query_ast_1.ASTQuery({ source, query: from })
17
+ : undefined;
18
+ if (q === undefined) {
19
+ throw new Error('Must specify either model or source');
20
+ }
21
+ f(q);
22
+ const query = q.build();
23
+ const eq = objectsMatch(query, to);
24
+ const diff = this.utils.diff(to, query);
25
+ if (!eq) {
26
+ return {
27
+ pass: false,
28
+ message: () => `Modified query object does not match expected: ${diff}`,
29
+ };
30
+ }
31
+ try {
32
+ ensureOnlyMinimalEdits(from, query, clone);
33
+ }
34
+ catch (error) {
35
+ return {
36
+ pass: false,
37
+ message: () => `Resulting query object should have minimal edits: ${error.message}`,
38
+ };
39
+ }
40
+ const actualMalloy = q.toMalloy();
41
+ const malloyDiff = this.utils.diff(malloy, actualMalloy);
42
+ if (malloy !== actualMalloy) {
43
+ return {
44
+ pass: false,
45
+ message: () => `Resulting query text does not match expected: ${malloyDiff}`,
46
+ };
47
+ }
48
+ return {
49
+ pass: true,
50
+ message: () => 'Result matched',
51
+ };
52
+ },
53
+ });
54
+ function ensureOnlyMinimalEdits(
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ a,
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ b,
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ aClone, path = []) {
61
+ if (typeof a === 'string' ||
62
+ typeof a === 'number' ||
63
+ typeof a === 'boolean') {
64
+ return aClone !== b;
65
+ }
66
+ let different = false;
67
+ if (Array.isArray(a)) {
68
+ different = aClone.length !== b.length;
69
+ for (let i = 0; i < aClone.length || i < b.length; i++) {
70
+ if (a === undefined || b === undefined) {
71
+ different = true;
72
+ }
73
+ else if (aClone[i] === b[i]) {
74
+ different || (different = ensureOnlyMinimalEdits(a[i], b[i], aClone[i], [
75
+ ...path,
76
+ i,
77
+ ]));
78
+ }
79
+ else {
80
+ different = true;
81
+ const found = aClone.findIndex(f => f === b[i]);
82
+ if (found !== -1) {
83
+ ensureOnlyMinimalEdits(a[found], b[i], aClone[found], [...path, i]);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ else {
89
+ for (const key in aClone) {
90
+ different || (different = ensureOnlyMinimalEdits(a[key], b[key], aClone[key], [
91
+ ...path,
92
+ key,
93
+ ]));
94
+ }
95
+ for (const key in b) {
96
+ if (key in aClone)
97
+ continue;
98
+ different = true;
99
+ }
100
+ }
101
+ const sameObject = a === b;
102
+ if (different) {
103
+ if (sameObject) {
104
+ throw new Error(`Path /${path.join('/')} was illegally mutated`);
105
+ }
106
+ }
107
+ else {
108
+ if (!sameObject) {
109
+ throw new Error(`Path /${path.join('/')} was unnecessarily cloned`);
110
+ }
111
+ }
112
+ return different;
113
+ }
114
+ function objectsMatch(a, b) {
115
+ if (typeof b === 'string' ||
116
+ typeof b === 'number' ||
117
+ typeof b === 'boolean' ||
118
+ typeof b === 'bigint' ||
119
+ b === undefined ||
120
+ b === null) {
121
+ return b === a;
122
+ }
123
+ else if (Array.isArray(b)) {
124
+ if (Array.isArray(a)) {
125
+ return a.length === b.length && a.every((v, i) => objectsMatch(v, b[i]));
126
+ }
127
+ return false;
128
+ }
129
+ else {
130
+ if (typeof a === 'string' ||
131
+ typeof a === 'number' ||
132
+ typeof a === 'boolean' ||
133
+ typeof a === 'bigint' ||
134
+ a === undefined ||
135
+ a === null) {
136
+ return false;
137
+ }
138
+ if (Array.isArray(a))
139
+ return false;
140
+ const keys = Object.keys(b);
141
+ for (const key of keys) {
142
+ if (!objectsMatch(a[key], b[key])) {
143
+ return false;
144
+ }
145
+ }
146
+ return true;
147
+ }
148
+ }
149
+ //# sourceMappingURL=expects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expects.js","sourceRoot":"","sources":["../src/expects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import * as Malloy from '@malloydata/malloy-interfaces';
2
+ export declare const flights_model: Malloy.ModelInfo;