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

Gen4: Keep track of left and right predicates in outer joins #8895

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions go/test/endtoend/vtgate/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,24 @@ func TestSimpleOrderBy(t *testing.T) {
assertMatches(t, conn, `SELECT id2 FROM t1 ORDER BY id2 ASC`, `[[INT64(5)] [INT64(6)] [INT64(7)] [INT64(8)] [INT64(9)] [INT64(10)]]`)
}

func TestSelectEqualUniqueOuterJoinRightPredicate(t *testing.T) {
defer cluster.PanicHandler(t)
ctx := context.Background()
conn, err := mysql.Connect(ctx, &vtParams)
require.NoError(t, err)
defer conn.Close()

exec(t, conn, `delete from t1`)
exec(t, conn, `delete from t2`)
defer func() {
exec(t, conn, `delete from t1`)
exec(t, conn, `delete from t2`)
}()
exec(t, conn, "insert into t1(id1, id2) values (0,10),(1,9),(2,8),(3,7),(4,6),(5,5)")
exec(t, conn, "insert into t2(id3, id4) values (0,20),(1,19),(2,18),(3,17),(4,16),(5,15)")
assertMatches(t, conn, `SELECT id3 FROM t1 LEFT JOIN t2 ON t1.id1 = t2.id3 WHERE t2.id3 = 10`, `[]`)
}

func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) {
t.Helper()
qr := exec(t, conn, query)
Expand Down
6 changes: 4 additions & 2 deletions go/vt/vtgate/planbuilder/abstract/left_join.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ var _ Operator = (*LeftJoin)(nil)
// PushPredicate implements the Operator interface
func (lj *LeftJoin) PushPredicate(expr sqlparser.Expr, semTable *semantics.SemTable) error {
deps := semTable.RecursiveDeps(expr)
if deps.IsSolvedBy(lj.Left.TableID()) {
switch {
case deps.IsSolvedBy(lj.Left.TableID()):
return lj.Left.PushPredicate(expr, semTable)
case deps.IsSolvedBy(lj.Right.TableID()):
return lj.Right.PushPredicate(expr, semTable)
}

return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "Cannot push predicate: %s", sqlparser.String(expr))
}

Expand Down
18 changes: 9 additions & 9 deletions go/vt/vtgate/planbuilder/gen4_compare_v3_planner.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@ func gen4CompareV3Planner(query string) func(sqlparser.Statement, *sqlparser.Res
// plan statement using Gen4
gen4Primitive, gen4Err := planWithPlannerVersion(statement, vars, ctxVSchema, query, Gen4)

// if onlyGen4 is set to true or Gen4's instruction contain a lock primitive,
// we use only Gen4's primitive and exit early without using V3's.
// since lock primitives can imply the creation or deletion of locks,
// we want to execute them once using Gen4 to avoid the duplicated locks
// or double lock-releases.
if onlyGen4 || hasLockPrimitive(gen4Primitive) {
return gen4Primitive, gen4Err
}

// get V3's plan
v3Primitive, v3Err := planWithPlannerVersion(statement, vars, ctxVSchema, query, V3)

Expand All @@ -55,6 +46,15 @@ func gen4CompareV3Planner(query string) func(sqlparser.Statement, *sqlparser.Res
return nil, err
}

// if onlyGen4 is set to true or Gen4's instruction contain a lock primitive,
// we use only Gen4's primitive and exit early without using V3's.
// since lock primitives can imply the creation or deletion of locks,
// we want to execute them once using Gen4 to avoid the duplicated locks
// or double lock-releases.
if onlyGen4 || hasLockPrimitive(gen4Primitive) {
return gen4Primitive, gen4Err
}

return &engine.Gen4CompareV3{
V3: v3Primitive,
Gen4: gen4Primitive,
Expand Down
1 change: 1 addition & 0 deletions go/vt/vtgate/planbuilder/route_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,7 @@ func createRoutePlanForOuter(ctx *planningContext, aRoute, bRoute *routeTree, ne
right: outer,
pred: sqlparser.AndExpressions(joinPredicates...),
}),
predicates: append(aRoute.predicates, bRoute.predicates...),
keyspace: aRoute.keyspace,
vindexPreds: append(aRoute.vindexPreds, bRoute.vindexPreds...),
}
Expand Down
1 change: 1 addition & 0 deletions go/vt/vtgate/planbuilder/testdata/filter_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ Gen4 plan same as above
"Vindex": "user_index"
}
}
Gen4 plan same as above

# Multi-route unique vindex constraint
"select user_extra.id from user join user_extra on user.col = user_extra.col where user.id = 5"
Expand Down