From 24993b009beb6282e863da9a1df6dbd6d591d042 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Thu, 17 Mar 2022 20:14:09 +0800 Subject: [PATCH 1/7] *: fix bug that UnionScan can't keep order caused wrong result --- executor/table_reader.go | 12 ++++++------ planner/core/handle_cols.go | 12 +++--------- planner/core/integration_test.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/executor/table_reader.go b/executor/table_reader.go index 3b20bf90c98d2..2fb64db378e4e 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -181,18 +181,18 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Calculate the kv ranges here, UnionScan rely on this kv ranges. // cached table and temporary table are similar if e.dummy { - kvReq, err := e.buildKVReq(ctx, firstPartRanges) - if err != nil { - return err - } - e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) if len(secondPartRanges) != 0 { - kvReq, err = e.buildKVReq(ctx, secondPartRanges) + kvReq, err := e.buildKVReq(ctx, secondPartRanges) if err != nil { return err } e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) } + kvReq, err := e.buildKVReq(ctx, firstPartRanges) + if err != nil { + return err + } + e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) return nil } diff --git a/planner/core/handle_cols.go b/planner/core/handle_cols.go index 48d6ab2444edd..ad59247a3b69a 100644 --- a/planner/core/handle_cols.go +++ b/planner/core/handle_cols.go @@ -239,15 +239,9 @@ func (ib *IntHandleCols) NumCols() int { // Compare implements the kv.HandleCols interface. func (ib *IntHandleCols) Compare(a, b []types.Datum, ctors []collate.Collator) (int, error) { - aInt := a[ib.col.Index].GetInt64() - bInt := b[ib.col.Index].GetInt64() - if aInt == bInt { - return 0, nil - } - if aInt < bInt { - return -1, nil - } - return 1, nil + aVal := &a[ib.col.Index] + bVal := &b[ib.col.Index] + return aVal.Compare(nil, bVal, ctors[ib.col.Index]) } // GetFieldsTypes implements the kv.HandleCols interface. diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 75f3c651866e5..bfdf130a4cc4c 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -6243,3 +6243,35 @@ func TestTiFlashPartitionTableScan(t *testing.T) { tk.MustExec("drop table rp_t;") tk.MustExec("drop table hp_t;") } + +func TestIssue33175(t *testing.T) { + store, _, clean := testkit.CreateMockStoreAndDomain(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (id bigint(45) unsigned not null, c varchar(20), primary key(id));") + tk.MustExec("insert into t values (9734095886065816707, 'a'), (10353107668348738101, 'b'), (0, 'c');") + tk.MustExec("begin") + tk.MustExec("insert into t values (33, 'd');") + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + tk.MustExec("rollback") + + tk.MustExec("alter table t cache") + for { + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + // With subquery, like the original issue case. + for { + tk.MustQuery("select * from t where id > (select max(id) from t where t.id > 0);").Check(testkit.Rows()) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + tk.MustExec("alter table t nocache") + tk.MustExec("drop table t") +} From 64fef564abd3b2cddbebb1a6291c643326ae07c0 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Mon, 21 Mar 2022 20:32:20 +0800 Subject: [PATCH 2/7] address comment --- executor/mem_reader.go | 29 ++++++++++++++++++++++ executor/table_reader.go | 10 ++++---- planner/core/integration_test.go | 42 +++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/executor/mem_reader.go b/executor/mem_reader.go index 6912a4fb1adfb..72be60d85ed03 100644 --- a/executor/mem_reader.go +++ b/executor/mem_reader.go @@ -119,6 +119,14 @@ func (m *memIndexReader) getMemRows(ctx context.Context) ([][]types.Datum, error } mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) + + // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, + // Then reverse the whole added rows. + // [99, 100] [44, 45] [1, 3] => [1, 3] [44, 45] [99, 100] => [100, 99] [45, 44] [3 1] + if m.desc { + reverseKVRanges(m.kvRanges) + } + err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { data, err := m.decodeIndexKeyValue(key, value, tps) if err != nil { @@ -239,6 +247,13 @@ func (m *memTableReader) getMemRows(ctx context.Context) ([][]types.Datum, error defer span1.Finish() opentracing.ContextWithSpan(ctx, span1) } + + // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, + // Then reverse the whole added rows. + if m.desc { + reverseKVRanges(m.kvRanges) + } + mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { row, err := m.decodeRecordKeyValue(key, value) @@ -407,6 +422,7 @@ func iterTxnMemBuffer(ctx sessionctx.Context, cacheTable kv.MemBuffer, kvRanges if len(iter.Value()) == 0 { continue } + err = fn(iter.Key(), iter.Value()) if err != nil { return err @@ -435,6 +451,12 @@ func getSnapIter(ctx sessionctx.Context, cacheTable kv.MemBuffer, rg kv.KeyRange return snapCacheIter, nil } +func reverseKVRanges(rows []kv.KeyRange) { + for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 { + rows[i], rows[j] = rows[j], rows[i] + } +} + func reverseDatumSlice(rows [][]types.Datum) { for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 { rows[i], rows[j] = rows[j], rows[i] @@ -540,6 +562,13 @@ func (m *memIndexLookUpReader) getMemRows(ctx context.Context) ([][]types.Datum, numHandles := 0 for i, tbl := range tbls { m.idxReader.kvRanges = kvRanges[i] + // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, + // Then reverse the whole added rows. + // [99, 100] [44, 45] [1, 3] => [1, 3] [44, 45] [99, 100] => [100, 99] [45, 44] [3 1] + if m.desc { + reverseKVRanges(m.idxReader.kvRanges) + } + handles, err := m.idxReader.getMemRowsHandle() if err != nil { return nil, err diff --git a/executor/table_reader.go b/executor/table_reader.go index 2fb64db378e4e..652bc2f4f78a6 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -181,6 +181,11 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Calculate the kv ranges here, UnionScan rely on this kv ranges. // cached table and temporary table are similar if e.dummy { + kvReq, err := e.buildKVReq(ctx, firstPartRanges) + if err != nil { + return err + } + e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) if len(secondPartRanges) != 0 { kvReq, err := e.buildKVReq(ctx, secondPartRanges) if err != nil { @@ -188,11 +193,6 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { } e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) } - kvReq, err := e.buildKVReq(ctx, firstPartRanges) - if err != nil { - return err - } - e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) return nil } diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index bfdf130a4cc4c..0dd0e6f99cc5c 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -6264,7 +6264,7 @@ func TestIssue33175(t *testing.T) { } } - // With subquery, like the original issue case. + // // With subquery, like the original issue case. for { tk.MustQuery("select * from t where id > (select max(id) from t where t.id > 0);").Check(testkit.Rows()) if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { @@ -6272,6 +6272,46 @@ func TestIssue33175(t *testing.T) { } } + // Test order by desc / asc. + tk.MustQuery("select id from t order by id desc;").Check(testkit.Rows( + "10353107668348738101", + "9734095886065816707", + "0")) + + tk.MustQuery("select id from t order by id asc;").Check(testkit.Rows( + "0", + "9734095886065816707", + "10353107668348738101")) + tk.MustExec("alter table t nocache") tk.MustExec("drop table t") + + // Cover more code that use union scan + // TableReader/IndexReader/IndexLookup + for idx, q := range []string{ + "create temporary table t (id bigint unsigned, c int default null, index(id))", + "create temporary table t (id bigint unsigned primary key)", + } { + tk.MustExec(q) + tk.MustExec("insert into t(id) values (1), (3), (9734095886065816707), (9734095886065816708)") + tk.MustQuery("select min(id) from t").Check(testkit.Rows("1")) + tk.MustQuery("select max(id) from t").Check(testkit.Rows("9734095886065816708")) + tk.MustQuery("select id from t order by id asc").Check(testkit.Rows( + "1", "3", "9734095886065816707", "9734095886065816708")) + tk.MustQuery("select id from t order by id desc").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "3", "1")) + if idx == 0 { + tk.MustQuery("select * from t order by id asc").Check(testkit.Rows( + "1 ", + "3 ", + "9734095886065816707 ", + "9734095886065816708 ")) + tk.MustQuery("select * from t order by id desc").Check(testkit.Rows( + "9734095886065816708 ", + "9734095886065816707 ", + "3 ", + "1 ")) + } + tk.MustExec("drop table t") + } } From 5e78b508d5fe904ce15da87de219c53c22dd02dd Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Mon, 21 Mar 2022 20:41:11 +0800 Subject: [PATCH 3/7] make fmt --- executor/table_reader.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/executor/table_reader.go b/executor/table_reader.go index 652bc2f4f78a6..77003b0c7e3cd 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -56,7 +56,7 @@ func (sr selectResultHook) SelectResult(ctx context.Context, sctx sessionctx.Con } type kvRangeBuilder interface { - buildKeyRange(pid int64, ranges []*ranger.Range) ([]kv.KeyRange, error) + buildKeyRange(ranges []*ranger.Range) ([]kv.KeyRange, error) buildKeyRangeSeparately(ranges []*ranger.Range) ([]int64, [][]kv.KeyRange, error) } @@ -187,7 +187,7 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { } e.kvRanges = append(e.kvRanges, kvReq.KeyRanges...) if len(secondPartRanges) != 0 { - kvReq, err := e.buildKVReq(ctx, secondPartRanges) + kvReq, err = e.buildKVReq(ctx, secondPartRanges) if err != nil { return err } @@ -246,15 +246,14 @@ func (e *TableReaderExecutor) Next(ctx context.Context, req *chunk.Chunk) error // Close implements the Executor Close interface. func (e *TableReaderExecutor) Close() error { - if e.dummy { - return nil - } - var err error if e.resultHandler != nil { err = e.resultHandler.Close() } e.kvRanges = e.kvRanges[:0] + if e.dummy { + return nil + } e.ctx.StoreQueryFeedback(e.feedback) return err } @@ -377,7 +376,7 @@ func (e *TableReaderExecutor) buildKVReq(ctx context.Context, ranges []*ranger.R var builder distsql.RequestBuilder var reqBuilder *distsql.RequestBuilder if e.kvRangeBuilder != nil { - kvRange, err := e.kvRangeBuilder.buildKeyRange(getPhysicalTableID(e.table), ranges) + kvRange, err := e.kvRangeBuilder.buildKeyRange(ranges) if err != nil { return nil, err } From 09ebb14640a1a55f94d80d19f43627b14fe18db7 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 22 Mar 2022 11:17:56 +0800 Subject: [PATCH 4/7] address comment --- distsql/request_builder.go | 4 ++++ executor/mem_reader.go | 28 ---------------------------- executor/table_reader.go | 11 +++++++++++ planner/core/integration_test.go | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/distsql/request_builder.go b/distsql/request_builder.go index 3ffb78c002cb3..5f6418f37382c 100644 --- a/distsql/request_builder.go +++ b/distsql/request_builder.go @@ -473,8 +473,10 @@ func SplitRangesAcrossInt64Boundary(ranges []*ranger.Range, keepOrder bool, desc return append(unsignedRanges, signedRanges...), nil } if desc { + fmt.Println("SplitRangesAcrossInt64Boundary desc, unsigned -> signed", unsignedRanges, signedRanges) return unsignedRanges, signedRanges } + fmt.Println("SplitRangesAcrossInt64Boundary asc, signed -> unsigned", signedRanges, unsignedRanges) return signedRanges, unsignedRanges } // need to split the range that straddles the int64 boundary @@ -504,8 +506,10 @@ func SplitRangesAcrossInt64Boundary(ranges []*ranger.Range, keepOrder bool, desc return append(unsignedRanges, signedRanges...), nil } if desc { + fmt.Println("SplitRangesAcrossInt64Boundary desc, unsigned -> signed", unsignedRanges, signedRanges) return unsignedRanges, signedRanges } + fmt.Println("SplitRangesAcrossInt64Boundary asc, signed -> unsigned", signedRanges, unsignedRanges) return signedRanges, unsignedRanges } diff --git a/executor/mem_reader.go b/executor/mem_reader.go index 72be60d85ed03..e8a5e08fa43a8 100644 --- a/executor/mem_reader.go +++ b/executor/mem_reader.go @@ -119,14 +119,6 @@ func (m *memIndexReader) getMemRows(ctx context.Context) ([][]types.Datum, error } mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) - - // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, - // Then reverse the whole added rows. - // [99, 100] [44, 45] [1, 3] => [1, 3] [44, 45] [99, 100] => [100, 99] [45, 44] [3 1] - if m.desc { - reverseKVRanges(m.kvRanges) - } - err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { data, err := m.decodeIndexKeyValue(key, value, tps) if err != nil { @@ -248,12 +240,6 @@ func (m *memTableReader) getMemRows(ctx context.Context) ([][]types.Datum, error opentracing.ContextWithSpan(ctx, span1) } - // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, - // Then reverse the whole added rows. - if m.desc { - reverseKVRanges(m.kvRanges) - } - mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { row, err := m.decodeRecordKeyValue(key, value) @@ -422,7 +408,6 @@ func iterTxnMemBuffer(ctx sessionctx.Context, cacheTable kv.MemBuffer, kvRanges if len(iter.Value()) == 0 { continue } - err = fn(iter.Key(), iter.Value()) if err != nil { return err @@ -451,12 +436,6 @@ func getSnapIter(ctx sessionctx.Context, cacheTable kv.MemBuffer, rg kv.KeyRange return snapCacheIter, nil } -func reverseKVRanges(rows []kv.KeyRange) { - for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 { - rows[i], rows[j] = rows[j], rows[i] - } -} - func reverseDatumSlice(rows [][]types.Datum) { for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 { rows[i], rows[j] = rows[j], rows[i] @@ -562,13 +541,6 @@ func (m *memIndexLookUpReader) getMemRows(ctx context.Context) ([][]types.Datum, numHandles := 0 for i, tbl := range tbls { m.idxReader.kvRanges = kvRanges[i] - // TODO: `IterReverse` is not used... to get the same effect, reverse the kv ranges first, - // Then reverse the whole added rows. - // [99, 100] [44, 45] [1, 3] => [1, 3] [44, 45] [99, 100] => [100, 99] [45, 44] [3 1] - if m.desc { - reverseKVRanges(m.idxReader.kvRanges) - } - handles, err := m.idxReader.getMemRowsHandle() if err != nil { return nil, err diff --git a/executor/table_reader.go b/executor/table_reader.go index 77003b0c7e3cd..128cb8a3af01c 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -181,6 +181,17 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Calculate the kv ranges here, UnionScan rely on this kv ranges. // cached table and temporary table are similar if e.dummy { + if e.desc { + // TiKV support reverse scan and the `resultHandler` process the range order. + // While in UnionScan, it doesn't use reverse scan and reverse the final result rows manually. + // So things are differ, we need to reverse the kv range here. + // TODO: If we refactor UnionScan to use reverse scan, update the code here. + // [9734095886065816708 9734095886065816709] | [1 3] [65535 9734095886065816707] => before the following change + // [1 3] [65535 9734095886065816707] | [9734095886065816708 9734095886065816709] => ranges part reverse here + // [1 3 65535 9734095886065816707 9734095886065816708 9734095886065816709] => scan (normal order) in UnionScan + // [9734095886065816709 9734095886065816708 9734095886065816707 65535 3 1] => rows reverse in UnionScan + firstPartRanges, secondPartRanges = secondPartRanges, firstPartRanges + } kvReq, err := e.buildKVReq(ctx, firstPartRanges) if err != nil { return err diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 0dd0e6f99cc5c..6f67640ab0dfa 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -6249,6 +6249,7 @@ func TestIssue33175(t *testing.T) { defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") + tk.MustExec("create table t (id bigint(45) unsigned not null, c varchar(20), primary key(id));") tk.MustExec("insert into t values (9734095886065816707, 'a'), (10353107668348738101, 'b'), (0, 'c');") tk.MustExec("begin") @@ -6314,4 +6315,20 @@ func TestIssue33175(t *testing.T) { } tk.MustExec("drop table t") } + + // More and more test + tk.MustExec("create global temporary table `tmp1` (id bigint unsigned primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp1 values (0),(1),(2),(65536),(9734095886065816707),(9734095886065816708);") + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id desc;").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "65536", "2", "1", "0")) + + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id asc;").Check(testkit.Rows( + "0", "1", "2", "65536", "9734095886065816707", "9734095886065816708")) + + tk.MustExec("create global temporary table `tmp2` (id bigint primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp2 values(-2),(-1),(0),(1),(2);") + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id desc;").Check(testkit.Rows("2", "1", "-1", "-2")) + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id asc;").Check(testkit.Rows("-2", "-1", "1", "2")) } From dac6e4d470def7b6b9476256baa024200c72d255 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 22 Mar 2022 11:21:26 +0800 Subject: [PATCH 5/7] clean debug code --- distsql/request_builder.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/distsql/request_builder.go b/distsql/request_builder.go index 5f6418f37382c..3ffb78c002cb3 100644 --- a/distsql/request_builder.go +++ b/distsql/request_builder.go @@ -473,10 +473,8 @@ func SplitRangesAcrossInt64Boundary(ranges []*ranger.Range, keepOrder bool, desc return append(unsignedRanges, signedRanges...), nil } if desc { - fmt.Println("SplitRangesAcrossInt64Boundary desc, unsigned -> signed", unsignedRanges, signedRanges) return unsignedRanges, signedRanges } - fmt.Println("SplitRangesAcrossInt64Boundary asc, signed -> unsigned", signedRanges, unsignedRanges) return signedRanges, unsignedRanges } // need to split the range that straddles the int64 boundary @@ -506,10 +504,8 @@ func SplitRangesAcrossInt64Boundary(ranges []*ranger.Range, keepOrder bool, desc return append(unsignedRanges, signedRanges...), nil } if desc { - fmt.Println("SplitRangesAcrossInt64Boundary desc, unsigned -> signed", unsignedRanges, signedRanges) return unsignedRanges, signedRanges } - fmt.Println("SplitRangesAcrossInt64Boundary asc, signed -> unsigned", signedRanges, unsignedRanges) return signedRanges, unsignedRanges } From 556bc7fd9aecff1a4ada0c8e8faa84d0c8ec1747 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 22 Mar 2022 11:28:11 +0800 Subject: [PATCH 6/7] clean up code --- executor/table_reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor/table_reader.go b/executor/table_reader.go index 128cb8a3af01c..a9decdd55b1a7 100644 --- a/executor/table_reader.go +++ b/executor/table_reader.go @@ -181,7 +181,7 @@ func (e *TableReaderExecutor) Open(ctx context.Context) error { // Calculate the kv ranges here, UnionScan rely on this kv ranges. // cached table and temporary table are similar if e.dummy { - if e.desc { + if e.desc && len(secondPartRanges) != 0 { // TiKV support reverse scan and the `resultHandler` process the range order. // While in UnionScan, it doesn't use reverse scan and reverse the final result rows manually. // So things are differ, we need to reverse the kv range here. From b3678e5da27f7b27081d5f7f6ec8f563ab32eb57 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 22 Mar 2022 11:56:14 +0800 Subject: [PATCH 7/7] Update executor/mem_reader.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 王超 --- executor/mem_reader.go | 1 - 1 file changed, 1 deletion(-) diff --git a/executor/mem_reader.go b/executor/mem_reader.go index e8a5e08fa43a8..6912a4fb1adfb 100644 --- a/executor/mem_reader.go +++ b/executor/mem_reader.go @@ -239,7 +239,6 @@ func (m *memTableReader) getMemRows(ctx context.Context) ([][]types.Datum, error defer span1.Finish() opentracing.ContextWithSpan(ctx, span1) } - mutableRow := chunk.MutRowFromTypes(m.retFieldTypes) err := iterTxnMemBuffer(m.ctx, m.cacheTable, m.kvRanges, func(key, value []byte) error { row, err := m.decodeRecordKeyValue(key, value)