Skip to content

Commit f30abe0

Browse files
Merge branch 'release-18.0' of https://github.com/vitessio/vitess into release-18.0-github
Signed-off-by: Arthur Schreiber <[email protected]>
2 parents d112b3f + aca5683 commit f30abe0

File tree

5 files changed

+103
-17
lines changed

5 files changed

+103
-17
lines changed

go/vt/vtgate/planbuilder/operators/SQL_builder.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -564,14 +564,20 @@ func buildProjection(op *Projection, qb *queryBuilder) error {
564564
}
565565

566566
func buildApplyJoin(op *ApplyJoin, qb *queryBuilder) error {
567-
predicates := slice.Map(op.JoinPredicates, func(jc JoinColumn) sqlparser.Expr {
567+
predicates, err := slice.MapWithError(op.JoinPredicates, func(jc JoinColumn) (sqlparser.Expr, error) {
568568
// since we are adding these join predicates, we need to mark to broken up version (RHSExpr) of it as done
569-
_ = qb.ctx.SkipJoinPredicates(jc.Original.Expr)
570-
return jc.Original.Expr
569+
err := qb.ctx.SkipJoinPredicates(jc.Original.Expr)
570+
if err != nil {
571+
return nil, err
572+
}
573+
return jc.Original.Expr, nil
571574
})
575+
if err != nil {
576+
return err
577+
}
572578

573579
pred := sqlparser.AndExpressions(predicates...)
574-
err := buildQuery(op.LHS, qb)
580+
err = buildQuery(op.LHS, qb)
575581
if err != nil {
576582
return err
577583
}

go/vt/vtgate/planbuilder/operators/apply_join.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,21 @@ func (aj *ApplyJoin) AddJoinPredicate(ctx *plancontext.PlanningContext, expr sql
153153
if expr == nil {
154154
return nil
155155
}
156-
col, err := BreakExpressionInLHSandRHS(ctx, expr, TableID(aj.LHS))
157-
if err != nil {
158-
return err
159-
}
160-
aj.JoinPredicates = append(aj.JoinPredicates, col)
161-
rhs, err := aj.RHS.AddPredicate(ctx, col.RHSExpr)
162-
if err != nil {
163-
return err
156+
rhs := aj.RHS
157+
predicates := sqlparser.SplitAndExpression(nil, expr)
158+
for _, pred := range predicates {
159+
col, err := BreakExpressionInLHSandRHS(ctx, pred, TableID(aj.LHS))
160+
if err != nil {
161+
return err
162+
}
163+
aj.JoinPredicates = append(aj.JoinPredicates, col)
164+
ctx.AddJoinPredicates(pred, col.RHSExpr)
165+
rhs, err = rhs.AddPredicate(ctx, col.RHSExpr)
166+
if err != nil {
167+
return err
168+
}
164169
}
170+
165171
aj.RHS = rhs
166172

167173
return nil

go/vt/vtgate/planbuilder/operators/operator.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops"
4545
"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/rewrite"
4646
"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
47+
"vitess.io/vitess/go/vt/vtgate/semantics"
4748
)
4849

4950
type (
@@ -81,10 +82,8 @@ func PlanQuery(ctx *plancontext.PlanningContext, stmt sqlparser.Statement) (ops.
8182
return nil, err
8283
}
8384

84-
_, isRoute := op.(*Route)
85-
if !isRoute && ctx.SemTable.NotSingleRouteErr != nil {
86-
// If we got here, we don't have a single shard plan
87-
return nil, ctx.SemTable.NotSingleRouteErr
85+
if err := checkSingleRouteError(ctx, op); err != nil {
86+
return nil, err
8887
}
8988

9089
return op, err
@@ -161,3 +160,27 @@ func transformColumnsToSelectExprs(ctx *plancontext.PlanningContext, op ops.Oper
161160
})
162161
return selExprs, nil
163162
}
163+
164+
// checkSingleRouteError checks if the query has a NotSingleRouteErr and more than one route, and returns an error if it does
165+
func checkSingleRouteError(ctx *plancontext.PlanningContext, op ops.Operator) error {
166+
if ctx.SemTable.NotSingleRouteErr == nil {
167+
return nil
168+
}
169+
routes := 0
170+
visitF := func(op ops.Operator, _ semantics.TableSet, _ bool) (ops.Operator, *rewrite.ApplyResult, error) {
171+
switch op.(type) {
172+
case *Route:
173+
routes++
174+
}
175+
return op, rewrite.SameTree, nil
176+
}
177+
178+
// we'll walk the tree and count the number of routes
179+
_, _ = rewrite.TopDown(op, TableID, visitF, stopAtRoute)
180+
181+
if routes <= 1 {
182+
return nil
183+
}
184+
185+
return ctx.SemTable.NotSingleRouteErr
186+
}

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@
511511
"Sharded": true
512512
},
513513
"FieldQuery": "select 42 from `user` as u, user_extra as ue, music as m where 1 != 1",
514-
"Query": "select 42 from `user` as u, user_extra as ue, music as m where u.id = ue.user_id and u.id = :m_user_id and (u.foo or :m_foo or ue.foo) and m.user_id = u.id and (u.foo or m.foo or ue.foo)",
514+
"Query": "select 42 from `user` as u, user_extra as ue, music as m where u.id = ue.user_id and m.user_id = u.id and (u.foo or m.foo or ue.foo)",
515515
"Table": "`user`, music, user_extra"
516516
},
517517
"TablesUsed": [
@@ -4193,5 +4193,27 @@
41934193
"zlookup_unique.t1"
41944194
]
41954195
}
4196+
},
4197+
{
4198+
"comment": "lots of joins that can be merged should not confuse the planner",
4199+
"query": "SELECT `music`.id FROM `music` INNER JOIN music `music2` ON `music2`.`id` = `music`.`id` INNER JOIN music `music3` ON `music3`.`id` = `music2`.`id` INNER JOIN music `music4` ON `music4`.`id` = `music3`.`id` WHERE music.user_index = music4.user_index",
4200+
"plan": {
4201+
"QueryType": "SELECT",
4202+
"Original": "SELECT `music`.id FROM `music` INNER JOIN music `music2` ON `music2`.`id` = `music`.`id` INNER JOIN music `music3` ON `music3`.`id` = `music2`.`id` INNER JOIN music `music4` ON `music4`.`id` = `music3`.`id` WHERE music.user_index = music4.user_index",
4203+
"Instructions": {
4204+
"OperatorType": "Route",
4205+
"Variant": "Scatter",
4206+
"Keyspace": {
4207+
"Name": "user",
4208+
"Sharded": true
4209+
},
4210+
"FieldQuery": "select music.id from music, music as music2, music as music3, music as music4 where 1 != 1",
4211+
"Query": "select music.id from music, music as music2, music as music3, music as music4 where music2.id = music.id and music4.id = music3.id and music3.id = music2.id and music.user_index = music4.user_index",
4212+
"Table": "music"
4213+
},
4214+
"TablesUsed": [
4215+
"user.music"
4216+
]
4217+
}
41964218
}
41974219
]

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@
6565
]
6666
}
6767
},
68+
{
69+
"comment": "join on sharding column with limit - should be a simple scatter query and limit on top with non resolved columns",
70+
"query": "select * from user u join user_metadata um on u.id = um.user_id where foo=41 limit 20",
71+
"plan": {
72+
"QueryType": "SELECT",
73+
"Original": "select * from user u join user_metadata um on u.id = um.user_id where foo=41 limit 20",
74+
"Instructions": {
75+
"OperatorType": "Limit",
76+
"Count": "INT64(20)",
77+
"Inputs": [
78+
{
79+
"OperatorType": "Route",
80+
"Variant": "Scatter",
81+
"Keyspace": {
82+
"Name": "user",
83+
"Sharded": true
84+
},
85+
"FieldQuery": "select * from `user` as u, user_metadata as um where 1 != 1",
86+
"Query": "select * from `user` as u, user_metadata as um where foo = 41 and u.id = um.user_id limit :__upper_limit",
87+
"Table": "`user`, user_metadata"
88+
}
89+
]
90+
},
91+
"TablesUsed": [
92+
"user.user",
93+
"user.user_metadata"
94+
]
95+
}
96+
},
6897
{
6998
"comment": "select with timeout directive sets QueryTimeout in the route",
7099
"query": "select /*vt+ QUERY_TIMEOUT_MS=1000 */ * from user",

0 commit comments

Comments
 (0)