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

     1  // Copyright 2024 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 val
    16  
    17  // ExtendedTupleComparator is a comparator that properly handles extended types.
    18  type ExtendedTupleComparator struct {
    19  	innerCmp TupleComparator
    20  	handlers []TupleTypeHandler
    21  }
    22  
    23  // TODO: compare performance of rolling this logic into the DefaultTupleComparator (nil check or generic handlers that call compare)
    24  var _ TupleComparator = ExtendedTupleComparator{}
    25  
    26  // Compare implements the TupleComparator interface.
    27  func (c ExtendedTupleComparator) Compare(left, right Tuple, desc TupleDesc) (cmp int) {
    28  	fast := desc.GetFixedAccess()
    29  	for i := range fast {
    30  		start, stop := fast[i][0], fast[i][1]
    31  		cmp = c.CompareValues(i, left[start:stop], right[start:stop], desc.Types[i])
    32  		if cmp != 0 {
    33  			return cmp
    34  		}
    35  	}
    36  
    37  	off := len(fast)
    38  	for i, typ := range desc.Types[off:] {
    39  		j := i + off
    40  		cmp = c.CompareValues(j, left.GetField(j), right.GetField(j), typ)
    41  		if cmp != 0 {
    42  			return cmp
    43  		}
    44  	}
    45  	return
    46  }
    47  
    48  // CompareValues implements the TupleComparator interface.
    49  func (c ExtendedTupleComparator) CompareValues(index int, left, right []byte, typ Type) int {
    50  	switch typ.Enc {
    51  	case ExtendedEnc, ExtendedAddrEnc:
    52  		cmp, err := c.handlers[index].SerializedCompare(left, right)
    53  		if err != nil {
    54  			panic(err)
    55  		}
    56  		return cmp
    57  	default:
    58  		return compare(typ, left, right)
    59  	}
    60  }
    61  
    62  // Prefix implements the TupleComparator interface.
    63  func (c ExtendedTupleComparator) Prefix(n int) TupleComparator {
    64  	return ExtendedTupleComparator{c.innerCmp.Prefix(n), c.handlers[:n]}
    65  }
    66  
    67  // Suffix implements the TupleComparator interface.
    68  func (c ExtendedTupleComparator) Suffix(n int) TupleComparator {
    69  	return ExtendedTupleComparator{c.innerCmp.Suffix(n), c.handlers[n:]}
    70  }
    71  
    72  // Validated implements the TupleComparator interface.
    73  func (c ExtendedTupleComparator) Validated(types []Type) TupleComparator {
    74  	innerCmp := c.innerCmp.Validated(types)
    75  	if len(c.handlers) == 0 {
    76  		c.handlers = make([]TupleTypeHandler, len(types))
    77  	} else if len(c.handlers) != len(types) {
    78  		panic("invalid handler count compared to types")
    79  	}
    80  	hasHandler := false
    81  	for i, handler := range c.handlers {
    82  		switch types[i].Enc {
    83  		case ExtendedEnc, ExtendedAddrEnc:
    84  			if handler == nil {
    85  				panic("extended encoding requires a handler")
    86  			} else {
    87  				hasHandler = true
    88  			}
    89  		}
    90  	}
    91  	if !hasHandler {
    92  		return innerCmp
    93  	}
    94  	return ExtendedTupleComparator{innerCmp, c.handlers}
    95  }