diff --git a/go/test/endtoend/vtgate/queries/misc/misc_test.go b/go/test/endtoend/vtgate/queries/misc/misc_test.go index 6712275592a..2d861b1a625 100644 --- a/go/test/endtoend/vtgate/queries/misc/misc_test.go +++ b/go/test/endtoend/vtgate/queries/misc/misc_test.go @@ -114,6 +114,21 @@ func TestInvalidDateTimeTimestampVals(t *testing.T) { require.Error(t, err) } +func TestJoinWithThreeTables(t *testing.T) { + version, err := cluster.GetMajorVersion("vtgate") + require.NoError(t, err) + if version != 19 { + t.Skip("cannot run upgrade/downgrade test") + } + + mcmp, closer := start(t) + defer closer() + + mcmp.Exec("insert into t1(id1, id2) values (0,0), (1,1), (2,2)") + mcmp.Exec("insert into tbl(id, unq_col, nonunq_col) values (0,0,0), (1,1,1), (2,2,1)") + mcmp.Exec("select 42 from t1 u1, t1 u2, tbl u3 where u1.id1 = u2.id1 and u1.id1 = u3.id and (u1.id2 or u2.id2 or u3.unq_col)") +} + // TestIntervalWithMathFunctions tests that the Interval keyword can be used with math functions. func TestIntervalWithMathFunctions(t *testing.T) { mcmp, closer := start(t) diff --git a/go/test/endtoend/vtgate/queries/misc/vschema.json b/go/test/endtoend/vtgate/queries/misc/vschema.json index 60aa2bc9c07..63e870ffd58 100644 --- a/go/test/endtoend/vtgate/queries/misc/vschema.json +++ b/go/test/endtoend/vtgate/queries/misc/vschema.json @@ -13,6 +13,14 @@ "name": "hash" } ] + }, + "tbl": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] } } } \ No newline at end of file diff --git a/go/vt/vtgate/planbuilder/operators/SQL_builder.go b/go/vt/vtgate/planbuilder/operators/SQL_builder.go index 65ff485c469..6339803af31 100644 --- a/go/vt/vtgate/planbuilder/operators/SQL_builder.go +++ b/go/vt/vtgate/planbuilder/operators/SQL_builder.go @@ -220,7 +220,9 @@ func (qb *queryBuilder) joinInnerWith(other *queryBuilder, onCondition sqlparser sel.Where = &sqlparser.Where{Type: sqlparser.WhereClause, Expr: predicate} } - qb.addPredicate(onCondition) + for _, pred := range sqlparser.SplitAndExpression(nil, onCondition) { + qb.addPredicate(pred) + } } func (qb *queryBuilder) joinOuterWith(other *queryBuilder, onCondition sqlparser.Expr) { diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.json b/go/vt/vtgate/planbuilder/testdata/from_cases.json index 6433c06ed89..86753825e42 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.json @@ -497,6 +497,30 @@ ] } }, + { + "comment": "three table join with join predicate touching all tables", + "query": "select 42 from user u join user_extra ue on u.id = ue.user_id join music m on m.user_id = u.id where u.foo or m.foo or ue.foo", + "plan": { + "QueryType": "SELECT", + "Original": "select 42 from user u join user_extra ue on u.id = ue.user_id join music m on m.user_id = u.id where u.foo or m.foo or ue.foo", + "Instructions": { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select 42 from `user` as u, user_extra as ue, music as m where 1 != 1", + "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)", + "Table": "`user`, music, user_extra" + }, + "TablesUsed": [ + "user.music", + "user.user", + "user.user_extra" + ] + } + }, { "comment": "Left join, multi-chunk", "query": "select u.col from user u left join unsharded m on u.a = m.b",