github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/prolly/tuple_range_iter.go (about)

     1  // Copyright 2021 Dolthub, Inc.
     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 prolly
    16  
    17  import (
    18  	"context"
    19  	"io"
    20  
    21  	"github.com/dolthub/dolt/go/store/prolly/tree"
    22  	"github.com/dolthub/dolt/go/store/skip"
    23  	"github.com/dolthub/dolt/go/store/val"
    24  )
    25  
    26  type MapIter tree.KvIter[val.Tuple, val.Tuple]
    27  
    28  var _ MapIter = &mutableMapIter[val.Tuple, val.Tuple, val.TupleDesc]{}
    29  var _ MapIter = &tree.OrderedTreeIter[val.Tuple, val.Tuple]{}
    30  
    31  type rangeIter[K, V ~[]byte] interface {
    32  	Iterate(ctx context.Context) error
    33  	Current() (key K, value V)
    34  }
    35  
    36  var _ rangeIter[val.Tuple, val.Tuple] = &tree.OrderedTreeIter[val.Tuple, val.Tuple]{}
    37  var _ rangeIter[val.Tuple, val.Tuple] = &memRangeIter{}
    38  var _ rangeIter[val.Tuple, val.Tuple] = emptyIter{}
    39  
    40  // mutableMapIter iterates over a Range of Tuples.
    41  type mutableMapIter[K, V ~[]byte, O tree.Ordering[K]] struct {
    42  	memory rangeIter[K, V]
    43  	prolly *tree.OrderedTreeIter[K, V]
    44  	order  O
    45  }
    46  
    47  // Next returns the next pair of Tuples in the Range, or io.EOF if the iter is done.
    48  func (it mutableMapIter[K, V, O]) Next(ctx context.Context) (key K, value V, err error) {
    49  	for {
    50  		mk, mv := it.memory.Current()
    51  		pk, pv := it.prolly.Current()
    52  
    53  		if mk == nil && pk == nil {
    54  			// range is exhausted
    55  			return nil, nil, io.EOF
    56  		}
    57  
    58  		cmp := it.compareKeys(pk, mk)
    59  		switch {
    60  		case cmp < 0:
    61  			key, value = pk, pv
    62  			if err = it.prolly.Iterate(ctx); err != nil {
    63  				return nil, nil, err
    64  			}
    65  
    66  		case cmp > 0:
    67  			key, value = mk, mv
    68  			if err = it.memory.Iterate(ctx); err != nil {
    69  				return nil, nil, err
    70  			}
    71  
    72  		case cmp == 0:
    73  			// |it.memory| wins ties
    74  			key, value = mk, mv
    75  			if err = it.memory.Iterate(ctx); err != nil {
    76  				return nil, nil, err
    77  			}
    78  			if err = it.prolly.Iterate(ctx); err != nil {
    79  				return nil, nil, err
    80  			}
    81  		}
    82  
    83  		if key != nil && value == nil {
    84  			continue // pending delete
    85  		}
    86  
    87  		return key, value, nil
    88  	}
    89  }
    90  
    91  func (it mutableMapIter[K, V, O]) currentKeys() (memKey, proKey K) {
    92  	if it.memory != nil {
    93  		memKey, _ = it.memory.Current()
    94  	}
    95  	if it.prolly != nil {
    96  		proKey, _ = it.prolly.Current()
    97  	}
    98  	return
    99  }
   100  
   101  func (it mutableMapIter[K, V, O]) compareKeys(memKey, proKey K) int {
   102  	if memKey == nil {
   103  		return 1
   104  	}
   105  	if proKey == nil {
   106  		return -1
   107  	}
   108  	return it.order.Compare(memKey, proKey)
   109  }
   110  
   111  func memIterFromRange(list *skip.List, rng Range) *memRangeIter {
   112  	// use the lower bound of |rng| to construct a skip.ListIter
   113  	iter := list.GetIterFromSeekFn(skipSearchFromRange(rng))
   114  
   115  	// enforce range start
   116  	var key val.Tuple
   117  	for {
   118  		key, _ = iter.Current()
   119  		if key == nil || rng.aboveStart(key) {
   120  			break // |i| inside |rng|
   121  		}
   122  		iter.Advance()
   123  	}
   124  
   125  	// enforce range end
   126  	if key == nil || !rng.belowStop(key) {
   127  		iter = nil
   128  	}
   129  
   130  	return &memRangeIter{
   131  		iter: iter,
   132  		rng:  rng,
   133  	}
   134  }
   135  
   136  // skipSearchFromRange is a skip.SeekFn used to initialize
   137  // a skip.List iterator for a given Range. The skip.SearchFn
   138  // returns true if the iter being initialized is not yet
   139  // within the bounds of Range |rng|.
   140  func skipSearchFromRange(rng Range) skip.SeekFn {
   141  	return func(nodeKey []byte) bool {
   142  		if nodeKey == nil {
   143  			return false
   144  		}
   145  		return !rng.aboveStart(nodeKey)
   146  	}
   147  }
   148  
   149  // todo(andy): generalize Range iteration and consolidate this
   150  // iterator with orderedListIter[K, V] in ordered_map.go.
   151  // This is not currently possible due to Range checking logic
   152  // that is specific to val.Tuple.
   153  type memRangeIter struct {
   154  	iter *skip.ListIter
   155  	rng  Range
   156  }
   157  
   158  // Current returns the iter's current Tuple pair, or nil Tuples
   159  // if the iter has exhausted its range, it will
   160  func (it *memRangeIter) Current() (key, value val.Tuple) {
   161  	// |it.iter| is set to nil when its range is exhausted
   162  	if it.iter != nil {
   163  		key, value = it.iter.Current()
   164  	}
   165  	return
   166  }
   167  
   168  // Iterate progresses the iter inside its range.
   169  func (it *memRangeIter) Iterate(context.Context) (err error) {
   170  	for {
   171  		it.iter.Advance()
   172  
   173  		k, _ := it.Current()
   174  		if k == nil || !it.rng.belowStop(k) {
   175  			it.iter = nil // range exhausted
   176  		}
   177  
   178  		return
   179  	}
   180  }
   181  
   182  type emptyIter struct{}
   183  
   184  func (e emptyIter) Next(context.Context) (val.Tuple, val.Tuple, error) {
   185  	return nil, nil, io.EOF
   186  }
   187  
   188  func (e emptyIter) Iterate(ctx context.Context) (err error) { return }
   189  
   190  func (e emptyIter) Current() (key, value val.Tuple) { return }
   191  
   192  type filteredIter struct {
   193  	iter MapIter
   194  	rng  Range
   195  }
   196  
   197  var _ MapIter = filteredIter{}
   198  
   199  func (f filteredIter) Next(ctx context.Context) (k, v val.Tuple, err error) {
   200  	for {
   201  		k, v, err = f.iter.Next(ctx)
   202  		if err != nil {
   203  			return nil, nil, err
   204  		}
   205  		if !f.rng.Matches(k) {
   206  			continue
   207  		}
   208  		return
   209  	}
   210  }