github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/prolly/tuple_range.go (about) 1 // Copyright 2022 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 "sort" 19 20 "github.com/dolthub/dolt/go/store/prolly/tree" 21 "github.com/dolthub/dolt/go/store/val" 22 ) 23 24 // OpenStopRange defines a half-open Range of Tuples [start, stop). 25 func OpenStopRange(start, stop val.Tuple, desc val.TupleDesc) Range { 26 return openStopRange(start, stop, desc) 27 } 28 29 // GreaterOrEqualRange defines a Range of Tuples greater than or equal to |start|. 30 func GreaterOrEqualRange(start val.Tuple, desc val.TupleDesc) Range { 31 return greaterOrEqualRange(start, desc) 32 } 33 34 // LesserRange defines a Range of Tuples less than |stop|. 35 func LesserRange(stop val.Tuple, desc val.TupleDesc) Range { 36 return lesserRange(stop, desc) 37 } 38 39 // PrefixRange constructs a Range for Tuples with a prefix of |prefix|. 40 func PrefixRange(prefix val.Tuple, desc val.TupleDesc) Range { 41 return closedRange(prefix, prefix, desc) 42 } 43 44 // Range defines a subset of a prolly Tree Tuple index. 45 // 46 // Range can be used either to physically partition an index or 47 // to logically filter an index. 48 // A Range's physical partition is a contiguous set of Tuples 49 // containing every Tuple matching the Range's predicates, but 50 // possibly containing non-matching Tuples. 51 // Non-matching Tuples can be filtered from physical partitions 52 // by using RangeFields as logical predicates (see filteredIter). 53 type Range struct { 54 Fields []RangeField 55 Desc val.TupleDesc 56 Tup val.Tuple 57 } 58 59 // RangeField bounds one dimension of a Range. 60 type RangeField struct { 61 Lo, Hi Bound 62 Exact bool // Lo.Value == Hi.Value 63 } 64 65 type Bound struct { 66 Binding bool 67 Inclusive bool 68 Value []byte 69 } 70 71 // aboveStart is used to find the start of the 72 // physical partition defined by a Range. 73 func (r Range) aboveStart(t val.Tuple) bool { 74 order := r.Desc.Comparator() 75 for i := range r.Fields { 76 bound := r.Fields[i].Lo 77 if !bound.Binding { 78 return true 79 } 80 81 field := r.Desc.GetField(i, t) 82 typ := r.Desc.Types[i] 83 84 cmp := order.CompareValues(i, field, bound.Value, typ) 85 if cmp < 0 { 86 // |field| is outside Range 87 return false 88 } 89 90 if r.Fields[i].Exact && cmp == 0 { 91 // for exact bounds (operators '=' and 'IS') 92 // we can use subsequent columns to narrow 93 // physical index scans. 94 // this is not possible for interval bounds. 95 continue 96 } 97 98 return cmp > 0 || bound.Inclusive 99 } 100 return true 101 } 102 103 // belowStop is used to find the end of the 104 // physical partition defined by a Range. 105 func (r Range) belowStop(t val.Tuple) bool { 106 order := r.Desc.Comparator() 107 for i := range r.Fields { 108 bound := r.Fields[i].Hi 109 if !bound.Binding { 110 return true 111 } 112 113 field := r.Desc.GetField(i, t) 114 typ := r.Desc.Types[i] 115 116 cmp := order.CompareValues(i, field, bound.Value, typ) 117 if cmp > 0 { 118 // |field| is outside Range 119 return false 120 } 121 122 if r.Fields[i].Exact && cmp == 0 { 123 // for exact bounds (operators '=' and 'IS') 124 // we can use subsequent columns to narrow 125 // physical index scans. 126 // this is not possible for interval bounds. 127 continue 128 } 129 130 return cmp < 0 || bound.Inclusive 131 } 132 return true 133 } 134 135 // Matches returns true if all the filter predicates 136 // for Range |r| are true for Tuple |t|. 137 func (r Range) Matches(t val.Tuple) bool { 138 order := r.Desc.Comparator() 139 for i := range r.Fields { 140 field := r.Desc.GetField(i, t) 141 typ := r.Desc.Types[i] 142 143 if r.Fields[i].Exact { 144 v := r.Fields[i].Lo.Value 145 if order.CompareValues(i, field, v, typ) == 0 { 146 continue 147 } 148 return false 149 } 150 151 lo := r.Fields[i].Lo 152 if lo.Binding { 153 cmp := order.CompareValues(i, field, lo.Value, typ) 154 if cmp < 0 || (cmp == 0 && !lo.Inclusive) { 155 return false 156 } 157 } 158 159 hi := r.Fields[i].Hi 160 if hi.Binding { 161 cmp := order.CompareValues(i, field, hi.Value, typ) 162 if cmp > 0 || (cmp == 0 && !hi.Inclusive) { 163 return false 164 } 165 } 166 } 167 return true 168 } 169 170 func (r Range) IsPointLookup(desc val.TupleDesc) bool { 171 if len(r.Fields) < len(desc.Types) { 172 return false 173 } 174 for i := range r.Fields { 175 if !r.Fields[i].Exact { 176 return false 177 } 178 } 179 return true 180 } 181 182 func rangeStartSearchFn(rng Range) tree.SearchFn { 183 return func(nd tree.Node) int { 184 // todo(andy): inline sort.Search() 185 return sort.Search(nd.Count(), func(i int) (in bool) { 186 // if |tup| ∈ |rng|, set |in| to true 187 tup := val.Tuple(nd.GetKey(i)) 188 in = rng.aboveStart(tup) 189 return 190 }) 191 } 192 } 193 194 func rangeStopSearchFn(rng Range) tree.SearchFn { 195 return func(nd tree.Node) (idx int) { 196 // todo(andy): inline sort.Search() 197 return sort.Search(nd.Count(), func(i int) (out bool) { 198 // if |tup| ∈ |rng|, set |out| to false 199 tup := val.Tuple(nd.GetKey(i)) 200 out = !rng.belowStop(tup) 201 return 202 }) 203 } 204 } 205 206 // closedRange defines an inclusive Range of Tuples from [start, stop]. 207 func closedRange(start, stop val.Tuple, desc val.TupleDesc) (rng Range) { 208 rng = Range{ 209 Fields: make([]RangeField, len(desc.Types)), 210 Desc: desc, 211 } 212 order := desc.Comparator() 213 214 for i := range rng.Fields { 215 lo := desc.GetField(i, start) 216 hi := desc.GetField(i, stop) 217 rng.Fields[i] = RangeField{ 218 Lo: Bound{Binding: true, Inclusive: true, Value: lo}, 219 Hi: Bound{Binding: true, Inclusive: true, Value: hi}, 220 Exact: order.CompareValues(i, lo, hi, desc.Types[i]) == 0, 221 } 222 } 223 return 224 } 225 226 // OpenStartRange defines a half-open Range of Tuples (start, stop]. 227 func openStartRange(start, stop val.Tuple, desc val.TupleDesc) (rng Range) { 228 rng = closedRange(start, stop, desc) 229 last := len(rng.Fields) - 1 230 rng.Fields[last].Lo.Inclusive = false 231 rng.Fields[last].Exact = false 232 return rng 233 } 234 235 // OpenStopRange defines a half-open Range of Tuples [start, stop). 236 func openStopRange(start, stop val.Tuple, desc val.TupleDesc) (rng Range) { 237 rng = closedRange(start, stop, desc) 238 last := len(rng.Fields) - 1 239 rng.Fields[last].Hi.Inclusive = false 240 rng.Fields[last].Exact = false 241 return 242 } 243 244 // OpenRange defines a non-inclusive Range of Tuples from (start, stop). 245 func openRange(start, stop val.Tuple, desc val.TupleDesc) (rng Range) { 246 rng = closedRange(start, stop, desc) 247 last := len(rng.Fields) - 1 248 rng.Fields[last].Lo.Inclusive = false 249 rng.Fields[last].Hi.Inclusive = false 250 rng.Fields[last].Exact = false 251 return 252 } 253 254 // GreaterRange defines a Range of Tuples greater than |start|. 255 func greaterRange(start val.Tuple, desc val.TupleDesc) (rng Range) { 256 rng = greaterOrEqualRange(start, desc) 257 last := len(rng.Fields) - 1 258 rng.Fields[last].Lo.Inclusive = false 259 return 260 } 261 262 // GreaterOrEqualRange defines a Range of Tuples greater than or equal to |start|. 263 func greaterOrEqualRange(start val.Tuple, desc val.TupleDesc) (rng Range) { 264 rng = Range{ 265 Fields: make([]RangeField, len(desc.Types)), 266 Desc: desc, 267 } 268 for i := range rng.Fields { 269 lo := desc.GetField(i, start) 270 rng.Fields[i] = RangeField{ 271 Lo: Bound{Binding: true, Inclusive: true, Value: lo}, 272 } 273 } 274 return 275 } 276 277 // LesserRange defines a Range of Tuples less than |stop|. 278 func lesserRange(stop val.Tuple, desc val.TupleDesc) (rng Range) { 279 rng = lesserOrEqualRange(stop, desc) 280 last := len(rng.Fields) - 1 281 rng.Fields[last].Hi.Inclusive = false 282 return 283 } 284 285 // LesserOrEqualRange defines a Range of Tuples less than or equal to |stop|. 286 func lesserOrEqualRange(stop val.Tuple, desc val.TupleDesc) (rng Range) { 287 rng = Range{ 288 Fields: make([]RangeField, len(desc.Types)), 289 Desc: desc, 290 } 291 for i := range rng.Fields { 292 hi := desc.GetField(i, stop) 293 rng.Fields[i] = RangeField{ 294 Hi: Bound{Binding: true, Inclusive: true, Value: hi}, 295 } 296 } 297 return 298 }