Skip to content

Commit 60eafac

Browse files
Fix AVG() sharded planning (#15626)
Signed-off-by: Manan Gupta <manan@planetscale.com>
1 parent 18d4128 commit 60eafac

File tree

4 files changed

+73
-14
lines changed

4 files changed

+73
-14
lines changed

go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ func TestAggregateTypes(t *testing.T) {
9191
mcmp.SkipIfBinaryIsBelowVersion(19, "vtgate")
9292
mcmp.AssertMatches("select avg(val1) from aggr_test", `[[FLOAT64(0)]]`)
9393
})
94+
mcmp.Run("Average with group by without selecting the grouped columns", func(mcmp *utils.MySQLCompare) {
95+
mcmp.SkipIfBinaryIsBelowVersion(20, "vtgate")
96+
mcmp.AssertMatches("select avg(val2) from aggr_test group by val1 order by val1", `[[DECIMAL(1.0000)] [DECIMAL(1.0000)] [DECIMAL(3.5000)] [NULL] [DECIMAL(1.0000)]]`)
97+
})
9498
}
9599

96100
func TestGroupBy(t *testing.T) {

go/vt/vtgate/planbuilder/operators/projection.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,12 @@ var _ selectExpressions = (*Projection)(nil)
182182

183183
// createSimpleProjection returns a projection where all columns are offsets.
184184
// used to change the name and order of the columns in the final output
185-
func createSimpleProjection(ctx *plancontext.PlanningContext, qp *QueryProjection, src Operator) *Projection {
185+
func createSimpleProjection(ctx *plancontext.PlanningContext, selExprs []sqlparser.SelectExpr, src Operator) *Projection {
186186
p := newAliasedProjection(src)
187-
for _, e := range qp.SelectExprs {
188-
ae, err := e.GetAliasedExpr()
189-
if err != nil {
190-
panic(err)
187+
for _, e := range selExprs {
188+
ae, isAe := e.(*sqlparser.AliasedExpr)
189+
if !isAe {
190+
panic(vterrors.VT09015())
191191
}
192192
offset := p.Source.AddColumn(ctx, true, false, ae)
193193
expr := newProjExpr(ae)

go/vt/vtgate/planbuilder/operators/query_planning.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ import (
2626
)
2727

2828
func planQuery(ctx *plancontext.PlanningContext, root Operator) Operator {
29+
var selExpr sqlparser.SelectExprs
30+
if horizon, isHorizon := root.(*Horizon); isHorizon {
31+
sel := sqlparser.GetFirstSelect(horizon.Query)
32+
selExpr = sqlparser.CloneSelectExprs(sel.SelectExprs)
33+
}
34+
2935
output := runPhases(ctx, root)
3036
output = planOffsets(ctx, output)
3137

@@ -36,7 +42,7 @@ func planQuery(ctx *plancontext.PlanningContext, root Operator) Operator {
3642

3743
output = compact(ctx, output)
3844

39-
return addTruncationOrProjectionToReturnOutput(ctx, root, output)
45+
return addTruncationOrProjectionToReturnOutput(ctx, selExpr, output)
4046
}
4147

4248
// runPhases is the process of figuring out how to perform the operations in the Horizon
@@ -571,24 +577,21 @@ func tryPushUnion(ctx *plancontext.PlanningContext, op *Union) (Operator, *Apply
571577
}
572578

573579
// addTruncationOrProjectionToReturnOutput uses the original Horizon to make sure that the output columns line up with what the user asked for
574-
func addTruncationOrProjectionToReturnOutput(ctx *plancontext.PlanningContext, oldHorizon Operator, output Operator) Operator {
575-
horizon, ok := oldHorizon.(*Horizon)
576-
if !ok {
580+
func addTruncationOrProjectionToReturnOutput(ctx *plancontext.PlanningContext, selExprs sqlparser.SelectExprs, output Operator) Operator {
581+
if len(selExprs) == 0 {
577582
return output
578583
}
579584

580585
cols := output.GetSelectExprs(ctx)
581-
sel := sqlparser.GetFirstSelect(horizon.Query)
582-
if len(sel.SelectExprs) == len(cols) {
586+
if len(selExprs) == len(cols) {
583587
return output
584588
}
585589

586-
if tryTruncateColumnsAt(output, len(sel.SelectExprs)) {
590+
if tryTruncateColumnsAt(output, len(selExprs)) {
587591
return output
588592
}
589593

590-
qp := horizon.getQP(ctx)
591-
proj := createSimpleProjection(ctx, qp, output)
594+
proj := createSimpleProjection(ctx, selExprs, output)
592595
return proj
593596
}
594597

go/vt/vtgate/planbuilder/testdata/select_cases.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,58 @@
16951695
]
16961696
}
16971697
},
1698+
{
1699+
"comment": "avg in sharded keyspace with group by without selecting the group by columns",
1700+
"query": "select avg(intcol) as avg_col from user group by textcol1, textcol2 order by textcol1, textcol2;",
1701+
"plan": {
1702+
"QueryType": "SELECT",
1703+
"Original": "select avg(intcol) as avg_col from user group by textcol1, textcol2 order by textcol1, textcol2;",
1704+
"Instructions": {
1705+
"OperatorType": "SimpleProjection",
1706+
"ColumnNames": [
1707+
"avg_col"
1708+
],
1709+
"Columns": [
1710+
0
1711+
],
1712+
"Inputs": [
1713+
{
1714+
"OperatorType": "Projection",
1715+
"Expressions": [
1716+
"sum(intcol) / count(intcol) as avg_col",
1717+
":1 as textcol1",
1718+
":2 as textcol2"
1719+
],
1720+
"Inputs": [
1721+
{
1722+
"OperatorType": "Aggregate",
1723+
"Variant": "Ordered",
1724+
"Aggregates": "sum(0) AS avg_col, sum_count(3) AS count(intcol)",
1725+
"GroupBy": "1 COLLATE latin1_swedish_ci, (2|4) COLLATE ",
1726+
"Inputs": [
1727+
{
1728+
"OperatorType": "Route",
1729+
"Variant": "Scatter",
1730+
"Keyspace": {
1731+
"Name": "user",
1732+
"Sharded": true
1733+
},
1734+
"FieldQuery": "select sum(intcol) as avg_col, textcol1, textcol2, count(intcol), weight_string(textcol2) from `user` where 1 != 1 group by textcol1, textcol2, weight_string(textcol2)",
1735+
"OrderBy": "1 ASC COLLATE latin1_swedish_ci, (2|4) ASC COLLATE ",
1736+
"Query": "select sum(intcol) as avg_col, textcol1, textcol2, count(intcol), weight_string(textcol2) from `user` group by textcol1, textcol2, weight_string(textcol2) order by textcol1 asc, textcol2 asc",
1737+
"Table": "`user`"
1738+
}
1739+
]
1740+
}
1741+
]
1742+
}
1743+
]
1744+
},
1745+
"TablesUsed": [
1746+
"user.user"
1747+
]
1748+
}
1749+
},
16981750
{
16991751
"comment": "don't filter on the vtgate",
17001752
"query": "select 42 from dual where false",

0 commit comments

Comments
 (0)