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 }