@malloydata/malloy-query-builder 0.0.266 → 0.0.267-dev250421220633
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/query-ast.d.ts +0 -1
- package/dist/query-ast.js +7 -5
- package/dist/query-ast.js.map +1 -1
- package/dist/query-ast.spec.js +304 -0
- package/dist/query-ast.spec.js.map +1 -1
- package/package.json +4 -4
- package/src/query-ast.spec.ts +304 -0
- package/src/query-ast.ts +6 -6
package/src/query-ast.spec.ts
CHANGED
|
@@ -2621,4 +2621,308 @@ describe('query builder', () => {
|
|
|
2621
2621
|
expect(query.isRunnable()).toBe(true);
|
|
2622
2622
|
});
|
|
2623
2623
|
});
|
|
2624
|
+
describe('insertion order', () => {
|
|
2625
|
+
const model: Malloy.ModelInfo = {
|
|
2626
|
+
entries: [
|
|
2627
|
+
{
|
|
2628
|
+
kind: 'source',
|
|
2629
|
+
name: 's',
|
|
2630
|
+
schema: {
|
|
2631
|
+
fields: [
|
|
2632
|
+
{kind: 'dimension', name: 'd1', type: {kind: 'number_type'}},
|
|
2633
|
+
{kind: 'dimension', name: 'd2', type: {kind: 'number_type'}},
|
|
2634
|
+
{kind: 'dimension', name: 'd3', type: {kind: 'number_type'}},
|
|
2635
|
+
{kind: 'measure', name: 'm1', type: {kind: 'number_type'}},
|
|
2636
|
+
{kind: 'measure', name: 'm2', type: {kind: 'number_type'}},
|
|
2637
|
+
{kind: 'measure', name: 'm3', type: {kind: 'number_type'}},
|
|
2638
|
+
{kind: 'view', name: 'v1', schema: {fields: []}},
|
|
2639
|
+
{kind: 'view', name: 'v2', schema: {fields: []}},
|
|
2640
|
+
{kind: 'view', name: 'v3', schema: {fields: []}},
|
|
2641
|
+
],
|
|
2642
|
+
},
|
|
2643
|
+
},
|
|
2644
|
+
],
|
|
2645
|
+
anonymous_queries: [],
|
|
2646
|
+
};
|
|
2647
|
+
function group_by(name: string): Malloy.ViewOperationWithGroupBy {
|
|
2648
|
+
return {
|
|
2649
|
+
kind: 'group_by',
|
|
2650
|
+
field: {
|
|
2651
|
+
expression: {
|
|
2652
|
+
kind: 'field_reference',
|
|
2653
|
+
name,
|
|
2654
|
+
},
|
|
2655
|
+
},
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
function aggregate(name: string): Malloy.ViewOperationWithAggregate {
|
|
2659
|
+
return {
|
|
2660
|
+
kind: 'aggregate',
|
|
2661
|
+
field: {
|
|
2662
|
+
expression: {
|
|
2663
|
+
kind: 'field_reference',
|
|
2664
|
+
name,
|
|
2665
|
+
},
|
|
2666
|
+
},
|
|
2667
|
+
};
|
|
2668
|
+
}
|
|
2669
|
+
function nest(name: string): Malloy.ViewOperationWithNest {
|
|
2670
|
+
return {
|
|
2671
|
+
kind: 'nest',
|
|
2672
|
+
view: {
|
|
2673
|
+
definition: {
|
|
2674
|
+
kind: 'view_reference',
|
|
2675
|
+
name,
|
|
2676
|
+
},
|
|
2677
|
+
},
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
test('add an aggregate after adding some group bys', () => {
|
|
2681
|
+
const from: Malloy.Query = {
|
|
2682
|
+
definition: {
|
|
2683
|
+
kind: 'arrow',
|
|
2684
|
+
source: {
|
|
2685
|
+
kind: 'source_reference',
|
|
2686
|
+
name: 's',
|
|
2687
|
+
},
|
|
2688
|
+
view: {
|
|
2689
|
+
kind: 'segment',
|
|
2690
|
+
operations: [],
|
|
2691
|
+
},
|
|
2692
|
+
},
|
|
2693
|
+
};
|
|
2694
|
+
expect((q: ASTQuery) => {
|
|
2695
|
+
const segment = q.getOrAddDefaultSegment();
|
|
2696
|
+
segment.addGroupBy('d1');
|
|
2697
|
+
segment.addGroupBy('d2');
|
|
2698
|
+
segment.addAggregate('m1');
|
|
2699
|
+
}).toModifyQuery({
|
|
2700
|
+
model,
|
|
2701
|
+
from,
|
|
2702
|
+
to: {
|
|
2703
|
+
definition: {
|
|
2704
|
+
kind: 'arrow',
|
|
2705
|
+
source: {
|
|
2706
|
+
kind: 'source_reference',
|
|
2707
|
+
name: 's',
|
|
2708
|
+
},
|
|
2709
|
+
view: {
|
|
2710
|
+
kind: 'segment',
|
|
2711
|
+
operations: [group_by('d1'), group_by('d2'), aggregate('m1')],
|
|
2712
|
+
},
|
|
2713
|
+
},
|
|
2714
|
+
},
|
|
2715
|
+
malloy: dedent`
|
|
2716
|
+
run: s -> {
|
|
2717
|
+
group_by:
|
|
2718
|
+
d1
|
|
2719
|
+
d2
|
|
2720
|
+
aggregate: m1
|
|
2721
|
+
}
|
|
2722
|
+
`,
|
|
2723
|
+
});
|
|
2724
|
+
});
|
|
2725
|
+
test('add GB, AGG, GB', () => {
|
|
2726
|
+
const from: Malloy.Query = {
|
|
2727
|
+
definition: {
|
|
2728
|
+
kind: 'arrow',
|
|
2729
|
+
source: {
|
|
2730
|
+
kind: 'source_reference',
|
|
2731
|
+
name: 's',
|
|
2732
|
+
},
|
|
2733
|
+
view: {
|
|
2734
|
+
kind: 'segment',
|
|
2735
|
+
operations: [],
|
|
2736
|
+
},
|
|
2737
|
+
},
|
|
2738
|
+
};
|
|
2739
|
+
expect((q: ASTQuery) => {
|
|
2740
|
+
const segment = q.getOrAddDefaultSegment();
|
|
2741
|
+
segment.addGroupBy('d1');
|
|
2742
|
+
segment.addAggregate('m1');
|
|
2743
|
+
segment.addGroupBy('d2');
|
|
2744
|
+
}).toModifyQuery({
|
|
2745
|
+
model,
|
|
2746
|
+
from,
|
|
2747
|
+
to: {
|
|
2748
|
+
definition: {
|
|
2749
|
+
kind: 'arrow',
|
|
2750
|
+
source: {
|
|
2751
|
+
kind: 'source_reference',
|
|
2752
|
+
name: 's',
|
|
2753
|
+
},
|
|
2754
|
+
view: {
|
|
2755
|
+
kind: 'segment',
|
|
2756
|
+
operations: [group_by('d1'), group_by('d2'), aggregate('m1')],
|
|
2757
|
+
},
|
|
2758
|
+
},
|
|
2759
|
+
},
|
|
2760
|
+
malloy: dedent`
|
|
2761
|
+
run: s -> {
|
|
2762
|
+
group_by:
|
|
2763
|
+
d1
|
|
2764
|
+
d2
|
|
2765
|
+
aggregate: m1
|
|
2766
|
+
}
|
|
2767
|
+
`,
|
|
2768
|
+
});
|
|
2769
|
+
});
|
|
2770
|
+
test('add GB, NEST, AGG', () => {
|
|
2771
|
+
const from: Malloy.Query = {
|
|
2772
|
+
definition: {
|
|
2773
|
+
kind: 'arrow',
|
|
2774
|
+
source: {
|
|
2775
|
+
kind: 'source_reference',
|
|
2776
|
+
name: 's',
|
|
2777
|
+
},
|
|
2778
|
+
view: {
|
|
2779
|
+
kind: 'segment',
|
|
2780
|
+
operations: [],
|
|
2781
|
+
},
|
|
2782
|
+
},
|
|
2783
|
+
};
|
|
2784
|
+
expect((q: ASTQuery) => {
|
|
2785
|
+
const segment = q.getOrAddDefaultSegment();
|
|
2786
|
+
segment.addGroupBy('d1');
|
|
2787
|
+
segment.addNest('v1');
|
|
2788
|
+
segment.addAggregate('m1');
|
|
2789
|
+
}).toModifyQuery({
|
|
2790
|
+
model,
|
|
2791
|
+
from,
|
|
2792
|
+
to: {
|
|
2793
|
+
definition: {
|
|
2794
|
+
kind: 'arrow',
|
|
2795
|
+
source: {
|
|
2796
|
+
kind: 'source_reference',
|
|
2797
|
+
name: 's',
|
|
2798
|
+
},
|
|
2799
|
+
view: {
|
|
2800
|
+
kind: 'segment',
|
|
2801
|
+
operations: [group_by('d1'), aggregate('m1'), nest('v1')],
|
|
2802
|
+
},
|
|
2803
|
+
},
|
|
2804
|
+
},
|
|
2805
|
+
malloy: dedent`
|
|
2806
|
+
run: s -> {
|
|
2807
|
+
group_by: d1
|
|
2808
|
+
aggregate: m1
|
|
2809
|
+
nest: v1
|
|
2810
|
+
}
|
|
2811
|
+
`,
|
|
2812
|
+
});
|
|
2813
|
+
});
|
|
2814
|
+
test('add GB, LIMIT, AGG', () => {
|
|
2815
|
+
const from: Malloy.Query = {
|
|
2816
|
+
definition: {
|
|
2817
|
+
kind: 'arrow',
|
|
2818
|
+
source: {
|
|
2819
|
+
kind: 'source_reference',
|
|
2820
|
+
name: 's',
|
|
2821
|
+
},
|
|
2822
|
+
view: {
|
|
2823
|
+
kind: 'segment',
|
|
2824
|
+
operations: [],
|
|
2825
|
+
},
|
|
2826
|
+
},
|
|
2827
|
+
};
|
|
2828
|
+
expect((q: ASTQuery) => {
|
|
2829
|
+
const segment = q.getOrAddDefaultSegment();
|
|
2830
|
+
segment.addGroupBy('d1');
|
|
2831
|
+
segment.setLimit(10);
|
|
2832
|
+
segment.addAggregate('m1');
|
|
2833
|
+
}).toModifyQuery({
|
|
2834
|
+
model,
|
|
2835
|
+
from,
|
|
2836
|
+
to: {
|
|
2837
|
+
definition: {
|
|
2838
|
+
kind: 'arrow',
|
|
2839
|
+
source: {
|
|
2840
|
+
kind: 'source_reference',
|
|
2841
|
+
name: 's',
|
|
2842
|
+
},
|
|
2843
|
+
view: {
|
|
2844
|
+
kind: 'segment',
|
|
2845
|
+
operations: [
|
|
2846
|
+
group_by('d1'),
|
|
2847
|
+
aggregate('m1'),
|
|
2848
|
+
{kind: 'limit', limit: 10},
|
|
2849
|
+
],
|
|
2850
|
+
},
|
|
2851
|
+
},
|
|
2852
|
+
},
|
|
2853
|
+
malloy: dedent`
|
|
2854
|
+
run: s -> {
|
|
2855
|
+
group_by: d1
|
|
2856
|
+
aggregate: m1
|
|
2857
|
+
limit: 10
|
|
2858
|
+
}
|
|
2859
|
+
`,
|
|
2860
|
+
});
|
|
2861
|
+
});
|
|
2862
|
+
test('add HAVING, WHERE, GROUP BY, LIMIT', () => {
|
|
2863
|
+
const from: Malloy.Query = {
|
|
2864
|
+
definition: {
|
|
2865
|
+
kind: 'arrow',
|
|
2866
|
+
source: {
|
|
2867
|
+
kind: 'source_reference',
|
|
2868
|
+
name: 's',
|
|
2869
|
+
},
|
|
2870
|
+
view: {
|
|
2871
|
+
kind: 'segment',
|
|
2872
|
+
operations: [],
|
|
2873
|
+
},
|
|
2874
|
+
},
|
|
2875
|
+
};
|
|
2876
|
+
expect((q: ASTQuery) => {
|
|
2877
|
+
const segment = q.getOrAddDefaultSegment();
|
|
2878
|
+
segment.addHaving('m1', '> 10');
|
|
2879
|
+
segment.addWhere('d1', '> 10');
|
|
2880
|
+
segment.addGroupBy('d2');
|
|
2881
|
+
segment.setLimit(10);
|
|
2882
|
+
}).toModifyQuery({
|
|
2883
|
+
model,
|
|
2884
|
+
from,
|
|
2885
|
+
to: {
|
|
2886
|
+
definition: {
|
|
2887
|
+
kind: 'arrow',
|
|
2888
|
+
source: {
|
|
2889
|
+
kind: 'source_reference',
|
|
2890
|
+
name: 's',
|
|
2891
|
+
},
|
|
2892
|
+
view: {
|
|
2893
|
+
kind: 'segment',
|
|
2894
|
+
operations: [
|
|
2895
|
+
group_by('d2'),
|
|
2896
|
+
{
|
|
2897
|
+
kind: 'where',
|
|
2898
|
+
filter: {
|
|
2899
|
+
kind: 'filter_string',
|
|
2900
|
+
filter: '> 10',
|
|
2901
|
+
field_reference: {name: 'd1'},
|
|
2902
|
+
},
|
|
2903
|
+
},
|
|
2904
|
+
{
|
|
2905
|
+
kind: 'having',
|
|
2906
|
+
filter: {
|
|
2907
|
+
kind: 'filter_string',
|
|
2908
|
+
filter: '> 10',
|
|
2909
|
+
field_reference: {name: 'm1'},
|
|
2910
|
+
},
|
|
2911
|
+
},
|
|
2912
|
+
{kind: 'limit', limit: 10},
|
|
2913
|
+
],
|
|
2914
|
+
},
|
|
2915
|
+
},
|
|
2916
|
+
},
|
|
2917
|
+
malloy: dedent`
|
|
2918
|
+
run: s -> {
|
|
2919
|
+
group_by: d2
|
|
2920
|
+
where: d1 ~ f\`> 10\`
|
|
2921
|
+
having: m1 ~ f\`> 10\`
|
|
2922
|
+
limit: 10
|
|
2923
|
+
}
|
|
2924
|
+
`,
|
|
2925
|
+
});
|
|
2926
|
+
});
|
|
2927
|
+
});
|
|
2624
2928
|
});
|
package/src/query-ast.ts
CHANGED
|
@@ -2574,11 +2574,13 @@ export class ASTSegmentViewDefinition
|
|
|
2574
2574
|
}
|
|
2575
2575
|
|
|
2576
2576
|
private DEFAULT_INSERTION_ORDER: Malloy.ViewOperationType[] = [
|
|
2577
|
-
'where',
|
|
2578
2577
|
'group_by',
|
|
2579
2578
|
'aggregate',
|
|
2579
|
+
'where',
|
|
2580
|
+
'having',
|
|
2580
2581
|
'nest',
|
|
2581
2582
|
'order_by',
|
|
2583
|
+
'limit',
|
|
2582
2584
|
];
|
|
2583
2585
|
|
|
2584
2586
|
private findInsertionPoint(kind: Malloy.ViewOperationType): number {
|
|
@@ -2600,7 +2602,7 @@ export class ASTSegmentViewDefinition
|
|
|
2600
2602
|
);
|
|
2601
2603
|
for (const laterType of laterOperations) {
|
|
2602
2604
|
const firstOfType = this.firstIndexOfOperationType(laterType);
|
|
2603
|
-
return firstOfType;
|
|
2605
|
+
if (firstOfType > -1) return firstOfType;
|
|
2604
2606
|
}
|
|
2605
2607
|
return this.operations.length;
|
|
2606
2608
|
}
|
|
@@ -4191,7 +4193,7 @@ export class ASTWhereViewOperation extends ASTObjectNode<
|
|
|
4191
4193
|
filter: ASTFilter;
|
|
4192
4194
|
}
|
|
4193
4195
|
> {
|
|
4194
|
-
readonly kind: Malloy.ViewOperationType = '
|
|
4196
|
+
readonly kind: Malloy.ViewOperationType = 'where';
|
|
4195
4197
|
constructor(public node: Malloy.ViewOperationWithWhere) {
|
|
4196
4198
|
super(node, {
|
|
4197
4199
|
kind: 'where',
|
|
@@ -4222,7 +4224,7 @@ export class ASTHavingViewOperation extends ASTObjectNode<
|
|
|
4222
4224
|
filter: ASTFilter;
|
|
4223
4225
|
}
|
|
4224
4226
|
> {
|
|
4225
|
-
readonly kind: Malloy.ViewOperationType = '
|
|
4227
|
+
readonly kind: Malloy.ViewOperationType = 'having';
|
|
4226
4228
|
constructor(public node: Malloy.ViewOperationWithHaving) {
|
|
4227
4229
|
super(node, {
|
|
4228
4230
|
kind: 'having',
|
|
@@ -4580,8 +4582,6 @@ export class ASTAnnotation extends ASTObjectNode<
|
|
|
4580
4582
|
value: string;
|
|
4581
4583
|
}
|
|
4582
4584
|
> {
|
|
4583
|
-
readonly kind: Malloy.ViewOperationType = 'limit';
|
|
4584
|
-
|
|
4585
4585
|
get value() {
|
|
4586
4586
|
return this.children.value;
|
|
4587
4587
|
}
|