github.com/matrixorigin/matrixone@v0.7.0/pkg/txn/storage/memorystorage/memtable/diff_iter.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 memtable 16 17 import ( 18 "database/sql" 19 20 "github.com/matrixorigin/matrixone/pkg/txn/storage/memorystorage/memorytable" 21 "github.com/tidwall/btree" 22 ) 23 24 func (t *Table[K, V, R]) NewDiffIter(fromTime, toTime *Time) *DiffIter[K, V] { 25 ret := &DiffIter[K, V]{ 26 fromTime: fromTime, 27 toTime: toTime, 28 iter: t.state.Load().rows.Copy().Iter(), 29 } 30 return ret 31 } 32 33 type DiffIter[ 34 K memorytable.Ordered[K], 35 V any, 36 ] struct { 37 fromTime *Time 38 toTime *Time 39 iter btree.GenericIter[*PhysicalRow[K, V]] 40 41 currentRow *PhysicalRow[K, V] 42 currentVersion Version[V] 43 currentIsDelete bool 44 } 45 46 func (t *DiffIter[K, V]) Close() error { 47 t.iter.Release() 48 return nil 49 } 50 51 func (t *DiffIter[K, V]) Seek(pivot K) bool { 52 if !t.iter.Seek(&PhysicalRow[K, V]{ 53 Key: pivot, 54 }) { 55 return false 56 } 57 return t.read() 58 } 59 60 func (t *DiffIter[K, V]) First() bool { 61 if !t.iter.First() { 62 return false 63 } 64 for { 65 if t.read() { 66 return true 67 } 68 if !t.iter.Next() { 69 return false 70 } 71 } 72 } 73 74 func (t *DiffIter[K, V]) Next() bool { 75 if !t.iter.Next() { 76 return false 77 } 78 for { 79 if t.read() { 80 return true 81 } 82 if !t.iter.Next() { 83 return false 84 } 85 } 86 } 87 88 func (t *DiffIter[K, V]) read() bool { 89 physicalRow := t.iter.Item() 90 91 for i := len(physicalRow.Versions) - 1; i >= 0; i-- { 92 version := physicalRow.Versions[i] 93 94 if version.LockTx != nil && 95 version.LockTx.State.Load() == Committed && 96 (t.fromTime == nil || version.LockTime.After(*t.fromTime)) && 97 (t.toTime == nil || version.LockTime.Before(*t.toTime)) { 98 // committed delete 99 t.currentRow = physicalRow 100 t.currentVersion = version 101 t.currentIsDelete = true 102 return true 103 104 } else if version.BornTx.State.Load() == Committed && 105 (t.fromTime == nil || version.BornTime.After(*t.fromTime)) && 106 (t.toTime == nil || version.BornTime.Before(*t.toTime)) { 107 // committed insert 108 t.currentRow = physicalRow 109 t.currentVersion = version 110 t.currentIsDelete = false 111 return true 112 } 113 114 } 115 116 t.currentRow = nil 117 return false 118 } 119 120 func (t *DiffIter[K, V]) Read() ( 121 key K, 122 value V, 123 bornTime Time, 124 lockTime *Time, 125 err error, 126 ) { 127 128 if t.currentRow == nil { 129 err = sql.ErrNoRows 130 return 131 } 132 133 key = t.currentRow.Key 134 value = t.currentVersion.Value 135 bornTime = t.currentVersion.BornTime 136 if t.currentIsDelete { 137 lockTime = &t.currentVersion.LockTime 138 } 139 140 return 141 }