github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/expreval/compare_ops.go (about)

     1  // Copyright 2020 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 expreval
    16  
    17  import (
    18  	"github.com/dolthub/go-mysql-server/sql/expression"
    19  
    20  	"github.com/dolthub/dolt/go/store/types"
    21  )
    22  
    23  func compareLiterals(l1, l2 *expression.Literal) (int, error) {
    24  	return l1.Type().Compare(l1.Value(), l2.Value())
    25  }
    26  
    27  // CompareOp is an interface for comparing values
    28  type CompareOp interface {
    29  	// CompareLiterals compares two go-mysql-server literals
    30  	CompareLiterals(l1, l2 *expression.Literal) (bool, error)
    31  	// CompareNomsValues compares two noms values
    32  	CompareNomsValues(v1, v2 types.Value) (bool, error)
    33  	// CompareToNil compares a noms value to nil using sql logic rules
    34  	CompareToNil(v2 types.Value) (bool, error)
    35  }
    36  
    37  // EqualsOp implements the CompareOp interface implementing equality logic
    38  type EqualsOp struct{}
    39  
    40  // CompareLiterals compares two go-mysql-server literals for equality
    41  func (op EqualsOp) CompareLiterals(l1, l2 *expression.Literal) (bool, error) {
    42  	n, err := compareLiterals(l1, l2)
    43  
    44  	if err != nil {
    45  		return false, err
    46  	}
    47  
    48  	return n == 0, nil
    49  }
    50  
    51  // CompareNomsValues compares two noms values for equality
    52  func (op EqualsOp) CompareNomsValues(v1, v2 types.Value) (bool, error) {
    53  	return v1.Equals(v2), nil
    54  }
    55  
    56  // CompareToNil always returns false as values are neither greater than, less than, or equal to nil
    57  func (op EqualsOp) CompareToNil(types.Value) (bool, error) {
    58  	return false, nil
    59  }
    60  
    61  // GreaterOp implements the CompareOp interface implementing greater than logic
    62  type GreaterOp struct {
    63  	NBF *types.NomsBinFormat
    64  }
    65  
    66  // CompareLiterals compares two go-mysql-server literals returning true if the value of the first
    67  // is greater than the second.
    68  func (op GreaterOp) CompareLiterals(l1, l2 *expression.Literal) (bool, error) {
    69  	n, err := compareLiterals(l1, l2)
    70  
    71  	if err != nil {
    72  		return false, err
    73  	}
    74  
    75  	return n > 0, nil
    76  }
    77  
    78  // CompareNomsValues compares two noms values returning true if the of the first
    79  // is greater than the second.
    80  func (op GreaterOp) CompareNomsValues(v1, v2 types.Value) (bool, error) {
    81  	eq := v1.Equals(v2)
    82  
    83  	if eq {
    84  		return false, nil
    85  	}
    86  
    87  	lt, err := v1.Less(op.NBF, v2)
    88  
    89  	if err != nil {
    90  		return false, nil
    91  	}
    92  
    93  	return !lt, err
    94  }
    95  
    96  // CompareToNil always returns false as values are neither greater than, less than, or equal to nil
    97  func (op GreaterOp) CompareToNil(types.Value) (bool, error) {
    98  	return false, nil
    99  }
   100  
   101  // GreaterEqualOp implements the CompareOp interface implementing greater than or equal to logic
   102  type GreaterEqualOp struct {
   103  	NBF *types.NomsBinFormat
   104  }
   105  
   106  // CompareLiterals compares two go-mysql-server literals returning true if the value of the first
   107  // is greater than or equal to the second.
   108  func (op GreaterEqualOp) CompareLiterals(l1, l2 *expression.Literal) (bool, error) {
   109  	n, err := compareLiterals(l1, l2)
   110  
   111  	if err != nil {
   112  		return false, err
   113  	}
   114  
   115  	return n >= 0, nil
   116  }
   117  
   118  // CompareNomsValues compares two noms values returning true if the of the first
   119  // is greater or equal to than the second.
   120  func (op GreaterEqualOp) CompareNomsValues(v1, v2 types.Value) (bool, error) {
   121  	res, err := v1.Less(op.NBF, v2)
   122  
   123  	if err != nil {
   124  		return false, err
   125  	}
   126  
   127  	return !res, nil
   128  }
   129  
   130  // CompareToNil always returns false as values are neither greater than, less than, or equal to nil
   131  func (op GreaterEqualOp) CompareToNil(types.Value) (bool, error) {
   132  	return false, nil
   133  }
   134  
   135  // LessOp implements the CompareOp interface implementing less than logic
   136  type LessOp struct {
   137  	NBF *types.NomsBinFormat
   138  }
   139  
   140  // CompareLiterals compares two go-mysql-server literals returning true if the value of the first
   141  // is less than the second.
   142  func (op LessOp) CompareLiterals(l1, l2 *expression.Literal) (bool, error) {
   143  	n, err := compareLiterals(l1, l2)
   144  
   145  	if err != nil {
   146  		return false, err
   147  	}
   148  
   149  	return n < 0, nil
   150  }
   151  
   152  // CompareNomsValues compares two noms values returning true if the of the first
   153  // is less than the second.
   154  func (op LessOp) CompareNomsValues(v1, v2 types.Value) (bool, error) {
   155  	return v1.Less(op.NBF, v2)
   156  }
   157  
   158  // CompareToNil always returns false as values are neither greater than, less than, or equal to nil
   159  func (op LessOp) CompareToNil(types.Value) (bool, error) {
   160  	return false, nil
   161  }
   162  
   163  // LessEqualOp implements the CompareOp interface implementing less than or equal to logic
   164  type LessEqualOp struct {
   165  	NBF *types.NomsBinFormat
   166  }
   167  
   168  // CompareLiterals compares two go-mysql-server literals returning true if the value of the first
   169  // is less than or equal to the second.
   170  func (op LessEqualOp) CompareLiterals(l1, l2 *expression.Literal) (bool, error) {
   171  	n, err := compareLiterals(l1, l2)
   172  
   173  	if err != nil {
   174  		return false, err
   175  	}
   176  
   177  	return n <= 0, nil
   178  }
   179  
   180  // CompareNomsValues compares two noms values returning true if the of the first
   181  // is less than or equal to the second.
   182  func (op LessEqualOp) CompareNomsValues(v1, v2 types.Value) (bool, error) {
   183  	eq := v1.Equals(v2)
   184  
   185  	if eq {
   186  		return true, nil
   187  	}
   188  
   189  	return v1.Less(op.NBF, v2)
   190  }
   191  
   192  // CompareToNil always returns false as values are neither greater than, less than, or equal to nil
   193  func (op LessEqualOp) CompareToNil(types.Value) (bool, error) {
   194  	return false, nil
   195  }