diff --git a/executor/merge_join.go b/executor/merge_join.go index 4be9c9facb94c..eddffe9df5eba 100644 --- a/executor/merge_join.go +++ b/executor/merge_join.go @@ -84,7 +84,7 @@ type mergeJoinInnerTable struct { } func (t *mergeJoinInnerTable) init(ctx context.Context, chk4Reader *chunk.Chunk) (err error) { - if t.reader == nil || t.joinKeys == nil || len(t.joinKeys) == 0 || ctx == nil { + if t.reader == nil || ctx == nil { return errors.Errorf("Invalid arguments: Empty arguments detected.") } t.ctx = ctx diff --git a/plan/gen_physical_plans.go b/plan/gen_physical_plans.go index 21d55c1fbe59b..da78398550115 100644 --- a/plan/gen_physical_plans.go +++ b/plan/gen_physical_plans.go @@ -359,12 +359,16 @@ func (p *LogicalJoin) buildFakeEqCondsForIndexJoin(keys, idxCols []*expression.C // tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value // will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost. func (p *LogicalJoin) tryToGetIndexJoin(prop *requiredProp) ([]PhysicalPlan, bool) { - if len(p.EqualConditions) == 0 { - return nil, false - } plans := make([]PhysicalPlan, 0, 2) leftOuter := (p.preferJoinType & preferLeftAsIndexOuter) > 0 rightOuter := (p.preferJoinType & preferRightAsIndexOuter) > 0 + if len(p.EqualConditions) == 0 { + if leftOuter || rightOuter { + warning := ErrInternal.GenByArgs("TIDB_INLJ hint is inapplicable without column equal ON condition") + p.ctx.GetSessionVars().StmtCtx.AppendWarning(warning) + } + return nil, false + } switch p.JoinType { case SemiJoin, AntiSemiJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin, LeftOuterJoin: join := p.getIndexJoinByOuterIdx(prop, 0) diff --git a/plan/physical_plan_test.go b/plan/physical_plan_test.go index c5dda0159fb3c..2dbb1b9fc091f 100644 --- a/plan/physical_plan_test.go +++ b/plan/physical_plan_test.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/tidb/plan" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/terror" "github.com/pingcap/tidb/util/testleak" "golang.org/x/net/context" ) @@ -1248,3 +1249,27 @@ func (s *testPlanSuite) TestRequestTypeSupportedOff(c *C) { c.Assert(err, IsNil) c.Assert(plan.ToString(p), Equals, expect, Commentf("for %s", sql)) } + +func (s *testPlanSuite) TestIndexLookupCartesianJoin(c *C) { + defer testleak.AfterTest(c)() + store, dom, err := newStoreWithBootstrap() + c.Assert(err, IsNil) + defer func() { + dom.Close() + store.Close() + }() + se, err := session.CreateSession4Test(store) + c.Assert(err, IsNil) + _, err = se.Execute(context.Background(), "use test") + c.Assert(err, IsNil) + sql := "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2" + stmt, err := s.ParseOneStmt(sql, "", "") + c.Assert(err, IsNil) + p, err := plan.Optimize(se, stmt, s.is) + c.Assert(err, IsNil) + c.Assert(core.ToString(p), Equals, "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}") + warnings := se.GetSessionVars().StmtCtx.GetWarnings() + lastWarn := warnings[len(warnings)-1] + err = plan.ErrInternal.GenByArgs("TIDB_INLJ hint is inapplicable without column equal ON condition") + c.Assert(terror.ErrorEqual(err, lastWarn.Err), IsTrue) +}