github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/function/operator_between.go (about)

     1  // Copyright 2023 Matrix Origin
     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 function
    16  
    17  import (
    18  	"bytes"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    21  	"github.com/matrixorigin/matrixone/pkg/container/types"
    22  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    24  	"golang.org/x/exp/constraints"
    25  )
    26  
    27  func betweenImpl(parameters []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) error {
    28  	paramType := parameters[0].GetType()
    29  	rs := vector.MustFunctionResult[bool](result)
    30  	switch paramType.Oid {
    31  	case types.T_bool:
    32  		return opBetweenBool(parameters, rs, proc, length)
    33  	case types.T_bit:
    34  		return opBetweenFixed[uint64](parameters, rs, proc, length)
    35  	case types.T_int8:
    36  		return opBetweenFixed[int8](parameters, rs, proc, length)
    37  	case types.T_int16:
    38  		return opBetweenFixed[int16](parameters, rs, proc, length)
    39  	case types.T_int32:
    40  		return opBetweenFixed[int32](parameters, rs, proc, length)
    41  	case types.T_int64:
    42  		return opBetweenFixed[int64](parameters, rs, proc, length)
    43  	case types.T_uint8:
    44  		return opBetweenFixed[uint8](parameters, rs, proc, length)
    45  	case types.T_uint16:
    46  		return opBetweenFixed[uint16](parameters, rs, proc, length)
    47  	case types.T_uint32:
    48  		return opBetweenFixed[uint32](parameters, rs, proc, length)
    49  	case types.T_uint64:
    50  		return opBetweenFixed[uint64](parameters, rs, proc, length)
    51  	case types.T_float32:
    52  		return opBetweenFixed[float32](parameters, rs, proc, length)
    53  	case types.T_float64:
    54  		return opBetweenFixed[float64](parameters, rs, proc, length)
    55  	case types.T_date:
    56  		return opBetweenFixed[types.Date](parameters, rs, proc, length)
    57  	case types.T_datetime:
    58  		return opBetweenFixed[types.Datetime](parameters, rs, proc, length)
    59  	case types.T_time:
    60  		return opBetweenFixed[types.Time](parameters, rs, proc, length)
    61  	case types.T_timestamp:
    62  		return opBetweenFixed[types.Timestamp](parameters, rs, proc, length)
    63  
    64  	case types.T_uuid:
    65  		return opBetweenFixedWithFn(parameters, rs, proc, length, func(lhs, rhs types.Uuid) bool {
    66  			return types.CompareUuid(lhs, rhs) <= 0
    67  		})
    68  	case types.T_decimal64:
    69  		return opBetweenFixedWithFn(parameters, rs, proc, length, func(lhs, rhs types.Decimal64) bool {
    70  			return lhs.Compare(rhs) <= 0
    71  		})
    72  	case types.T_decimal128:
    73  		return opBetweenFixedWithFn(parameters, rs, proc, length, func(lhs, rhs types.Decimal128) bool {
    74  			return lhs.Compare(rhs) <= 0
    75  		})
    76  	case types.T_Rowid:
    77  		return opBetweenFixedWithFn(parameters, rs, proc, length, func(lhs, rhs types.Rowid) bool {
    78  			return lhs.Le(rhs)
    79  		})
    80  
    81  	case types.T_char, types.T_varchar, types.T_blob, types.T_text, types.T_binary, types.T_varbinary:
    82  		return opBetweenBytes(parameters, rs, proc, length)
    83  	}
    84  
    85  	panic("unreached code")
    86  }
    87  
    88  func opBetweenBool(
    89  	parameters []*vector.Vector,
    90  	result vector.FunctionResultWrapper,
    91  	_ *process.Process,
    92  	length int,
    93  ) error {
    94  	p0 := vector.GenerateFunctionFixedTypeParameter[bool](parameters[0])
    95  	p1 := vector.GenerateFunctionFixedTypeParameter[bool](parameters[1])
    96  	p2 := vector.GenerateFunctionFixedTypeParameter[bool](parameters[2])
    97  	rs := vector.MustFunctionResult[bool](result)
    98  	rsVec := rs.GetResultVector()
    99  	rss := vector.MustFixedCol[bool](rsVec)
   100  
   101  	// The lower and upper bound of BETWEEN must be non-null constants, or it should be collapsed to "a >= b and a <= c"
   102  	lb, _ := p1.GetValue(0)
   103  	ub, _ := p2.GetValue(0)
   104  	alwaysTrue := lb != ub
   105  
   106  	if parameters[0].IsConst() {
   107  		v0, null0 := p0.GetValue(0)
   108  		if null0 {
   109  			nulls.AddRange(rsVec.GetNulls(), 0, uint64(length))
   110  		} else {
   111  			if alwaysTrue {
   112  				for i := 0; i < length; i++ {
   113  					rss[i] = true
   114  				}
   115  			}
   116  			r := lb == v0
   117  			for i := 0; i < length; i++ {
   118  				rss[i] = r
   119  			}
   120  		}
   121  		return nil
   122  	}
   123  
   124  	// basic case.
   125  	if p0.WithAnyNullValue() {
   126  		nulls.Set(rsVec.GetNulls(), parameters[0].GetNulls())
   127  		for i := 0; i < length; i++ {
   128  			v0, null0 := p0.GetValue(uint64(i))
   129  			if null0 {
   130  				continue
   131  			}
   132  			rss[i] = alwaysTrue || lb == v0
   133  		}
   134  		return nil
   135  	}
   136  
   137  	if alwaysTrue {
   138  		for i := 0; i < length; i++ {
   139  			rss[i] = true
   140  		}
   141  	} else {
   142  		for i := 0; i < length; i++ {
   143  			v0, _ := p0.GetValue(uint64(i))
   144  			rss[i] = lb == v0
   145  		}
   146  	}
   147  	return nil
   148  }
   149  
   150  func opBetweenFixed[T constraints.Integer | constraints.Float](
   151  	parameters []*vector.Vector,
   152  	result vector.FunctionResultWrapper,
   153  	_ *process.Process,
   154  	length int,
   155  ) error {
   156  	p0 := vector.GenerateFunctionFixedTypeParameter[T](parameters[0])
   157  	p1 := vector.GenerateFunctionFixedTypeParameter[T](parameters[1])
   158  	p2 := vector.GenerateFunctionFixedTypeParameter[T](parameters[2])
   159  	rs := vector.MustFunctionResult[bool](result)
   160  	rsVec := rs.GetResultVector()
   161  	rss := vector.MustFixedCol[bool](rsVec)
   162  
   163  	// The lower and upper bound of BETWEEN must be non-null constants, or it should be collapsed to "a >= b and a <= c"
   164  	lb, _ := p1.GetValue(0)
   165  	ub, _ := p2.GetValue(0)
   166  
   167  	if parameters[0].IsConst() {
   168  		v0, null0 := p0.GetValue(0)
   169  		if null0 {
   170  			nulls.AddRange(rsVec.GetNulls(), 0, uint64(length))
   171  		} else {
   172  			r := v0 >= lb && v0 <= ub
   173  			rowCount := uint64(length)
   174  			for i := uint64(0); i < rowCount; i++ {
   175  				rss[i] = r
   176  			}
   177  		}
   178  		return nil
   179  	}
   180  
   181  	// basic case.
   182  	if p0.WithAnyNullValue() {
   183  		nulls.Set(rsVec.GetNulls(), parameters[0].GetNulls())
   184  		rowCount := uint64(length)
   185  		for i := uint64(0); i < rowCount; i++ {
   186  			v0, null0 := p0.GetValue(i)
   187  			if null0 {
   188  				continue
   189  			}
   190  			rss[i] = v0 >= lb && v0 <= ub
   191  		}
   192  		return nil
   193  	}
   194  
   195  	rowCount := uint64(length)
   196  	for i := uint64(0); i < rowCount; i++ {
   197  		v0, _ := p0.GetValue(i)
   198  		rss[i] = v0 >= lb && v0 <= ub
   199  	}
   200  	return nil
   201  }
   202  
   203  func opBetweenFixedWithFn[T types.FixedSizeTExceptStrType](
   204  	parameters []*vector.Vector,
   205  	result vector.FunctionResultWrapper,
   206  	_ *process.Process,
   207  	length int,
   208  	lessEqualFn func(v1, v2 T) bool,
   209  ) error {
   210  	p0 := vector.GenerateFunctionFixedTypeParameter[T](parameters[0])
   211  	p1 := vector.GenerateFunctionFixedTypeParameter[T](parameters[1])
   212  	p2 := vector.GenerateFunctionFixedTypeParameter[T](parameters[2])
   213  	rs := vector.MustFunctionResult[bool](result)
   214  	rsVec := rs.GetResultVector()
   215  	rss := vector.MustFixedCol[bool](rsVec)
   216  
   217  	// The lower and upper bound of BETWEEN must be non-null constants, or it should be collapsed to "a >= b and a <= c"
   218  	lb, _ := p1.GetValue(0)
   219  	ub, _ := p2.GetValue(0)
   220  
   221  	if parameters[0].IsConst() {
   222  		v0, null0 := p0.GetValue(0)
   223  		if null0 {
   224  			nulls.AddRange(rsVec.GetNulls(), 0, uint64(length))
   225  		} else {
   226  			r := lessEqualFn(lb, v0) && lessEqualFn(v0, ub)
   227  			rowCount := uint64(length)
   228  			for i := uint64(0); i < rowCount; i++ {
   229  				rss[i] = r
   230  			}
   231  		}
   232  		return nil
   233  	}
   234  
   235  	// basic case.
   236  	if p0.WithAnyNullValue() {
   237  		nulls.Set(rsVec.GetNulls(), parameters[0].GetNulls())
   238  		rowCount := uint64(length)
   239  		for i := uint64(0); i < rowCount; i++ {
   240  			v0, null0 := p0.GetValue(i)
   241  			if null0 {
   242  				continue
   243  			}
   244  			rss[i] = lessEqualFn(lb, v0) && lessEqualFn(v0, ub)
   245  		}
   246  		return nil
   247  	}
   248  
   249  	rowCount := uint64(length)
   250  	for i := uint64(0); i < rowCount; i++ {
   251  		v0, _ := p0.GetValue(i)
   252  		rss[i] = lessEqualFn(lb, v0) && lessEqualFn(v0, ub)
   253  	}
   254  	return nil
   255  }
   256  
   257  func opBetweenBytes(
   258  	parameters []*vector.Vector,
   259  	result vector.FunctionResultWrapper,
   260  	_ *process.Process,
   261  	length int,
   262  ) error {
   263  	p0 := vector.GenerateFunctionStrParameter(parameters[0])
   264  	p1 := vector.GenerateFunctionStrParameter(parameters[1])
   265  	p2 := vector.GenerateFunctionStrParameter(parameters[2])
   266  	rs := vector.MustFunctionResult[bool](result)
   267  	rsVec := rs.GetResultVector()
   268  	rss := vector.MustFixedCol[bool](rsVec)
   269  
   270  	// The lower and upper bound of BETWEEN must be non-null constants, or it should be collapsed to "a >= b and a <= c"
   271  	lb, _ := p1.GetStrValue(0)
   272  	ub, _ := p2.GetStrValue(0)
   273  
   274  	if parameters[0].IsConst() {
   275  		v0, null0 := p0.GetStrValue(0)
   276  		if null0 {
   277  			nulls.AddRange(rsVec.GetNulls(), 0, uint64(length))
   278  		} else {
   279  			r := bytes.Compare(v0, lb) >= 0 && bytes.Compare(v0, ub) <= 0
   280  			rowCount := uint64(length)
   281  			for i := uint64(0); i < rowCount; i++ {
   282  				rss[i] = r
   283  			}
   284  		}
   285  		return nil
   286  	}
   287  
   288  	// basic case.
   289  	if p0.WithAnyNullValue() {
   290  		nulls.Set(rsVec.GetNulls(), parameters[0].GetNulls())
   291  		rowCount := uint64(length)
   292  		for i := uint64(0); i < rowCount; i++ {
   293  			v0, null0 := p0.GetStrValue(i)
   294  			if null0 {
   295  				continue
   296  			}
   297  			rss[i] = bytes.Compare(v0, lb) >= 0 && bytes.Compare(v0, ub) <= 0
   298  		}
   299  		return nil
   300  	}
   301  
   302  	rowCount := uint64(length)
   303  	for i := uint64(0); i < rowCount; i++ {
   304  		v0, _ := p0.GetStrValue(i)
   305  		rss[i] = bytes.Compare(v0, lb) >= 0 && bytes.Compare(v0, ub) <= 0
   306  	}
   307  	return nil
   308  }