github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/interval/interval.go (about)

     1  // Copyright ©2012 The bíogo Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Portions of this file are additionally subject to the following
     6  // license and copyright.
     7  //
     8  // Copyright 2016 The Cockroach Authors.
     9  //
    10  // Use of this software is governed by the Business Source License
    11  // included in the file licenses/BSL.txt.
    12  //
    13  // As of the Change Date specified in that file, in accordance with
    14  // the Business Source License, use of this software will be governed
    15  // by the Apache License, Version 2.0, included in the file
    16  // licenses/APL.txt.
    17  
    18  // This code originated in the github.com/biogo/store/interval package.
    19  
    20  // Package interval provides two implementations for an interval tree. One is
    21  // based on an augmented Left-Leaning Red Black tree. The other is based on an
    22  // augmented BTree.
    23  package interval
    24  
    25  import (
    26  	"bytes"
    27  	"fmt"
    28  
    29  	"github.com/cockroachdb/cockroachdb-parser/pkg/util/envutil"
    30  	"github.com/cockroachdb/errors"
    31  )
    32  
    33  // ErrInvertedRange is returned if an interval is used where the start value is greater
    34  // than the end value.
    35  var ErrInvertedRange = errors.Newf("interval: inverted range")
    36  
    37  // ErrEmptyRange is returned if an interval is used where the start value is equal
    38  // to the end value.
    39  var ErrEmptyRange = errors.Newf("interval: empty range")
    40  
    41  // ErrNilRange is returned if an interval is used where both the start value and
    42  // the end value are nil. This is a specialization of ErrEmptyRange.
    43  var ErrNilRange = errors.Newf("interval: nil range")
    44  
    45  func rangeError(r Range) error {
    46  	switch r.Start.Compare(r.End) {
    47  	case 1:
    48  		return ErrInvertedRange
    49  	case 0:
    50  		if len(r.Start) == 0 && len(r.End) == 0 {
    51  			return ErrNilRange
    52  		}
    53  		return ErrEmptyRange
    54  	default:
    55  		return nil
    56  	}
    57  }
    58  
    59  // A Range is a type that describes the basic characteristics of an interval.
    60  type Range struct {
    61  	Start, End Comparable
    62  }
    63  
    64  // Equal returns whether the two ranges are equal.
    65  func (r Range) Equal(other Range) bool {
    66  	return r.Start.Equal(other.Start) && r.End.Equal(other.End)
    67  }
    68  
    69  // String implements the Stringer interface.
    70  func (r Range) String() string {
    71  	return fmt.Sprintf("{%x-%x}", r.Start, r.End)
    72  }
    73  
    74  // Overlapper specifies the overlapping relationship.
    75  type Overlapper interface {
    76  	// Overlap checks whether two ranges overlap.
    77  	Overlap(Range, Range) bool
    78  }
    79  
    80  type inclusiveOverlapper struct{}
    81  
    82  // Overlap checks where a and b overlap in the inclusive way.
    83  func (overlapper inclusiveOverlapper) Overlap(a Range, b Range) bool {
    84  	return overlapsInclusive(a, b)
    85  }
    86  
    87  func overlapsInclusive(a Range, b Range) bool {
    88  	return a.Start.Compare(b.End) <= 0 && b.Start.Compare(a.End) <= 0
    89  }
    90  
    91  // InclusiveOverlapper defines overlapping as a pair of ranges that share a segment of the keyspace
    92  // in the inclusive way. "inclusive" means that both start and end keys treated as inclusive values.
    93  var InclusiveOverlapper = inclusiveOverlapper{}
    94  
    95  type exclusiveOverlapper struct{}
    96  
    97  // Overlap checks where a and b overlap in the exclusive way.
    98  func (overlapper exclusiveOverlapper) Overlap(a Range, b Range) bool {
    99  	return overlapsExclusive(a, b)
   100  }
   101  
   102  func overlapsExclusive(a Range, b Range) bool {
   103  	return a.Start.Compare(b.End) < 0 && b.Start.Compare(a.End) < 0
   104  }
   105  
   106  // ExclusiveOverlapper defines overlapping as a pair of ranges that share a segment of the keyspace
   107  // in the exclusive. "exclusive" means that the start keys are treated as inclusive and the end keys
   108  // are treated as exclusive.
   109  var ExclusiveOverlapper = exclusiveOverlapper{}
   110  
   111  // An Interface is a type that can be inserted into an interval tree.
   112  type Interface interface {
   113  	Range() Range
   114  	// Returns a unique ID for the element.
   115  	// TODO(nvanbenschoten): Should this be changed to an int64?
   116  	ID() uintptr
   117  }
   118  
   119  // Compare returns a value indicating the sort order relationship between a and b. The comparison is
   120  // performed lexicographically on (a.Range().Start, a.ID()) and (b.Range().Start, b.ID()) tuples
   121  // where Range().Start is more significant that ID().
   122  //
   123  // Given c = Compare(a, b):
   124  //
   125  //	c == -1  if (a.Range().Start, a.ID()) < (b.Range().Start, b.ID());
   126  //	c == 0 if (a.Range().Start, a.ID()) == (b.Range().Start, b.ID()); and
   127  //	c == 1 if (a.Range().Start, a.ID()) > (b.Range().Start, b.ID()).
   128  //
   129  // "c == 0" is equivalent to "Equal(a, b) == true".
   130  func Compare(a, b Interface) int {
   131  	startCmp := a.Range().Start.Compare(b.Range().Start)
   132  	if startCmp != 0 {
   133  		return startCmp
   134  	}
   135  	aID := a.ID()
   136  	bID := b.ID()
   137  	if aID < bID {
   138  		return -1
   139  	} else if aID > bID {
   140  		return 1
   141  	} else {
   142  		return 0
   143  	}
   144  }
   145  
   146  // Equal returns a boolean indicating whether the given Interfaces are equal to each other. If
   147  // "Equal(a, b) == true", "a.Range().End == b.Range().End" must hold. Otherwise, the interval tree
   148  // behavior is undefined. "Equal(a, b) == true" is equivalent to "Compare(a, b) == 0". But the
   149  // former has measurably better performance than the latter. So Equal should be used when only
   150  // equality state is needed.
   151  func Equal(a, b Interface) bool {
   152  	return a.ID() == b.ID() && a.Range().Start.Equal(b.Range().Start)
   153  }
   154  
   155  // A Comparable is a type that describes the ends of a Range.
   156  type Comparable []byte
   157  
   158  // Compare returns a value indicating the sort order relationship between the
   159  // receiver and the parameter.
   160  //
   161  // Given c = a.Compare(b):
   162  //
   163  //	c == -1 if a < b;
   164  //	c == 0 if a == b; and
   165  //	c == 1 if a > b.
   166  func (c Comparable) Compare(o Comparable) int {
   167  	return bytes.Compare(c, o)
   168  }
   169  
   170  // Equal returns a boolean indicating if the given comparables are equal to
   171  // each other. Note that this has measurably better performance than
   172  // Compare() == 0, so it should be used when only equality state is needed.
   173  func (c Comparable) Equal(o Comparable) bool {
   174  	return bytes.Equal(c, o)
   175  }
   176  
   177  // An Operation is a function that operates on an Interface. If done is returned true, the
   178  // Operation is indicating that no further work needs to be done and so the DoMatching function
   179  // should traverse no further.
   180  type Operation func(Interface) (done bool)
   181  
   182  // Tree is an interval tree. For all the functions which have a fast argument,
   183  // fast being true means a fast operation which does not adjust node ranges. If
   184  // fast is false, node ranges are adjusted.
   185  type Tree interface {
   186  	// AdjustRanges fixes range fields for all nodes in the tree. This must be
   187  	// called before Get, Do or DoMatching* is used if fast insertion or deletion
   188  	// has been performed.
   189  	AdjustRanges()
   190  	// Len returns the number of intervals stored in the Tree.
   191  	Len() int
   192  	// Get returns a slice of Interfaces that overlap r in the tree. The slice is
   193  	// sorted nondecreasingly by interval start.
   194  	Get(r Range) []Interface
   195  	// GetWithOverlapper returns a slice of Interfaces that overlap r in the tree
   196  	// using the provided overlapper function. The slice is sorted nondecreasingly
   197  	// by interval start.
   198  	GetWithOverlapper(r Range, overlapper Overlapper) []Interface
   199  	// Insert inserts the Interface e into the tree. Insertions may replace an
   200  	// existing Interface which is equal to the Interface e.
   201  	Insert(e Interface, fast bool) error
   202  	// Delete deletes the Interface e if it exists in the tree. The deleted
   203  	// Interface is equal to the Interface e.
   204  	Delete(e Interface, fast bool) error
   205  	// Do performs fn on all intervals stored in the tree. The traversal is done
   206  	// in the nondecreasing order of interval start. A boolean is returned
   207  	// indicating whether the traversal was interrupted by an Operation returning
   208  	// true. If fn alters stored intervals' sort relationships, future tree
   209  	// operation behaviors are undefined.
   210  	Do(fn Operation) bool
   211  	// DoMatching performs fn on all intervals stored in the tree that overlaps r.
   212  	// The traversal is done in the nondecreasing order of interval start. A
   213  	// boolean is returned indicating whether the traversal was interrupted by an
   214  	// Operation returning true. If fn alters stored intervals' sort
   215  	// relationships, future tree operation behaviors are undefined.
   216  	DoMatching(fn Operation, r Range) bool
   217  	// Iterator creates an iterator to iterate over all intervals stored in the
   218  	// tree, in-order.
   219  	Iterator() TreeIterator
   220  	// Clear this tree.
   221  	Clear()
   222  	// Clone clones the tree, returning a copy.
   223  	Clone() Tree
   224  }
   225  
   226  // TreeIterator iterates over all intervals stored in the interval tree, in-order.
   227  type TreeIterator interface {
   228  	// Next returns the current interval stored in the interval tree	and moves
   229  	// the iterator to the next interval. The method returns false if no intervals
   230  	// remain in the interval tree.
   231  	Next() (Interface, bool)
   232  }
   233  
   234  var useBTreeImpl = envutil.EnvOrDefaultBool("COCKROACH_INTERVAL_BTREE", false)
   235  
   236  // NewTree creates a new interval tree with the given overlapper function. It
   237  // uses the augmented Left-Leaning Red Black tree implementation unless the
   238  // envvar COCKROACH_INTERVAL_BTREE is set.
   239  func NewTree(overlapper Overlapper) Tree {
   240  	if useBTreeImpl {
   241  		return newBTree(overlapper)
   242  	}
   243  	return newLLRBTree(overlapper)
   244  }