github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/kv/kv.go (about)

     1  // Copyright 2019 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package kv
    15  
    16  import (
    17  	"bytes"
    18  	"fmt"
    19  	"math"
    20  	"sort"
    21  
    22  	"github.com/pingcap/errors"
    23  	sst "github.com/pingcap/kvproto/pkg/import_sstpb"
    24  	"github.com/pingcap/log"
    25  	"github.com/pingcap/parser/model"
    26  	"github.com/pingcap/parser/mysql"
    27  	"github.com/pingcap/tidb/kv"
    28  	"github.com/pingcap/tidb/meta/autoid"
    29  	"github.com/pingcap/tidb/table"
    30  	"github.com/pingcap/tidb/table/tables"
    31  	"github.com/pingcap/tidb/tablecodec"
    32  	"github.com/pingcap/tidb/types"
    33  	"go.uber.org/zap"
    34  
    35  	"github.com/pingcap/br/pkg/logutil"
    36  	"github.com/pingcap/br/pkg/redact"
    37  )
    38  
    39  var extraHandleColumnInfo = model.NewExtraHandleColInfo()
    40  
    41  // Iter abstract iterator method for Ingester.
    42  type Iter interface {
    43  	// Seek seek to specify position.
    44  	// if key not found, seeks next key position in iter.
    45  	Seek(key []byte) bool
    46  	// Error return current error on this iter.
    47  	Error() error
    48  	// First moves this iter to the first key.
    49  	First() bool
    50  	// Last moves this iter to the last key.
    51  	Last() bool
    52  	// Valid check this iter reach the end.
    53  	Valid() bool
    54  	// Next moves this iter forward.
    55  	Next() bool
    56  	// Key represents current position pair's key.
    57  	Key() []byte
    58  	// Value represents current position pair's Value.
    59  	Value() []byte
    60  	// Close close this iter.
    61  	Close() error
    62  	// OpType represents operations of pair. currently we have two types.
    63  	// 1. Put
    64  	// 2. Delete
    65  	OpType() sst.Pair_OP
    66  }
    67  
    68  // IterProducer produces iterator with given range.
    69  type IterProducer interface {
    70  	// Produce produces iterator with given range [start, end).
    71  	Produce(start []byte, end []byte) Iter
    72  }
    73  
    74  // SimpleKVIterProducer represents kv iter producer.
    75  type SimpleKVIterProducer struct {
    76  	pairs Pairs
    77  }
    78  
    79  // NewSimpleKVIterProducer creates SimpleKVIterProducer.
    80  func NewSimpleKVIterProducer(pairs Pairs) IterProducer {
    81  	return &SimpleKVIterProducer{
    82  		pairs: pairs,
    83  	}
    84  }
    85  
    86  // Produce implements Iter.Producer.Produce.
    87  func (p *SimpleKVIterProducer) Produce(start []byte, end []byte) Iter {
    88  	startIndex := sort.Search(len(p.pairs), func(i int) bool {
    89  		return bytes.Compare(start, p.pairs[i].Key) < 1
    90  	})
    91  	endIndex := sort.Search(len(p.pairs), func(i int) bool {
    92  		return bytes.Compare(end, p.pairs[i].Key) < 1
    93  	})
    94  	if startIndex >= endIndex {
    95  		log.Warn("produce failed due to start key is large than end key",
    96  			zap.Binary("start", start), zap.Binary("end", end))
    97  		return nil
    98  	}
    99  	return newSimpleKVIter(p.pairs[startIndex:endIndex])
   100  }
   101  
   102  // SimpleKVIter represents simple pair iterator.
   103  // which is used for log restore.
   104  type SimpleKVIter struct {
   105  	index int
   106  	pairs Pairs
   107  }
   108  
   109  // newSimpleKVIter creates SimpleKVIter.
   110  func newSimpleKVIter(pairs Pairs) Iter {
   111  	return &SimpleKVIter{
   112  		index: -1,
   113  		pairs: pairs,
   114  	}
   115  }
   116  
   117  // Seek implements Iter.Seek.
   118  func (s *SimpleKVIter) Seek(key []byte) bool {
   119  	s.index = sort.Search(len(s.pairs), func(i int) bool {
   120  		return bytes.Compare(key, s.pairs[i].Key) < 1
   121  	})
   122  	return s.index < len(s.pairs)
   123  }
   124  
   125  // Error implements Iter.Error.
   126  func (s *SimpleKVIter) Error() error {
   127  	return nil
   128  }
   129  
   130  // First implements Iter.First.
   131  func (s *SimpleKVIter) First() bool {
   132  	if len(s.pairs) == 0 {
   133  		return false
   134  	}
   135  	s.index = 0
   136  	return true
   137  }
   138  
   139  // Last implements Iter.Last.
   140  func (s *SimpleKVIter) Last() bool {
   141  	if len(s.pairs) == 0 {
   142  		return false
   143  	}
   144  	s.index = len(s.pairs) - 1
   145  	return true
   146  }
   147  
   148  // Valid implements Iter.Valid.
   149  func (s *SimpleKVIter) Valid() bool {
   150  	return s.index >= 0 && s.index < len(s.pairs)
   151  }
   152  
   153  // Next implements Iter.Next.
   154  func (s *SimpleKVIter) Next() bool {
   155  	s.index++
   156  	return s.index < len(s.pairs)
   157  }
   158  
   159  // Key implements Iter.Key.
   160  func (s *SimpleKVIter) Key() []byte {
   161  	if s.index >= 0 && s.index < len(s.pairs) {
   162  		return s.pairs[s.index].Key
   163  	}
   164  	return nil
   165  }
   166  
   167  // Value implements Iter.Value.
   168  func (s *SimpleKVIter) Value() []byte {
   169  	if s.index >= 0 && s.index < len(s.pairs) {
   170  		return s.pairs[s.index].Val
   171  	}
   172  	return nil
   173  }
   174  
   175  // Close implements Iter.Close.
   176  func (s *SimpleKVIter) Close() error {
   177  	return nil
   178  }
   179  
   180  // OpType implements Iter.KeyIsDelete.
   181  func (s *SimpleKVIter) OpType() sst.Pair_OP {
   182  	if s.Valid() && s.pairs[s.index].IsDelete {
   183  		return sst.Pair_Delete
   184  	}
   185  	return sst.Pair_Put
   186  }
   187  
   188  // Encoder encodes a row of SQL values into some opaque type which can be
   189  // consumed by OpenEngine.WriteEncoded.
   190  type Encoder interface {
   191  	// Close the encoder.
   192  	Close()
   193  
   194  	// AddRecord encode encodes a row of SQL values into a backend-friendly format.
   195  	AddRecord(
   196  		row []types.Datum,
   197  		rowID int64,
   198  		columnPermutation []int,
   199  	) (Row, int, error)
   200  
   201  	// RemoveRecord encode encodes a row of SQL delete values into a backend-friendly format.
   202  	RemoveRecord(
   203  		row []types.Datum,
   204  		rowID int64,
   205  		columnPermutation []int,
   206  	) (Row, int, error)
   207  }
   208  
   209  // Row represents a single encoded row.
   210  type Row interface {
   211  	// ClassifyAndAppend separates the data-like and index-like parts of the
   212  	// encoded row, and appends these parts into the existing buffers and
   213  	// checksums.
   214  	ClassifyAndAppend(
   215  		data *Pairs,
   216  		dataChecksum *Checksum,
   217  		indices *Pairs,
   218  		indexChecksum *Checksum,
   219  	)
   220  }
   221  
   222  type tableKVEncoder struct {
   223  	tbl         table.Table
   224  	se          *session
   225  	recordCache []types.Datum
   226  }
   227  
   228  // NewTableKVEncoder creates the Encoder.
   229  func NewTableKVEncoder(tbl table.Table, options *SessionOptions) Encoder {
   230  	se := newSession(options)
   231  	// Set CommonAddRecordCtx to session to reuse the slices and BufStore in AddRecord
   232  	recordCtx := tables.NewCommonAddRecordCtx(len(tbl.Cols()))
   233  	tables.SetAddRecordCtx(se, recordCtx)
   234  	return &tableKVEncoder{
   235  		tbl: tbl,
   236  		se:  se,
   237  	}
   238  }
   239  
   240  var kindStr = [...]string{
   241  	types.KindNull:          "null",
   242  	types.KindInt64:         "int64",
   243  	types.KindUint64:        "uint64",
   244  	types.KindFloat32:       "float32",
   245  	types.KindFloat64:       "float64",
   246  	types.KindString:        "string",
   247  	types.KindBytes:         "bytes",
   248  	types.KindBinaryLiteral: "binary",
   249  	types.KindMysqlDecimal:  "decimal",
   250  	types.KindMysqlDuration: "duration",
   251  	types.KindMysqlEnum:     "enum",
   252  	types.KindMysqlBit:      "bit",
   253  	types.KindMysqlSet:      "set",
   254  	types.KindMysqlTime:     "time",
   255  	types.KindInterface:     "interface",
   256  	types.KindMinNotNull:    "min",
   257  	types.KindMaxValue:      "max",
   258  	types.KindRaw:           "raw",
   259  	types.KindMysqlJSON:     "json",
   260  }
   261  
   262  // MarshalLogArray implements the zapcore.ArrayMarshaler interface.
   263  func zapRow(key string, row []types.Datum) zap.Field {
   264  	return logutil.AbbreviatedArray(key, row, func(input interface{}) []string {
   265  		row := input.([]types.Datum)
   266  		vals := make([]string, 0, len(row))
   267  		for _, datum := range row {
   268  			kind := datum.Kind()
   269  			var str string
   270  			var err error
   271  			switch kind {
   272  			case types.KindNull:
   273  				str = "NULL"
   274  			case types.KindMinNotNull:
   275  				str = "-inf"
   276  			case types.KindMaxValue:
   277  				str = "+inf"
   278  			default:
   279  				str, err = datum.ToString()
   280  				if err != nil {
   281  					vals = append(vals, err.Error())
   282  					continue
   283  				}
   284  			}
   285  			vals = append(vals,
   286  				fmt.Sprintf("kind: %s, val: %s", kindStr[kind], redact.String(str)))
   287  		}
   288  		return vals
   289  	})
   290  }
   291  
   292  // Pairs represents the slice of Pair.
   293  type Pairs []Pair
   294  
   295  // Close ...
   296  func (kvcodec *tableKVEncoder) Close() {
   297  }
   298  
   299  // AddRecord encode a row of data into KV pairs.
   300  //
   301  // See comments in `(*TableRestore).initializeColumns` for the meaning of the
   302  // `columnPermutation` parameter.
   303  func (kvcodec *tableKVEncoder) AddRecord(
   304  	row []types.Datum,
   305  	rowID int64,
   306  	columnPermutation []int,
   307  ) (Row, int, error) {
   308  	cols := kvcodec.tbl.Cols()
   309  
   310  	var value types.Datum
   311  	var err error
   312  
   313  	record := kvcodec.recordCache
   314  	if record == nil {
   315  		record = make([]types.Datum, 0, len(cols)+1)
   316  	}
   317  
   318  	isAutoRandom := false
   319  	if kvcodec.tbl.Meta().PKIsHandle && kvcodec.tbl.Meta().ContainsAutoRandomBits() {
   320  		isAutoRandom = true
   321  	}
   322  
   323  	for i, col := range cols {
   324  		j := columnPermutation[i]
   325  		isAutoIncCol := mysql.HasAutoIncrementFlag(col.Flag)
   326  		isPk := mysql.HasPriKeyFlag(col.Flag)
   327  		switch {
   328  		case j >= 0 && j < len(row):
   329  			value, err = table.CastValue(kvcodec.se, row[j], col.ToInfo(), false, false)
   330  			if err == nil {
   331  				err = col.HandleBadNull(&value, kvcodec.se.vars.StmtCtx)
   332  			}
   333  		case isAutoIncCol:
   334  			// we still need a conversion, e.g. to catch overflow with a TINYINT column.
   335  			value, err = table.CastValue(kvcodec.se, types.NewIntDatum(rowID), col.ToInfo(), false, false)
   336  		default:
   337  			value, err = table.GetColDefaultValue(kvcodec.se, col.ToInfo())
   338  		}
   339  		if err != nil {
   340  			return nil, 0, errors.Trace(err)
   341  		}
   342  
   343  		record = append(record, value)
   344  
   345  		if isAutoRandom && isPk {
   346  			typeBitsLength := uint64(mysql.DefaultLengthOfMysqlTypes[col.Tp] * 8)
   347  			incrementalBits := typeBitsLength - kvcodec.tbl.Meta().AutoRandomBits
   348  			hasSignBit := !mysql.HasUnsignedFlag(col.Flag)
   349  			if hasSignBit {
   350  				incrementalBits--
   351  			}
   352  			_ = kvcodec.tbl.RebaseAutoID(kvcodec.se, value.GetInt64()&((1<<incrementalBits)-1), false, autoid.AutoRandomType)
   353  		}
   354  		if isAutoIncCol {
   355  			// TODO use auto incremental type
   356  			_ = kvcodec.tbl.RebaseAutoID(kvcodec.se, getAutoRecordID(value, &col.FieldType), false, autoid.RowIDAllocType)
   357  		}
   358  	}
   359  
   360  	if TableHasAutoRowID(kvcodec.tbl.Meta()) {
   361  		j := columnPermutation[len(cols)]
   362  		if j >= 0 && j < len(row) {
   363  			value, err = table.CastValue(kvcodec.se, row[j], extraHandleColumnInfo, false, false)
   364  		} else {
   365  			value, err = types.NewIntDatum(rowID), nil
   366  		}
   367  		if err != nil {
   368  			return nil, 0, errors.Trace(err)
   369  		}
   370  		record = append(record, value)
   371  		_ = kvcodec.tbl.RebaseAutoID(kvcodec.se, value.GetInt64(), false, autoid.RowIDAllocType)
   372  	}
   373  	_, err = kvcodec.tbl.AddRecord(kvcodec.se, record)
   374  	if err != nil {
   375  		log.Error("kv add Record failed",
   376  			zapRow("originalRow", row),
   377  			zapRow("convertedRow", record),
   378  			zap.Error(err),
   379  		)
   380  		return nil, 0, errors.Trace(err)
   381  	}
   382  
   383  	pairs, size := kvcodec.se.takeKvPairs()
   384  	kvcodec.recordCache = record[:0]
   385  	return Pairs(pairs), size, nil
   386  }
   387  
   388  // get record value for auto-increment field
   389  //
   390  // See: https://github.com/pingcap/tidb/blob/47f0f15b14ed54fc2222f3e304e29df7b05e6805/executor/insert_common.go#L781-L852
   391  // TODO: merge this with pkg/lightning/backend/kv/sql2kv.go
   392  func getAutoRecordID(d types.Datum, target *types.FieldType) int64 {
   393  	switch target.Tp {
   394  	case mysql.TypeFloat, mysql.TypeDouble:
   395  		return int64(math.Round(d.GetFloat64()))
   396  	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong:
   397  		return d.GetInt64()
   398  	default:
   399  		panic(fmt.Sprintf("unsupported auto-increment field type '%d'", target.Tp))
   400  	}
   401  }
   402  
   403  // RemoveRecord encode a row of data into KV pairs.
   404  func (kvcodec *tableKVEncoder) RemoveRecord(
   405  	row []types.Datum,
   406  	rowID int64,
   407  	columnPermutation []int,
   408  ) (Row, int, error) {
   409  	cols := kvcodec.tbl.Cols()
   410  
   411  	var value types.Datum
   412  	var err error
   413  
   414  	record := kvcodec.recordCache
   415  	if record == nil {
   416  		record = make([]types.Datum, 0, len(cols)+1)
   417  	}
   418  
   419  	for i, col := range cols {
   420  		j := columnPermutation[i]
   421  		isAutoIncCol := mysql.HasAutoIncrementFlag(col.Flag)
   422  		switch {
   423  		case j >= 0 && j < len(row):
   424  			value, err = table.CastValue(kvcodec.se, row[j], col.ToInfo(), false, false)
   425  			if err == nil {
   426  				err = col.HandleBadNull(&value, kvcodec.se.vars.StmtCtx)
   427  			}
   428  		case isAutoIncCol:
   429  			// we still need a conversion, e.g. to catch overflow with a TINYINT column.
   430  			value, err = table.CastValue(kvcodec.se, types.NewIntDatum(rowID), col.ToInfo(), false, false)
   431  		default:
   432  			value, err = table.GetColDefaultValue(kvcodec.se, col.ToInfo())
   433  		}
   434  		if err != nil {
   435  			return nil, 0, errors.Trace(err)
   436  		}
   437  		record = append(record, value)
   438  	}
   439  	err = kvcodec.tbl.RemoveRecord(kvcodec.se, kv.IntHandle(rowID), record)
   440  	if err != nil {
   441  		log.Error("kv remove record failed",
   442  			zapRow("originalRow", row),
   443  			zapRow("convertedRow", record),
   444  			zap.Error(err),
   445  		)
   446  		return nil, 0, errors.Trace(err)
   447  	}
   448  
   449  	pairs, size := kvcodec.se.takeKvPairs()
   450  	kvcodec.recordCache = record[:0]
   451  	return Pairs(pairs), size, nil
   452  }
   453  
   454  // ClassifyAndAppend split Pairs to data rows and index rows.
   455  func (kvs Pairs) ClassifyAndAppend(
   456  	data *Pairs,
   457  	dataChecksum *Checksum,
   458  	indices *Pairs,
   459  	indexChecksum *Checksum,
   460  ) {
   461  	dataKVs := *data
   462  	indexKVs := *indices
   463  
   464  	for _, kv := range kvs {
   465  		if kv.Key[tablecodec.TableSplitKeyLen+1] == 'r' {
   466  			dataKVs = append(dataKVs, kv)
   467  			dataChecksum.UpdateOne(kv)
   468  		} else {
   469  			indexKVs = append(indexKVs, kv)
   470  			indexChecksum.UpdateOne(kv)
   471  		}
   472  	}
   473  
   474  	*data = dataKVs
   475  	*indices = indexKVs
   476  }
   477  
   478  // Clear resets the Pairs.
   479  func (kvs Pairs) Clear() Pairs {
   480  	return kvs[:0]
   481  }
   482  
   483  // NextKey return the smallest []byte that is bigger than current bytes.
   484  // special case when key is empty, empty bytes means infinity in our context, so directly return itself.
   485  func NextKey(key []byte) []byte {
   486  	if len(key) == 0 {
   487  		return []byte{}
   488  	}
   489  
   490  	// in tikv <= 4.x, tikv will truncate the row key, so we should fetch the next valid row key
   491  	// See: https://github.com/tikv/tikv/blob/f7f22f70e1585d7ca38a59ea30e774949160c3e8/components/raftstore/src/coprocessor/split_observer.rs#L36-L41
   492  	if tablecodec.IsRecordKey(key) {
   493  		tableID, handle, _ := tablecodec.DecodeRecordKey(key)
   494  		return tablecodec.EncodeRowKeyWithHandle(tableID, handle.Next())
   495  	}
   496  
   497  	// if key is an index, directly append a 0x00 to the key.
   498  	res := make([]byte, 0, len(key)+1)
   499  	res = append(res, key...)
   500  	res = append(res, 0)
   501  	return res
   502  }