github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/rowcodec/decoder.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 rowcodec
    15  
    16  import (
    17  	"fmt"
    18  	"time"
    19  
    20  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    21  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    22  	"github.com/whtcorpsinc/errors"
    23  	"github.com/whtcorpsinc/milevadb/ekv"
    24  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    25  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    26  	"github.com/whtcorpsinc/milevadb/types"
    27  	"github.com/whtcorpsinc/milevadb/types/json"
    28  )
    29  
    30  // causetDecoder contains base soliton for decode event.
    31  type causetDecoder struct {
    32  	event
    33  	defCausumns      []DefCausInfo
    34  	handleDefCausIDs []int64
    35  	loc              *time.Location
    36  }
    37  
    38  // NewCausetDecoder creates a causetDecoder.
    39  func NewCausetDecoder(defCausumns []DefCausInfo, handleDefCausIDs []int64, loc *time.Location) *causetDecoder {
    40  	return &causetDecoder{
    41  		defCausumns:      defCausumns,
    42  		handleDefCausIDs: handleDefCausIDs,
    43  		loc:              loc,
    44  	}
    45  }
    46  
    47  // DefCausInfo is used as defCausumn spacetime info for event causetDecoder.
    48  type DefCausInfo struct {
    49  	ID                int64
    50  	IsPKHandle        bool
    51  	VirtualGenDefCaus bool
    52  	Ft                *types.FieldType
    53  }
    54  
    55  // CausetFIDeliocoderdecodes the event to causet map.
    56  type CausetFIDeliocoderstruct {
    57  	causetDecoder
    58  }
    59  
    60  // NewCausetFIDeliocodercreates a CausetFIDelioecoder.
    61  func NewCausetFIDelioecoder(defCausumns []DefCausInfo, loc *time.Location) *CausetFIDeliocoder{
    62  	return &CausetFIDelioecoder{causetDecoder{
    63  		defCausumns: defCausumns,
    64  		loc:         loc,
    65  	}}
    66  }
    67  
    68  // DecodeToCausetMap decodes byte slices to causet map.
    69  func (causetDecoder *CausetFIDelioecoder) DecodeToCausetMap(rowData []byte, event map[int64]types.Causet) (map[int64]types.Causet, error) {
    70  	if event == nil {
    71  		event = make(map[int64]types.Causet, len(causetDecoder.defCausumns))
    72  	}
    73  	err := causetDecoder.fromBytes(rowData)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	for i := range causetDecoder.defCausumns {
    78  		defCaus := &causetDecoder.defCausumns[i]
    79  		idx, isNil, notFound := causetDecoder.event.findDefCausID(defCaus.ID)
    80  		if !notFound && !isNil {
    81  			defCausData := causetDecoder.getData(idx)
    82  			d, err := causetDecoder.decodeDefCausCauset(defCaus, defCausData)
    83  			if err != nil {
    84  				return nil, err
    85  			}
    86  			event[defCaus.ID] = d
    87  			continue
    88  		}
    89  
    90  		if isNil {
    91  			var d types.Causet
    92  			d.SetNull()
    93  			event[defCaus.ID] = d
    94  			continue
    95  		}
    96  	}
    97  	return event, nil
    98  }
    99  
   100  func (causetDecoder *CausetFIDelioecoder) decodeDefCausCauset(defCaus *DefCausInfo, defCausData []byte) (types.Causet, error) {
   101  	var d types.Causet
   102  	switch defCaus.Ft.Tp {
   103  	case allegrosql.TypeLonglong, allegrosql.TypeLong, allegrosql.TypeInt24, allegrosql.TypeShort, allegrosql.TypeTiny:
   104  		if allegrosql.HasUnsignedFlag(defCaus.Ft.Flag) {
   105  			d.SetUint64(decodeUint(defCausData))
   106  		} else {
   107  			d.SetInt64(decodeInt(defCausData))
   108  		}
   109  	case allegrosql.TypeYear:
   110  		d.SetInt64(decodeInt(defCausData))
   111  	case allegrosql.TypeFloat:
   112  		_, fVal, err := codec.DecodeFloat(defCausData)
   113  		if err != nil {
   114  			return d, err
   115  		}
   116  		d.SetFloat32(float32(fVal))
   117  	case allegrosql.TypeDouble:
   118  		_, fVal, err := codec.DecodeFloat(defCausData)
   119  		if err != nil {
   120  			return d, err
   121  		}
   122  		d.SetFloat64(fVal)
   123  	case allegrosql.TypeVarString, allegrosql.TypeVarchar, allegrosql.TypeString:
   124  		d.SetString(string(defCausData), defCaus.Ft.DefCauslate)
   125  	case allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   126  		d.SetBytes(defCausData)
   127  	case allegrosql.TypeNewDecimal:
   128  		_, dec, precision, frac, err := codec.DecodeDecimal(defCausData)
   129  		if err != nil {
   130  			return d, err
   131  		}
   132  		d.SetMysqlDecimal(dec)
   133  		d.SetLength(precision)
   134  		d.SetFrac(frac)
   135  	case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   136  		var t types.Time
   137  		t.SetType(defCaus.Ft.Tp)
   138  		t.SetFsp(int8(defCaus.Ft.Decimal))
   139  		err := t.FromPackedUint(decodeUint(defCausData))
   140  		if err != nil {
   141  			return d, err
   142  		}
   143  		if defCaus.Ft.Tp == allegrosql.TypeTimestamp && !t.IsZero() {
   144  			err = t.ConvertTimeZone(time.UTC, causetDecoder.loc)
   145  			if err != nil {
   146  				return d, err
   147  			}
   148  		}
   149  		d.SetMysqlTime(t)
   150  	case allegrosql.TypeDuration:
   151  		var dur types.Duration
   152  		dur.Duration = time.Duration(decodeInt(defCausData))
   153  		dur.Fsp = int8(defCaus.Ft.Decimal)
   154  		d.SetMysqlDuration(dur)
   155  	case allegrosql.TypeEnum:
   156  		// ignore error deliberately, to read empty enum value.
   157  		enum, err := types.ParseEnumValue(defCaus.Ft.Elems, decodeUint(defCausData))
   158  		if err != nil {
   159  			enum = types.Enum{}
   160  		}
   161  		d.SetMysqlEnum(enum, defCaus.Ft.DefCauslate)
   162  	case allegrosql.TypeSet:
   163  		set, err := types.ParseSetValue(defCaus.Ft.Elems, decodeUint(defCausData))
   164  		if err != nil {
   165  			return d, err
   166  		}
   167  		d.SetMysqlSet(set, defCaus.Ft.DefCauslate)
   168  	case allegrosql.TypeBit:
   169  		byteSize := (defCaus.Ft.Flen + 7) >> 3
   170  		d.SetMysqlBit(types.NewBinaryLiteralFromUint(decodeUint(defCausData), byteSize))
   171  	case allegrosql.TypeJSON:
   172  		var j json.BinaryJSON
   173  		j.TypeCode = defCausData[0]
   174  		j.Value = defCausData[1:]
   175  		d.SetMysqlJSON(j)
   176  	default:
   177  		return d, errors.Errorf("unknown type %d", defCaus.Ft.Tp)
   178  	}
   179  	return d, nil
   180  }
   181  
   182  // ChunkCausetDecoder decodes the event to chunk.Chunk.
   183  type ChunkCausetDecoder struct {
   184  	causetDecoder
   185  	defCauset func(i int, chk *chunk.Chunk) error
   186  }
   187  
   188  // NewChunkCausetDecoder creates a NewChunkCausetDecoder.
   189  func NewChunkCausetDecoder(defCausumns []DefCausInfo, handleDefCausIDs []int64, defCauset func(i int, chk *chunk.Chunk) error, loc *time.Location) *ChunkCausetDecoder {
   190  	return &ChunkCausetDecoder{
   191  		causetDecoder: causetDecoder{
   192  			defCausumns:      defCausumns,
   193  			handleDefCausIDs: handleDefCausIDs,
   194  			loc:              loc,
   195  		},
   196  		defCauset: defCauset,
   197  	}
   198  }
   199  
   200  // DecodeToChunk decodes a event to chunk.
   201  func (causetDecoder *ChunkCausetDecoder) DecodeToChunk(rowData []byte, handle ekv.Handle, chk *chunk.Chunk) error {
   202  	err := causetDecoder.fromBytes(rowData)
   203  	if err != nil {
   204  		return err
   205  	}
   206  
   207  	for defCausIdx := range causetDecoder.defCausumns {
   208  		defCaus := &causetDecoder.defCausumns[defCausIdx]
   209  		// fill the virtual defCausumn value after event calculation
   210  		if defCaus.VirtualGenDefCaus {
   211  			chk.AppendNull(defCausIdx)
   212  			continue
   213  		}
   214  
   215  		idx, isNil, notFound := causetDecoder.event.findDefCausID(defCaus.ID)
   216  		if !notFound && !isNil {
   217  			defCausData := causetDecoder.getData(idx)
   218  			err := causetDecoder.decodeDefCausToChunk(defCausIdx, defCaus, defCausData, chk)
   219  			if err != nil {
   220  				return err
   221  			}
   222  			continue
   223  		}
   224  
   225  		if causetDecoder.tryAppendHandleDeferredCauset(defCausIdx, defCaus, handle, chk) {
   226  			continue
   227  		}
   228  
   229  		if isNil {
   230  			chk.AppendNull(defCausIdx)
   231  			continue
   232  		}
   233  
   234  		if causetDecoder.defCauset == nil {
   235  			chk.AppendNull(defCausIdx)
   236  			continue
   237  		}
   238  
   239  		err := causetDecoder.defCauset(defCausIdx, chk)
   240  		if err != nil {
   241  			return err
   242  		}
   243  	}
   244  	return nil
   245  }
   246  
   247  func (causetDecoder *ChunkCausetDecoder) tryAppendHandleDeferredCauset(defCausIdx int, defCaus *DefCausInfo, handle ekv.Handle, chk *chunk.Chunk) bool {
   248  	if handle == nil {
   249  		return false
   250  	}
   251  	if handle.IsInt() && defCaus.ID == causetDecoder.handleDefCausIDs[0] {
   252  		chk.AppendInt64(defCausIdx, handle.IntValue())
   253  		return true
   254  	}
   255  	for i, id := range causetDecoder.handleDefCausIDs {
   256  		if defCaus.ID == id {
   257  			coder := codec.NewCausetDecoder(chk, causetDecoder.loc)
   258  			_, err := coder.DecodeOne(handle.EncodedDefCaus(i), defCausIdx, defCaus.Ft)
   259  			if err != nil {
   260  				return false
   261  			}
   262  			return true
   263  		}
   264  	}
   265  	return false
   266  }
   267  
   268  func (causetDecoder *ChunkCausetDecoder) decodeDefCausToChunk(defCausIdx int, defCaus *DefCausInfo, defCausData []byte, chk *chunk.Chunk) error {
   269  	switch defCaus.Ft.Tp {
   270  	case allegrosql.TypeLonglong, allegrosql.TypeLong, allegrosql.TypeInt24, allegrosql.TypeShort, allegrosql.TypeTiny:
   271  		if allegrosql.HasUnsignedFlag(defCaus.Ft.Flag) {
   272  			chk.AppendUint64(defCausIdx, decodeUint(defCausData))
   273  		} else {
   274  			chk.AppendInt64(defCausIdx, decodeInt(defCausData))
   275  		}
   276  	case allegrosql.TypeYear:
   277  		chk.AppendInt64(defCausIdx, decodeInt(defCausData))
   278  	case allegrosql.TypeFloat:
   279  		_, fVal, err := codec.DecodeFloat(defCausData)
   280  		if err != nil {
   281  			return err
   282  		}
   283  		chk.AppendFloat32(defCausIdx, float32(fVal))
   284  	case allegrosql.TypeDouble:
   285  		_, fVal, err := codec.DecodeFloat(defCausData)
   286  		if err != nil {
   287  			return err
   288  		}
   289  		chk.AppendFloat64(defCausIdx, fVal)
   290  	case allegrosql.TypeVarString, allegrosql.TypeVarchar, allegrosql.TypeString,
   291  		allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   292  		chk.AppendBytes(defCausIdx, defCausData)
   293  	case allegrosql.TypeNewDecimal:
   294  		_, dec, _, frac, err := codec.DecodeDecimal(defCausData)
   295  		if err != nil {
   296  			return err
   297  		}
   298  		if defCaus.Ft.Decimal != types.UnspecifiedLength && frac > defCaus.Ft.Decimal {
   299  			to := new(types.MyDecimal)
   300  			err := dec.Round(to, defCaus.Ft.Decimal, types.ModeHalfEven)
   301  			if err != nil {
   302  				return errors.Trace(err)
   303  			}
   304  			dec = to
   305  		}
   306  		chk.AppendMyDecimal(defCausIdx, dec)
   307  	case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   308  		var t types.Time
   309  		t.SetType(defCaus.Ft.Tp)
   310  		t.SetFsp(int8(defCaus.Ft.Decimal))
   311  		err := t.FromPackedUint(decodeUint(defCausData))
   312  		if err != nil {
   313  			return err
   314  		}
   315  		if defCaus.Ft.Tp == allegrosql.TypeTimestamp && causetDecoder.loc != nil && !t.IsZero() {
   316  			err = t.ConvertTimeZone(time.UTC, causetDecoder.loc)
   317  			if err != nil {
   318  				return err
   319  			}
   320  		}
   321  		chk.AppendTime(defCausIdx, t)
   322  	case allegrosql.TypeDuration:
   323  		var dur types.Duration
   324  		dur.Duration = time.Duration(decodeInt(defCausData))
   325  		dur.Fsp = int8(defCaus.Ft.Decimal)
   326  		chk.AppendDuration(defCausIdx, dur)
   327  	case allegrosql.TypeEnum:
   328  		// ignore error deliberately, to read empty enum value.
   329  		enum, err := types.ParseEnumValue(defCaus.Ft.Elems, decodeUint(defCausData))
   330  		if err != nil {
   331  			enum = types.Enum{}
   332  		}
   333  		chk.AppendEnum(defCausIdx, enum)
   334  	case allegrosql.TypeSet:
   335  		set, err := types.ParseSetValue(defCaus.Ft.Elems, decodeUint(defCausData))
   336  		if err != nil {
   337  			return err
   338  		}
   339  		chk.AppendSet(defCausIdx, set)
   340  	case allegrosql.TypeBit:
   341  		byteSize := (defCaus.Ft.Flen + 7) >> 3
   342  		chk.AppendBytes(defCausIdx, types.NewBinaryLiteralFromUint(decodeUint(defCausData), byteSize))
   343  	case allegrosql.TypeJSON:
   344  		var j json.BinaryJSON
   345  		j.TypeCode = defCausData[0]
   346  		j.Value = defCausData[1:]
   347  		chk.AppendJSON(defCausIdx, j)
   348  	default:
   349  		return errors.Errorf("unknown type %d", defCaus.Ft.Tp)
   350  	}
   351  	return nil
   352  }
   353  
   354  // BytesCausetDecoder decodes the event to old datums bytes.
   355  type BytesCausetDecoder struct {
   356  	causetDecoder
   357  	defBytes func(i int) ([]byte, error)
   358  }
   359  
   360  // NewByteCausetDecoder creates a BytesCausetDecoder.
   361  // defBytes: provided default value bytes in old causet format(flag+defCausData).
   362  func NewByteCausetDecoder(defCausumns []DefCausInfo, handleDefCausIDs []int64, defBytes func(i int) ([]byte, error), loc *time.Location) *BytesCausetDecoder {
   363  	return &BytesCausetDecoder{
   364  		causetDecoder: causetDecoder{
   365  			defCausumns:      defCausumns,
   366  			handleDefCausIDs: handleDefCausIDs,
   367  			loc:              loc,
   368  		},
   369  		defBytes: defBytes,
   370  	}
   371  }
   372  
   373  func (causetDecoder *BytesCausetDecoder) decodeToBytesInternal(outputOffset map[int64]int, handle ekv.Handle, value []byte, cacheBytes []byte) ([][]byte, error) {
   374  	var r event
   375  	err := r.fromBytes(value)
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  	values := make([][]byte, len(outputOffset))
   380  	for i := range causetDecoder.defCausumns {
   381  		defCaus := &causetDecoder.defCausumns[i]
   382  		tp := fieldType2Flag(defCaus.Ft.Tp, defCaus.Ft.Flag&allegrosql.UnsignedFlag == 0)
   383  		defCausID := defCaus.ID
   384  		offset := outputOffset[defCausID]
   385  		if causetDecoder.tryDecodeHandle(values, offset, defCaus, handle, cacheBytes) {
   386  			continue
   387  		}
   388  
   389  		idx, isNil, notFound := r.findDefCausID(defCausID)
   390  		if !notFound && !isNil {
   391  			val := r.getData(idx)
   392  			values[offset] = causetDecoder.encodeOldCauset(tp, val)
   393  			continue
   394  		}
   395  
   396  		if isNil {
   397  			values[offset] = []byte{NilFlag}
   398  			continue
   399  		}
   400  
   401  		if causetDecoder.defBytes != nil {
   402  			defVal, err := causetDecoder.defBytes(i)
   403  			if err != nil {
   404  				return nil, err
   405  			}
   406  			if len(defVal) > 0 {
   407  				values[offset] = defVal
   408  				continue
   409  			}
   410  		}
   411  
   412  		values[offset] = []byte{NilFlag}
   413  	}
   414  	return values, nil
   415  }
   416  
   417  func (causetDecoder *BytesCausetDecoder) tryDecodeHandle(values [][]byte, offset int, defCaus *DefCausInfo,
   418  	handle ekv.Handle, cacheBytes []byte) bool {
   419  	if handle == nil {
   420  		return false
   421  	}
   422  	if defCaus.IsPKHandle || defCaus.ID == perceptron.ExtraHandleID {
   423  		handleData := cacheBytes
   424  		if allegrosql.HasUnsignedFlag(defCaus.Ft.Flag) {
   425  			handleData = append(handleData, UintFlag)
   426  			handleData = codec.EncodeUint(handleData, uint64(handle.IntValue()))
   427  		} else {
   428  			handleData = append(handleData, IntFlag)
   429  			handleData = codec.EncodeInt(handleData, handle.IntValue())
   430  		}
   431  		values[offset] = handleData
   432  		return true
   433  	}
   434  	var handleData []byte
   435  	for i, hid := range causetDecoder.handleDefCausIDs {
   436  		if defCaus.ID == hid {
   437  			handleData = append(handleData, handle.EncodedDefCaus(i)...)
   438  		}
   439  	}
   440  	if len(handleData) > 0 {
   441  		values[offset] = handleData
   442  		return true
   443  	}
   444  	return false
   445  }
   446  
   447  // DecodeToBytesNoHandle decodes raw byte slice to event dat without handle.
   448  func (causetDecoder *BytesCausetDecoder) DecodeToBytesNoHandle(outputOffset map[int64]int, value []byte) ([][]byte, error) {
   449  	return causetDecoder.decodeToBytesInternal(outputOffset, nil, value, nil)
   450  }
   451  
   452  // DecodeToBytes decodes raw byte slice to event data.
   453  func (causetDecoder *BytesCausetDecoder) DecodeToBytes(outputOffset map[int64]int, handle ekv.Handle, value []byte, cacheBytes []byte) ([][]byte, error) {
   454  	return causetDecoder.decodeToBytesInternal(outputOffset, handle, value, cacheBytes)
   455  }
   456  
   457  func (causetDecoder *BytesCausetDecoder) encodeOldCauset(tp byte, val []byte) []byte {
   458  	var buf []byte
   459  	switch tp {
   460  	case BytesFlag:
   461  		buf = append(buf, CompactBytesFlag)
   462  		buf = codec.EncodeCompactBytes(buf, val)
   463  	case IntFlag:
   464  		buf = append(buf, VarintFlag)
   465  		buf = codec.EncodeVarint(buf, decodeInt(val))
   466  	case UintFlag:
   467  		buf = append(buf, VaruintFlag)
   468  		buf = codec.EncodeUvarint(buf, decodeUint(val))
   469  	default:
   470  		buf = append(buf, tp)
   471  		buf = append(buf, val...)
   472  	}
   473  	return buf
   474  }
   475  
   476  // fieldType2Flag transforms field type into ekv type flag.
   477  func fieldType2Flag(tp byte, signed bool) (flag byte) {
   478  	switch tp {
   479  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong:
   480  		if signed {
   481  			flag = IntFlag
   482  		} else {
   483  			flag = UintFlag
   484  		}
   485  	case allegrosql.TypeFloat, allegrosql.TypeDouble:
   486  		flag = FloatFlag
   487  	case allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob,
   488  		allegrosql.TypeString, allegrosql.TypeVarchar, allegrosql.TypeVarString:
   489  		flag = BytesFlag
   490  	case allegrosql.TypeDatetime, allegrosql.TypeDate, allegrosql.TypeTimestamp:
   491  		flag = UintFlag
   492  	case allegrosql.TypeDuration:
   493  		flag = IntFlag
   494  	case allegrosql.TypeNewDecimal:
   495  		flag = DecimalFlag
   496  	case allegrosql.TypeYear:
   497  		flag = IntFlag
   498  	case allegrosql.TypeEnum, allegrosql.TypeBit, allegrosql.TypeSet:
   499  		flag = UintFlag
   500  	case allegrosql.TypeJSON:
   501  		flag = JSONFlag
   502  	case allegrosql.TypeNull:
   503  		flag = NilFlag
   504  	default:
   505  		panic(fmt.Sprintf("unknown field type %d", tp))
   506  	}
   507  	return
   508  }