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 }