Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-16.0] Fix aggregation on outer joins (#12298) #12311

Merged
merged 3 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,17 @@ func TestAggregateRandom(t *testing.T) {

mcmp.AssertMatches("SELECT /*vt+ PLANNER=gen4 */ t1.shardKey, t1.name, count(t2.id) FROM t1 JOIN t2 ON t1.value != t2.shardKey GROUP BY t1.t1_id", `[[INT64(1) VARCHAR("name 1") INT64(2)] [INT64(2) VARCHAR("name 2") INT64(2)]]`)
}

// TestAggregateLeftJoin tests that aggregates work with left joins and does not ignore the count when column value does not match the right side table.
func TestAggregateLeftJoin(t *testing.T) {
mcmp, closer := start(t)
defer closer()

mcmp.Exec("insert into t1(t1_id, name, value, shardKey) values (11, 'r', 'r', 1), (3, 'r', 'r', 0)")
mcmp.Exec("insert into t2(id, shardKey) values (11, 1)")

mcmp.AssertMatchesNoOrder("SELECT t1.shardkey FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[INT64(1)] [INT64(0)]]`)
mcmp.AssertMatches("SELECT count(t1.shardkey) FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[INT64(2)]]`)
mcmp.AssertMatches("SELECT count(*) FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[INT64(2)]]`)
mcmp.AssertMatches("SELECT sum(t1.shardkey) FROM t1 LEFT JOIN t2 ON t1.t1_id = t2.id", `[[DECIMAL(1)]]`)
}
8 changes: 7 additions & 1 deletion go/vt/vtgate/planbuilder/horizon_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,13 @@ func generateAggregateParams(aggrs []operators.Aggr, aggrParamOffsets [][]offset
aggrExpr = &sqlparser.BinaryExpr{
Operator: sqlparser.MultOp,
Left: aggrExpr,
Right: curr,
Right: &sqlparser.FuncExpr{
Name: sqlparser.NewIdentifierCI("coalesce"),
Exprs: sqlparser.SelectExprs{
&sqlparser.AliasedExpr{Expr: curr},
&sqlparser.AliasedExpr{Expr: sqlparser.NewIntLiteral("1")},
},
},
}
}
}
Expand Down
78 changes: 69 additions & 9 deletions go/vt/vtgate/planbuilder/testdata/aggr_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -2926,7 +2926,7 @@
{
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] * [COLUMN 1] as count(*)"
"[COLUMN 0] * COALESCE([COLUMN 1], INT64(1)) as count(*)"
],
"Inputs": [
{
Expand Down Expand Up @@ -3045,7 +3045,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as a",
"[COLUMN 2] * [COLUMN 3] as count(*)",
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as count(*)",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -3108,7 +3108,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as a",
"[COLUMN 2] * [COLUMN 3] as count(user_extra.a)",
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as count(user_extra.a)",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -3170,8 +3170,8 @@
{
"OperatorType": "Projection",
"Expressions": [
"([COLUMN 2] * [COLUMN 3]) * [COLUMN 4] as count(u.textcol1)",
"([COLUMN 5] * [COLUMN 6]) * [COLUMN 7] as count(ue.foo)",
"([COLUMN 2] * COALESCE([COLUMN 3], INT64(1))) * COALESCE([COLUMN 4], INT64(1)) as count(u.textcol1)",
"([COLUMN 5] * COALESCE([COLUMN 6], INT64(1))) * COALESCE([COLUMN 7], INT64(1)) as count(ue.foo)",
"[COLUMN 0] as bar",
"[COLUMN 1]"
],
Expand Down Expand Up @@ -3804,7 +3804,7 @@
{
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 2] * [COLUMN 3] as sum(col)"
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as sum(col)"
],
"Inputs": [
{
Expand Down Expand Up @@ -4063,7 +4063,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as id",
"[COLUMN 2] * [COLUMN 3] as count(u.`name`)",
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as count(u.`name`)",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -4190,7 +4190,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as id",
"[COLUMN 2] * [COLUMN 3] as count(*)",
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as count(*)",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -4847,7 +4847,7 @@
"Expressions": [
"[COLUMN 0] as id",
"[COLUMN 2] as name",
"[COLUMN 3] * [COLUMN 4] as count(m.predef1)",
"[COLUMN 3] * COALESCE([COLUMN 4], INT64(1)) as count(m.predef1)",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -4904,5 +4904,65 @@
"user.user_extra"
]
}
},
{
"comment": "Aggregation in a left join query",
"query": "select count (u.id) from user u left join user_extra ue on u.col = ue.col",
"plan": {
"QueryType": "SELECT",
"Original": "select count (u.id) from user u left join user_extra ue on u.col = ue.col",
"Instructions": {
"OperatorType": "Aggregate",
"Variant": "Scalar",
"Aggregates": "sum_count(0) AS count(u.id)",
"Inputs": [
{
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] * COALESCE([COLUMN 1], INT64(1)) as count(u.id)"
],
"Inputs": [
{
"OperatorType": "Join",
"Variant": "LeftJoin",
"JoinColumnIndexes": "L:1,R:1",
"JoinVars": {
"u_col": 0
},
"TableName": "`user`_user_extra",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select u.col, count(u.id) from `user` as u where 1 != 1 group by u.col",
"Query": "select u.col, count(u.id) from `user` as u group by u.col",
"Table": "`user`"
},
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select 1, count(*) from user_extra as ue where 1 != 1 group by 1",
"Query": "select 1, count(*) from user_extra as ue where ue.col = :u_col group by 1",
"Table": "user_extra"
}
]
}
]
}
]
},
"TablesUsed": [
"user.user",
"user.user_extra"
]
}
}
]
2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/testdata/filter_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -6610,7 +6610,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as textcol1",
"[COLUMN 1] * [COLUMN 2] as sum(a.id)"
"[COLUMN 1] * COALESCE([COLUMN 2], INT64(1)) as sum(a.id)"
],
"Inputs": [
{
Expand Down
18 changes: 9 additions & 9 deletions go/vt/vtgate/planbuilder/testdata/tpch_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as l_orderkey",
"([COLUMN 6] * [COLUMN 7]) * [COLUMN 8] as revenue",
"([COLUMN 6] * COALESCE([COLUMN 7], INT64(1))) * COALESCE([COLUMN 8], INT64(1)) as revenue",
"[COLUMN 1] as o_orderdate",
"[COLUMN 2] as o_shippriority",
"[COLUMN 5]",
Expand Down Expand Up @@ -247,7 +247,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as n_name",
"(((([COLUMN 2] * [COLUMN 3]) * [COLUMN 4]) * [COLUMN 5]) * [COLUMN 6]) * [COLUMN 7] as revenue",
"(((([COLUMN 2] * COALESCE([COLUMN 3], INT64(1))) * COALESCE([COLUMN 4], INT64(1))) * COALESCE([COLUMN 5], INT64(1))) * COALESCE([COLUMN 6], INT64(1))) * COALESCE([COLUMN 7], INT64(1)) as revenue",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -512,7 +512,7 @@
"[COLUMN 4] as supp_nation",
"[COLUMN 5] as cust_nation",
"[COLUMN 6] as l_year",
"(((([COLUMN 10] * [COLUMN 11]) * [COLUMN 12]) * [COLUMN 13]) * [COLUMN 14]) * [COLUMN 15] as revenue",
"(((([COLUMN 10] * COALESCE([COLUMN 11], INT64(1))) * COALESCE([COLUMN 12], INT64(1))) * COALESCE([COLUMN 13], INT64(1))) * COALESCE([COLUMN 14], INT64(1))) * COALESCE([COLUMN 15], INT64(1)) as revenue",
"[COLUMN 9]",
"[COLUMN 8]",
"[COLUMN 7]"
Expand Down Expand Up @@ -720,7 +720,7 @@
"Expressions": [
"[COLUMN 0] as c_custkey",
"[COLUMN 1] as c_name",
"(([COLUMN 14] * [COLUMN 15]) * [COLUMN 16]) * [COLUMN 17] as revenue",
"(([COLUMN 14] * COALESCE([COLUMN 15], INT64(1))) * COALESCE([COLUMN 16], INT64(1))) * COALESCE([COLUMN 17], INT64(1)) as revenue",
"[COLUMN 2] as c_acctbal",
"[COLUMN 4] as n_name",
"[COLUMN 5] as c_address",
Expand Down Expand Up @@ -896,8 +896,8 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as l_shipmode",
"[COLUMN 2] * [COLUMN 3] as high_line_count",
"[COLUMN 4] * [COLUMN 5] as low_line_count",
"[COLUMN 2] * COALESCE([COLUMN 3], INT64(1)) as high_line_count",
"[COLUMN 4] * COALESCE([COLUMN 5], INT64(1)) as low_line_count",
"[COLUMN 1]"
],
"Inputs": [
Expand Down Expand Up @@ -1153,7 +1153,7 @@
"[COLUMN 4] as o_orderkey",
"[COLUMN 1] as o_orderdate",
"[COLUMN 0] as o_totalprice",
"([COLUMN 10] * [COLUMN 11]) * [COLUMN 12] as sum(l_quantity)",
"([COLUMN 10] * COALESCE([COLUMN 11], INT64(1))) * COALESCE([COLUMN 12], INT64(1)) as sum(l_quantity)",
"[COLUMN 9]",
"[COLUMN 8]",
"[COLUMN 7]",
Expand Down Expand Up @@ -1288,7 +1288,7 @@
{
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] * [COLUMN 1] as revenue"
"[COLUMN 0] * COALESCE([COLUMN 1], INT64(1)) as revenue"
],
"Inputs": [
{
Expand Down Expand Up @@ -1370,7 +1370,7 @@
"OperatorType": "Projection",
"Expressions": [
"[COLUMN 0] as s_name",
"(([COLUMN 2] * [COLUMN 3]) * [COLUMN 4]) * [COLUMN 5] as numwait",
"(([COLUMN 2] * COALESCE([COLUMN 3], INT64(1))) * COALESCE([COLUMN 4], INT64(1))) * COALESCE([COLUMN 5], INT64(1)) as numwait",
"[COLUMN 1]"
],
"Inputs": [
Expand Down