[Gen4] Only remove extracted subquery from predicates on merge#11072
[Gen4] Only remove extracted subquery from predicates on merge#11072arthurschreiber wants to merge 1 commit intovitessio:mainfrom
Conversation
When merging a subquery into a route, all vindex predicates were reset and filled again from the route's `SeenPredicates`. For routes of `ApplyJoin` nodes, the `SeenPredicates` list is empty and thus routing information could not be restored correctly. Instead of resetting the vindex predicates, we can just remove all vindex predicate options for the merged subquery instead, and leave all other options untouched. Signed-off-by: Arthur Schreiber <arthurschreiber@github.com>
Review ChecklistHello reviewers! 👋 Please follow this checklist when reviewing this Pull Request. General
Bug fixes
Non-trivial changes
New/Existing features
Backward compatibility
|
|
|
||
| for j, option := range vp.Options { | ||
| if sqlparser.EqualsExpr(option.Predicates[0], extractedSubquery.Original) { | ||
| idx = j |
There was a problem hiding this comment.
I guess we could break here after we found one matching option?
There was a problem hiding this comment.
I am unsure whether the extracted subquery can match more than one vindex option or not. @harshit-gangal, do you know?
Otherwise, let's break yes
There was a problem hiding this comment.
I double checked this. Even if the same inner query exists multiple times in an outer query, each ExtractedSubquery object is unique. This is due to the unique name generated for each subquery's replacement bind variable.
I added a comment over at https://github.com/vitessio/vitess/pull/11104/files#diff-ecda8980a2e86d0f2a98ac67bb7b55d759fa7d1e8037dab2497f8fd167ada4c5R120-R121 that describes this.
| idx := -1 | ||
|
|
||
| for j, option := range vp.Options { | ||
| if sqlparser.EqualsExpr(option.Predicates[0], extractedSubquery.Original) { |
There was a problem hiding this comment.
This only looks at the first predicate in the list. I think that's correct for all single column vindexes. Do we need to do anything special here for multi column vindexes? I don't think there's any other support for subqueries that match against tuples, so multi column vindex (and thus vindex predicates with more than one value) are not relevant yet.
There was a problem hiding this comment.
I think the safest bet would be to check the length of option.Predicates, and, only if the length is equal to one, compare the two predicates.
| idx := -1 | ||
| for i, predicate := range route.SeenPredicates { | ||
| if sqlparser.EqualsExpr(predicate, extractedSubquery) { | ||
| idx = i |
There was a problem hiding this comment.
Same here, we could break after we found one match.
| return nil, err | ||
| outer.Selected = nil | ||
| switch outer.RouteOpCode { | ||
| case engine.DBA, engine.Next, engine.Reference, engine.Unsharded: |
There was a problem hiding this comment.
I've taken this list from resetRoutingSelections, but I'm not sure we can actually ever reach this code with one of these routing op codes? 🤔
There was a problem hiding this comment.
I am unsure too. I am assuming if, for instance, we had a DBA query with a subquery? cc @systay
|
@systay After having talked this through with @evaccaro and @pudiva, there might be a different way of fixing this: diff --git a/go/vt/vtgate/planbuilder/physical/route_planning.go b/go/vt/vtgate/planbuilder/physical/route_planning.go
index 8c78dc4667..5ac19a3e94 100644
--- a/go/vt/vtgate/planbuilder/physical/route_planning.go
+++ b/go/vt/vtgate/planbuilder/physical/route_planning.go
@@ -563,6 +563,7 @@ func createRouteOperatorForJoin(aRoute, bRoute *Route, joinPredicates []sqlparse
VindexPreds: append(aRoute.VindexPreds, bRoute.VindexPreds...),
SysTableTableSchema: append(aRoute.SysTableTableSchema, bRoute.SysTableTableSchema...),
SysTableTableName: sysTableName,
+ SeenPredicates: append(aRoute.SeenPredicates, bRoute.SeenPredicates...),
Source: &ApplyJoin{
LHS: aRoute.Source,
RHS: bRoute.Source,By merging the Which fix do you prefer? 🙇♂️ |
frouioui
left a comment
There was a problem hiding this comment.
Looks good to me. I will let one more person ack this and answer my questions.
| return nil, err | ||
| outer.Selected = nil | ||
| switch outer.RouteOpCode { | ||
| case engine.DBA, engine.Next, engine.Reference, engine.Unsharded: |
There was a problem hiding this comment.
I am unsure too. I am assuming if, for instance, we had a DBA query with a subquery? cc @systay
| idx := -1 | ||
|
|
||
| for j, option := range vp.Options { | ||
| if sqlparser.EqualsExpr(option.Predicates[0], extractedSubquery.Original) { |
There was a problem hiding this comment.
I think the safest bet would be to check the length of option.Predicates, and, only if the length is equal to one, compare the two predicates.
|
|
||
| for j, option := range vp.Options { | ||
| if sqlparser.EqualsExpr(option.Predicates[0], extractedSubquery.Original) { | ||
| idx = j |
There was a problem hiding this comment.
I am unsure whether the extracted subquery can match more than one vindex option or not. @harshit-gangal, do you know?
Otherwise, let's break yes
Description
When merging a subquery into an outer route, all vindex predicates are currently reset and filled again from the outer route's
SeenPredicates.vitess/go/vt/vtgate/planbuilder/physical/route.go
Lines 603 to 623 in 3d376ea
For routes of
ApplyJoinnodes, theSeenPredicateslist is empty and thus routing information could not be restored correctly.Instead of resetting the vindex predicates, we can just remove all vindex predicate options for the merged subquery instead, and leave all other options untouched. This ensures that we still can pick any vindexes derived from the join operation, instead of falling back to a
Scatterroute.Related Issue(s)
This fixes #10823.
Checklist