github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/partition_reader.go (about)

     1  // Copyright 2022 Matrix Origin
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package disttae
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/objectio"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/logutil"
    23  	"github.com/matrixorigin/matrixone/pkg/testutil"
    24  	"go.uber.org/zap"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/catalog"
    27  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    28  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    29  	"github.com/matrixorigin/matrixone/pkg/container/types"
    30  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    31  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    33  	"github.com/matrixorigin/matrixone/pkg/vm/engine/disttae/logtailreplay"
    34  )
    35  
    36  type PartitionReader struct {
    37  	table    *txnTable
    38  	prepared bool
    39  	// inserted rows comes from txn.writes.
    40  	inserts []*batch.Batch
    41  	//deleted rows comes from txn.writes or partitionState.rows.
    42  	deletes  map[types.Rowid]uint8
    43  	iter     logtailreplay.RowsIter
    44  	seqnumMp map[string]int
    45  	typsMap  map[string]types.Type
    46  }
    47  
    48  var _ engine.Reader = new(PartitionReader)
    49  
    50  func (p *PartitionReader) SetFilterZM(objectio.ZoneMap) {
    51  }
    52  
    53  func (p *PartitionReader) GetOrderBy() []*plan.OrderBySpec {
    54  	return nil
    55  }
    56  
    57  func (p *PartitionReader) SetOrderBy([]*plan.OrderBySpec) {
    58  }
    59  
    60  func (p *PartitionReader) Close() error {
    61  	//p.withFilterMixin.reset()
    62  	p.inserts = nil
    63  	p.deletes = nil
    64  	return p.iter.Close()
    65  }
    66  
    67  func (p *PartitionReader) prepare() error {
    68  	txn := p.table.getTxn()
    69  	var inserts []*batch.Batch
    70  	var deletes map[types.Rowid]uint8
    71  	//prepare inserts and deletes for partition reader.
    72  	if !txn.readOnly.Load() && !p.prepared {
    73  		inserts = make([]*batch.Batch, 0)
    74  		deletes = make(map[types.Rowid]uint8)
    75  		//load inserts and deletes from txn.writes.
    76  		p.table.getTxn().forEachTableWrites(p.table.db.databaseId, p.table.tableId,
    77  			p.table.getTxn().GetSnapshotWriteOffset(), func(entry Entry) {
    78  				if entry.typ == INSERT || entry.typ == INSERT_TXN {
    79  					if entry.bat == nil || entry.bat.IsEmpty() {
    80  						return
    81  					}
    82  					if entry.bat.Attrs[0] == catalog.BlockMeta_MetaLoc {
    83  						return
    84  					}
    85  					inserts = append(inserts, entry.bat)
    86  					return
    87  				}
    88  				//entry.typ == DELETE
    89  				if entry.bat.GetVector(0).GetType().Oid == types.T_Rowid {
    90  					/*
    91  						CASE:
    92  						create table t1(a int);
    93  						begin;
    94  						truncate t1; //txnDatabase.Truncate will DELETE mo_tables
    95  						show tables; // t1 must be shown
    96  					*/
    97  					if entry.isGeneratedByTruncate() {
    98  						return
    99  					}
   100  					//deletes in txn.Write maybe comes from PartitionState.Rows ,
   101  					// PartitionReader need to skip them.
   102  					vs := vector.MustFixedCol[types.Rowid](entry.bat.GetVector(0))
   103  					for _, v := range vs {
   104  						deletes[v] = 0
   105  					}
   106  				}
   107  			})
   108  		//deletes maybe comes from PartitionState.rows, PartitionReader need to skip them;
   109  		// so, here only load deletes which don't belong to PartitionState.blks.
   110  		if err := p.table.LoadDeletesForMemBlocksIn(p.table._partState.Load(), deletes); err != nil {
   111  			return err
   112  		}
   113  		p.inserts = inserts
   114  		p.deletes = deletes
   115  		p.prepared = true
   116  	}
   117  	return nil
   118  }
   119  
   120  func (p *PartitionReader) Read(
   121  	_ context.Context,
   122  	colNames []string,
   123  	_ *plan.Expr,
   124  	mp *mpool.MPool,
   125  	pool engine.VectorPool) (result *batch.Batch, err error) {
   126  	if p == nil {
   127  		return
   128  	}
   129  	// prepare the data for read.
   130  	if err = p.prepare(); err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	defer func() {
   135  		if err != nil && result != nil {
   136  			if pool == nil {
   137  				result.Clean(mp)
   138  			} else {
   139  				pool.PutBatch(result)
   140  			}
   141  		}
   142  	}()
   143  	result = batch.NewWithSize(len(colNames))
   144  	result.SetAttributes(colNames)
   145  	for i, name := range colNames {
   146  		if pool == nil {
   147  			result.Vecs[i] = vector.NewVec(p.typsMap[name])
   148  		} else {
   149  			result.Vecs[i] = pool.GetVector(p.typsMap[name])
   150  		}
   151  	}
   152  
   153  	// read batch resided in the memory from txn.writes.
   154  	if len(p.inserts) > 0 {
   155  		bat := p.inserts[0].GetSubBatch(colNames)
   156  
   157  		rowIDs := vector.MustFixedCol[types.Rowid](p.inserts[0].Vecs[0])
   158  		p.inserts = p.inserts[1:]
   159  
   160  		for i, vec := range result.Vecs {
   161  			uf := vector.GetUnionOneFunction(*vec.GetType(), mp)
   162  
   163  			for j, k := int64(0), int64(bat.RowCount()); j < k; j++ {
   164  				if _, ok := p.deletes[rowIDs[j]]; ok {
   165  					continue
   166  				}
   167  				if err = uf(vec, bat.Vecs[i], j); err != nil {
   168  					return
   169  				}
   170  			}
   171  		}
   172  
   173  		logutil.Debugf("read %v with %v", colNames, p.seqnumMp)
   174  		//		CORNER CASE:
   175  		//		if some rowIds[j] is in p.deletes above, then some rows has been filtered.
   176  		//		the bat.RowCount() is not always the right value for the result batch b.
   177  		result.SetRowCount(result.Vecs[0].Length())
   178  		if logutil.GetSkip1Logger().Core().Enabled(zap.DebugLevel) {
   179  			logutil.Debug(testutil.OperatorCatchBatch(
   180  				"partition reader[workspace:memory]",
   181  				result))
   182  		}
   183  		return result, err
   184  	}
   185  
   186  	{
   187  		const maxRows = 8192
   188  		rows := 0
   189  		appendFuncs := make([]func(*vector.Vector, *vector.Vector, int64) error, len(result.Attrs))
   190  		for i, name := range result.Attrs {
   191  			if name == catalog.Row_ID {
   192  				appendFuncs[i] = vector.GetUnionOneFunction(types.T_Rowid.ToType(), mp)
   193  			} else {
   194  				appendFuncs[i] = vector.GetUnionOneFunction(p.typsMap[name], mp)
   195  			}
   196  		}
   197  		// read rows from partitionState.rows.
   198  		for p.iter.Next() {
   199  			entry := p.iter.Entry()
   200  			if _, ok := p.deletes[entry.RowID]; ok {
   201  				continue
   202  			}
   203  
   204  			for i, name := range result.Attrs {
   205  				if name == catalog.Row_ID {
   206  					if err = vector.AppendFixed(
   207  						result.Vecs[i],
   208  						entry.RowID,
   209  						false,
   210  						mp); err != nil {
   211  						return nil, err
   212  					}
   213  				} else {
   214  					idx := 2 /*rowid and commits*/ + p.seqnumMp[name]
   215  					if idx >= len(entry.Batch.Vecs) /*add column*/ ||
   216  						entry.Batch.Attrs[idx] == "" /*drop column*/ {
   217  						err = vector.AppendAny(
   218  							result.Vecs[i],
   219  							nil,
   220  							true,
   221  							mp)
   222  					} else {
   223  						err = appendFuncs[i](
   224  							result.Vecs[i],
   225  							entry.Batch.Vecs[2 /*rowid and commits*/ +p.seqnumMp[name]],
   226  							entry.Offset,
   227  						)
   228  					}
   229  					if err != nil {
   230  						return nil, err
   231  					}
   232  				}
   233  			}
   234  			rows++
   235  			if rows == maxRows {
   236  				break
   237  			}
   238  		}
   239  
   240  		if rows == 0 {
   241  			if pool == nil {
   242  				result.Clean(mp)
   243  			} else {
   244  				pool.PutBatch(result)
   245  			}
   246  			return nil, nil
   247  		}
   248  
   249  		result.SetRowCount(rows)
   250  		if logutil.GetSkip1Logger().Core().Enabled(zap.DebugLevel) {
   251  			logutil.Debug(testutil.OperatorCatchBatch(
   252  				"partition reader[snapshot: partitionState.rows]",
   253  				result))
   254  		}
   255  		return result, nil
   256  	}
   257  }