github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/logtailreplay/rows_iter.go (about) 1 // Copyright 2023 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 logtailreplay 16 17 import ( 18 "bytes" 19 "github.com/matrixorigin/matrixone/pkg/container/types" 20 "github.com/tidwall/btree" 21 ) 22 23 type RowsIter interface { 24 Next() bool 25 Close() error 26 Entry() RowEntry 27 } 28 29 type rowsIter struct { 30 ts types.TS 31 iter btree.IterG[RowEntry] 32 firstCalled bool 33 lastRowID types.Rowid 34 checkBlockID bool 35 blockID types.Blockid 36 iterDeleted bool 37 } 38 39 func (p *PartitionState) NewRowsIter(ts types.TS, blockID *types.Blockid, iterDeleted bool) *rowsIter { 40 iter := p.rows.Copy().Iter() 41 ret := &rowsIter{ 42 ts: ts, 43 iter: iter, 44 iterDeleted: iterDeleted, 45 } 46 if blockID != nil { 47 ret.checkBlockID = true 48 ret.blockID = *blockID 49 } 50 return ret 51 } 52 53 var _ RowsIter = new(rowsIter) 54 55 func (p *rowsIter) Next() bool { 56 for { 57 58 if !p.firstCalled { 59 if p.checkBlockID { 60 if !p.iter.Seek(RowEntry{ 61 BlockID: p.blockID, 62 }) { 63 return false 64 } 65 } else { 66 if !p.iter.First() { 67 return false 68 } 69 } 70 p.firstCalled = true 71 } else { 72 if !p.iter.Next() { 73 return false 74 } 75 } 76 77 entry := p.iter.Item() 78 79 if p.checkBlockID && entry.BlockID != p.blockID { 80 // no more 81 return false 82 } 83 if entry.Time.Greater(&p.ts) { 84 // not visible 85 continue 86 } 87 if entry.RowID.Equal(p.lastRowID) { 88 // already met 89 continue 90 } 91 if entry.Deleted != p.iterDeleted { 92 // not wanted, skip to next row id 93 p.lastRowID = entry.RowID 94 continue 95 } 96 97 p.lastRowID = entry.RowID 98 return true 99 } 100 } 101 102 func (p *rowsIter) Entry() RowEntry { 103 return p.iter.Item() 104 } 105 106 func (p *rowsIter) Close() error { 107 p.iter.Release() 108 return nil 109 } 110 111 type primaryKeyIter struct { 112 ts types.TS 113 spec PrimaryKeyMatchSpec 114 iter btree.IterG[*PrimaryIndexEntry] 115 rows *btree.BTreeG[RowEntry] 116 primaryIndex *btree.BTreeG[*PrimaryIndexEntry] 117 curRow RowEntry 118 } 119 120 type PrimaryKeyMatchSpec struct { 121 // Move moves to the target 122 Move func(p *primaryKeyIter) bool 123 Name string 124 } 125 126 func Exact(key []byte) PrimaryKeyMatchSpec { 127 first := true 128 return PrimaryKeyMatchSpec{ 129 Name: "Exact", 130 Move: func(p *primaryKeyIter) bool { 131 var ok bool 132 if first { 133 first = false 134 ok = p.iter.Seek(&PrimaryIndexEntry{ 135 Bytes: key, 136 }) 137 } else { 138 ok = p.iter.Next() 139 } 140 141 if !ok { 142 return false 143 } 144 145 item := p.iter.Item() 146 return bytes.Equal(item.Bytes, key) 147 }, 148 } 149 } 150 151 func Prefix(prefix []byte) PrimaryKeyMatchSpec { 152 first := true 153 return PrimaryKeyMatchSpec{ 154 Name: "Prefix", 155 Move: func(p *primaryKeyIter) bool { 156 var ok bool 157 if first { 158 first = false 159 ok = p.iter.Seek(&PrimaryIndexEntry{ 160 Bytes: prefix, 161 }) 162 } else { 163 ok = p.iter.Next() 164 } 165 166 if !ok { 167 return false 168 } 169 170 item := p.iter.Item() 171 return bytes.HasPrefix(item.Bytes, prefix) 172 }, 173 } 174 } 175 176 func MinMax(min []byte, max []byte) PrimaryKeyMatchSpec { 177 return PrimaryKeyMatchSpec{} 178 } 179 180 type phase int 181 182 const ( 183 scan phase = 0 184 seek phase = 1 185 judge phase = 2 186 ) 187 188 func ExactIn(encodes [][]byte) PrimaryKeyMatchSpec { 189 var encoded []byte 190 191 first := true 192 iterateAll := false 193 194 idx := 0 195 vecLen := len(encodes) 196 currentPhase := seek 197 198 updateEncoded := func() bool { 199 if idx >= vecLen { 200 return false 201 } 202 encoded = encodes[idx] 203 idx++ 204 return true 205 } 206 207 match := func(key []byte) bool { 208 return bytes.Equal(key, encoded) 209 } 210 211 return PrimaryKeyMatchSpec{ 212 Name: "ExactIn", 213 Move: func(p *primaryKeyIter) bool { 214 if first { 215 first = false 216 // each seek may visit height items 217 // we choose to scan all if the seek is more expensive 218 if len(encodes)*p.primaryIndex.Height() > p.primaryIndex.Len() { 219 iterateAll = true 220 } 221 } 222 223 for { 224 switch currentPhase { 225 case judge: 226 if iterateAll { 227 if !updateEncoded() { 228 return false 229 } 230 currentPhase = scan 231 } else { 232 currentPhase = seek 233 } 234 235 case seek: 236 if !updateEncoded() { 237 // out of vec 238 return false 239 } 240 if !p.iter.Seek(&PrimaryIndexEntry{Bytes: encoded}) { 241 return false 242 } 243 if match(p.iter.Item().Bytes) { 244 currentPhase = scan 245 return true 246 } 247 248 case scan: 249 if !p.iter.Next() { 250 return false 251 } 252 if match(p.iter.Item().Bytes) { 253 return true 254 } 255 p.iter.Prev() 256 currentPhase = judge 257 } 258 } 259 }, 260 } 261 } 262 263 func (p *PartitionState) NewPrimaryKeyIter( 264 ts types.TS, 265 spec PrimaryKeyMatchSpec, 266 ) *primaryKeyIter { 267 index := p.primaryIndex.Copy() 268 return &primaryKeyIter{ 269 ts: ts, 270 spec: spec, 271 iter: index.Iter(), 272 primaryIndex: index, 273 rows: p.rows.Copy(), 274 } 275 } 276 277 var _ RowsIter = new(primaryKeyIter) 278 279 func (p *primaryKeyIter) Next() bool { 280 for { 281 if !p.spec.Move(p) { 282 return false 283 } 284 285 entry := p.iter.Item() 286 287 // validate 288 valid := false 289 rowsIter := p.rows.Iter() 290 for ok := rowsIter.Seek(RowEntry{ 291 BlockID: entry.BlockID, 292 RowID: entry.RowID, 293 Time: p.ts, 294 }); ok; ok = rowsIter.Next() { 295 row := rowsIter.Item() 296 if row.BlockID != entry.BlockID { 297 // no more 298 break 299 } 300 if row.RowID != entry.RowID { 301 // no more 302 break 303 } 304 if row.Time.Greater(&p.ts) { 305 // not visible 306 continue 307 } 308 if row.Deleted { 309 // visible and deleted, no longer valid 310 break 311 } 312 valid = row.ID == entry.RowEntryID 313 if valid { 314 p.curRow = row 315 } 316 break 317 } 318 rowsIter.Release() 319 320 if !valid { 321 continue 322 } 323 324 return true 325 } 326 } 327 328 func (p *primaryKeyIter) Entry() RowEntry { 329 return p.curRow 330 } 331 332 func (p *primaryKeyIter) Close() error { 333 p.iter.Release() 334 return nil 335 } 336 337 type primaryKeyDelIter struct { 338 primaryKeyIter 339 bid types.Blockid 340 } 341 342 func (p *PartitionState) NewPrimaryKeyDelIter( 343 ts types.TS, 344 spec PrimaryKeyMatchSpec, 345 bid types.Blockid, 346 ) *primaryKeyDelIter { 347 iter := p.primaryIndex.Copy().Iter() 348 return &primaryKeyDelIter{ 349 primaryKeyIter: primaryKeyIter{ 350 ts: ts, 351 spec: spec, 352 iter: iter, 353 rows: p.rows.Copy(), 354 }, 355 bid: bid, 356 } 357 } 358 359 var _ RowsIter = new(primaryKeyDelIter) 360 361 func (p *primaryKeyDelIter) Next() bool { 362 for { 363 if !p.spec.Move(&p.primaryKeyIter) { 364 return false 365 } 366 367 entry := p.iter.Item() 368 369 if entry.BlockID.Compare(p.bid) != 0 { 370 continue 371 } 372 373 // validate 374 valid := false 375 rowsIter := p.rows.Iter() 376 for ok := rowsIter.Seek(RowEntry{ 377 BlockID: entry.BlockID, 378 RowID: entry.RowID, 379 Time: p.ts, 380 }); ok; ok = rowsIter.Next() { 381 row := rowsIter.Item() 382 if row.BlockID != entry.BlockID { 383 // no more 384 break 385 } 386 if row.RowID != entry.RowID { 387 // no more 388 break 389 } 390 if row.Time.Greater(&p.ts) { 391 // not visible 392 continue 393 } 394 if !row.Deleted { 395 // skip not deleted 396 continue 397 } 398 valid = row.ID == entry.RowEntryID 399 if valid { 400 p.curRow = row 401 } 402 break 403 } 404 rowsIter.Release() 405 406 if !valid { 407 continue 408 } 409 410 return true 411 } 412 }