diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 9123ab2b0c5eb..2564fad5d7716 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -416,6 +416,45 @@ func (s *testIntegrationSuite) TestReadFromStorageHintAndIsolationRead(c *C) { } } +func (s *testIntegrationSuite) TestIsolationReadTiFlashUseIndexHint(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, index idx(a));") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Se) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + c.Assert(exists, IsTrue) + for _, tblInfo := range db.Tables { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + + tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"") + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + s.testData.GetTestCases(c, &input, &output) + for i, tt := range input { + s.testData.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()) + }) + res := tk.MustQuery(tt) + res.Check(testkit.Rows(output[i].Plan...)) + c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn) + } +} + func (s *testIntegrationSuite) TestPartitionTableStats(c *C) { tk := testkit.NewTestKit(c, s.store) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 46473480da94c..e36c269a26609 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -564,6 +564,7 @@ func (b *PlanBuilder) getPossibleAccessPaths(indexHints []*ast.IndexHint, tblInf } } + _, isolationReadEnginesHasTiKV := b.ctx.GetSessionVars().GetIsolationReadEngines()[kv.TiKV] for i, hint := range indexHints { if hint.HintScope != ast.HintForScan { continue @@ -571,6 +572,17 @@ func (b *PlanBuilder) getPossibleAccessPaths(indexHints []*ast.IndexHint, tblInf hasScanHint = true + if !isolationReadEnginesHasTiKV { + if hint.IndexNames != nil { + engineVals, _ := b.ctx.GetSessionVars().GetSystemVar(variable.TiDBIsolationReadEngines) + err := errors.New(fmt.Sprintf("TiDB doesn't support index in the isolation read engines(value: '%v')", engineVals)) + if i < indexHintsLen { + return nil, err + } + b.ctx.GetSessionVars().StmtCtx.AppendWarning(err) + } + continue + } // It is syntactically valid to omit index_list for USE INDEX, which means “use no indexes”. // Omitting index_list for FORCE INDEX or IGNORE INDEX is a syntax error. // See https://dev.mysql.com/doc/refman/8.0/en/index-hints.html. diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 839af504e7858..397c54f9ccaad 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -63,5 +63,14 @@ "desc select /*+ read_from_storage(tikv[t]) */ avg(a) from t", "desc select /*+ read_from_storage(tiflash[t]) */ avg(a) from t" ] + }, + { + "name": "TestIsolationReadTiFlashUseIndexHint", + "cases": [ + "explain select * from t", + "explain select * from t use index();", + "explain select /*+ use_index(t, idx)*/ * from t", + "explain select /*+ use_index(t)*/ * from t" + ] } ] diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index eb27a19c88832..29fe8582b7f39 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -247,5 +247,44 @@ ] } ] + }, + { + "Name": "TestIsolationReadTiFlashUseIndexHint", + "Cases": [ + { + "SQL": "explain select * from t", + "Plan": [ + "TableReader_5 10000.00 root data:TableScan_4", + "└─TableScan_4 10000.00 cop[tiflash] table:t, range:[-inf,+inf], keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select * from t use index();", + "Plan": [ + "TableReader_5 10000.00 root data:TableScan_4", + "└─TableScan_4 10000.00 cop[tiflash] table:t, range:[-inf,+inf], keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ use_index(t, idx)*/ * from t", + "Plan": [ + "TableReader_5 10000.00 root data:TableScan_4", + "└─TableScan_4 10000.00 cop[tiflash] table:t, range:[-inf,+inf], keep order:false, stats:pseudo" + ], + "Warn": [ + "TiDB doesn't support index in the isolation read engines(value: 'tiflash')" + ] + }, + { + "SQL": "explain select /*+ use_index(t)*/ * from t", + "Plan": [ + "TableReader_5 10000.00 root data:TableScan_4", + "└─TableScan_4 10000.00 cop[tiflash] table:t, range:[-inf,+inf], keep order:false, stats:pseudo" + ], + "Warn": null + } + ] } ]