Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 730be6c

Browse files
committed
done
1 parent 5a41028 commit 730be6c

File tree

3 files changed

+250
-271
lines changed

3 files changed

+250
-271
lines changed

quesma/queryparser/pancake_sql_query_generation_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ func TestPancakeQueryGeneration(t *testing.T) {
5252
if filters(test.TestName) {
5353
t.Skip("Fix filters")
5454
}
55-
if test.TestName == "complex sum_bucket. Reproduce: Visualize -> Vertical Bar: Metrics: Sum Bucket (Bucket: Date Histogram, Metric: Average), Buckets: X-Asis: Histogram(file:opensearch-visualize/pipeline_agg_req,nr:22)" {
56-
t.Skip("error: filter(s)/range/dataRange aggregation must be the last bucket aggregation")
57-
}
5855

5956
if test.TestName == "Terms with order by top metrics(file:kibana-visualize/agg_req,nr:8)" {
6057
t.Skip("Need to implement order by top metrics (talk with Jacek, he has an idea)")
@@ -72,10 +69,6 @@ func TestPancakeQueryGeneration(t *testing.T) {
7269
t.Skip("Was skipped before. Wrong key in max_bucket, should be an easy fix")
7370
}
7471

75-
if test.TestName == "complex sum_bucket. Reproduce: Visualize -> Vertical Bar: Metrics: Sum Bucket (Bucket: Date Histogram, Metric: Average), Buckets: X-Asis: Histogram(file:opensearch-visualize/pipeline_agg_req,nr:24)" {
76-
t.Skip("Was skipped before, no expected results")
77-
}
78-
7972
// TODO: add test for filter(s) both at the beginning and end of aggregation tree
8073

8174
fmt.Println("i:", i, "test:", test.TestName)

quesma/queryparser/pancake_transformer.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -408,48 +408,57 @@ func (a *pancakeTransformer) aggregationTreeToPancakes(topLevel pancakeAggregati
408408
// TODO: if both top_hits/top_metrics, and filters, it probably won't work...
409409
// Care: order of these two functions is unfortunately important.
410410
// Should be fixed after this TODO
411-
newFiltersPancakes := a.createFiltersPancakes(&newPancake)
411+
newCombinatorPancakes := a.createCombinatorPancakes(&newPancake)
412412
additionalTopHitPancakes, err := a.createTopHitAndTopMetricsPancakes(&newPancake)
413413
if err != nil {
414414
return nil, err
415415
}
416416

417417
pancakeResults = append(pancakeResults, additionalTopHitPancakes...)
418-
pancakeResults = append(pancakeResults, newFiltersPancakes...)
418+
pancakeResults = append(pancakeResults, newCombinatorPancakes...)
419419
}
420420

421421
return
422422
}
423423

424424
// createFiltersPancakes only does something, if first layer aggregation is Filters.
425425
// It creates new pancakes for each filter in that aggregation, and updates `pancake` to have only first filter.
426-
func (a *pancakeTransformer) createFiltersPancakes(pancake *pancakeModel) (newPancakes []*pancakeModel) {
426+
func (a *pancakeTransformer) createCombinatorPancakes(pancake *pancakeModel) (newPancakes []*pancakeModel) {
427427
if len(pancake.layers) == 0 || pancake.layers[0].nextBucketAggregation == nil {
428428
return
429429
}
430430

431431
firstLayer := pancake.layers[0]
432-
filters, isFilters := firstLayer.nextBucketAggregation.queryType.(bucket_aggregations.Filters)
433-
canSimplyAddFilterToWhereClause := len(firstLayer.currentMetricAggregations) == 0 && len(firstLayer.currentPipelineAggregations) == 0
434-
areNewPancakesReallyNeeded := len(pancake.layers) > 1 // if there is only one layer, it's better to get it done with combinators.
432+
combinator, isCombinator := firstLayer.nextBucketAggregation.queryType.(bucket_aggregations.CombinatorAggregationInterface)
433+
if !isCombinator {
434+
return
435+
}
436+
437+
noMoreBucket := len(pancake.layers) == 1 || (len(pancake.layers) == 2 && pancake.layers[1].nextBucketAggregation == nil)
438+
noMetricOnFirstLayer := len(firstLayer.currentMetricAggregations) == 0 && len(firstLayer.currentPipelineAggregations) == 0
439+
canSimplyAddCombinatorToWhereClause := noMoreBucket && noMetricOnFirstLayer
440+
areNewPancakesReallyNeeded := len(pancake.layers) > 1 // if there is only one layer above combinator, it easily can be done with 1 pancake, no need for more
435441

436-
if !isFilters || !canSimplyAddFilterToWhereClause || !areNewPancakesReallyNeeded || len(filters.Filters) == 0 {
442+
groups := combinator.CombinatorGroups()
443+
if canSimplyAddCombinatorToWhereClause || !areNewPancakesReallyNeeded || len(groups) == 0 {
437444
return
438445
}
439446

440-
// First create N-1 new pancakes, each with different filter
441-
for i := 1; i < len(filters.Filters); i++ {
447+
combinatorSplit := combinator.CombinatorSplit()
448+
combinatorGroups := combinator.CombinatorGroups()
449+
// First create N-1 new pancakes, each with different filter (we use 0th group to create new, we'll update it at the end)
450+
for i := 1; i < len(groups); i++ {
442451
newPancake := pancake.Clone()
443452
bucketAggr := newPancake.layers[0].nextBucketAggregation.ShallowClone()
444-
bucketAggr.queryType = filters.NewFiltersSingleFilter(i)
453+
bucketAggr.queryType = combinatorSplit[i]
445454
newPancake.layers[0] = newPancakeModelLayer(&bucketAggr)
446-
newPancake.whereClause = model.And([]model.Expr{newPancake.whereClause, filters.Filters[i].Sql.WhereClause})
455+
newPancake.whereClause = model.And([]model.Expr{newPancake.whereClause, combinatorGroups[i].WhereClause})
447456
newPancakes = append(newPancakes, newPancake)
448457
}
449458

450459
// Then update original to have 1 filter as well
451-
pancake.layers[0].nextBucketAggregation.queryType = filters.NewFiltersSingleFilter(0)
452-
pancake.whereClause = model.And([]model.Expr{pancake.whereClause, filters.Filters[0].Sql.WhereClause})
460+
pancake.layers[0].nextBucketAggregation.queryType = combinatorSplit[0]
461+
pancake.whereClause = model.And([]model.Expr{pancake.whereClause, combinatorGroups[0].WhereClause})
453462

454463
return
455464
}

0 commit comments

Comments
 (0)