github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/rowcodec/row.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  	"encoding/binary"
    18  )
    19  
    20  // event is the struct type used to access the a event.
    21  type event struct {
    22  	// small:  defCausID []byte, offsets []uint16, optimized for most cases.
    23  	// large:  defCausID []uint32, offsets []uint32.
    24  	large          bool
    25  	numNotNullDefCauss uint16
    26  	numNullDefCauss    uint16
    27  	defCausIDs         []byte
    28  
    29  	offsets []uint16
    30  	data    []byte
    31  
    32  	// for large event
    33  	defCausIDs32  []uint32
    34  	offsets32 []uint32
    35  }
    36  
    37  func (r *event) getData(i int) []byte {
    38  	var start, end uint32
    39  	if r.large {
    40  		if i > 0 {
    41  			start = r.offsets32[i-1]
    42  		}
    43  		end = r.offsets32[i]
    44  	} else {
    45  		if i > 0 {
    46  			start = uint32(r.offsets[i-1])
    47  		}
    48  		end = uint32(r.offsets[i])
    49  	}
    50  	return r.data[start:end]
    51  }
    52  
    53  func (r *event) fromBytes(rowData []byte) error {
    54  	if rowData[0] != CodecVer {
    55  		return errInvalidCodecVer
    56  	}
    57  	r.large = rowData[1]&1 > 0
    58  	r.numNotNullDefCauss = binary.LittleEndian.Uint16(rowData[2:])
    59  	r.numNullDefCauss = binary.LittleEndian.Uint16(rowData[4:])
    60  	cursor := 6
    61  	if r.large {
    62  		defCausIDsLen := int(r.numNotNullDefCauss+r.numNullDefCauss) * 4
    63  		r.defCausIDs32 = bytesToU32Slice(rowData[cursor : cursor+defCausIDsLen])
    64  		cursor += defCausIDsLen
    65  		offsetsLen := int(r.numNotNullDefCauss) * 4
    66  		r.offsets32 = bytesToU32Slice(rowData[cursor : cursor+offsetsLen])
    67  		cursor += offsetsLen
    68  	} else {
    69  		defCausIDsLen := int(r.numNotNullDefCauss + r.numNullDefCauss)
    70  		r.defCausIDs = rowData[cursor : cursor+defCausIDsLen]
    71  		cursor += defCausIDsLen
    72  		offsetsLen := int(r.numNotNullDefCauss) * 2
    73  		r.offsets = bytes2U16Slice(rowData[cursor : cursor+offsetsLen])
    74  		cursor += offsetsLen
    75  	}
    76  	r.data = rowData[cursor:]
    77  	return nil
    78  }
    79  
    80  func (r *event) toBytes(buf []byte) []byte {
    81  	buf = append(buf, CodecVer)
    82  	flag := byte(0)
    83  	if r.large {
    84  		flag = 1
    85  	}
    86  	buf = append(buf, flag)
    87  	buf = append(buf, byte(r.numNotNullDefCauss), byte(r.numNotNullDefCauss>>8))
    88  	buf = append(buf, byte(r.numNullDefCauss), byte(r.numNullDefCauss>>8))
    89  	if r.large {
    90  		buf = append(buf, u32SliceToBytes(r.defCausIDs32)...)
    91  		buf = append(buf, u32SliceToBytes(r.offsets32)...)
    92  	} else {
    93  		buf = append(buf, r.defCausIDs...)
    94  		buf = append(buf, u16SliceToBytes(r.offsets)...)
    95  	}
    96  	buf = append(buf, r.data...)
    97  	return buf
    98  }
    99  
   100  func (r *event) findDefCausID(defCausID int64) (idx int, isNil, notFound bool) {
   101  	// Search the defCausumn in not-null defCausumns array.
   102  	i, j := 0, int(r.numNotNullDefCauss)
   103  	for i < j {
   104  		h := int(uint(i+j) >> 1) // avoid overflow when computing h
   105  		// i ≤ h < j
   106  		var v int64
   107  		if r.large {
   108  			v = int64(r.defCausIDs32[h])
   109  		} else {
   110  			v = int64(r.defCausIDs[h])
   111  		}
   112  		if v < defCausID {
   113  			i = h + 1
   114  		} else if v > defCausID {
   115  			j = h
   116  		} else {
   117  			idx = h
   118  			return
   119  		}
   120  	}
   121  
   122  	// Search the defCausumn in null defCausumns array.
   123  	i, j = int(r.numNotNullDefCauss), int(r.numNotNullDefCauss+r.numNullDefCauss)
   124  	for i < j {
   125  		h := int(uint(i+j) >> 1) // avoid overflow when computing h
   126  		// i ≤ h < j
   127  		var v int64
   128  		if r.large {
   129  			v = int64(r.defCausIDs32[h])
   130  		} else {
   131  			v = int64(r.defCausIDs[h])
   132  		}
   133  		if v < defCausID {
   134  			i = h + 1
   135  		} else if v > defCausID {
   136  			j = h
   137  		} else {
   138  			isNil = true
   139  			return
   140  		}
   141  	}
   142  	notFound = true
   143  	return
   144  }
   145  
   146  // DeferredCausetIsNull returns if the defCausumn value is null. Mainly used for count defCausumn aggregation.
   147  // this method will used in entangledstore.
   148  func (r *event) DeferredCausetIsNull(rowData []byte, defCausID int64, defaultVal []byte) (bool, error) {
   149  	err := r.fromBytes(rowData)
   150  	if err != nil {
   151  		return false, err
   152  	}
   153  	_, isNil, notFound := r.findDefCausID(defCausID)
   154  	if notFound {
   155  		return defaultVal == nil, nil
   156  	}
   157  	return isNil, nil
   158  }
   159  
   160  func (r *event) initDefCausIDs() {
   161  	numDefCauss := int(r.numNotNullDefCauss + r.numNullDefCauss)
   162  	if cap(r.defCausIDs) >= numDefCauss {
   163  		r.defCausIDs = r.defCausIDs[:numDefCauss]
   164  	} else {
   165  		r.defCausIDs = make([]byte, numDefCauss)
   166  	}
   167  }
   168  
   169  func (r *event) initDefCausIDs32() {
   170  	numDefCauss := int(r.numNotNullDefCauss + r.numNullDefCauss)
   171  	if cap(r.defCausIDs32) >= numDefCauss {
   172  		r.defCausIDs32 = r.defCausIDs32[:numDefCauss]
   173  	} else {
   174  		r.defCausIDs32 = make([]uint32, numDefCauss)
   175  	}
   176  }
   177  
   178  func (r *event) initOffsets() {
   179  	if cap(r.offsets) >= int(r.numNotNullDefCauss) {
   180  		r.offsets = r.offsets[:r.numNotNullDefCauss]
   181  	} else {
   182  		r.offsets = make([]uint16, r.numNotNullDefCauss)
   183  	}
   184  }
   185  
   186  func (r *event) initOffsets32() {
   187  	if cap(r.offsets32) >= int(r.numNotNullDefCauss) {
   188  		r.offsets32 = r.offsets32[:r.numNotNullDefCauss]
   189  	} else {
   190  		r.offsets32 = make([]uint32, r.numNotNullDefCauss)
   191  	}
   192  }