github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/codec/codec.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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 codec
    15  
    16  import (
    17  	"bytes"
    18  	"encoding/binary"
    19  	"fmt"
    20  	"hash"
    21  	"io"
    22  	"time"
    23  	"unsafe"
    24  
    25  	"github.com/whtcorpsinc/errors"
    26  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    27  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    28  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    29  	"github.com/whtcorpsinc/milevadb/types"
    30  	"github.com/whtcorpsinc/milevadb/types/json"
    31  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    32  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    33  	"github.com/whtcorpsinc/milevadb/soliton/replog"
    34  )
    35  
    36  // First byte in the encoded value which specifies the encoding type.
    37  const (
    38  	NilFlag          byte = 0
    39  	bytesFlag        byte = 1
    40  	compactBytesFlag byte = 2
    41  	intFlag          byte = 3
    42  	uintFlag         byte = 4
    43  	floatFlag        byte = 5
    44  	decimalFlag      byte = 6
    45  	durationFlag     byte = 7
    46  	varintFlag       byte = 8
    47  	uvarintFlag      byte = 9
    48  	jsonFlag         byte = 10
    49  	maxFlag          byte = 250
    50  )
    51  
    52  const (
    53  	sizeUint64  = unsafe.Sizeof(uint64(0))
    54  	sizeFloat64 = unsafe.Sizeof(float64(0))
    55  )
    56  
    57  func preRealloc(b []byte, vals []types.Causet, comparable bool) []byte {
    58  	var size int
    59  	for i := range vals {
    60  		switch vals[i].HoTT() {
    61  		case types.HoTTInt64, types.HoTTUint64, types.HoTTMysqlEnum, types.HoTTMysqlSet, types.HoTTMysqlBit, types.HoTTBinaryLiteral:
    62  			size += sizeInt(comparable)
    63  		case types.HoTTString, types.HoTTBytes:
    64  			size += sizeBytes(vals[i].GetBytes(), comparable)
    65  		case types.HoTTMysqlTime, types.HoTTMysqlDuration, types.HoTTFloat32, types.HoTTFloat64:
    66  			size += 9
    67  		case types.HoTTNull, types.HoTTMinNotNull, types.HoTTMaxValue:
    68  			size += 1
    69  		case types.HoTTMysqlJSON:
    70  			size += 2 + len(vals[i].GetBytes())
    71  		case types.HoTTMysqlDecimal:
    72  			size += 1 + types.MyDecimalStructSize
    73  		default:
    74  			return b
    75  		}
    76  	}
    77  	return reallocBytes(b, size)
    78  }
    79  
    80  // encode will encode a causet and append it to a byte slice. If comparable is true, the encoded bytes can be sorted as it's original order.
    81  // If hash is true, the encoded bytes can be checked equal as it's original value.
    82  func encode(sc *stmtctx.StatementContext, b []byte, vals []types.Causet, comparable bool) (_ []byte, err error) {
    83  	b = preRealloc(b, vals, comparable)
    84  	for i, length := 0, len(vals); i < length; i++ {
    85  		switch vals[i].HoTT() {
    86  		case types.HoTTInt64:
    87  			b = encodeSignedInt(b, vals[i].GetInt64(), comparable)
    88  		case types.HoTTUint64:
    89  			b = encodeUnsignedInt(b, vals[i].GetUint64(), comparable)
    90  		case types.HoTTFloat32, types.HoTTFloat64:
    91  			b = append(b, floatFlag)
    92  			b = EncodeFloat(b, vals[i].GetFloat64())
    93  		case types.HoTTString:
    94  			b = encodeString(b, vals[i], comparable)
    95  		case types.HoTTBytes:
    96  			b = encodeBytes(b, vals[i].GetBytes(), comparable)
    97  		case types.HoTTMysqlTime:
    98  			b = append(b, uintFlag)
    99  			b, err = EncodeMyALLEGROSQLTime(sc, vals[i].GetMysqlTime(), allegrosql.TypeUnspecified, b)
   100  			if err != nil {
   101  				return b, err
   102  			}
   103  		case types.HoTTMysqlDuration:
   104  			// duration may have negative value, so we cannot use String to encode directly.
   105  			b = append(b, durationFlag)
   106  			b = EncodeInt(b, int64(vals[i].GetMysqlDuration().Duration))
   107  		case types.HoTTMysqlDecimal:
   108  			b = append(b, decimalFlag)
   109  			b, err = EncodeDecimal(b, vals[i].GetMysqlDecimal(), vals[i].Length(), vals[i].Frac())
   110  			if terror.ErrorEqual(err, types.ErrTruncated) {
   111  				err = sc.HandleTruncate(err)
   112  			} else if terror.ErrorEqual(err, types.ErrOverflow) {
   113  				err = sc.HandleOverflow(err, err)
   114  			}
   115  		case types.HoTTMysqlEnum:
   116  			b = encodeUnsignedInt(b, uint64(vals[i].GetMysqlEnum().ToNumber()), comparable)
   117  		case types.HoTTMysqlSet:
   118  			b = encodeUnsignedInt(b, uint64(vals[i].GetMysqlSet().ToNumber()), comparable)
   119  		case types.HoTTMysqlBit, types.HoTTBinaryLiteral:
   120  			// We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit.
   121  			var val uint64
   122  			val, err = vals[i].GetBinaryLiteral().ToInt(sc)
   123  			terror.Log(errors.Trace(err))
   124  			b = encodeUnsignedInt(b, val, comparable)
   125  		case types.HoTTMysqlJSON:
   126  			b = append(b, jsonFlag)
   127  			j := vals[i].GetMysqlJSON()
   128  			b = append(b, j.TypeCode)
   129  			b = append(b, j.Value...)
   130  		case types.HoTTNull:
   131  			b = append(b, NilFlag)
   132  		case types.HoTTMinNotNull:
   133  			b = append(b, bytesFlag)
   134  		case types.HoTTMaxValue:
   135  			b = append(b, maxFlag)
   136  		default:
   137  			return b, errors.Errorf("unsupport encode type %d", vals[i].HoTT())
   138  		}
   139  	}
   140  
   141  	return b, errors.Trace(err)
   142  }
   143  
   144  // EstimateValueSize uses to estimate the value  size of the encoded values.
   145  func EstimateValueSize(sc *stmtctx.StatementContext, val types.Causet) (int, error) {
   146  	l := 0
   147  	switch val.HoTT() {
   148  	case types.HoTTInt64:
   149  		l = valueSizeOfSignedInt(val.GetInt64())
   150  	case types.HoTTUint64:
   151  		l = valueSizeOfUnsignedInt(val.GetUint64())
   152  	case types.HoTTFloat32, types.HoTTFloat64, types.HoTTMysqlTime, types.HoTTMysqlDuration:
   153  		l = 9
   154  	case types.HoTTString, types.HoTTBytes:
   155  		l = valueSizeOfBytes(val.GetBytes())
   156  	case types.HoTTMysqlDecimal:
   157  		l = valueSizeOfDecimal(val.GetMysqlDecimal(), val.Length(), val.Frac()) + 1
   158  	case types.HoTTMysqlEnum:
   159  		l = valueSizeOfUnsignedInt(uint64(val.GetMysqlEnum().ToNumber()))
   160  	case types.HoTTMysqlSet:
   161  		l = valueSizeOfUnsignedInt(uint64(val.GetMysqlSet().ToNumber()))
   162  	case types.HoTTMysqlBit, types.HoTTBinaryLiteral:
   163  		val, err := val.GetBinaryLiteral().ToInt(sc)
   164  		terror.Log(errors.Trace(err))
   165  		l = valueSizeOfUnsignedInt(val)
   166  	case types.HoTTMysqlJSON:
   167  		l = 2 + len(val.GetMysqlJSON().Value)
   168  	case types.HoTTNull, types.HoTTMinNotNull, types.HoTTMaxValue:
   169  		l = 1
   170  	default:
   171  		return l, errors.Errorf("unsupported encode type %d", val.HoTT())
   172  	}
   173  	return l, nil
   174  }
   175  
   176  // EncodeMyALLEGROSQLTime encodes causet of `HoTTMysqlTime` to []byte.
   177  func EncodeMyALLEGROSQLTime(sc *stmtctx.StatementContext, t types.Time, tp byte, b []byte) (_ []byte, err error) {
   178  	// Encoding timestamp need to consider timezone. If it's not in UTC, transform to UTC first.
   179  	// This is compatible with `PBToExpr > convertTime`, and interlock assumes the passed timestamp is in UTC as well.
   180  	if tp == allegrosql.TypeUnspecified {
   181  		tp = t.Type()
   182  	}
   183  	if tp == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC {
   184  		err = t.ConvertTimeZone(sc.TimeZone, time.UTC)
   185  		if err != nil {
   186  			return nil, err
   187  		}
   188  	}
   189  	var v uint64
   190  	v, err = t.ToPackedUint()
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  	b = EncodeUint(b, v)
   195  	return b, nil
   196  }
   197  
   198  func encodeString(b []byte, val types.Causet, comparable bool) []byte {
   199  	if defCauslate.NewDefCauslationEnabled() && comparable {
   200  		return encodeBytes(b, defCauslate.GetDefCauslator(val.DefCauslation()).Key(val.GetString()), true)
   201  	}
   202  	return encodeBytes(b, val.GetBytes(), comparable)
   203  }
   204  
   205  func encodeBytes(b []byte, v []byte, comparable bool) []byte {
   206  	if comparable {
   207  		b = append(b, bytesFlag)
   208  		b = EncodeBytes(b, v)
   209  	} else {
   210  		b = append(b, compactBytesFlag)
   211  		b = EncodeCompactBytes(b, v)
   212  	}
   213  	return b
   214  }
   215  
   216  func valueSizeOfBytes(v []byte) int {
   217  	return valueSizeOfSignedInt(int64(len(v))) + len(v)
   218  }
   219  
   220  func sizeBytes(v []byte, comparable bool) int {
   221  	if comparable {
   222  		reallocSize := (len(v)/encGroupSize + 1) * (encGroupSize + 1)
   223  		return 1 + reallocSize
   224  	}
   225  	reallocSize := binary.MaxVarintLen64 + len(v)
   226  	return 1 + reallocSize
   227  }
   228  
   229  func encodeSignedInt(b []byte, v int64, comparable bool) []byte {
   230  	if comparable {
   231  		b = append(b, intFlag)
   232  		b = EncodeInt(b, v)
   233  	} else {
   234  		b = append(b, varintFlag)
   235  		b = EncodeVarint(b, v)
   236  	}
   237  	return b
   238  }
   239  
   240  func valueSizeOfSignedInt(v int64) int {
   241  	if v < 0 {
   242  		v = 0 - v - 1
   243  	}
   244  	// Flag occupy 1 bit and at lease 1 bit.
   245  	size := 2
   246  	v = v >> 6
   247  	for v > 0 {
   248  		size++
   249  		v = v >> 7
   250  	}
   251  	return size
   252  }
   253  
   254  func encodeUnsignedInt(b []byte, v uint64, comparable bool) []byte {
   255  	if comparable {
   256  		b = append(b, uintFlag)
   257  		b = EncodeUint(b, v)
   258  	} else {
   259  		b = append(b, uvarintFlag)
   260  		b = EncodeUvarint(b, v)
   261  	}
   262  	return b
   263  }
   264  
   265  func valueSizeOfUnsignedInt(v uint64) int {
   266  	// Flag occupy 1 bit and at lease 1 bit.
   267  	size := 2
   268  	v = v >> 7
   269  	for v > 0 {
   270  		size++
   271  		v = v >> 7
   272  	}
   273  	return size
   274  }
   275  
   276  func sizeInt(comparable bool) int {
   277  	if comparable {
   278  		return 9
   279  	}
   280  	return 1 + binary.MaxVarintLen64
   281  }
   282  
   283  // EncodeKey appends the encoded values to byte slice b, returns the appended
   284  // slice. It guarantees the encoded value is in ascending order for comparison.
   285  // For Decimal type, causet must set causet's length and frac.
   286  func EncodeKey(sc *stmtctx.StatementContext, b []byte, v ...types.Causet) ([]byte, error) {
   287  	return encode(sc, b, v, true)
   288  }
   289  
   290  // EncodeValue appends the encoded values to byte slice b, returning the appended
   291  // slice. It does not guarantee the order for comparison.
   292  func EncodeValue(sc *stmtctx.StatementContext, b []byte, v ...types.Causet) ([]byte, error) {
   293  	return encode(sc, b, v, false)
   294  }
   295  
   296  func encodeHashChunkRowIdx(sc *stmtctx.StatementContext, event chunk.Row, tp *types.FieldType, idx int) (flag byte, b []byte, err error) {
   297  	if event.IsNull(idx) {
   298  		flag = NilFlag
   299  		return
   300  	}
   301  	switch tp.Tp {
   302  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
   303  		flag = uvarintFlag
   304  		if !allegrosql.HasUnsignedFlag(tp.Flag) && event.GetInt64(idx) < 0 {
   305  			flag = varintFlag
   306  		}
   307  		b = event.GetRaw(idx)
   308  	case allegrosql.TypeFloat:
   309  		flag = floatFlag
   310  		f := float64(event.GetFloat32(idx))
   311  		// For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128].
   312  		// It makes -0's hash val different from 0's.
   313  		if f == 0 {
   314  			f = 0
   315  		}
   316  		b = (*[unsafe.Sizeof(f)]byte)(unsafe.Pointer(&f))[:]
   317  	case allegrosql.TypeDouble:
   318  		flag = floatFlag
   319  		f := event.GetFloat64(idx)
   320  		// For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128].
   321  		// It makes -0's hash val different from 0's.
   322  		if f == 0 {
   323  			f = 0
   324  		}
   325  		b = (*[unsafe.Sizeof(f)]byte)(unsafe.Pointer(&f))[:]
   326  	case allegrosql.TypeVarchar, allegrosql.TypeVarString, allegrosql.TypeString, allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   327  		flag = compactBytesFlag
   328  		b = event.GetBytes(idx)
   329  		b = ConvertByDefCauslation(b, tp)
   330  	case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   331  		flag = uintFlag
   332  		t := event.GetTime(idx)
   333  		// Encoding timestamp need to consider timezone.
   334  		// If it's not in UTC, transform to UTC first.
   335  		if t.Type() == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC {
   336  			err = t.ConvertTimeZone(sc.TimeZone, time.UTC)
   337  			if err != nil {
   338  				return
   339  			}
   340  		}
   341  		var v uint64
   342  		v, err = t.ToPackedUint()
   343  		if err != nil {
   344  			return
   345  		}
   346  		b = (*[unsafe.Sizeof(v)]byte)(unsafe.Pointer(&v))[:]
   347  	case allegrosql.TypeDuration:
   348  		flag = durationFlag
   349  		// duration may have negative value, so we cannot use String to encode directly.
   350  		b = event.GetRaw(idx)
   351  	case allegrosql.TypeNewDecimal:
   352  		flag = decimalFlag
   353  		// If hash is true, we only consider the original value of this decimal and ignore it's precision.
   354  		dec := event.GetMyDecimal(idx)
   355  		b, err = dec.ToHashKey()
   356  		if err != nil {
   357  			return
   358  		}
   359  	case allegrosql.TypeEnum:
   360  		flag = compactBytesFlag
   361  		v := uint64(event.GetEnum(idx).ToNumber())
   362  		str := tp.Elems[v-1]
   363  		b = ConvertByDefCauslation(replog.Slice(str), tp)
   364  	case allegrosql.TypeSet:
   365  		flag = compactBytesFlag
   366  		v := uint64(event.GetSet(idx).ToNumber())
   367  		str := tp.Elems[v-1]
   368  		b = ConvertByDefCauslation(replog.Slice(str), tp)
   369  	case allegrosql.TypeBit:
   370  		// We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit.
   371  		flag = uvarintFlag
   372  		v, err1 := types.BinaryLiteral(event.GetBytes(idx)).ToInt(sc)
   373  		terror.Log(errors.Trace(err1))
   374  		b = (*[unsafe.Sizeof(v)]byte)(unsafe.Pointer(&v))[:]
   375  	case allegrosql.TypeJSON:
   376  		flag = jsonFlag
   377  		b = event.GetBytes(idx)
   378  	default:
   379  		return 0, nil, errors.Errorf("unsupport defCausumn type for encode %d", tp.Tp)
   380  	}
   381  	return
   382  }
   383  
   384  // HashChunkDeferredCausets writes the encoded value of each event's defCausumn, which of index `defCausIdx`, to h.
   385  func HashChunkDeferredCausets(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk.Chunk, tp *types.FieldType, defCausIdx int, buf []byte, isNull []bool) (err error) {
   386  	return HashChunkSelected(sc, h, chk, tp, defCausIdx, buf, isNull, nil, false)
   387  }
   388  
   389  // HashChunkSelected writes the encoded value of selected event's defCausumn, which of index `defCausIdx`, to h.
   390  // sel indicates which rows are selected. If it is nil, all rows are selected.
   391  func HashChunkSelected(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk.Chunk, tp *types.FieldType, defCausIdx int, buf []byte,
   392  	isNull, sel []bool, ignoreNull bool) (err error) {
   393  	var b []byte
   394  	defCausumn := chk.DeferredCauset(defCausIdx)
   395  	rows := chk.NumRows()
   396  	switch tp.Tp {
   397  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
   398  		i64s := defCausumn.Int64s()
   399  		for i, v := range i64s {
   400  			if sel != nil && !sel[i] {
   401  				continue
   402  			}
   403  			if defCausumn.IsNull(i) {
   404  				buf[0], b = NilFlag, nil
   405  				isNull[i] = !ignoreNull
   406  			} else {
   407  				buf[0] = uvarintFlag
   408  				if !allegrosql.HasUnsignedFlag(tp.Flag) && v < 0 {
   409  					buf[0] = varintFlag
   410  				}
   411  				b = defCausumn.GetRaw(i)
   412  			}
   413  
   414  			// As the golang doc described, `Hash.Write` never returns an error.
   415  			// See https://golang.org/pkg/hash/#Hash
   416  			_, _ = h[i].Write(buf)
   417  			_, _ = h[i].Write(b)
   418  		}
   419  	case allegrosql.TypeFloat:
   420  		f32s := defCausumn.Float32s()
   421  		for i, f := range f32s {
   422  			if sel != nil && !sel[i] {
   423  				continue
   424  			}
   425  			if defCausumn.IsNull(i) {
   426  				buf[0], b = NilFlag, nil
   427  				isNull[i] = !ignoreNull
   428  			} else {
   429  				buf[0] = floatFlag
   430  				d := float64(f)
   431  				// For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128].
   432  				// It makes -0's hash val different from 0's.
   433  				if d == 0 {
   434  					d = 0
   435  				}
   436  				b = (*[sizeFloat64]byte)(unsafe.Pointer(&d))[:]
   437  			}
   438  
   439  			// As the golang doc described, `Hash.Write` never returns an error.
   440  			// See https://golang.org/pkg/hash/#Hash
   441  			_, _ = h[i].Write(buf)
   442  			_, _ = h[i].Write(b)
   443  		}
   444  	case allegrosql.TypeDouble:
   445  		f64s := defCausumn.Float64s()
   446  		for i, f := range f64s {
   447  			if sel != nil && !sel[i] {
   448  				continue
   449  			}
   450  			if defCausumn.IsNull(i) {
   451  				buf[0], b = NilFlag, nil
   452  				isNull[i] = !ignoreNull
   453  			} else {
   454  				buf[0] = floatFlag
   455  				// For negative zero. In memory, 0 is [0, 0, 0, 0, 0, 0, 0, 0] and -0 is [0, 0, 0, 0, 0, 0, 0, 128].
   456  				// It makes -0's hash val different from 0's.
   457  				if f == 0 {
   458  					f = 0
   459  				}
   460  				b = (*[sizeFloat64]byte)(unsafe.Pointer(&f))[:]
   461  			}
   462  
   463  			// As the golang doc described, `Hash.Write` never returns an error.
   464  			// See https://golang.org/pkg/hash/#Hash
   465  			_, _ = h[i].Write(buf)
   466  			_, _ = h[i].Write(b)
   467  		}
   468  	case allegrosql.TypeVarchar, allegrosql.TypeVarString, allegrosql.TypeString, allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   469  		for i := 0; i < rows; i++ {
   470  			if sel != nil && !sel[i] {
   471  				continue
   472  			}
   473  			if defCausumn.IsNull(i) {
   474  				buf[0], b = NilFlag, nil
   475  				isNull[i] = !ignoreNull
   476  			} else {
   477  				buf[0] = compactBytesFlag
   478  				b = defCausumn.GetBytes(i)
   479  				b = ConvertByDefCauslation(b, tp)
   480  			}
   481  
   482  			// As the golang doc described, `Hash.Write` never returns an error.
   483  			// See https://golang.org/pkg/hash/#Hash
   484  			_, _ = h[i].Write(buf)
   485  			_, _ = h[i].Write(b)
   486  		}
   487  	case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   488  		ts := defCausumn.Times()
   489  		for i, t := range ts {
   490  			if sel != nil && !sel[i] {
   491  				continue
   492  			}
   493  			if defCausumn.IsNull(i) {
   494  				buf[0], b = NilFlag, nil
   495  				isNull[i] = !ignoreNull
   496  			} else {
   497  				buf[0] = uintFlag
   498  				// Encoding timestamp need to consider timezone.
   499  				// If it's not in UTC, transform to UTC first.
   500  				if t.Type() == allegrosql.TypeTimestamp && sc.TimeZone != time.UTC {
   501  					err = t.ConvertTimeZone(sc.TimeZone, time.UTC)
   502  					if err != nil {
   503  						return
   504  					}
   505  				}
   506  				var v uint64
   507  				v, err = t.ToPackedUint()
   508  				if err != nil {
   509  					return
   510  				}
   511  				b = (*[sizeUint64]byte)(unsafe.Pointer(&v))[:]
   512  			}
   513  
   514  			// As the golang doc described, `Hash.Write` never returns an error.
   515  			// See https://golang.org/pkg/hash/#Hash
   516  			_, _ = h[i].Write(buf)
   517  			_, _ = h[i].Write(b)
   518  		}
   519  	case allegrosql.TypeDuration:
   520  		for i := 0; i < rows; i++ {
   521  			if sel != nil && !sel[i] {
   522  				continue
   523  			}
   524  			if defCausumn.IsNull(i) {
   525  				buf[0], b = NilFlag, nil
   526  				isNull[i] = !ignoreNull
   527  			} else {
   528  				buf[0] = durationFlag
   529  				// duration may have negative value, so we cannot use String to encode directly.
   530  				b = defCausumn.GetRaw(i)
   531  			}
   532  
   533  			// As the golang doc described, `Hash.Write` never returns an error.
   534  			// See https://golang.org/pkg/hash/#Hash
   535  			_, _ = h[i].Write(buf)
   536  			_, _ = h[i].Write(b)
   537  		}
   538  	case allegrosql.TypeNewDecimal:
   539  		ds := defCausumn.Decimals()
   540  		for i, d := range ds {
   541  			if sel != nil && !sel[i] {
   542  				continue
   543  			}
   544  			if defCausumn.IsNull(i) {
   545  				buf[0], b = NilFlag, nil
   546  				isNull[i] = !ignoreNull
   547  			} else {
   548  				buf[0] = decimalFlag
   549  				// If hash is true, we only consider the original value of this decimal and ignore it's precision.
   550  				b, err = d.ToHashKey()
   551  				if err != nil {
   552  					return
   553  				}
   554  			}
   555  
   556  			// As the golang doc described, `Hash.Write` never returns an error.
   557  			// See https://golang.org/pkg/hash/#Hash
   558  			_, _ = h[i].Write(buf)
   559  			_, _ = h[i].Write(b)
   560  		}
   561  	case allegrosql.TypeEnum:
   562  		for i := 0; i < rows; i++ {
   563  			if sel != nil && !sel[i] {
   564  				continue
   565  			}
   566  			if defCausumn.IsNull(i) {
   567  				buf[0], b = NilFlag, nil
   568  				isNull[i] = !ignoreNull
   569  			} else {
   570  				buf[0] = compactBytesFlag
   571  				v := uint64(defCausumn.GetEnum(i).ToNumber())
   572  				str := tp.Elems[v-1]
   573  				b = ConvertByDefCauslation(replog.Slice(str), tp)
   574  			}
   575  
   576  			// As the golang doc described, `Hash.Write` never returns an error.
   577  			// See https://golang.org/pkg/hash/#Hash
   578  			_, _ = h[i].Write(buf)
   579  			_, _ = h[i].Write(b)
   580  		}
   581  	case allegrosql.TypeSet:
   582  		for i := 0; i < rows; i++ {
   583  			if sel != nil && !sel[i] {
   584  				continue
   585  			}
   586  			if defCausumn.IsNull(i) {
   587  				buf[0], b = NilFlag, nil
   588  				isNull[i] = !ignoreNull
   589  			} else {
   590  				buf[0] = compactBytesFlag
   591  				v := uint64(defCausumn.GetSet(i).ToNumber())
   592  				str := tp.Elems[v-1]
   593  				b = ConvertByDefCauslation(replog.Slice(str), tp)
   594  			}
   595  
   596  			// As the golang doc described, `Hash.Write` never returns an error.
   597  			// See https://golang.org/pkg/hash/#Hash
   598  			_, _ = h[i].Write(buf)
   599  			_, _ = h[i].Write(b)
   600  		}
   601  	case allegrosql.TypeBit:
   602  		for i := 0; i < rows; i++ {
   603  			if sel != nil && !sel[i] {
   604  				continue
   605  			}
   606  			if defCausumn.IsNull(i) {
   607  				buf[0], b = NilFlag, nil
   608  				isNull[i] = !ignoreNull
   609  			} else {
   610  				// We don't need to handle errors here since the literal is ensured to be able to causetstore in uint64 in convertToMysqlBit.
   611  				buf[0] = uvarintFlag
   612  				v, err1 := types.BinaryLiteral(defCausumn.GetBytes(i)).ToInt(sc)
   613  				terror.Log(errors.Trace(err1))
   614  				b = (*[sizeUint64]byte)(unsafe.Pointer(&v))[:]
   615  			}
   616  
   617  			// As the golang doc described, `Hash.Write` never returns an error.
   618  			// See https://golang.org/pkg/hash/#Hash
   619  			_, _ = h[i].Write(buf)
   620  			_, _ = h[i].Write(b)
   621  		}
   622  	case allegrosql.TypeJSON:
   623  		for i := 0; i < rows; i++ {
   624  			if sel != nil && !sel[i] {
   625  				continue
   626  			}
   627  			if defCausumn.IsNull(i) {
   628  				buf[0], b = NilFlag, nil
   629  				isNull[i] = !ignoreNull
   630  			} else {
   631  				buf[0] = jsonFlag
   632  				b = defCausumn.GetBytes(i)
   633  			}
   634  
   635  			// As the golang doc described, `Hash.Write` never returns an error..
   636  			// See https://golang.org/pkg/hash/#Hash
   637  			_, _ = h[i].Write(buf)
   638  			_, _ = h[i].Write(b)
   639  		}
   640  	case allegrosql.TypeNull:
   641  		for i := 0; i < rows; i++ {
   642  			if sel != nil && !sel[i] {
   643  				continue
   644  			}
   645  			isNull[i] = !ignoreNull
   646  			buf[0] = NilFlag
   647  			_, _ = h[i].Write(buf)
   648  		}
   649  	default:
   650  		return errors.Errorf("unsupport defCausumn type for encode %d", tp.Tp)
   651  	}
   652  	return
   653  }
   654  
   655  // HashChunkRow writes the encoded values to w.
   656  // If two rows are logically equal, it will generate the same bytes.
   657  func HashChunkRow(sc *stmtctx.StatementContext, w io.Writer, event chunk.Row, allTypes []*types.FieldType, defCausIdx []int, buf []byte) (err error) {
   658  	var b []byte
   659  	for _, idx := range defCausIdx {
   660  		buf[0], b, err = encodeHashChunkRowIdx(sc, event, allTypes[idx], idx)
   661  		if err != nil {
   662  			return errors.Trace(err)
   663  		}
   664  		_, err = w.Write(buf)
   665  		if err != nil {
   666  			return
   667  		}
   668  		_, err = w.Write(b)
   669  		if err != nil {
   670  			return
   671  		}
   672  	}
   673  	return err
   674  }
   675  
   676  // EqualChunkRow returns a boolean reporting whether row1 and row2
   677  // with their types and defCausumn index are logically equal.
   678  func EqualChunkRow(sc *stmtctx.StatementContext,
   679  	row1 chunk.Row, allTypes1 []*types.FieldType, defCausIdx1 []int,
   680  	row2 chunk.Row, allTypes2 []*types.FieldType, defCausIdx2 []int,
   681  ) (bool, error) {
   682  	for i := range defCausIdx1 {
   683  		idx1, idx2 := defCausIdx1[i], defCausIdx2[i]
   684  		flag1, b1, err := encodeHashChunkRowIdx(sc, row1, allTypes1[idx1], idx1)
   685  		if err != nil {
   686  			return false, errors.Trace(err)
   687  		}
   688  		flag2, b2, err := encodeHashChunkRowIdx(sc, row2, allTypes2[idx2], idx2)
   689  		if err != nil {
   690  			return false, errors.Trace(err)
   691  		}
   692  		if !(flag1 == flag2 && bytes.Equal(b1, b2)) {
   693  			return false, nil
   694  		}
   695  	}
   696  	return true, nil
   697  }
   698  
   699  // Decode decodes values from a byte slice generated with EncodeKey or EncodeValue
   700  // before.
   701  // size is the size of decoded causet slice.
   702  func Decode(b []byte, size int) ([]types.Causet, error) {
   703  	if len(b) < 1 {
   704  		return nil, errors.New("invalid encoded key")
   705  	}
   706  
   707  	var (
   708  		err    error
   709  		values = make([]types.Causet, 0, size)
   710  	)
   711  
   712  	for len(b) > 0 {
   713  		var d types.Causet
   714  		b, d, err = DecodeOne(b)
   715  		if err != nil {
   716  			return nil, errors.Trace(err)
   717  		}
   718  
   719  		values = append(values, d)
   720  	}
   721  
   722  	return values, nil
   723  }
   724  
   725  // DecodeRange decodes the range values from a byte slice that generated by EncodeKey.
   726  // It handles some special values like `MinNotNull` and `MaxValueCauset`.
   727  // loc can be nil and only used in when the corresponding type is `allegrosql.TypeTimestamp`.
   728  func DecodeRange(b []byte, size int, idxDeferredCausetTypes []byte, loc *time.Location) ([]types.Causet, []byte, error) {
   729  	if len(b) < 1 {
   730  		return nil, b, errors.New("invalid encoded key: length of key is zero")
   731  	}
   732  
   733  	var (
   734  		err    error
   735  		values = make([]types.Causet, 0, size)
   736  	)
   737  
   738  	i := 0
   739  	for len(b) > 1 {
   740  		var d types.Causet
   741  		if idxDeferredCausetTypes == nil {
   742  			b, d, err = DecodeOne(b)
   743  		} else {
   744  			if i >= len(idxDeferredCausetTypes) {
   745  				return values, b, errors.New("invalid length of index's defCausumns")
   746  			}
   747  			if idxDeferredCausetTypes[i] == allegrosql.TypeDatetime || idxDeferredCausetTypes[i] == allegrosql.TypeTimestamp || idxDeferredCausetTypes[i] == allegrosql.TypeDate {
   748  				b, d, err = DecodeAsDateTime(b, idxDeferredCausetTypes[i], loc)
   749  			} else {
   750  				b, d, err = DecodeOne(b)
   751  			}
   752  		}
   753  		if err != nil {
   754  			return values, b, errors.Trace(err)
   755  		}
   756  		values = append(values, d)
   757  		i++
   758  	}
   759  
   760  	if len(b) == 1 {
   761  		switch b[0] {
   762  		case NilFlag:
   763  			values = append(values, types.Causet{})
   764  		case bytesFlag:
   765  			values = append(values, types.MinNotNullCauset())
   766  		// `maxFlag + 1` for PrefixNext
   767  		case maxFlag, maxFlag + 1:
   768  			values = append(values, types.MaxValueCauset())
   769  		default:
   770  			return values, b, errors.Errorf("invalid encoded key flag %v", b[0])
   771  		}
   772  	}
   773  	return values, nil, nil
   774  }
   775  
   776  // DecodeOne decodes on causet from a byte slice generated with EncodeKey or EncodeValue.
   777  func DecodeOne(b []byte) (remain []byte, d types.Causet, err error) {
   778  	if len(b) < 1 {
   779  		return nil, d, errors.New("invalid encoded key")
   780  	}
   781  	flag := b[0]
   782  	b = b[1:]
   783  	switch flag {
   784  	case intFlag:
   785  		var v int64
   786  		b, v, err = DecodeInt(b)
   787  		d.SetInt64(v)
   788  	case uintFlag:
   789  		var v uint64
   790  		b, v, err = DecodeUint(b)
   791  		d.SetUint64(v)
   792  	case varintFlag:
   793  		var v int64
   794  		b, v, err = DecodeVarint(b)
   795  		d.SetInt64(v)
   796  	case uvarintFlag:
   797  		var v uint64
   798  		b, v, err = DecodeUvarint(b)
   799  		d.SetUint64(v)
   800  	case floatFlag:
   801  		var v float64
   802  		b, v, err = DecodeFloat(b)
   803  		d.SetFloat64(v)
   804  	case bytesFlag:
   805  		var v []byte
   806  		b, v, err = DecodeBytes(b, nil)
   807  		d.SetBytes(v)
   808  	case compactBytesFlag:
   809  		var v []byte
   810  		b, v, err = DecodeCompactBytes(b)
   811  		d.SetBytes(v)
   812  	case decimalFlag:
   813  		var (
   814  			dec             *types.MyDecimal
   815  			precision, frac int
   816  		)
   817  		b, dec, precision, frac, err = DecodeDecimal(b)
   818  		if err == nil {
   819  			d.SetMysqlDecimal(dec)
   820  			d.SetLength(precision)
   821  			d.SetFrac(frac)
   822  		}
   823  	case durationFlag:
   824  		var r int64
   825  		b, r, err = DecodeInt(b)
   826  		if err == nil {
   827  			// use max fsp, let outer to do round manually.
   828  			v := types.Duration{Duration: time.Duration(r), Fsp: types.MaxFsp}
   829  			d.SetMysqlDuration(v)
   830  		}
   831  	case jsonFlag:
   832  		var size int
   833  		size, err = json.PeekBytesAsJSON(b)
   834  		if err != nil {
   835  			return b, d, err
   836  		}
   837  		j := json.BinaryJSON{TypeCode: b[0], Value: b[1:size]}
   838  		d.SetMysqlJSON(j)
   839  		b = b[size:]
   840  	case NilFlag:
   841  	default:
   842  		return b, d, errors.Errorf("invalid encoded key flag %v", flag)
   843  	}
   844  	if err != nil {
   845  		return b, d, errors.Trace(err)
   846  	}
   847  	return b, d, nil
   848  }
   849  
   850  // DecodeAsDateTime decodes on causet from []byte of `HoTTMysqlTime`.
   851  func DecodeAsDateTime(b []byte, tp byte, loc *time.Location) (remain []byte, d types.Causet, err error) {
   852  	if len(b) < 1 {
   853  		return nil, d, errors.New("invalid encoded key")
   854  	}
   855  	flag := b[0]
   856  	b = b[1:]
   857  	switch flag {
   858  	case uintFlag:
   859  		var v uint64
   860  		b, v, err = DecodeUint(b)
   861  		if err != nil {
   862  			return b, d, err
   863  		}
   864  		t := types.NewTime(types.ZeroCoreTime, tp, 0)
   865  		err = t.FromPackedUint(v)
   866  		if err == nil {
   867  			if tp == allegrosql.TypeTimestamp && !t.IsZero() && loc != nil {
   868  				err = t.ConvertTimeZone(time.UTC, loc)
   869  				if err != nil {
   870  					return b, d, err
   871  				}
   872  			}
   873  			d.SetMysqlTime(t)
   874  		}
   875  	default:
   876  		return b, d, errors.Errorf("invalid encoded key flag %v", flag)
   877  	}
   878  	if err != nil {
   879  		return b, d, errors.Trace(err)
   880  	}
   881  	return b, d, nil
   882  }
   883  
   884  // CutOne cuts the first encoded value from b.
   885  // It will return the first encoded item and the remains as byte slice.
   886  func CutOne(b []byte) (data []byte, remain []byte, err error) {
   887  	l, err := peek(b)
   888  	if err != nil {
   889  		return nil, nil, errors.Trace(err)
   890  	}
   891  	return b[:l], b[l:], nil
   892  }
   893  
   894  // CutDeferredCausetID cuts the defCausumn ID from b.
   895  // It will return the remains as byte slice and defCausumn ID
   896  func CutDeferredCausetID(b []byte) (remain []byte, n int64, err error) {
   897  	if len(b) < 1 {
   898  		return nil, 0, errors.New("invalid encoded key")
   899  	}
   900  	// skip the flag
   901  	b = b[1:]
   902  	return DecodeVarint(b)
   903  }
   904  
   905  // SetRawValues set raw causet values from a event data.
   906  func SetRawValues(data []byte, values []types.Causet) error {
   907  	for i := 0; i < len(values); i++ {
   908  		l, err := peek(data)
   909  		if err != nil {
   910  			return errors.Trace(err)
   911  		}
   912  		values[i].SetRaw(data[:l:l])
   913  		data = data[l:]
   914  	}
   915  	return nil
   916  }
   917  
   918  // peek peeks the first encoded value from b and returns its length.
   919  func peek(b []byte) (length int, err error) {
   920  	if len(b) < 1 {
   921  		return 0, errors.New("invalid encoded key")
   922  	}
   923  	flag := b[0]
   924  	length++
   925  	b = b[1:]
   926  	var l int
   927  	switch flag {
   928  	case NilFlag:
   929  	case intFlag, uintFlag, floatFlag, durationFlag:
   930  		// Those types are stored in 8 bytes.
   931  		l = 8
   932  	case bytesFlag:
   933  		l, err = peekBytes(b)
   934  	case compactBytesFlag:
   935  		l, err = peekCompactBytes(b)
   936  	case decimalFlag:
   937  		l, err = types.DecimalPeak(b)
   938  	case varintFlag:
   939  		l, err = peekVarint(b)
   940  	case uvarintFlag:
   941  		l, err = peekUvarint(b)
   942  	case jsonFlag:
   943  		l, err = json.PeekBytesAsJSON(b)
   944  	default:
   945  		return 0, errors.Errorf("invalid encoded key flag %v", flag)
   946  	}
   947  	if err != nil {
   948  		return 0, errors.Trace(err)
   949  	}
   950  	length += l
   951  	return
   952  }
   953  
   954  func peekBytes(b []byte) (int, error) {
   955  	offset := 0
   956  	for {
   957  		if len(b) < offset+encGroupSize+1 {
   958  			return 0, errors.New("insufficient bytes to decode value")
   959  		}
   960  		// The byte slice is encoded into many groups.
   961  		// For each group, there are 8 bytes for data and 1 byte for marker.
   962  		marker := b[offset+encGroupSize]
   963  		padCount := encMarker - marker
   964  		offset += encGroupSize + 1
   965  		// When padCount is not zero, it means we get the end of the byte slice.
   966  		if padCount != 0 {
   967  			break
   968  		}
   969  	}
   970  	return offset, nil
   971  }
   972  
   973  func peekCompactBytes(b []byte) (int, error) {
   974  	// Get length.
   975  	v, n := binary.Varint(b)
   976  	vi := int(v)
   977  	if n < 0 {
   978  		return 0, errors.New("value larger than 64 bits")
   979  	} else if n == 0 {
   980  		return 0, errors.New("insufficient bytes to decode value")
   981  	}
   982  	if len(b) < vi+n {
   983  		return 0, errors.Errorf("insufficient bytes to decode value, expected length: %v", n)
   984  	}
   985  	return n + vi, nil
   986  }
   987  
   988  func peekVarint(b []byte) (int, error) {
   989  	_, n := binary.Varint(b)
   990  	if n < 0 {
   991  		return 0, errors.New("value larger than 64 bits")
   992  	}
   993  	return n, nil
   994  }
   995  
   996  func peekUvarint(b []byte) (int, error) {
   997  	_, n := binary.Uvarint(b)
   998  	if n < 0 {
   999  		return 0, errors.New("value larger than 64 bits")
  1000  	}
  1001  	return n, nil
  1002  }
  1003  
  1004  // CausetDecoder is used to decode value to chunk.
  1005  type CausetDecoder struct {
  1006  	chk      *chunk.Chunk
  1007  	timezone *time.Location
  1008  
  1009  	// buf is only used for DecodeBytes to avoid the cost of makeslice.
  1010  	buf []byte
  1011  }
  1012  
  1013  // NewCausetDecoder creates a CausetDecoder.
  1014  func NewCausetDecoder(chk *chunk.Chunk, timezone *time.Location) *CausetDecoder {
  1015  	return &CausetDecoder{
  1016  		chk:      chk,
  1017  		timezone: timezone,
  1018  	}
  1019  }
  1020  
  1021  // DecodeOne decodes one value to chunk and returns the remained bytes.
  1022  func (causetDecoder *CausetDecoder) DecodeOne(b []byte, defCausIdx int, ft *types.FieldType) (remain []byte, err error) {
  1023  	if len(b) < 1 {
  1024  		return nil, errors.New("invalid encoded key")
  1025  	}
  1026  	chk := causetDecoder.chk
  1027  	flag := b[0]
  1028  	b = b[1:]
  1029  	switch flag {
  1030  	case intFlag:
  1031  		var v int64
  1032  		b, v, err = DecodeInt(b)
  1033  		if err != nil {
  1034  			return nil, errors.Trace(err)
  1035  		}
  1036  		appendIntToChunk(v, chk, defCausIdx, ft)
  1037  	case uintFlag:
  1038  		var v uint64
  1039  		b, v, err = DecodeUint(b)
  1040  		if err != nil {
  1041  			return nil, errors.Trace(err)
  1042  		}
  1043  		err = appendUintToChunk(v, chk, defCausIdx, ft, causetDecoder.timezone)
  1044  	case varintFlag:
  1045  		var v int64
  1046  		b, v, err = DecodeVarint(b)
  1047  		if err != nil {
  1048  			return nil, errors.Trace(err)
  1049  		}
  1050  		appendIntToChunk(v, chk, defCausIdx, ft)
  1051  	case uvarintFlag:
  1052  		var v uint64
  1053  		b, v, err = DecodeUvarint(b)
  1054  		if err != nil {
  1055  			return nil, errors.Trace(err)
  1056  		}
  1057  		err = appendUintToChunk(v, chk, defCausIdx, ft, causetDecoder.timezone)
  1058  	case floatFlag:
  1059  		var v float64
  1060  		b, v, err = DecodeFloat(b)
  1061  		if err != nil {
  1062  			return nil, errors.Trace(err)
  1063  		}
  1064  		appendFloatToChunk(v, chk, defCausIdx, ft)
  1065  	case bytesFlag:
  1066  		b, causetDecoder.buf, err = DecodeBytes(b, causetDecoder.buf)
  1067  		if err != nil {
  1068  			return nil, errors.Trace(err)
  1069  		}
  1070  		chk.AppendBytes(defCausIdx, causetDecoder.buf)
  1071  	case compactBytesFlag:
  1072  		var v []byte
  1073  		b, v, err = DecodeCompactBytes(b)
  1074  		if err != nil {
  1075  			return nil, errors.Trace(err)
  1076  		}
  1077  		chk.AppendBytes(defCausIdx, v)
  1078  	case decimalFlag:
  1079  		var dec *types.MyDecimal
  1080  		var frac int
  1081  		b, dec, _, frac, err = DecodeDecimal(b)
  1082  		if err != nil {
  1083  			return nil, errors.Trace(err)
  1084  		}
  1085  		if ft.Decimal != types.UnspecifiedLength && frac > ft.Decimal {
  1086  			to := new(types.MyDecimal)
  1087  			err := dec.Round(to, ft.Decimal, types.ModeHalfEven)
  1088  			if err != nil {
  1089  				return nil, errors.Trace(err)
  1090  			}
  1091  			dec = to
  1092  		}
  1093  		chk.AppendMyDecimal(defCausIdx, dec)
  1094  	case durationFlag:
  1095  		var r int64
  1096  		b, r, err = DecodeInt(b)
  1097  		if err != nil {
  1098  			return nil, errors.Trace(err)
  1099  		}
  1100  		v := types.Duration{Duration: time.Duration(r), Fsp: int8(ft.Decimal)}
  1101  		chk.AppendDuration(defCausIdx, v)
  1102  	case jsonFlag:
  1103  		var size int
  1104  		size, err = json.PeekBytesAsJSON(b)
  1105  		if err != nil {
  1106  			return nil, errors.Trace(err)
  1107  		}
  1108  		chk.AppendJSON(defCausIdx, json.BinaryJSON{TypeCode: b[0], Value: b[1:size]})
  1109  		b = b[size:]
  1110  	case NilFlag:
  1111  		chk.AppendNull(defCausIdx)
  1112  	default:
  1113  		return nil, errors.Errorf("invalid encoded key flag %v", flag)
  1114  	}
  1115  	if err != nil {
  1116  		return nil, errors.Trace(err)
  1117  	}
  1118  	return b, nil
  1119  }
  1120  
  1121  func appendIntToChunk(val int64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType) {
  1122  	switch ft.Tp {
  1123  	case allegrosql.TypeDuration:
  1124  		v := types.Duration{Duration: time.Duration(val), Fsp: int8(ft.Decimal)}
  1125  		chk.AppendDuration(defCausIdx, v)
  1126  	default:
  1127  		chk.AppendInt64(defCausIdx, val)
  1128  	}
  1129  }
  1130  
  1131  func appendUintToChunk(val uint64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType, loc *time.Location) error {
  1132  	switch ft.Tp {
  1133  	case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
  1134  		t := types.NewTime(types.ZeroCoreTime, ft.Tp, int8(ft.Decimal))
  1135  		var err error
  1136  		err = t.FromPackedUint(val)
  1137  		if err != nil {
  1138  			return errors.Trace(err)
  1139  		}
  1140  		if ft.Tp == allegrosql.TypeTimestamp && !t.IsZero() {
  1141  			err = t.ConvertTimeZone(time.UTC, loc)
  1142  			if err != nil {
  1143  				return errors.Trace(err)
  1144  			}
  1145  		}
  1146  		chk.AppendTime(defCausIdx, t)
  1147  	case allegrosql.TypeEnum:
  1148  		// ignore error deliberately, to read empty enum value.
  1149  		enum, err := types.ParseEnumValue(ft.Elems, val)
  1150  		if err != nil {
  1151  			enum = types.Enum{}
  1152  		}
  1153  		chk.AppendEnum(defCausIdx, enum)
  1154  	case allegrosql.TypeSet:
  1155  		set, err := types.ParseSetValue(ft.Elems, val)
  1156  		if err != nil {
  1157  			return errors.Trace(err)
  1158  		}
  1159  		chk.AppendSet(defCausIdx, set)
  1160  	case allegrosql.TypeBit:
  1161  		byteSize := (ft.Flen + 7) >> 3
  1162  		chk.AppendBytes(defCausIdx, types.NewBinaryLiteralFromUint(val, byteSize))
  1163  	default:
  1164  		chk.AppendUint64(defCausIdx, val)
  1165  	}
  1166  	return nil
  1167  }
  1168  
  1169  func appendFloatToChunk(val float64, chk *chunk.Chunk, defCausIdx int, ft *types.FieldType) {
  1170  	if ft.Tp == allegrosql.TypeFloat {
  1171  		chk.AppendFloat32(defCausIdx, float32(val))
  1172  	} else {
  1173  		chk.AppendFloat64(defCausIdx, val)
  1174  	}
  1175  }
  1176  
  1177  // HashGroupKey encodes each event of this defCausumn and append encoded data into buf.
  1178  // Only use in the aggregate interlock.
  1179  func HashGroupKey(sc *stmtctx.StatementContext, n int, defCaus *chunk.DeferredCauset, buf [][]byte, ft *types.FieldType) ([][]byte, error) {
  1180  	var err error
  1181  	switch ft.EvalType() {
  1182  	case types.ETInt:
  1183  		i64s := defCaus.Int64s()
  1184  		for i := 0; i < n; i++ {
  1185  			if defCaus.IsNull(i) {
  1186  				buf[i] = append(buf[i], NilFlag)
  1187  			} else {
  1188  				buf[i] = encodeSignedInt(buf[i], i64s[i], false)
  1189  			}
  1190  		}
  1191  	case types.ETReal:
  1192  		f64s := defCaus.Float64s()
  1193  		for i := 0; i < n; i++ {
  1194  			if defCaus.IsNull(i) {
  1195  				buf[i] = append(buf[i], NilFlag)
  1196  			} else {
  1197  				buf[i] = append(buf[i], floatFlag)
  1198  				buf[i] = EncodeFloat(buf[i], f64s[i])
  1199  			}
  1200  		}
  1201  	case types.ETDecimal:
  1202  		ds := defCaus.Decimals()
  1203  		for i := 0; i < n; i++ {
  1204  			if defCaus.IsNull(i) {
  1205  				buf[i] = append(buf[i], NilFlag)
  1206  			} else {
  1207  				buf[i] = append(buf[i], decimalFlag)
  1208  				buf[i], err = EncodeDecimal(buf[i], &ds[i], ft.Flen, ft.Decimal)
  1209  				if terror.ErrorEqual(err, types.ErrTruncated) {
  1210  					err = sc.HandleTruncate(err)
  1211  				} else if terror.ErrorEqual(err, types.ErrOverflow) {
  1212  					err = sc.HandleOverflow(err, err)
  1213  				}
  1214  				if err != nil {
  1215  					return nil, err
  1216  				}
  1217  			}
  1218  		}
  1219  	case types.ETDatetime, types.ETTimestamp:
  1220  		ts := defCaus.Times()
  1221  		for i := 0; i < n; i++ {
  1222  			if defCaus.IsNull(i) {
  1223  				buf[i] = append(buf[i], NilFlag)
  1224  			} else {
  1225  				buf[i] = append(buf[i], uintFlag)
  1226  				buf[i], err = EncodeMyALLEGROSQLTime(sc, ts[i], allegrosql.TypeUnspecified, buf[i])
  1227  				if err != nil {
  1228  					return nil, err
  1229  				}
  1230  			}
  1231  		}
  1232  	case types.ETDuration:
  1233  		ds := defCaus.GoDurations()
  1234  		for i := 0; i < n; i++ {
  1235  			if defCaus.IsNull(i) {
  1236  				buf[i] = append(buf[i], NilFlag)
  1237  			} else {
  1238  				buf[i] = append(buf[i], durationFlag)
  1239  				buf[i] = EncodeInt(buf[i], int64(ds[i]))
  1240  			}
  1241  		}
  1242  	case types.ETJson:
  1243  		for i := 0; i < n; i++ {
  1244  			if defCaus.IsNull(i) {
  1245  				buf[i] = append(buf[i], NilFlag)
  1246  			} else {
  1247  				buf[i] = append(buf[i], jsonFlag)
  1248  				j := defCaus.GetJSON(i)
  1249  				buf[i] = append(buf[i], j.TypeCode)
  1250  				buf[i] = append(buf[i], j.Value...)
  1251  			}
  1252  		}
  1253  	case types.ETString:
  1254  		for i := 0; i < n; i++ {
  1255  			if defCaus.IsNull(i) {
  1256  				buf[i] = append(buf[i], NilFlag)
  1257  			} else {
  1258  				buf[i] = encodeBytes(buf[i], ConvertByDefCauslation(defCaus.GetBytes(i), ft), false)
  1259  			}
  1260  		}
  1261  	default:
  1262  		return nil, errors.New(fmt.Sprintf("invalid eval type %v", ft.EvalType()))
  1263  	}
  1264  	return buf, nil
  1265  }
  1266  
  1267  // ConvertByDefCauslation converts these bytes according to its defCauslation.
  1268  func ConvertByDefCauslation(raw []byte, tp *types.FieldType) []byte {
  1269  	defCauslator := defCauslate.GetDefCauslator(tp.DefCauslate)
  1270  	return defCauslator.Key(string(replog.String(raw)))
  1271  }
  1272  
  1273  // ConvertByDefCauslationStr converts this string according to its defCauslation.
  1274  func ConvertByDefCauslationStr(str string, tp *types.FieldType) string {
  1275  	defCauslator := defCauslate.GetDefCauslator(tp.DefCauslate)
  1276  	return string(replog.String(defCauslator.Key(str)))
  1277  }