diff --git a/pkg/ddl/column.go b/pkg/ddl/column.go index 2141112d814d5..57e6d1cc4170a 100644 --- a/pkg/ddl/column.go +++ b/pkg/ddl/column.go @@ -1384,7 +1384,8 @@ func (w *updateColumnWorker) getRowRecord(handle kv.Handle, recordKey []byte, ra } checksums := w.calcChecksums() sctx, rd := w.sessCtx.GetSessionVars().StmtCtx, &w.sessCtx.GetSessionVars().RowEncoder - newRowVal, err := tablecodec.EncodeRow(sctx, newRow, newColumnIDs, nil, nil, rd, checksums...) + newRowVal, err := tablecodec.EncodeRow(sctx.TimeZone(), newRow, newColumnIDs, nil, nil, rd, checksums...) + err = sctx.HandleError(err) if err != nil { return errors.Trace(err) } diff --git a/pkg/errctx/BUILD.bazel b/pkg/errctx/BUILD.bazel index c2f2edc0efdeb..ef0f7368ccd79 100644 --- a/pkg/errctx/BUILD.bazel +++ b/pkg/errctx/BUILD.bazel @@ -22,5 +22,6 @@ go_test( "//pkg/types", "@com_github_pingcap_errors//:errors", "@com_github_stretchr_testify//require", + "@org_uber_go_multierr//:multierr", ], ) diff --git a/pkg/errctx/context.go b/pkg/errctx/context.go index df47173a58940..18dd3e5b22c1a 100644 --- a/pkg/errctx/context.go +++ b/pkg/errctx/context.go @@ -68,7 +68,27 @@ func (ctx *Context) appendWarning(err error) { } // HandleError handles the error according to the context. See the comment of `HandleErrorWithAlias` for detailed logic. +// +// It also allows using `errors.ErrorGroup`, in this case, it'll handle each error in order, and return the first error +// it founds. func (ctx *Context) HandleError(err error) error { + // The function of handling `errors.ErrorGroup` is placed in `HandleError` but not in `HandleErrorWithAlias`, because + // it's hard to give a proper error and warn alias for an error group. + if errs, ok := err.(errors.ErrorGroup); ok { + for _, singleErr := range errs.Errors() { + singleErr = ctx.HandleError(singleErr) + // If the one error is found, just return it. + // TODO: consider whether it's more appropriate to continue to handle other errors. For example, other errors + // may need to append warnings. The current behavior is same with TiDB original behavior before using + // `errctx` to handle multiple errors. + if singleErr != nil { + return singleErr + } + } + + return nil + } + return ctx.HandleErrorWithAlias(err, err, err) } diff --git a/pkg/errctx/context_test.go b/pkg/errctx/context_test.go index 9cf60797380e7..e78cbb09c7640 100644 --- a/pkg/errctx/context_test.go +++ b/pkg/errctx/context_test.go @@ -21,6 +21,7 @@ import ( "github.com/pingcap/tidb/pkg/errctx" "github.com/pingcap/tidb/pkg/types" "github.com/stretchr/testify/require" + "go.uber.org/multierr" ) func TestContext(t *testing.T) { @@ -50,4 +51,13 @@ func TestContext(t *testing.T) { require.Equal(t, warn, testWarn) // newCtx2 will return all errors require.Equal(t, newCtx2.HandleErrorWithAlias(testInternalErr, testErr, testWarn), testErr) + + // test `multierr` + testErrs := multierr.Append(testInternalErr, testErr) + require.Equal(t, ctx.HandleError(testErrs), testInternalErr) + require.Equal(t, newCtx.HandleError(testErrs), testErr) + require.Equal(t, warn, testInternalErr) + + // test nil + require.Nil(t, ctx.HandleError(nil)) } diff --git a/pkg/executor/mem_reader.go b/pkg/executor/mem_reader.go index 2142037adf9af..38fab12f728a2 100644 --- a/pkg/executor/mem_reader.go +++ b/pkg/executor/mem_reader.go @@ -252,7 +252,9 @@ func buildMemTableReader(ctx context.Context, us *UnionScanExec, kvRanges []kv.K if err != nil { return nil, err } - return tablecodec.EncodeValue(us.Ctx().GetSessionVars().StmtCtx, nil, d) + sctx := us.Ctx().GetSessionVars().StmtCtx + buf, err := tablecodec.EncodeValue(sctx.TimeZone(), nil, d) + return buf, sctx.HandleError(err) } cd := NewRowDecoder(us.Ctx(), us.Schema(), us.table.Meta()) rd := rowcodec.NewByteDecoder(colInfo, pkColIDs, defVal, us.Ctx().GetSessionVars().Location()) @@ -1164,7 +1166,8 @@ func getColIDAndPkColIDs(ctx sessionctx.Context, tbl table.Table, columns []*mod if err != nil { return nil, err } - return tablecodec.EncodeValue(ctx.GetSessionVars().StmtCtx, nil, d) + buf, err := tablecodec.EncodeValue(ctx.GetSessionVars().StmtCtx.TimeZone(), nil, d) + return buf, ctx.GetSessionVars().StmtCtx.HandleError(err) } rd := rowcodec.NewByteDecoder(colInfos, pkColIDs, defVal, ctx.GetSessionVars().Location()) return colIDs, pkColIDs, rd diff --git a/pkg/executor/test/executor/executor_test.go b/pkg/executor/test/executor/executor_test.go index 54a3c0a1b79e7..6061cc242d3c4 100644 --- a/pkg/executor/test/executor/executor_test.go +++ b/pkg/executor/test/executor/executor_test.go @@ -388,7 +388,7 @@ func setColValue(t *testing.T, txn kv.Transaction, key kv.Key, v types.Datum) { colIDs := []int64{2, 3} sc := stmtctx.NewStmtCtxWithTimeZone(time.Local) rd := rowcodec.Encoder{Enable: true} - value, err := tablecodec.EncodeRow(sc, row, colIDs, nil, nil, &rd) + value, err := tablecodec.EncodeRow(sc.TimeZone(), row, colIDs, nil, nil, &rd) require.NoError(t, err) err = txn.Set(key, value) require.NoError(t, err) diff --git a/pkg/executor/write.go b/pkg/executor/write.go index 28733152208ea..f609110d56b29 100644 --- a/pkg/executor/write.go +++ b/pkg/executor/write.go @@ -268,7 +268,7 @@ func addUnchangedKeysForLockByRow( return count, err } unchangedUniqueKey, _, err := tablecodec.GenIndexKey( - stmtCtx, + stmtCtx.TimeZone(), idx.TableMeta(), meta, physicalID, @@ -276,6 +276,7 @@ func addUnchangedKeysForLockByRow( h, nil, ) + err = stmtCtx.HandleError(err) if err != nil { return count, err } diff --git a/pkg/server/handler/tests/http_handler_test.go b/pkg/server/handler/tests/http_handler_test.go index 4113a3ef42675..80902cbf88bf3 100644 --- a/pkg/server/handler/tests/http_handler_test.go +++ b/pkg/server/handler/tests/http_handler_test.go @@ -705,7 +705,7 @@ func TestDecodeColumnValue(t *testing.T) { } rd := rowcodec.Encoder{Enable: true} sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - bs, err := tablecodec.EncodeRow(sc, row, colIDs, nil, nil, &rd) + bs, err := tablecodec.EncodeRow(sc.TimeZone(), row, colIDs, nil, nil, &rd) require.NoError(t, err) require.NotNil(t, bs) bin := base64.StdEncoding.EncodeToString(bs) diff --git a/pkg/sessionctx/stmtctx/stmtctx.go b/pkg/sessionctx/stmtctx/stmtctx.go index e65a55ebf5a99..9764ca5fcc1a2 100644 --- a/pkg/sessionctx/stmtctx/stmtctx.go +++ b/pkg/sessionctx/stmtctx/stmtctx.go @@ -504,6 +504,10 @@ func (sc *StatementContext) HandleTruncate(err error) error { // HandleError handles the error based on `ErrCtx()` func (sc *StatementContext) HandleError(err error) error { + intest.AssertNotNil(sc) + if sc == nil { + return err + } errCtx := sc.ErrCtx() return errCtx.HandleError(err) } diff --git a/pkg/statistics/cmsketch.go b/pkg/statistics/cmsketch.go index 9643e6b7188b2..5851749238052 100644 --- a/pkg/statistics/cmsketch.go +++ b/pkg/statistics/cmsketch.go @@ -23,6 +23,7 @@ import ( "slices" "sort" "strings" + "time" "github.com/pingcap/errors" "github.com/pingcap/failpoint" @@ -259,10 +260,15 @@ func (c *CMSketch) SubValue(h1, h2 uint64, count uint64) { // QueryValue is used to query the count of specified value. func QueryValue(sctx sessionctx.Context, c *CMSketch, t *TopN, val types.Datum) (uint64, error) { var sc *stmtctx.StatementContext + tz := time.UTC if sctx != nil { sc = sctx.GetSessionVars().StmtCtx + tz = sc.TimeZone() + } + rawData, err := tablecodec.EncodeValue(tz, nil, val) + if sc != nil { + err = sc.HandleError(err) } - rawData, err := tablecodec.EncodeValue(sc, nil, val) if err != nil { return 0, errors.Trace(err) } diff --git a/pkg/statistics/row_sampler.go b/pkg/statistics/row_sampler.go index 3c26c366ad2b7..97e9235e74412 100644 --- a/pkg/statistics/row_sampler.go +++ b/pkg/statistics/row_sampler.go @@ -195,7 +195,8 @@ func (s *RowSampleBuilder) Collect() (RowSampleCollector, error) { return nil, err } decodedVal.SetBytesAsString(s.Collators[i].Key(decodedVal.GetString()), decodedVal.Collation(), uint32(decodedVal.Length())) - encodedKey, err := tablecodec.EncodeValue(s.Sc, nil, decodedVal) + encodedKey, err := tablecodec.EncodeValue(s.Sc.TimeZone(), nil, decodedVal) + err = s.Sc.HandleError(err) if err != nil { return nil, err } diff --git a/pkg/statistics/sample.go b/pkg/statistics/sample.go index 54dc0a4892d13..5d056abd115d9 100644 --- a/pkg/statistics/sample.go +++ b/pkg/statistics/sample.go @@ -259,7 +259,8 @@ func (s SampleBuilder) CollectColumnStats() ([]*SampleCollector, *SortedBuilder, return nil, nil, err } decodedVal.SetBytesAsString(s.Collators[i].Key(decodedVal.GetString()), decodedVal.Collation(), uint32(decodedVal.Length())) - encodedKey, err := tablecodec.EncodeValue(s.Sc, nil, decodedVal) + encodedKey, err := tablecodec.EncodeValue(s.Sc.TimeZone(), nil, decodedVal) + err = s.Sc.HandleError(err) if err != nil { return nil, nil, err } @@ -306,7 +307,8 @@ func (c *SampleCollector) ExtractTopN(numTop uint32, sc *stmtctx.StatementContex if err != nil { return err } - data, err := tablecodec.EncodeValue(sc, nil, d) + data, err := tablecodec.EncodeValue(sc.TimeZone(), nil, d) + err = sc.HandleError(err) if err != nil { return err } diff --git a/pkg/store/mockstore/cluster_test.go b/pkg/store/mockstore/cluster_test.go index caeaee56722d1..b3958b1ce9475 100644 --- a/pkg/store/mockstore/cluster_test.go +++ b/pkg/store/mockstore/cluster_test.go @@ -58,7 +58,7 @@ func TestClusterSplit(t *testing.T) { colValue := types.NewStringDatum(strconv.Itoa(int(handle))) // TODO: Should use session's TimeZone instead of UTC. rd := rowcodec.Encoder{Enable: true} - rowValue, err1 := tablecodec.EncodeRow(sc, []types.Datum{colValue}, []int64{colID}, nil, nil, &rd) + rowValue, err1 := tablecodec.EncodeRow(sc.TimeZone(), []types.Datum{colValue}, []int64{colID}, nil, nil, &rd) require.NoError(t, err1) txn.Set(rowKey, rowValue) diff --git a/pkg/store/mockstore/unistore/cophandler/analyze.go b/pkg/store/mockstore/unistore/cophandler/analyze.go index 2b58c57d4ecb2..e77a41942a2a1 100644 --- a/pkg/store/mockstore/unistore/cophandler/analyze.go +++ b/pkg/store/mockstore/unistore/cophandler/analyze.go @@ -495,7 +495,8 @@ func (e *analyzeColumnsExec) Process(key, value []byte) error { continue } - value, err := tablecodec.EncodeValue(e.evalCtx.sc, nil, d) + value, err := tablecodec.EncodeValue(e.evalCtx.sc.TimeZone(), nil, d) + err = e.evalCtx.sc.HandleError(err) if err != nil { return err } diff --git a/pkg/store/mockstore/unistore/cophandler/cop_handler_test.go b/pkg/store/mockstore/unistore/cophandler/cop_handler_test.go index 87aea1bd48dd6..b3155d288ee64 100644 --- a/pkg/store/mockstore/unistore/cophandler/cop_handler_test.go +++ b/pkg/store/mockstore/unistore/cophandler/cop_handler_test.go @@ -118,7 +118,7 @@ func prepareTestTableData(keyNumber int, tableID int64) (*data, error) { for i := 0; i < keyNumber; i++ { datum := types.MakeDatums(i, "abc", 10.0) rows[int64(i)] = datum - rowEncodedData, err := tablecodec.EncodeRow(stmtCtx, datum, colIds, nil, nil, encoder) + rowEncodedData, err := tablecodec.EncodeRow(stmtCtx.TimeZone(), datum, colIds, nil, nil, encoder) if err != nil { return nil, err } diff --git a/pkg/store/mockstore/unistore/tikv/BUILD.bazel b/pkg/store/mockstore/unistore/tikv/BUILD.bazel index 978b52db23886..396ae089245c8 100644 --- a/pkg/store/mockstore/unistore/tikv/BUILD.bazel +++ b/pkg/store/mockstore/unistore/tikv/BUILD.bazel @@ -18,7 +18,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/kv", - "//pkg/sessionctx/stmtctx", "//pkg/store/mockstore/unistore/client", "//pkg/store/mockstore/unistore/config", "//pkg/store/mockstore/unistore/cophandler", diff --git a/pkg/store/mockstore/unistore/tikv/mvcc.go b/pkg/store/mockstore/unistore/tikv/mvcc.go index 7f8f8eb9104e3..3607abfd0ae31 100644 --- a/pkg/store/mockstore/unistore/tikv/mvcc.go +++ b/pkg/store/mockstore/unistore/tikv/mvcc.go @@ -33,7 +33,6 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" "github.com/pingcap/log" - "github.com/pingcap/tidb/pkg/sessionctx/stmtctx" "github.com/pingcap/tidb/pkg/store/mockstore/unistore/config" "github.com/pingcap/tidb/pkg/store/mockstore/unistore/lockstore" "github.com/pingcap/tidb/pkg/store/mockstore/unistore/pd" @@ -1001,7 +1000,7 @@ func encodeFromOldRow(oldRow, buf []byte) ([]byte, error) { } var encoder rowcodec.Encoder buf = buf[:0] - return encoder.Encode(stmtctx.NewStmtCtx(), colIDs, datums, buf) + return encoder.Encode(time.UTC, colIDs, datums, buf) } func (store *MVCCStore) buildPrewriteLock(reqCtx *requestCtx, m *kvrpcpb.Mutation, item *badger.Item, diff --git a/pkg/table/tables/index.go b/pkg/table/tables/index.go index f0fb1b45878e0..8fb48acb87db8 100644 --- a/pkg/table/tables/index.go +++ b/pkg/table/tables/index.go @@ -93,7 +93,9 @@ func (c *index) GenIndexKey(sc *stmtctx.StatementContext, indexedValues []types. if c.idxInfo.Global { idxTblID = c.tblInfo.ID } - return tablecodec.GenIndexKey(sc, c.tblInfo, c.idxInfo, idxTblID, indexedValues, h, buf) + key, distinct, err = tablecodec.GenIndexKey(sc.TimeZone(), c.tblInfo, c.idxInfo, idxTblID, indexedValues, h, buf) + err = sc.HandleError(err) + return } // GenIndexValue generates the index value. @@ -102,7 +104,9 @@ func (c *index) GenIndexValue(sc *stmtctx.StatementContext, distinct bool, index c.initNeedRestoreData.Do(func() { c.needRestoredData = NeedRestoredData(c.idxInfo.Columns, c.tblInfo.Columns) }) - return tablecodec.GenIndexValuePortal(sc, c.tblInfo, c.idxInfo, c.needRestoredData, distinct, false, indexedValues, h, c.phyTblID, restoredData, buf) + idx, err := tablecodec.GenIndexValuePortal(sc.TimeZone(), c.tblInfo, c.idxInfo, c.needRestoredData, distinct, false, indexedValues, h, c.phyTblID, restoredData, buf) + err = sc.HandleError(err) + return idx, err } // getIndexedValue will produce the result like: @@ -233,8 +237,9 @@ func (c *index) Create(sctx sessionctx.Context, txn kv.Transaction, indexedValue c.initNeedRestoreData.Do(func() { c.needRestoredData = NeedRestoredData(c.idxInfo.Columns, c.tblInfo.Columns) }) - idxVal, err := tablecodec.GenIndexValuePortal(sctx.GetSessionVars().StmtCtx, c.tblInfo, c.idxInfo, + idxVal, err := tablecodec.GenIndexValuePortal(sctx.GetSessionVars().StmtCtx.TimeZone(), c.tblInfo, c.idxInfo, c.needRestoredData, distinct, opt.Untouched, value, h, c.phyTblID, handleRestoreData, nil) + err = sctx.GetSessionVars().StmtCtx.HandleError(err) if err != nil { return nil, err } diff --git a/pkg/table/tables/mutation_checker_test.go b/pkg/table/tables/mutation_checker_test.go index 759800780f273..ee65710595cee 100644 --- a/pkg/table/tables/mutation_checker_test.go +++ b/pkg/table/tables/mutation_checker_test.go @@ -93,7 +93,7 @@ func TestCheckRowInsertionConsistency(t *testing.T) { // mocked data mockRowKey233 := tablecodec.EncodeRowKeyWithHandle(1, kv.IntHandle(233)) mockValue233, err := tablecodec.EncodeRow( - sessVars.StmtCtx, []types.Datum{types.NewIntDatum(233)}, []int64{101}, nil, nil, &rd, + sessVars.StmtCtx.TimeZone(), []types.Datum{types.NewIntDatum(233)}, []int64{101}, nil, nil, &rd, ) require.Nil(t, err) fakeRowInsertion := mutation{key: []byte{1, 1}, value: []byte{1, 1, 1}} @@ -306,7 +306,7 @@ func TestCheckIndexKeysAndCheckHandleConsistency(t *testing.T) { // test checkHandleConsistency rowKey := tablecodec.EncodeRowKeyWithHandle(table.tableID, handle) corruptedRowKey := tablecodec.EncodeRowKeyWithHandle(table.tableID, corruptedHandle) - rowValue, err := tablecodec.EncodeRow(sessVars.StmtCtx, rowToInsert, []int64{1, 2}, nil, nil, &rd) + rowValue, err := tablecodec.EncodeRow(sessVars.StmtCtx.TimeZone(), rowToInsert, []int64{1, 2}, nil, nil, &rd) require.Nil(t, err) rowMutation := mutation{key: rowKey, value: rowValue} corruptedRowMutation := mutation{key: corruptedRowKey, value: rowValue} @@ -327,14 +327,14 @@ func buildIndexKeyValue(index table.Index, rowToInsert []types.Datum, sessVars * return nil, nil, err } key, distinct, err := tablecodec.GenIndexKey( - sessVars.StmtCtx, &tableInfo, indexInfo, 1, indexedValues, handle, nil, + sessVars.StmtCtx.TimeZone(), &tableInfo, indexInfo, 1, indexedValues, handle, nil, ) if err != nil { return nil, nil, err } rsData := TryGetHandleRestoredDataWrapper(table.meta, rowToInsert, nil, indexInfo) value, err := tablecodec.GenIndexValuePortal( - sessVars.StmtCtx, &tableInfo, indexInfo, NeedRestoredData(indexInfo.Columns, tableInfo.Columns), + sessVars.StmtCtx.TimeZone(), &tableInfo, indexInfo, NeedRestoredData(indexInfo.Columns, tableInfo.Columns), distinct, false, indexedValues, handle, 0, rsData, nil, ) if err != nil { diff --git a/pkg/table/tables/tables.go b/pkg/table/tables/tables.go index ac9878783b261..640f6e0244768 100644 --- a/pkg/table/tables/tables.go +++ b/pkg/table/tables/tables.go @@ -549,7 +549,8 @@ func (t *TableCommon) UpdateRecord(ctx context.Context, sctx sessionctx.Context, key := t.RecordKey(h) sc, rd := sessVars.StmtCtx, &sessVars.RowEncoder checksums, writeBufs.RowValBuf = t.calcChecksums(sctx, h, checksumData, writeBufs.RowValBuf) - writeBufs.RowValBuf, err = tablecodec.EncodeRow(sc, row, colIDs, writeBufs.RowValBuf, writeBufs.AddRowValues, rd, checksums...) + writeBufs.RowValBuf, err = tablecodec.EncodeRow(sc.TimeZone(), row, colIDs, writeBufs.RowValBuf, writeBufs.AddRowValues, rd, checksums...) + err = sc.HandleError(err) if err != nil { return err } @@ -988,7 +989,8 @@ func (t *TableCommon) AddRecord(sctx sessionctx.Context, r []types.Datum, opts . zap.Stringer("key", key)) sc, rd := sessVars.StmtCtx, &sessVars.RowEncoder checksums, writeBufs.RowValBuf = t.calcChecksums(sctx, recordID, checksumData, writeBufs.RowValBuf) - writeBufs.RowValBuf, err = tablecodec.EncodeRow(sc, row, colIDs, writeBufs.RowValBuf, writeBufs.AddRowValues, rd, checksums...) + writeBufs.RowValBuf, err = tablecodec.EncodeRow(sc.TimeZone(), row, colIDs, writeBufs.RowValBuf, writeBufs.AddRowValues, rd, checksums...) + err = sc.HandleError(err) if err != nil { return nil, err } @@ -1395,7 +1397,8 @@ func (t *TableCommon) addInsertBinlog(ctx sessionctx.Context, h kv.Handle, row [ if err != nil { return err } - value, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx, row, colIDs, nil, nil) + value, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx.TimeZone(), row, colIDs, nil, nil) + err = ctx.GetSessionVars().StmtCtx.HandleError(err) if err != nil { return err } @@ -1406,11 +1409,13 @@ func (t *TableCommon) addInsertBinlog(ctx sessionctx.Context, h kv.Handle, row [ } func (t *TableCommon) addUpdateBinlog(ctx sessionctx.Context, oldRow, newRow []types.Datum, colIDs []int64) error { - old, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx, oldRow, colIDs, nil, nil) + old, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx.TimeZone(), oldRow, colIDs, nil, nil) + err = ctx.GetSessionVars().StmtCtx.HandleError(err) if err != nil { return err } - newVal, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx, newRow, colIDs, nil, nil) + newVal, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx.TimeZone(), newRow, colIDs, nil, nil) + err = ctx.GetSessionVars().StmtCtx.HandleError(err) if err != nil { return err } @@ -1422,7 +1427,8 @@ func (t *TableCommon) addUpdateBinlog(ctx sessionctx.Context, oldRow, newRow []t } func (t *TableCommon) addDeleteBinlog(ctx sessionctx.Context, r []types.Datum, colIDs []int64) error { - data, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx, r, colIDs, nil, nil) + data, err := tablecodec.EncodeOldRow(ctx.GetSessionVars().StmtCtx.TimeZone(), r, colIDs, nil, nil) + err = ctx.GetSessionVars().StmtCtx.HandleError(err) if err != nil { return err } @@ -2316,7 +2322,8 @@ func SetPBColumnsDefaultValue(ctx sessionctx.Context, pbColumns []*tipb.ColumnIn return err } - pbColumns[i].DefaultVal, err = tablecodec.EncodeValue(sessVars.StmtCtx, nil, d) + pbColumns[i].DefaultVal, err = tablecodec.EncodeValue(sessVars.StmtCtx.TimeZone(), nil, d) + err = sessVars.StmtCtx.HandleError(err) if err != nil { return err } diff --git a/pkg/tablecodec/BUILD.bazel b/pkg/tablecodec/BUILD.bazel index 14474ee75b26a..8c891275c29f0 100644 --- a/pkg/tablecodec/BUILD.bazel +++ b/pkg/tablecodec/BUILD.bazel @@ -6,14 +6,12 @@ go_library( importpath = "github.com/pingcap/tidb/pkg/tablecodec", visibility = ["//visibility:public"], deps = [ - "//pkg/errctx", "//pkg/errno", "//pkg/kv", "//pkg/parser/charset", "//pkg/parser/model", "//pkg/parser/mysql", "//pkg/parser/terror", - "//pkg/sessionctx/stmtctx", "//pkg/structure", "//pkg/types", "//pkg/util/codec", diff --git a/pkg/tablecodec/tablecodec.go b/pkg/tablecodec/tablecodec.go index 2220d29761c1e..347d71221cbe0 100644 --- a/pkg/tablecodec/tablecodec.go +++ b/pkg/tablecodec/tablecodec.go @@ -24,14 +24,12 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/kvproto/pkg/kvrpcpb" - "github.com/pingcap/tidb/pkg/errctx" "github.com/pingcap/tidb/pkg/errno" "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/parser/charset" "github.com/pingcap/tidb/pkg/parser/model" "github.com/pingcap/tidb/pkg/parser/mysql" "github.com/pingcap/tidb/pkg/parser/terror" - "github.com/pingcap/tidb/pkg/sessionctx/stmtctx" "github.com/pingcap/tidb/pkg/structure" "github.com/pingcap/tidb/pkg/types" "github.com/pingcap/tidb/pkg/util/codec" @@ -324,22 +322,16 @@ func DecodeRowKey(key kv.Key) (kv.Handle, error) { } // EncodeValue encodes a go value to bytes. -func EncodeValue(sc *stmtctx.StatementContext, b []byte, raw types.Datum) ([]byte, error) { +// This function may return both a valid encoded bytes and an error (actually `"pingcap/errors".ErrorGroup`). If the caller +// expects to handle these errors according to `SQL_MODE` or other configuration, please refer to `pkg/errctx`. +func EncodeValue(loc *time.Location, b []byte, raw types.Datum) ([]byte, error) { var v types.Datum - err := flatten(sc, raw, &v) + err := flatten(loc, raw, &v) if err != nil { return nil, err } - // `sc` is possible to be `nil` here. - tz := time.UTC - errCtx := errctx.StrictNoWarningContext - if sc != nil { - tz = sc.TimeZone() - errCtx = sc.ErrCtx() - } - val, err := codec.EncodeValue(tz, b, v) - err = errCtx.HandleError(err) + val, err := codec.EncodeValue(loc, b, v) return val, err } @@ -347,22 +339,24 @@ func EncodeValue(sc *stmtctx.StatementContext, b []byte, raw types.Datum) ([]byt // EncodeRow encode row data and column ids into a slice of byte. // valBuf and values pass by caller, for reducing EncodeRow allocates temporary bufs. If you pass valBuf and values as nil, // EncodeRow will allocate it. -func EncodeRow(sc *stmtctx.StatementContext, row []types.Datum, colIDs []int64, valBuf []byte, values []types.Datum, e *rowcodec.Encoder, checksums ...uint32) ([]byte, error) { +// This function may return both a valid encoded bytes and an error (actually `"pingcap/errors".ErrorGroup`). If the caller +// expects to handle these errors according to `SQL_MODE` or other configuration, please refer to `pkg/errctx`. +func EncodeRow(loc *time.Location, row []types.Datum, colIDs []int64, valBuf []byte, values []types.Datum, e *rowcodec.Encoder, checksums ...uint32) ([]byte, error) { if len(row) != len(colIDs) { return nil, errors.Errorf("EncodeRow error: data and columnID count not match %d vs %d", len(row), len(colIDs)) } if e.Enable { valBuf = valBuf[:0] - return e.Encode(sc, colIDs, row, valBuf, checksums...) + return e.Encode(loc, colIDs, row, valBuf, checksums...) } - return EncodeOldRow(sc, row, colIDs, valBuf, values) + return EncodeOldRow(loc, row, colIDs, valBuf, values) } // EncodeOldRow encode row data and column ids into a slice of byte. // Row layout: colID1, value1, colID2, value2, ..... // valBuf and values pass by caller, for reducing EncodeOldRow allocates temporary bufs. If you pass valBuf and values as nil, // EncodeOldRow will allocate it. -func EncodeOldRow(sc *stmtctx.StatementContext, row []types.Datum, colIDs []int64, valBuf []byte, values []types.Datum) ([]byte, error) { +func EncodeOldRow(loc *time.Location, row []types.Datum, colIDs []int64, valBuf []byte, values []types.Datum) ([]byte, error) { if len(row) != len(colIDs) { return nil, errors.Errorf("EncodeRow error: data and columnID count not match %d vs %d", len(row), len(colIDs)) } @@ -373,7 +367,7 @@ func EncodeOldRow(sc *stmtctx.StatementContext, row []types.Datum, colIDs []int6 for i, c := range row { id := colIDs[i] values[2*i].SetInt64(id) - err := flatten(sc, c, &values[2*i+1]) + err := flatten(loc, c, &values[2*i+1]) if err != nil { return valBuf, errors.Trace(err) } @@ -382,16 +376,16 @@ func EncodeOldRow(sc *stmtctx.StatementContext, row []types.Datum, colIDs []int6 // We could not set nil value into kv. return append(valBuf, codec.NilFlag), nil } - return codec.EncodeValue(sc.TimeZone(), valBuf, values...) + return codec.EncodeValue(loc, valBuf, values...) } -func flatten(sc *stmtctx.StatementContext, data types.Datum, ret *types.Datum) error { +func flatten(loc *time.Location, data types.Datum, ret *types.Datum) error { switch data.Kind() { case types.KindMysqlTime: // for mysql datetime, timestamp and date type t := data.GetMysqlTime() - if t.Type() == mysql.TypeTimestamp && sc.TimeZone() != time.UTC { - err := t.ConvertTimeZone(sc.TimeZone(), time.UTC) + if t.Type() == mysql.TypeTimestamp && loc != nil && loc != time.UTC { + err := t.ConvertTimeZone(loc, time.UTC) if err != nil { return errors.Trace(err) } @@ -411,7 +405,7 @@ func flatten(sc *stmtctx.StatementContext, data types.Datum, ret *types.Datum) e return nil case types.KindBinaryLiteral, types.KindMysqlBit: // We don't need to handle errors here since the literal is ensured to be able to store in uint64 in convertToMysqlBit. - val, err := data.GetBinaryLiteral().ToInt(sc.TypeCtx()) + val, err := data.GetBinaryLiteral().ToInt(types.StrictContext) if err != nil { return errors.Trace(err) } @@ -1123,7 +1117,7 @@ func GetIndexKeyBuf(buf []byte, defaultCap int) []byte { } // GenIndexKey generates index key using input physical table id -func GenIndexKey(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, +func GenIndexKey(loc *time.Location, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, phyTblID int64, indexedValues []types.Datum, h kv.Handle, buf []byte) (key []byte, distinct bool, err error) { if idxInfo.Unique { // See https://dev.mysql.com/doc/refman/5.7/en/create-index.html @@ -1144,7 +1138,7 @@ func GenIndexKey(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo key = GetIndexKeyBuf(buf, RecordRowKeyLen+len(indexedValues)*9+9) key = appendTableIndexPrefix(key, phyTblID) key = codec.EncodeInt(key, idxInfo.ID) - key, err = codec.EncodeKey(sc.TimeZone(), key, indexedValues...) + key, err = codec.EncodeKey(loc, key, indexedValues...) if err != nil { return nil, false, err } @@ -1440,13 +1434,13 @@ func TempIndexValueIsUntouched(b []byte) bool { // | In v5.0, restored data contains only non-binary data(except for char and _bin). In the above example, the restored data contains only the value of b. // | Besides, if the collation of b is _bin, then restored data is an integer indicate the spaces are truncated. Then we use sortKey // | and the restored data together to restore original data. -func GenIndexValuePortal(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, +func GenIndexValuePortal(loc *time.Location, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, needRestoredData bool, distinct bool, untouched bool, indexedValues []types.Datum, h kv.Handle, partitionID int64, restoredData []types.Datum, buf []byte) ([]byte, error) { if tblInfo.IsCommonHandle && tblInfo.CommonHandleVersion == 1 { - return GenIndexValueForClusteredIndexVersion1(sc, tblInfo, idxInfo, needRestoredData, distinct, untouched, indexedValues, h, partitionID, restoredData, buf) + return GenIndexValueForClusteredIndexVersion1(loc, tblInfo, idxInfo, needRestoredData, distinct, untouched, indexedValues, h, partitionID, restoredData, buf) } - return genIndexValueVersion0(sc, tblInfo, idxInfo, needRestoredData, distinct, untouched, indexedValues, h, partitionID, buf) + return genIndexValueVersion0(loc, tblInfo, idxInfo, needRestoredData, distinct, untouched, indexedValues, h, partitionID, buf) } // TryGetCommonPkColumnRestoredIds get the IDs of primary key columns which need restored data if the table has common handle. @@ -1472,7 +1466,7 @@ func TryGetCommonPkColumnRestoredIds(tbl *model.TableInfo) []int64 { } // GenIndexValueForClusteredIndexVersion1 generates the index value for the clustered index with version 1(New in v5.0.0). -func GenIndexValueForClusteredIndexVersion1(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, +func GenIndexValueForClusteredIndexVersion1(loc *time.Location, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, idxValNeedRestoredData bool, distinct bool, untouched bool, indexedValues []types.Datum, h kv.Handle, partitionID int64, handleRestoredData []types.Datum, buf []byte) ([]byte, error) { var idxVal []byte @@ -1521,7 +1515,7 @@ func GenIndexValueForClusteredIndexVersion1(sc *stmtctx.StatementContext, tblInf rd := rowcodec.Encoder{Enable: true} var err error - idxVal, err = rd.Encode(sc, colIds, allRestoredData, idxVal) + idxVal, err = rd.Encode(loc, colIds, allRestoredData, idxVal) if err != nil { return nil, err } @@ -1537,7 +1531,7 @@ func GenIndexValueForClusteredIndexVersion1(sc *stmtctx.StatementContext, tblInf } // genIndexValueVersion0 create index value for both local and global index. -func genIndexValueVersion0(sc *stmtctx.StatementContext, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, +func genIndexValueVersion0(loc *time.Location, tblInfo *model.TableInfo, idxInfo *model.IndexInfo, idxValNeedRestoredData bool, distinct bool, untouched bool, indexedValues []types.Datum, h kv.Handle, partitionID int64, buf []byte) ([]byte, error) { var idxVal []byte @@ -1565,7 +1559,7 @@ func genIndexValueVersion0(sc *stmtctx.StatementContext, tblInfo *model.TableInf rd := rowcodec.Encoder{Enable: true} // Encode row restored value. var err error - idxVal, err = rd.Encode(sc, colIds, indexedValues, idxVal) + idxVal, err = rd.Encode(loc, colIds, indexedValues, idxVal) if err != nil { return nil, err } diff --git a/pkg/tablecodec/tablecodec_test.go b/pkg/tablecodec/tablecodec_test.go index ffb889c5f2f9d..89d9659619acd 100644 --- a/pkg/tablecodec/tablecodec_test.go +++ b/pkg/tablecodec/tablecodec_test.go @@ -100,7 +100,7 @@ func TestRowCodec(t *testing.T) { } rd := rowcodec.Encoder{Enable: true} sc := stmtctx.NewStmtCtxWithTimeZone(time.Local) - bs, err := EncodeRow(sc, row, colIDs, nil, nil, &rd) + bs, err := EncodeRow(sc.TimeZone(), row, colIDs, nil, nil, &rd) require.NoError(t, err) require.NotNil(t, bs) @@ -155,7 +155,7 @@ func TestRowCodec(t *testing.T) { } // Make sure empty row return not nil value. - bs, err = EncodeOldRow(sc, []types.Datum{}, []int64{}, nil, nil) + bs, err = EncodeOldRow(sc.TimeZone(), []types.Datum{}, []int64{}, nil, nil) require.NoError(t, err) require.Len(t, bs, 1) @@ -169,7 +169,7 @@ func TestDecodeColumnValue(t *testing.T) { // test timestamp d := types.NewTimeDatum(types.NewTime(types.FromGoTime(time.Now()), mysql.TypeTimestamp, types.DefaultFsp)) - bs, err := EncodeOldRow(sc, []types.Datum{d}, []int64{1}, nil, nil) + bs, err := EncodeOldRow(sc.TimeZone(), []types.Datum{d}, []int64{1}, nil, nil) require.NoError(t, err) require.NotNil(t, bs) _, bs, err = codec.CutOne(bs) // ignore colID @@ -185,7 +185,7 @@ func TestDecodeColumnValue(t *testing.T) { elems := []string{"a", "b", "c", "d", "e"} e, _ := types.ParseSetValue(elems, uint64(1)) d = types.NewMysqlSetDatum(e, "") - bs, err = EncodeOldRow(sc, []types.Datum{d}, []int64{1}, nil, nil) + bs, err = EncodeOldRow(sc.TimeZone(), []types.Datum{d}, []int64{1}, nil, nil) require.NoError(t, err) require.NotNil(t, bs) _, bs, err = codec.CutOne(bs) // ignore colID @@ -200,7 +200,7 @@ func TestDecodeColumnValue(t *testing.T) { // test bit d = types.NewMysqlBitDatum(types.NewBinaryLiteralFromUint(3223600, 3)) - bs, err = EncodeOldRow(sc, []types.Datum{d}, []int64{1}, nil, nil) + bs, err = EncodeOldRow(sc.TimeZone(), []types.Datum{d}, []int64{1}, nil, nil) require.NoError(t, err) require.NotNil(t, bs) _, bs, err = codec.CutOne(bs) // ignore colID @@ -215,7 +215,7 @@ func TestDecodeColumnValue(t *testing.T) { // test empty enum d = types.NewMysqlEnumDatum(types.Enum{}) - bs, err = EncodeOldRow(sc, []types.Datum{d}, []int64{1}, nil, nil) + bs, err = EncodeOldRow(sc.TimeZone(), []types.Datum{d}, []int64{1}, nil, nil) require.NoError(t, err) require.NotNil(t, bs) _, bs, err = codec.CutOne(bs) // ignore colID @@ -275,7 +275,7 @@ func TestTimeCodec(t *testing.T) { } rd := rowcodec.Encoder{Enable: true} sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - bs, err := EncodeRow(sc, row, colIDs, nil, nil, &rd) + bs, err := EncodeRow(sc.TimeZone(), row, colIDs, nil, nil, &rd) require.NoError(t, err) require.NotNil(t, bs) @@ -312,18 +312,18 @@ func TestCutRow(t *testing.T) { sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) data := make([][]byte, 3) - data[0], err = EncodeValue(sc, nil, row[0]) + data[0], err = EncodeValue(sc.TimeZone(), nil, row[0]) require.NoError(t, err) - data[1], err = EncodeValue(sc, nil, row[1]) + data[1], err = EncodeValue(sc.TimeZone(), nil, row[1]) require.NoError(t, err) - data[2], err = EncodeValue(sc, nil, row[2]) + data[2], err = EncodeValue(sc.TimeZone(), nil, row[2]) require.NoError(t, err) // Encode colIDs := make([]int64, 0, 3) for _, col := range cols { colIDs = append(colIDs, col.id) } - bs, err := EncodeOldRow(sc, row, colIDs, nil, nil) + bs, err := EncodeOldRow(sc.TimeZone(), row, colIDs, nil, nil) require.NoError(t, err) require.NotNil(t, bs) @@ -567,7 +567,7 @@ func BenchmarkEncodeValue(b *testing.B) { for i := 0; i < b.N; i++ { for _, d := range row { encodedCol = encodedCol[:0] - _, err := EncodeValue(sc, encodedCol, d) + _, err := EncodeValue(sc.TimeZone(), encodedCol, d) if err != nil { b.Fatal(err) } diff --git a/pkg/util/rowDecoder/decoder_test.go b/pkg/util/rowDecoder/decoder_test.go index 78eb540bedbf5..3f8cadb2fac3b 100644 --- a/pkg/util/rowDecoder/decoder_test.go +++ b/pkg/util/rowDecoder/decoder_test.go @@ -112,7 +112,7 @@ func TestRowDecoder(t *testing.T) { if i > 0 { c7.AddFlag(mysql.UnsignedFlag) } - bs, err := tablecodec.EncodeRow(sc, row.input, row.cols, nil, nil, &rd) + bs, err := tablecodec.EncodeRow(sc.TimeZone(), row.input, row.cols, nil, nil, &rd) require.NoError(t, err) require.NotNil(t, bs) @@ -187,7 +187,7 @@ func TestClusterIndexRowDecoder(t *testing.T) { } rd := rowcodec.Encoder{Enable: true} for _, row := range testRows { - bs, err := tablecodec.EncodeRow(sc, row.input, row.cols, nil, nil, &rd) + bs, err := tablecodec.EncodeRow(sc.TimeZone(), row.input, row.cols, nil, nil, &rd) require.NoError(t, err) require.NotNil(t, bs) diff --git a/pkg/util/rowcodec/BUILD.bazel b/pkg/util/rowcodec/BUILD.bazel index 42eb49b739d7d..22f366b5ac02e 100644 --- a/pkg/util/rowcodec/BUILD.bazel +++ b/pkg/util/rowcodec/BUILD.bazel @@ -14,13 +14,12 @@ go_library( "//pkg/kv", "//pkg/parser/model", "//pkg/parser/mysql", - "//pkg/parser/terror", "//pkg/parser/types", - "//pkg/sessionctx/stmtctx", "//pkg/types", "//pkg/util/chunk", "//pkg/util/codec", "@com_github_pingcap_errors//:errors", + "@org_uber_go_multierr//:multierr", ], ) diff --git a/pkg/util/rowcodec/bench_test.go b/pkg/util/rowcodec/bench_test.go index ef5698f27f9a7..1735b0c96fea6 100644 --- a/pkg/util/rowcodec/bench_test.go +++ b/pkg/util/rowcodec/bench_test.go @@ -21,7 +21,6 @@ import ( "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/parser/model" "github.com/pingcap/tidb/pkg/parser/mysql" - "github.com/pingcap/tidb/pkg/sessionctx/stmtctx" "github.com/pingcap/tidb/pkg/tablecodec" "github.com/pingcap/tidb/pkg/types" "github.com/pingcap/tidb/pkg/util/benchdaily" @@ -68,7 +67,7 @@ func BenchmarkEncode(b *testing.B) { func BenchmarkEncodeFromOldRow(b *testing.B) { b.ReportAllocs() oldRow := types.MakeDatums(1, "abc", 1.1) - oldRowData, err := tablecodec.EncodeOldRow(stmtctx.NewStmtCtx(), oldRow, []int64{1, 2, 3}, nil, nil) + oldRowData, err := tablecodec.EncodeOldRow(nil, oldRow, []int64{1, 2, 3}, nil, nil) if err != nil { b.Fatal(err) } diff --git a/pkg/util/rowcodec/encoder.go b/pkg/util/rowcodec/encoder.go index 0f72745045f20..a725537a96028 100644 --- a/pkg/util/rowcodec/encoder.go +++ b/pkg/util/rowcodec/encoder.go @@ -21,10 +21,9 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/pkg/parser/mysql" - "github.com/pingcap/tidb/pkg/parser/terror" - "github.com/pingcap/tidb/pkg/sessionctx/stmtctx" "github.com/pingcap/tidb/pkg/types" "github.com/pingcap/tidb/pkg/util/codec" + "go.uber.org/multierr" ) // Encoder is used to encode a row. @@ -38,16 +37,15 @@ type Encoder struct { // Encode encodes a row from a datums slice. // `buf` is not truncated before encoding. -func (encoder *Encoder) Encode(sc *stmtctx.StatementContext, colIDs []int64, values []types.Datum, buf []byte, checksums ...uint32) ([]byte, error) { +// This function may return both a valid encoded bytes and an error (actually `"pingcap/errors".ErrorGroup`). If the caller +// expects to handle these errors according to `SQL_MODE` or other configuration, please refer to `pkg/errctx`. +func (encoder *Encoder) Encode(loc *time.Location, colIDs []int64, values []types.Datum, buf []byte, checksums ...uint32) ([]byte, error) { encoder.reset() encoder.appendColVals(colIDs, values) numCols, notNullIdx := encoder.reformatCols() - err := encoder.encodeRowCols(sc, numCols, notNullIdx) - if err != nil { - return nil, err - } + err := encoder.encodeRowCols(loc, numCols, notNullIdx) encoder.setChecksums(checksums...) - return encoder.row.toBytes(buf), nil + return encoder.row.toBytes(buf), err } func (encoder *Encoder) reset() { @@ -131,14 +129,15 @@ func (encoder *Encoder) reformatCols() (numCols, notNullIdx int) { return } -func (encoder *Encoder) encodeRowCols(sc *stmtctx.StatementContext, numCols, notNullIdx int) error { +func (encoder *Encoder) encodeRowCols(loc *time.Location, numCols, notNullIdx int) error { r := &encoder.row + var errs error for i := 0; i < notNullIdx; i++ { d := encoder.values[i] var err error - r.data, err = encodeValueDatum(sc, d, r.data) + r.data, err = encodeValueDatum(loc, d, r.data) if err != nil { - return err + errs = multierr.Append(errs, err) } // handle convert to large if len(r.data) > math.MaxUint16 && !r.large() { @@ -158,12 +157,12 @@ func (encoder *Encoder) encodeRowCols(sc *stmtctx.StatementContext, numCols, not r.offsets[i] = uint16(len(r.data)) } } - return nil + return errs } // encodeValueDatum encodes one row datum entry into bytes. // due to encode as value, this method will flatten value type like tablecodec.flatten -func encodeValueDatum(sc *stmtctx.StatementContext, d *types.Datum, buffer []byte) (nBuffer []byte, err error) { +func encodeValueDatum(loc *time.Location, d *types.Datum, buffer []byte) (nBuffer []byte, err error) { switch d.Kind() { case types.KindInt64: buffer = encodeInt(buffer, d.GetInt64()) @@ -174,8 +173,8 @@ func encodeValueDatum(sc *stmtctx.StatementContext, d *types.Datum, buffer []byt case types.KindMysqlTime: // for mysql datetime, timestamp and date type t := d.GetMysqlTime() - if t.Type() == mysql.TypeTimestamp && sc != nil && sc.TimeZone() != time.UTC { - err = t.ConvertTimeZone(sc.TimeZone(), time.UTC) + if t.Type() == mysql.TypeTimestamp && loc != nil && loc != time.UTC { + err = t.ConvertTimeZone(loc, time.UTC) if err != nil { return } @@ -195,7 +194,7 @@ func encodeValueDatum(sc *stmtctx.StatementContext, d *types.Datum, buffer []byt case types.KindBinaryLiteral, types.KindMysqlBit: // We don't need to handle errors here since the literal is ensured to be able to store in uint64 in convertToMysqlBit. var val uint64 - val, err = d.GetBinaryLiteral().ToInt(sc.TypeCtxOrDefault()) + val, err = d.GetBinaryLiteral().ToInt(types.StrictContext) if err != nil { return } @@ -204,13 +203,6 @@ func encodeValueDatum(sc *stmtctx.StatementContext, d *types.Datum, buffer []byt buffer = codec.EncodeFloat(buffer, d.GetFloat64()) case types.KindMysqlDecimal: buffer, err = codec.EncodeDecimal(buffer, d.GetMysqlDecimal(), d.Length(), d.Frac()) - if err != nil && sc != nil { - if terror.ErrorEqual(err, types.ErrTruncated) { - err = sc.HandleTruncate(err) - } else if terror.ErrorEqual(err, types.ErrOverflow) { - err = sc.HandleOverflow(err, err) - } - } case types.KindMysqlJSON: j := d.GetMysqlJSON() buffer = append(buffer, j.TypeCode) diff --git a/pkg/util/rowcodec/main_test.go b/pkg/util/rowcodec/main_test.go index d6c88fe255ad7..a59f3a2efe399 100644 --- a/pkg/util/rowcodec/main_test.go +++ b/pkg/util/rowcodec/main_test.go @@ -16,8 +16,8 @@ package rowcodec import ( "testing" + "time" - "github.com/pingcap/tidb/pkg/sessionctx/stmtctx" "github.com/pingcap/tidb/pkg/testkit/testsetup" "github.com/pingcap/tidb/pkg/types" "github.com/pingcap/tidb/pkg/util/codec" @@ -36,7 +36,7 @@ func TestMain(m *testing.M) { // EncodeFromOldRow encodes a row from an old-format row. // this method will be used in test. -func EncodeFromOldRow(encoder *Encoder, sc *stmtctx.StatementContext, oldRow, buf []byte) ([]byte, error) { +func EncodeFromOldRow(encoder *Encoder, loc *time.Location, oldRow, buf []byte) ([]byte, error) { if len(oldRow) > 0 && oldRow[0] == CodecVer { return oldRow, nil } @@ -56,7 +56,7 @@ func EncodeFromOldRow(encoder *Encoder, sc *stmtctx.StatementContext, oldRow, bu encoder.appendColVal(colID, &d) } numCols, notNullIdx := encoder.reformatCols() - err := encoder.encodeRowCols(sc, numCols, notNullIdx) + err := encoder.encodeRowCols(loc, numCols, notNullIdx) if err != nil { return nil, err } diff --git a/pkg/util/rowcodec/rowcodec_test.go b/pkg/util/rowcodec/rowcodec_test.go index 94f49bf3c3abd..700bb9276d73e 100644 --- a/pkg/util/rowcodec/rowcodec_test.go +++ b/pkg/util/rowcodec/rowcodec_test.go @@ -51,7 +51,7 @@ func TestEncodeLargeSmallReuseBug(t *testing.T) { colFt := types.NewFieldType(mysql.TypeString) largeColID := int64(300) - b, err := encoder.Encode(stmtctx.NewStmtCtx(), []int64{largeColID}, []types.Datum{types.NewBytesDatum([]byte(""))}, nil) + b, err := encoder.Encode(nil, []int64{largeColID}, []types.Datum{types.NewBytesDatum([]byte(""))}, nil) require.NoError(t, err) bDecoder := rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{ @@ -66,7 +66,7 @@ func TestEncodeLargeSmallReuseBug(t *testing.T) { colFt = types.NewFieldType(mysql.TypeLonglong) smallColID := int64(1) - b, err = encoder.Encode(stmtctx.NewStmtCtx(), []int64{smallColID}, []types.Datum{types.NewIntDatum(2)}, nil) + b, err = encoder.Encode(nil, []int64{smallColID}, []types.Datum{types.NewIntDatum(2)}, nil) require.NoError(t, err) bDecoder = rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{ @@ -162,16 +162,15 @@ func TestDecodeRowWithHandle(t *testing.T) { // test encode input. var encoder rowcodec.Encoder - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) // decode to datum map. - mDecoder := rowcodec.NewDatumMapDecoder(cols, sc.TimeZone()) + mDecoder := rowcodec.NewDatumMapDecoder(cols, time.UTC) dm, err := mDecoder.DecodeToDatumMap(newRow, nil) require.NoError(t, err) - dm, err = tablecodec.DecodeHandleToDatumMap(kv.IntHandle(handleValue), []int64{handleID}, handleColFtMap, sc.TimeZone(), dm) + dm, err = tablecodec.DecodeHandleToDatumMap(kv.IntHandle(handleValue), []int64{handleID}, handleColFtMap, time.UTC, dm) require.NoError(t, err) for _, d := range td { @@ -181,7 +180,7 @@ func TestDecodeRowWithHandle(t *testing.T) { } // decode to chunk. - cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, time.UTC) chk := chunk.New(fts, 1, 1) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(handleValue), chk) require.NoError(t, err) @@ -222,7 +221,6 @@ func TestDecodeRowWithHandle(t *testing.T) { func TestEncodeKindNullDatum(t *testing.T) { var encoder rowcodec.Encoder - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) colIDs := []int64{1, 2} var nilDt types.Datum @@ -230,11 +228,11 @@ func TestEncodeKindNullDatum(t *testing.T) { dts := []types.Datum{nilDt, types.NewIntDatum(2)} ft := types.NewFieldType(mysql.TypeLonglong) fts := []*types.FieldType{ft, ft} - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) cols := []rowcodec.ColInfo{{ID: 1, Ft: ft}, {ID: 2, Ft: ft}} - cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, time.UTC) chk := chunk.New(fts, 1, 1) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(-1), chk) require.NoError(t, err) @@ -247,7 +245,6 @@ func TestEncodeKindNullDatum(t *testing.T) { func TestDecodeDecimalFspNotMatch(t *testing.T) { var encoder rowcodec.Encoder - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) colIDs := []int64{ 1, } @@ -256,7 +253,7 @@ func TestDecodeDecimalFspNotMatch(t *testing.T) { ft := types.NewFieldType(mysql.TypeNewDecimal) ft.SetDecimal(4) fts := []*types.FieldType{ft} - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) // decode to chunk. @@ -267,7 +264,7 @@ func TestDecodeDecimalFspNotMatch(t *testing.T) { ID: 1, Ft: ft, }) - cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, time.UTC) chk := chunk.New(fts, 1, 1) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(-1), chk) require.NoError(t, err) @@ -512,12 +509,11 @@ func TestTypesNewRowCodec(t *testing.T) { } // test encode input. - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) // decode to datum map. - mDecoder := rowcodec.NewDatumMapDecoder(cols, sc.TimeZone()) + mDecoder := rowcodec.NewDatumMapDecoder(cols, time.UTC) dm, err := mDecoder.DecodeToDatumMap(newRow, nil) require.NoError(t, err) @@ -528,7 +524,7 @@ func TestTypesNewRowCodec(t *testing.T) { } // decode to chunk. - cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, time.UTC) chk := chunk.New(fts, 1, 1) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(-1), chk) require.NoError(t, err) @@ -626,12 +622,11 @@ func TestNilAndDefault(t *testing.T) { // test encode input. var encoder rowcodec.Encoder - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) // decode to datum map. - mDecoder := rowcodec.NewDatumMapDecoder(cols, sc.TimeZone()) + mDecoder := rowcodec.NewDatumMapDecoder(cols, time.UTC) dm, err := mDecoder.DecodeToDatumMap(newRow, nil) require.NoError(t, err) @@ -648,7 +643,7 @@ func TestNilAndDefault(t *testing.T) { // decode to chunk. chk := chunk.New(fts, 1, 1) - cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, ddf, sc.TimeZone()) + cDecoder := rowcodec.NewChunkDecoder(cols, []int64{-1}, ddf, time.UTC) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(-1), chk) require.NoError(t, err) @@ -664,7 +659,7 @@ func TestNilAndDefault(t *testing.T) { } chk = chunk.New(fts, 1, 1) - cDecoder = rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + cDecoder = rowcodec.NewChunkDecoder(cols, []int64{-1}, nil, time.UTC) err = cDecoder.DecodeToChunk(newRow, kv.IntHandle(-1), chk) require.NoError(t, err) @@ -682,7 +677,7 @@ func TestNilAndDefault(t *testing.T) { for i, t := range td { colOffset[t.id] = i } - bDecoder := rowcodec.NewByteDecoder(cols, []int64{-1}, bdf, sc.TimeZone()) + bDecoder := rowcodec.NewByteDecoder(cols, []int64{-1}, bdf, time.UTC) oldRow, err := bDecoder.DecodeToBytes(colOffset, kv.IntHandle(-1), newRow, nil) require.NoError(t, err) @@ -735,11 +730,10 @@ func TestVarintCompatibility(t *testing.T) { // test encode input. var encoder rowcodec.Encoder - sc := stmtctx.NewStmtCtxWithTimeZone(time.UTC) - newRow, err := encoder.Encode(sc, colIDs, dts, nil) + newRow, err := encoder.Encode(time.UTC, colIDs, dts, nil) require.NoError(t, err) - decoder := rowcodec.NewByteDecoder(cols, []int64{-1}, nil, sc.TimeZone()) + decoder := rowcodec.NewByteDecoder(cols, []int64{-1}, nil, time.UTC) // decode to old row bytes. colOffset := make(map[int64]int) for i, t := range td { @@ -763,7 +757,7 @@ func TestCodecUtil(t *testing.T) { } tps[3] = types.NewFieldType(mysql.TypeNull) sc := stmtctx.NewStmtCtx() - oldRow, err := tablecodec.EncodeOldRow(sc, types.MakeDatums(1, 2, 3, nil), colIDs, nil, nil) + oldRow, err := tablecodec.EncodeOldRow(sc.TimeZone(), types.MakeDatums(1, 2, 3, nil), colIDs, nil, nil) require.NoError(t, err) var ( @@ -813,7 +807,7 @@ func TestOldRowCodec(t *testing.T) { } tps[3] = types.NewFieldType(mysql.TypeNull) sc := stmtctx.NewStmtCtx() - oldRow, err := tablecodec.EncodeOldRow(sc, types.MakeDatums(1, 2, 3, nil), colIDs, nil, nil) + oldRow, err := tablecodec.EncodeOldRow(sc.TimeZone(), types.MakeDatums(1, 2, 3, nil), colIDs, nil, nil) require.NoError(t, err) var ( @@ -844,10 +838,9 @@ func Test65535Bug(t *testing.T) { colIds := []int64{1} tps := make([]*types.FieldType, 1) tps[0] = types.NewFieldType(mysql.TypeString) - sc := stmtctx.NewStmtCtx() text65535 := strings.Repeat("a", 65535) encode := rowcodec.Encoder{} - bd, err := encode.Encode(sc, colIds, []types.Datum{types.NewStringDatum(text65535)}, nil) + bd, err := encode.Encode(time.UTC, colIds, []types.Datum{types.NewStringDatum(text65535)}, nil) require.NoError(t, err) cols := make([]rowcodec.ColInfo, 1) @@ -1195,7 +1188,6 @@ func TestRowChecksum(t *testing.T) { } func TestEncodeDecodeRowWithChecksum(t *testing.T) { - sc := stmtctx.NewStmtCtx() enc := rowcodec.Encoder{} for _, tt := range []struct { @@ -1208,9 +1200,9 @@ func TestEncodeDecodeRowWithChecksum(t *testing.T) { {"ThreeChecksum", []uint32{1, 2, 3}}, } { t.Run(tt.name, func(t *testing.T) { - raw, err := enc.Encode(sc, nil, nil, nil, tt.checksums...) + raw, err := enc.Encode(time.UTC, nil, nil, nil, tt.checksums...) require.NoError(t, err) - dec := rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{}, sc.TimeZone()) + dec := rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{}, time.UTC) _, err = dec.DecodeToDatumMap(raw, nil) require.NoError(t, err) v1, ok1 := enc.GetChecksum() @@ -1245,9 +1237,9 @@ func TestEncodeDecodeRowWithChecksum(t *testing.T) { } t.Run("ReuseDecoder", func(t *testing.T) { - dec := rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{}, sc.TimeZone()) + dec := rowcodec.NewDatumMapDecoder([]rowcodec.ColInfo{}, time.UTC) - raw1, err := enc.Encode(sc, nil, nil, nil) + raw1, err := enc.Encode(time.UTC, nil, nil, nil) require.NoError(t, err) _, err = dec.DecodeToDatumMap(raw1, nil) require.NoError(t, err) @@ -1258,7 +1250,7 @@ func TestEncodeDecodeRowWithChecksum(t *testing.T) { require.Zero(t, v1) require.Zero(t, v2) - raw2, err := enc.Encode(sc, nil, nil, nil, 1, 2) + raw2, err := enc.Encode(time.UTC, nil, nil, nil, 1, 2) require.NoError(t, err) _, err = dec.DecodeToDatumMap(raw2, nil) require.NoError(t, err) @@ -1269,7 +1261,7 @@ func TestEncodeDecodeRowWithChecksum(t *testing.T) { require.Equal(t, uint32(1), v1) require.Equal(t, uint32(2), v2) - raw3, err := enc.Encode(sc, nil, nil, nil, 1) + raw3, err := enc.Encode(time.UTC, nil, nil, nil, 1) require.NoError(t, err) _, err = dec.DecodeToDatumMap(raw3, nil) require.NoError(t, err) diff --git a/tests/realtikvtest/addindextest1/disttask_test.go b/tests/realtikvtest/addindextest1/disttask_test.go index 27715a0613ecb..54a3ee5d32e6c 100644 --- a/tests/realtikvtest/addindextest1/disttask_test.go +++ b/tests/realtikvtest/addindextest1/disttask_test.go @@ -271,7 +271,7 @@ func TestAddIndexTSErrorWhenResetImportEngine(t *testing.T) { dts := []types.Datum{types.NewIntDatum(1)} sctx := tk.Session().GetSessionVars().StmtCtx - idxKey, _, err := tablecodec.GenIndexKey(sctx, tblInfo, idxInfo, tblInfo.ID, dts, kv.IntHandle(1), nil) + idxKey, _, err := tablecodec.GenIndexKey(sctx.TimeZone(), tblInfo, idxInfo, tblInfo.ID, dts, kv.IntHandle(1), nil) require.NoError(t, err) tikvStore := dom.Store().(helper.Storage)