github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/mem_reader.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 interlock 15 16 import ( 17 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 18 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 19 "github.com/whtcorpsinc/errors" 20 "github.com/whtcorpsinc/milevadb/allegrosql" 21 "github.com/whtcorpsinc/milevadb/blockcodec" 22 "github.com/whtcorpsinc/milevadb/causet" 23 "github.com/whtcorpsinc/milevadb/causet/blocks" 24 causetembedded "github.com/whtcorpsinc/milevadb/causet/embedded" 25 "github.com/whtcorpsinc/milevadb/ekv" 26 "github.com/whtcorpsinc/milevadb/memex" 27 "github.com/whtcorpsinc/milevadb/soliton/chunk" 28 "github.com/whtcorpsinc/milevadb/soliton/codec" 29 "github.com/whtcorpsinc/milevadb/soliton/rowcodec" 30 "github.com/whtcorpsinc/milevadb/stochastikctx" 31 "github.com/whtcorpsinc/milevadb/types" 32 ) 33 34 type memIndexReader struct { 35 ctx stochastikctx.Context 36 index *perceptron.IndexInfo 37 causet *perceptron.BlockInfo 38 ekvRanges []ekv.KeyRange 39 desc bool 40 conditions []memex.Expression 41 addedEvents [][]types.Causet 42 addedEventsLen int 43 retFieldTypes []*types.FieldType 44 outputOffset []int 45 // belowHandleDefCauss is the handle's position of the below scan plan. 46 belowHandleDefCauss causetembedded.HandleDefCauss 47 } 48 49 func buildMemIndexReader(us *UnionScanInterDirc, idxReader *IndexReaderInterlockingDirectorate) *memIndexReader { 50 ekvRanges := idxReader.ekvRanges 51 outputOffset := make([]int, 0, len(us.defCausumns)) 52 for _, defCaus := range idxReader.outputDeferredCausets { 53 outputOffset = append(outputOffset, defCaus.Index) 54 } 55 return &memIndexReader{ 56 ctx: us.ctx, 57 index: idxReader.index, 58 causet: idxReader.causet.Meta(), 59 ekvRanges: ekvRanges, 60 desc: us.desc, 61 conditions: us.conditions, 62 retFieldTypes: retTypes(us), 63 outputOffset: outputOffset, 64 belowHandleDefCauss: us.belowHandleDefCauss, 65 } 66 } 67 68 func (m *memIndexReader) getMemEvents() ([][]types.Causet, error) { 69 tps := make([]*types.FieldType, 0, len(m.index.DeferredCausets)+1) 70 defcaus := m.causet.DeferredCausets 71 for _, defCaus := range m.index.DeferredCausets { 72 tps = append(tps, &defcaus[defCaus.Offset].FieldType) 73 } 74 switch { 75 case m.causet.PKIsHandle: 76 for _, defCaus := range m.causet.DeferredCausets { 77 if allegrosql.HasPriKeyFlag(defCaus.Flag) { 78 tps = append(tps, &defCaus.FieldType) 79 break 80 } 81 } 82 case m.causet.IsCommonHandle: 83 pkIdx := blocks.FindPrimaryIndex(m.causet) 84 for _, pkDefCaus := range pkIdx.DeferredCausets { 85 defCausInfo := m.causet.DeferredCausets[pkDefCaus.Offset] 86 tps = append(tps, &defCausInfo.FieldType) 87 } 88 default: // ExtraHandle DeferredCauset tp. 89 tps = append(tps, types.NewFieldType(allegrosql.TypeLonglong)) 90 } 91 92 mublockEvent := chunk.MutEventFromTypes(m.retFieldTypes) 93 err := iterTxnMemBuffer(m.ctx, m.ekvRanges, func(key, value []byte) error { 94 data, err := m.decodeIndexKeyValue(key, value, tps) 95 if err != nil { 96 return err 97 } 98 99 mublockEvent.SetCausets(data...) 100 matched, _, err := memex.EvalBool(m.ctx, m.conditions, mublockEvent.ToEvent()) 101 if err != nil || !matched { 102 return err 103 } 104 m.addedEvents = append(m.addedEvents, data) 105 return nil 106 }) 107 108 if err != nil { 109 return nil, err 110 } 111 // TODO: After refine `IterReverse`, remove below logic and use `IterReverse` when do reverse scan. 112 if m.desc { 113 reverseCausetSlice(m.addedEvents) 114 } 115 return m.addedEvents, nil 116 } 117 118 func (m *memIndexReader) decodeIndexKeyValue(key, value []byte, tps []*types.FieldType) ([]types.Causet, error) { 119 hdStatus := blockcodec.HandleDefault 120 if allegrosql.HasUnsignedFlag(tps[len(tps)-1].Flag) { 121 hdStatus = blockcodec.HandleIsUnsigned 122 } 123 defCausInfos := make([]rowcodec.DefCausInfo, 0, len(m.index.DeferredCausets)) 124 for _, idxDefCaus := range m.index.DeferredCausets { 125 defCaus := m.causet.DeferredCausets[idxDefCaus.Offset] 126 defCausInfos = append(defCausInfos, rowcodec.DefCausInfo{ 127 ID: defCaus.ID, 128 IsPKHandle: m.causet.PKIsHandle && allegrosql.HasPriKeyFlag(defCaus.Flag), 129 Ft: rowcodec.FieldTypeFromPerceptronDeferredCauset(defCaus), 130 }) 131 } 132 values, err := blockcodec.DecodeIndexKV(key, value, len(m.index.DeferredCausets), hdStatus, defCausInfos) 133 if err != nil { 134 return nil, errors.Trace(err) 135 } 136 137 ds := make([]types.Causet, 0, len(m.outputOffset)) 138 for _, offset := range m.outputOffset { 139 d, err := blockcodec.DecodeDeferredCausetValue(values[offset], tps[offset], m.ctx.GetStochastikVars().TimeZone) 140 if err != nil { 141 return nil, err 142 } 143 ds = append(ds, d) 144 } 145 return ds, nil 146 } 147 148 type memBlockReader struct { 149 ctx stochastikctx.Context 150 causet *perceptron.BlockInfo 151 defCausumns []*perceptron.DeferredCausetInfo 152 ekvRanges []ekv.KeyRange 153 desc bool 154 conditions []memex.Expression 155 addedEvents [][]types.Causet 156 retFieldTypes []*types.FieldType 157 defCausIDs map[int64]int 158 buffer allocBuf 159 pkDefCausIDs []int64 160 } 161 162 type allocBuf struct { 163 // cache for decode handle. 164 handleBytes []byte 165 rd *rowcodec.BytesCausetDecoder 166 } 167 168 func buildMemBlockReader(us *UnionScanInterDirc, tblReader *BlockReaderInterlockingDirectorate) *memBlockReader { 169 defCausIDs := make(map[int64]int, len(us.defCausumns)) 170 for i, defCaus := range us.defCausumns { 171 defCausIDs[defCaus.ID] = i 172 } 173 174 defCausInfo := make([]rowcodec.DefCausInfo, 0, len(us.defCausumns)) 175 for i := range us.defCausumns { 176 defCaus := us.defCausumns[i] 177 defCausInfo = append(defCausInfo, rowcodec.DefCausInfo{ 178 ID: defCaus.ID, 179 IsPKHandle: us.causet.Meta().PKIsHandle && allegrosql.HasPriKeyFlag(defCaus.Flag), 180 Ft: rowcodec.FieldTypeFromPerceptronDeferredCauset(defCaus), 181 }) 182 } 183 184 pkDefCausIDs := blocks.TryGetCommonPkDeferredCausetIds(us.causet.Meta()) 185 if len(pkDefCausIDs) == 0 { 186 pkDefCausIDs = []int64{-1} 187 } 188 rd := rowcodec.NewByteCausetDecoder(defCausInfo, pkDefCausIDs, nil, us.ctx.GetStochastikVars().TimeZone) 189 return &memBlockReader{ 190 ctx: us.ctx, 191 causet: us.causet.Meta(), 192 defCausumns: us.defCausumns, 193 ekvRanges: tblReader.ekvRanges, 194 desc: us.desc, 195 conditions: us.conditions, 196 retFieldTypes: retTypes(us), 197 defCausIDs: defCausIDs, 198 buffer: allocBuf{ 199 handleBytes: make([]byte, 0, 16), 200 rd: rd, 201 }, 202 pkDefCausIDs: pkDefCausIDs, 203 } 204 } 205 206 // TODO: Try to make memXXXReader lazy, There is no need to decode many rows when parent operator only need 1 event. 207 func (m *memBlockReader) getMemEvents() ([][]types.Causet, error) { 208 mublockEvent := chunk.MutEventFromTypes(m.retFieldTypes) 209 err := iterTxnMemBuffer(m.ctx, m.ekvRanges, func(key, value []byte) error { 210 event, err := m.decodeRecordKeyValue(key, value) 211 if err != nil { 212 return err 213 } 214 215 mublockEvent.SetCausets(event...) 216 matched, _, err := memex.EvalBool(m.ctx, m.conditions, mublockEvent.ToEvent()) 217 if err != nil || !matched { 218 return err 219 } 220 m.addedEvents = append(m.addedEvents, event) 221 return nil 222 }) 223 if err != nil { 224 return nil, err 225 } 226 227 // TODO: After refine `IterReverse`, remove below logic and use `IterReverse` when do reverse scan. 228 if m.desc { 229 reverseCausetSlice(m.addedEvents) 230 } 231 return m.addedEvents, nil 232 } 233 234 func (m *memBlockReader) decodeRecordKeyValue(key, value []byte) ([]types.Causet, error) { 235 handle, err := blockcodec.DecodeEventKey(key) 236 if err != nil { 237 return nil, errors.Trace(err) 238 } 239 return m.decodeEventData(handle, value) 240 } 241 242 // decodeEventData uses to decode event data value. 243 func (m *memBlockReader) decodeEventData(handle ekv.Handle, value []byte) ([]types.Causet, error) { 244 values, err := m.getEventData(handle, value) 245 if err != nil { 246 return nil, err 247 } 248 ds := make([]types.Causet, 0, len(m.defCausumns)) 249 for _, defCaus := range m.defCausumns { 250 offset := m.defCausIDs[defCaus.ID] 251 d, err := blockcodec.DecodeDeferredCausetValue(values[offset], &defCaus.FieldType, m.ctx.GetStochastikVars().TimeZone) 252 if err != nil { 253 return nil, err 254 } 255 ds = append(ds, d) 256 } 257 return ds, nil 258 } 259 260 // getEventData decodes raw byte slice to event data. 261 func (m *memBlockReader) getEventData(handle ekv.Handle, value []byte) ([][]byte, error) { 262 defCausIDs := m.defCausIDs 263 pkIsHandle := m.causet.PKIsHandle 264 buffer := &m.buffer 265 ctx := m.ctx.GetStochastikVars().StmtCtx 266 if rowcodec.IsNewFormat(value) { 267 return buffer.rd.DecodeToBytes(defCausIDs, handle, value, buffer.handleBytes) 268 } 269 values, err := blockcodec.CutEventNew(value, defCausIDs) 270 if err != nil { 271 return nil, errors.Trace(err) 272 } 273 if values == nil { 274 values = make([][]byte, len(defCausIDs)) 275 } 276 // Fill the handle and null defCausumns. 277 for _, defCaus := range m.defCausumns { 278 id := defCaus.ID 279 offset := defCausIDs[id] 280 if m.causet.IsCommonHandle { 281 for i, defCausID := range m.pkDefCausIDs { 282 if defCausID == defCaus.ID { 283 values[offset] = handle.EncodedDefCaus(i) 284 break 285 } 286 } 287 continue 288 } 289 if (pkIsHandle && allegrosql.HasPriKeyFlag(defCaus.Flag)) || id == perceptron.ExtraHandleID { 290 var handleCauset types.Causet 291 if allegrosql.HasUnsignedFlag(defCaus.Flag) { 292 // PK defCausumn is Unsigned. 293 handleCauset = types.NewUintCauset(uint64(handle.IntValue())) 294 } else { 295 handleCauset = types.NewIntCauset(handle.IntValue()) 296 } 297 handleData, err1 := codec.EncodeValue(ctx, buffer.handleBytes, handleCauset) 298 if err1 != nil { 299 return nil, errors.Trace(err1) 300 } 301 values[offset] = handleData 302 continue 303 } 304 if hasDefCausVal(values, defCausIDs, id) { 305 continue 306 } 307 // no need to fill default value. 308 values[offset] = []byte{codec.NilFlag} 309 } 310 311 return values, nil 312 } 313 314 func hasDefCausVal(data [][]byte, defCausIDs map[int64]int, id int64) bool { 315 offset, ok := defCausIDs[id] 316 if ok && data[offset] != nil { 317 return true 318 } 319 return false 320 } 321 322 type processKVFunc func(key, value []byte) error 323 324 func iterTxnMemBuffer(ctx stochastikctx.Context, ekvRanges []ekv.KeyRange, fn processKVFunc) error { 325 txn, err := ctx.Txn(true) 326 if err != nil { 327 return err 328 } 329 for _, rg := range ekvRanges { 330 iter := txn.GetMemBuffer().SnapshotIter(rg.StartKey, rg.EndKey) 331 for ; iter.Valid(); err = iter.Next() { 332 if err != nil { 333 return err 334 } 335 // check whether the key was been deleted. 336 if len(iter.Value()) == 0 { 337 continue 338 } 339 err = fn(iter.Key(), iter.Value()) 340 if err != nil { 341 return err 342 } 343 } 344 } 345 return nil 346 } 347 348 func reverseCausetSlice(rows [][]types.Causet) { 349 for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 { 350 rows[i], rows[j] = rows[j], rows[i] 351 } 352 } 353 354 func (m *memIndexReader) getMemEventsHandle() ([]ekv.Handle, error) { 355 handles := make([]ekv.Handle, 0, m.addedEventsLen) 356 err := iterTxnMemBuffer(m.ctx, m.ekvRanges, func(key, value []byte) error { 357 handle, err := blockcodec.DecodeIndexHandle(key, value, len(m.index.DeferredCausets)) 358 if err != nil { 359 return err 360 } 361 handles = append(handles, handle) 362 return nil 363 }) 364 if err != nil { 365 return nil, err 366 } 367 368 if m.desc { 369 for i, j := 0, len(handles)-1; i < j; i, j = i+1, j-1 { 370 handles[i], handles[j] = handles[j], handles[i] 371 } 372 } 373 return handles, nil 374 } 375 376 type memIndexLookUpReader struct { 377 ctx stochastikctx.Context 378 index *perceptron.IndexInfo 379 defCausumns []*perceptron.DeferredCausetInfo 380 causet causet.Block 381 desc bool 382 conditions []memex.Expression 383 retFieldTypes []*types.FieldType 384 385 idxReader *memIndexReader 386 } 387 388 func buildMemIndexLookUpReader(us *UnionScanInterDirc, idxLookUpReader *IndexLookUpInterlockingDirectorate) *memIndexLookUpReader { 389 ekvRanges := idxLookUpReader.ekvRanges 390 outputOffset := []int{len(idxLookUpReader.index.DeferredCausets)} 391 memIdxReader := &memIndexReader{ 392 ctx: us.ctx, 393 index: idxLookUpReader.index, 394 causet: idxLookUpReader.causet.Meta(), 395 ekvRanges: ekvRanges, 396 desc: idxLookUpReader.desc, 397 retFieldTypes: retTypes(us), 398 outputOffset: outputOffset, 399 belowHandleDefCauss: us.belowHandleDefCauss, 400 } 401 402 return &memIndexLookUpReader{ 403 ctx: us.ctx, 404 index: idxLookUpReader.index, 405 defCausumns: idxLookUpReader.defCausumns, 406 causet: idxLookUpReader.causet, 407 desc: idxLookUpReader.desc, 408 conditions: us.conditions, 409 retFieldTypes: retTypes(us), 410 idxReader: memIdxReader, 411 } 412 } 413 414 func (m *memIndexLookUpReader) getMemEvents() ([][]types.Causet, error) { 415 handles, err := m.idxReader.getMemEventsHandle() 416 if err != nil || len(handles) == 0 { 417 return nil, err 418 } 419 420 tblKVRanges := allegrosql.BlockHandlesToKVRanges(getPhysicalBlockID(m.causet), handles) 421 defCausIDs := make(map[int64]int, len(m.defCausumns)) 422 for i, defCaus := range m.defCausumns { 423 defCausIDs[defCaus.ID] = i 424 } 425 426 tblInfo := m.causet.Meta() 427 defCausInfos := make([]rowcodec.DefCausInfo, 0, len(m.defCausumns)) 428 for i := range m.defCausumns { 429 defCaus := m.defCausumns[i] 430 defCausInfos = append(defCausInfos, rowcodec.DefCausInfo{ 431 ID: defCaus.ID, 432 IsPKHandle: tblInfo.PKIsHandle && allegrosql.HasPriKeyFlag(defCaus.Flag), 433 Ft: rowcodec.FieldTypeFromPerceptronDeferredCauset(defCaus), 434 }) 435 } 436 handleDefCausIDs := []int64{-1} 437 if tblInfo.IsCommonHandle { 438 handleDefCausIDs = handleDefCausIDs[:0] 439 pkIdx := blocks.FindPrimaryIndex(tblInfo) 440 for _, idxDefCaus := range pkIdx.DeferredCausets { 441 defCausID := tblInfo.DeferredCausets[idxDefCaus.Offset].ID 442 handleDefCausIDs = append(handleDefCausIDs, defCausID) 443 } 444 } 445 rd := rowcodec.NewByteCausetDecoder(defCausInfos, handleDefCausIDs, nil, nil) 446 memTblReader := &memBlockReader{ 447 ctx: m.ctx, 448 causet: m.causet.Meta(), 449 defCausumns: m.defCausumns, 450 ekvRanges: tblKVRanges, 451 conditions: m.conditions, 452 addedEvents: make([][]types.Causet, 0, len(handles)), 453 retFieldTypes: m.retFieldTypes, 454 defCausIDs: defCausIDs, 455 buffer: allocBuf{ 456 handleBytes: make([]byte, 0, 16), 457 rd: rd, 458 }, 459 } 460 461 return memTblReader.getMemEvents() 462 }