From 7b0814c11511939ef5be148788a5e7c868dbdb4c Mon Sep 17 00:00:00 2001 From: Chao Wang Date: Thu, 24 Jun 2021 22:15:12 +0800 Subject: [PATCH] executor: tablesample for temporary table should always return empty --- executor/builder.go | 21 +++++++++++++------ executor/executor_test.go | 44 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/executor/builder.go b/executor/builder.go index 177bf394f2bc9..7d17b63b2e211 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -4211,12 +4211,17 @@ func fullRangePartition(idxArr []int) bool { return len(idxArr) == 1 && idxArr[0] == plannercore.FullRange } -func (b *executorBuilder) buildTableSample(v *plannercore.PhysicalTableSample) *TableSampleExecutor { - if v.TableInfo.Meta().TempTableType != model.TempTableNone { - b.err = errors.New("TABLESAMPLE clause can not be applied to temporary tables") - return nil - } +type emptySampler struct{} + +func (s *emptySampler) writeChunk(_ *chunk.Chunk) error { + return nil +} +func (s *emptySampler) finished() bool { + return true +} + +func (b *executorBuilder) buildTableSample(v *plannercore.PhysicalTableSample) *TableSampleExecutor { startTS, err := b.getSnapshotTS() if err != nil { b.err = err @@ -4227,11 +4232,15 @@ func (b *executorBuilder) buildTableSample(v *plannercore.PhysicalTableSample) * table: v.TableInfo, startTS: startTS, } - if v.TableSampleInfo.AstNode.SampleMethod == ast.SampleMethodTypeTiDBRegion { + + if v.TableInfo.Meta().TempTableType != model.TempTableNone { + e.sampler = &emptySampler{} + } else if v.TableSampleInfo.AstNode.SampleMethod == ast.SampleMethodTypeTiDBRegion { e.sampler = newTableRegionSampler( b.ctx, v.TableInfo, startTS, v.TableSampleInfo.Partitions, v.Schema(), v.TableSampleInfo.FullSchema, e.retFieldTypes, v.Desc) } + return e } diff --git a/executor/executor_test.go b/executor/executor_test.go index 249c8f16b8205..c31ae509554e6 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -8583,8 +8583,6 @@ func (s *testStaleTxnSuite) TestInvalidReadTemporaryTable(c *C) { // sleep 1us to make test stale time.Sleep(time.Microsecond) - tk.MustGetErrMsg("select * from tmp1 tablesample regions()", "TABLESAMPLE clause can not be applied to temporary tables") - queries := []struct { sql string }{ @@ -8658,6 +8656,48 @@ func (s *testStaleTxnSuite) TestInvalidReadTemporaryTable(c *C) { } } +func (s *testSuite) TestEmptyTableSampleTemporaryTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + safePointName := "tikv_gc_safe_point" + safePointValue := "20160102-15:04:05 -0700" + safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)" + updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') + ON DUPLICATE KEY + UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment) + tk.MustExec(updateSafePoint) + + tk.MustExec("set @@tidb_enable_global_temporary_table=1") + tk.MustExec("use test") + tk.MustExec("drop table if exists tmp1") + tk.MustExec("create global temporary table tmp1 " + + "(id int not null primary key, code int not null, value int default null, unique key code(code))" + + "on commit delete rows") + + // sleep 1us to make test stale + time.Sleep(time.Microsecond) + + // test tablesample return empty + rs := tk.MustQuery("select * from tmp1 tablesample regions()") + rs.Check(testkit.Rows()) + + tk.MustExec("begin") + tk.MustExec("insert into tmp1 values (1, 1, 1)") + rs = tk.MustQuery("select * from tmp1 tablesample regions()") + rs.Check(testkit.Rows()) + tk.MustExec("commit") + + // tablesample should not return error for compatibility of tools like dumpling + tk.MustExec("set @@tidb_snapshot=NOW(6)") + rs = tk.MustQuery("select * from tmp1 tablesample regions()") + rs.Check(testkit.Rows()) + + tk.MustExec("begin") + rs = tk.MustQuery("select * from tmp1 tablesample regions()") + rs.Check(testkit.Rows()) + tk.MustExec("commit") +} + func (s *testSuite) TestIssue25506(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test")