github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/chunk/mutrow.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 chunk
    15  
    16  import (
    17  	"encoding/binary"
    18  	"math"
    19  	"unsafe"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    22  	"github.com/whtcorpsinc/milevadb/types"
    23  	"github.com/whtcorpsinc/milevadb/types/json"
    24  	"github.com/whtcorpsinc/milevadb/soliton/replog"
    25  )
    26  
    27  // MutRow represents a mublock Row.
    28  // The underlying defCausumns only contains one event and not exposed to the user.
    29  type MutRow Row
    30  
    31  // ToRow converts the MutRow to Row, so it can be used to read data.
    32  func (mr MutRow) ToRow() Row {
    33  	return Row(mr)
    34  }
    35  
    36  // Len returns the number of defCausumns.
    37  func (mr MutRow) Len() int {
    38  	return len(mr.c.defCausumns)
    39  }
    40  
    41  // Clone deep clone a MutRow.
    42  func (mr MutRow) Clone() MutRow {
    43  	newChk := mr.c
    44  	if mr.c != nil {
    45  		newChk = mr.c.CopyConstruct()
    46  	}
    47  	return MutRow{
    48  		c:   newChk,
    49  		idx: mr.idx,
    50  	}
    51  }
    52  
    53  // MutRowFromValues creates a MutRow from a interface slice.
    54  func MutRowFromValues(vals ...interface{}) MutRow {
    55  	c := &Chunk{defCausumns: make([]*DeferredCauset, 0, len(vals))}
    56  	for _, val := range vals {
    57  		defCaus := makeMutRowDeferredCauset(val)
    58  		c.defCausumns = append(c.defCausumns, defCaus)
    59  	}
    60  	return MutRow{c: c}
    61  }
    62  
    63  // MutRowFromCausets creates a MutRow from a causet slice.
    64  func MutRowFromCausets(datums []types.Causet) MutRow {
    65  	c := &Chunk{defCausumns: make([]*DeferredCauset, 0, len(datums))}
    66  	for _, d := range datums {
    67  		defCaus := makeMutRowDeferredCauset(d.GetValue())
    68  		c.defCausumns = append(c.defCausumns, defCaus)
    69  	}
    70  	return MutRow{c: c, idx: 0}
    71  }
    72  
    73  // MutRowFromTypes creates a MutRow from a FieldType slice, each DeferredCauset is initialized to zero value.
    74  func MutRowFromTypes(types []*types.FieldType) MutRow {
    75  	c := &Chunk{defCausumns: make([]*DeferredCauset, 0, len(types))}
    76  	for _, tp := range types {
    77  		defCaus := makeMutRowDeferredCauset(zeroValForType(tp))
    78  		c.defCausumns = append(c.defCausumns, defCaus)
    79  	}
    80  	return MutRow{c: c, idx: 0}
    81  }
    82  
    83  func zeroValForType(tp *types.FieldType) interface{} {
    84  	switch tp.Tp {
    85  	case allegrosql.TypeFloat:
    86  		return float32(0)
    87  	case allegrosql.TypeDouble:
    88  		return float64(0)
    89  	case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
    90  		if allegrosql.HasUnsignedFlag(tp.Flag) {
    91  			return uint64(0)
    92  		}
    93  		return int64(0)
    94  	case allegrosql.TypeString, allegrosql.TypeVarString, allegrosql.TypeVarchar:
    95  		return ""
    96  	case allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
    97  		return []byte{}
    98  	case allegrosql.TypeDuration:
    99  		return types.ZeroDuration
   100  	case allegrosql.TypeNewDecimal:
   101  		return types.NewDecFromInt(0)
   102  	case allegrosql.TypeDate:
   103  		return types.ZeroDate
   104  	case allegrosql.TypeDatetime:
   105  		return types.ZeroDatetime
   106  	case allegrosql.TypeTimestamp:
   107  		return types.ZeroTimestamp
   108  	case allegrosql.TypeBit:
   109  		return types.BinaryLiteral{}
   110  	case allegrosql.TypeSet:
   111  		return types.Set{}
   112  	case allegrosql.TypeEnum:
   113  		return types.Enum{}
   114  	case allegrosql.TypeJSON:
   115  		return json.CreateBinary(nil)
   116  	default:
   117  		return nil
   118  	}
   119  }
   120  
   121  func makeMutRowDeferredCauset(in interface{}) *DeferredCauset {
   122  	switch x := in.(type) {
   123  	case nil:
   124  		defCaus := makeMutRowBytesDeferredCauset(nil)
   125  		defCaus.nullBitmap[0] = 0
   126  		return defCaus
   127  	case int:
   128  		return makeMutRowUint64DeferredCauset(uint64(x))
   129  	case int64:
   130  		return makeMutRowUint64DeferredCauset(uint64(x))
   131  	case uint64:
   132  		return makeMutRowUint64DeferredCauset(x)
   133  	case float64:
   134  		return makeMutRowUint64DeferredCauset(math.Float64bits(x))
   135  	case float32:
   136  		defCaus := newMutRowFixedLenDeferredCauset(4)
   137  		*(*uint32)(unsafe.Pointer(&defCaus.data[0])) = math.Float32bits(x)
   138  		return defCaus
   139  	case string:
   140  		return makeMutRowBytesDeferredCauset(replog.Slice(x))
   141  	case []byte:
   142  		return makeMutRowBytesDeferredCauset(x)
   143  	case types.BinaryLiteral:
   144  		return makeMutRowBytesDeferredCauset(x)
   145  	case *types.MyDecimal:
   146  		defCaus := newMutRowFixedLenDeferredCauset(types.MyDecimalStructSize)
   147  		*(*types.MyDecimal)(unsafe.Pointer(&defCaus.data[0])) = *x
   148  		return defCaus
   149  	case types.Time:
   150  		defCaus := newMutRowFixedLenDeferredCauset(sizeTime)
   151  		*(*types.Time)(unsafe.Pointer(&defCaus.data[0])) = x
   152  		return defCaus
   153  	case json.BinaryJSON:
   154  		defCaus := newMutRowVarLenDeferredCauset(len(x.Value) + 1)
   155  		defCaus.data[0] = x.TypeCode
   156  		copy(defCaus.data[1:], x.Value)
   157  		return defCaus
   158  	case types.Duration:
   159  		defCaus := newMutRowFixedLenDeferredCauset(8)
   160  		*(*int64)(unsafe.Pointer(&defCaus.data[0])) = int64(x.Duration)
   161  		return defCaus
   162  	case types.Enum:
   163  		defCaus := newMutRowVarLenDeferredCauset(len(x.Name) + 8)
   164  		copy(defCaus.data, (*[8]byte)(unsafe.Pointer(&x.Value))[:])
   165  		copy(defCaus.data[8:], x.Name)
   166  		return defCaus
   167  	case types.Set:
   168  		defCaus := newMutRowVarLenDeferredCauset(len(x.Name) + 8)
   169  		copy(defCaus.data, (*[8]byte)(unsafe.Pointer(&x.Value))[:])
   170  		copy(defCaus.data[8:], x.Name)
   171  		return defCaus
   172  	default:
   173  		return nil
   174  	}
   175  }
   176  
   177  func newMutRowFixedLenDeferredCauset(elemSize int) *DeferredCauset {
   178  	buf := make([]byte, elemSize)
   179  	defCaus := &DeferredCauset{
   180  		length:     1,
   181  		elemBuf:    buf,
   182  		data:       buf,
   183  		nullBitmap: make([]byte, 1),
   184  	}
   185  	defCaus.nullBitmap[0] = 1
   186  	return defCaus
   187  }
   188  
   189  func newMutRowVarLenDeferredCauset(valSize int) *DeferredCauset {
   190  	buf := make([]byte, valSize+1)
   191  	defCaus := &DeferredCauset{
   192  		length:     1,
   193  		offsets:    []int64{0, int64(valSize)},
   194  		data:       buf[:valSize],
   195  		nullBitmap: buf[valSize:],
   196  	}
   197  	defCaus.nullBitmap[0] = 1
   198  	return defCaus
   199  }
   200  
   201  func makeMutRowUint64DeferredCauset(val uint64) *DeferredCauset {
   202  	defCaus := newMutRowFixedLenDeferredCauset(8)
   203  	*(*uint64)(unsafe.Pointer(&defCaus.data[0])) = val
   204  	return defCaus
   205  }
   206  
   207  func makeMutRowBytesDeferredCauset(bin []byte) *DeferredCauset {
   208  	defCaus := newMutRowVarLenDeferredCauset(len(bin))
   209  	copy(defCaus.data, bin)
   210  	return defCaus
   211  }
   212  
   213  // SetRow sets the MutRow with Row.
   214  func (mr MutRow) SetRow(event Row) {
   215  	for defCausIdx, rDefCaus := range event.c.defCausumns {
   216  		mrDefCaus := mr.c.defCausumns[defCausIdx]
   217  		if rDefCaus.IsNull(event.idx) {
   218  			mrDefCaus.nullBitmap[0] = 0
   219  			continue
   220  		}
   221  		elemLen := len(rDefCaus.elemBuf)
   222  		if elemLen > 0 {
   223  			copy(mrDefCaus.data, rDefCaus.data[event.idx*elemLen:(event.idx+1)*elemLen])
   224  		} else {
   225  			setMutRowBytes(mrDefCaus, rDefCaus.data[rDefCaus.offsets[event.idx]:rDefCaus.offsets[event.idx+1]])
   226  		}
   227  		mrDefCaus.nullBitmap[0] = 1
   228  	}
   229  }
   230  
   231  // SetValues sets the MutRow with values.
   232  func (mr MutRow) SetValues(vals ...interface{}) {
   233  	for i, v := range vals {
   234  		mr.SetValue(i, v)
   235  	}
   236  }
   237  
   238  // SetValue sets the MutRow with defCausIdx and value.
   239  func (mr MutRow) SetValue(defCausIdx int, val interface{}) {
   240  	defCaus := mr.c.defCausumns[defCausIdx]
   241  	if val == nil {
   242  		defCaus.nullBitmap[0] = 0
   243  		return
   244  	}
   245  	switch x := val.(type) {
   246  	case int:
   247  		binary.LittleEndian.PutUint64(defCaus.data, uint64(x))
   248  	case int64:
   249  		binary.LittleEndian.PutUint64(defCaus.data, uint64(x))
   250  	case uint64:
   251  		binary.LittleEndian.PutUint64(defCaus.data, x)
   252  	case float64:
   253  		binary.LittleEndian.PutUint64(defCaus.data, math.Float64bits(x))
   254  	case float32:
   255  		binary.LittleEndian.PutUint32(defCaus.data, math.Float32bits(x))
   256  	case string:
   257  		setMutRowBytes(defCaus, replog.Slice(x))
   258  	case []byte:
   259  		setMutRowBytes(defCaus, x)
   260  	case types.BinaryLiteral:
   261  		setMutRowBytes(defCaus, x)
   262  	case types.Duration:
   263  		*(*int64)(unsafe.Pointer(&defCaus.data[0])) = int64(x.Duration)
   264  	case *types.MyDecimal:
   265  		*(*types.MyDecimal)(unsafe.Pointer(&defCaus.data[0])) = *x
   266  	case types.Time:
   267  		*(*types.Time)(unsafe.Pointer(&defCaus.data[0])) = x
   268  	case types.Enum:
   269  		setMutRowNameValue(defCaus, x.Name, x.Value)
   270  	case types.Set:
   271  		setMutRowNameValue(defCaus, x.Name, x.Value)
   272  	case json.BinaryJSON:
   273  		setMutRowJSON(defCaus, x)
   274  	}
   275  	defCaus.nullBitmap[0] = 1
   276  }
   277  
   278  // SetCausets sets the MutRow with causet slice.
   279  func (mr MutRow) SetCausets(datums ...types.Causet) {
   280  	for i, d := range datums {
   281  		mr.SetCauset(i, d)
   282  	}
   283  }
   284  
   285  // SetCauset sets the MutRow with defCausIdx and causet.
   286  func (mr MutRow) SetCauset(defCausIdx int, d types.Causet) {
   287  	defCaus := mr.c.defCausumns[defCausIdx]
   288  	if d.IsNull() {
   289  		defCaus.nullBitmap[0] = 0
   290  		return
   291  	}
   292  	switch d.HoTT() {
   293  	case types.HoTTInt64, types.HoTTUint64, types.HoTTFloat64:
   294  		binary.LittleEndian.PutUint64(mr.c.defCausumns[defCausIdx].data, d.GetUint64())
   295  	case types.HoTTFloat32:
   296  		binary.LittleEndian.PutUint32(mr.c.defCausumns[defCausIdx].data, math.Float32bits(d.GetFloat32()))
   297  	case types.HoTTString, types.HoTTBytes, types.HoTTBinaryLiteral:
   298  		setMutRowBytes(defCaus, d.GetBytes())
   299  	case types.HoTTMysqlTime:
   300  		*(*types.Time)(unsafe.Pointer(&defCaus.data[0])) = d.GetMysqlTime()
   301  	case types.HoTTMysqlDuration:
   302  		*(*int64)(unsafe.Pointer(&defCaus.data[0])) = int64(d.GetMysqlDuration().Duration)
   303  	case types.HoTTMysqlDecimal:
   304  		*(*types.MyDecimal)(unsafe.Pointer(&defCaus.data[0])) = *d.GetMysqlDecimal()
   305  	case types.HoTTMysqlJSON:
   306  		setMutRowJSON(defCaus, d.GetMysqlJSON())
   307  	case types.HoTTMysqlEnum:
   308  		e := d.GetMysqlEnum()
   309  		setMutRowNameValue(defCaus, e.Name, e.Value)
   310  	case types.HoTTMysqlSet:
   311  		s := d.GetMysqlSet()
   312  		setMutRowNameValue(defCaus, s.Name, s.Value)
   313  	default:
   314  		mr.c.defCausumns[defCausIdx] = makeMutRowDeferredCauset(d.GetValue())
   315  	}
   316  	defCaus.nullBitmap[0] = 1
   317  }
   318  
   319  func setMutRowBytes(defCaus *DeferredCauset, bin []byte) {
   320  	if len(defCaus.data) >= len(bin) {
   321  		defCaus.data = defCaus.data[:len(bin)]
   322  	} else {
   323  		buf := make([]byte, len(bin)+1)
   324  		defCaus.data = buf[:len(bin)]
   325  		defCaus.nullBitmap = buf[len(bin):]
   326  	}
   327  	copy(defCaus.data, bin)
   328  	defCaus.offsets[1] = int64(len(bin))
   329  }
   330  
   331  func setMutRowNameValue(defCaus *DeferredCauset, name string, val uint64) {
   332  	dataLen := len(name) + 8
   333  	if len(defCaus.data) >= dataLen {
   334  		defCaus.data = defCaus.data[:dataLen]
   335  	} else {
   336  		buf := make([]byte, dataLen+1)
   337  		defCaus.data = buf[:dataLen]
   338  		defCaus.nullBitmap = buf[dataLen:]
   339  	}
   340  	binary.LittleEndian.PutUint64(defCaus.data, val)
   341  	copy(defCaus.data[8:], name)
   342  	defCaus.offsets[1] = int64(dataLen)
   343  }
   344  
   345  func setMutRowJSON(defCaus *DeferredCauset, j json.BinaryJSON) {
   346  	dataLen := len(j.Value) + 1
   347  	if len(defCaus.data) >= dataLen {
   348  		defCaus.data = defCaus.data[:dataLen]
   349  	} else {
   350  		// In MutRow, there always exists 1 data in every DeferredCauset,
   351  		// we should allocate one more byte for null bitmap.
   352  		buf := make([]byte, dataLen+1)
   353  		defCaus.data = buf[:dataLen]
   354  		defCaus.nullBitmap = buf[dataLen:]
   355  	}
   356  	defCaus.data[0] = j.TypeCode
   357  	copy(defCaus.data[1:], j.Value)
   358  	defCaus.offsets[1] = int64(dataLen)
   359  }
   360  
   361  // ShallowCopyPartialRow shallow copies the data of `event` to MutRow.
   362  func (mr MutRow) ShallowCopyPartialRow(defCausIdx int, event Row) {
   363  	for i, srcDefCaus := range event.c.defCausumns {
   364  		dstDefCaus := mr.c.defCausumns[defCausIdx+i]
   365  		if !srcDefCaus.IsNull(event.idx) {
   366  			// MutRow only contains one event, so we can directly set the whole byte.
   367  			dstDefCaus.nullBitmap[0] = 1
   368  		} else {
   369  			dstDefCaus.nullBitmap[0] = 0
   370  		}
   371  
   372  		if srcDefCaus.isFixed() {
   373  			elemLen := len(srcDefCaus.elemBuf)
   374  			offset := event.idx * elemLen
   375  			dstDefCaus.data = srcDefCaus.data[offset : offset+elemLen]
   376  		} else {
   377  			start, end := srcDefCaus.offsets[event.idx], srcDefCaus.offsets[event.idx+1]
   378  			dstDefCaus.data = srcDefCaus.data[start:end]
   379  			dstDefCaus.offsets[1] = int64(len(dstDefCaus.data))
   380  		}
   381  	}
   382  }