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  }