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  }