github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/operator/like.go (about)

     1  // Copyright 2022 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 operator
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    20  	"github.com/matrixorigin/matrixone/pkg/container/types"
    21  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    22  	"github.com/matrixorigin/matrixone/pkg/vectorize/like"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    24  	"strings"
    25  )
    26  
    27  func Like(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    28  	lv, rv := vectors[0], vectors[1]
    29  	lvs, rvs := vector.MustStrCols(lv), vector.MustBytesCols(rv)
    30  	rtyp := types.T_bool.ToType()
    31  
    32  	if lv.IsScalarNull() || rv.IsScalarNull() {
    33  		return proc.AllocConstNullVector(rtyp, lv.Length()), nil
    34  	}
    35  
    36  	var err error
    37  	rs := make([]bool, lv.Length())
    38  
    39  	switch {
    40  	case !lv.IsScalar() && rv.IsScalar():
    41  		if nulls.Any(lv.Nsp) {
    42  			rs, err = like.BtSliceNullAndConst(lvs, rvs[0], lv.Nsp, rs)
    43  			if err != nil {
    44  				return nil, err
    45  			}
    46  		} else {
    47  			rs, err = like.BtSliceAndConst(lvs, rvs[0], rs)
    48  			if err != nil {
    49  				return nil, err
    50  			}
    51  		}
    52  		return vector.NewWithFixed(rtyp, rs, lv.Nsp, proc.Mp()), nil
    53  	case lv.IsScalar() && rv.IsScalar(): // in our design, this case should deal while pruning extends.
    54  		ok, err := like.BtConstAndConst(lvs[0], rvs[0])
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  		return vector.NewConstFixed(rtyp, lv.Length(), ok, proc.Mp()), nil
    59  	case lv.IsScalar() && !rv.IsScalar():
    60  		rs, err = like.BtConstAndSliceNull(lvs[0], rvs, rv.Nsp, rs)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		return vector.NewWithFixed(rtyp, rs, lv.Nsp, proc.Mp()), nil
    65  	case !lv.IsScalar() && !rv.IsScalar():
    66  		var nsp *nulls.Nulls
    67  		if nulls.Any(rv.Nsp) && nulls.Any(lv.Nsp) {
    68  			nulls.Or(lv.Nsp, rv.Nsp, nsp)
    69  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
    70  			if err != nil {
    71  				return nil, err
    72  			}
    73  		} else if nulls.Any(rv.Nsp) && !nulls.Any(lv.Nsp) {
    74  			nsp = rv.Nsp
    75  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
    76  			if err != nil {
    77  				return nil, err
    78  			}
    79  		} else if !nulls.Any(rv.Nsp) && nulls.Any(lv.Nsp) {
    80  			nsp = lv.Nsp
    81  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
    82  			if err != nil {
    83  				return nil, err
    84  			}
    85  		} else {
    86  			rs, err = like.BtSliceAndSlice(lvs, rvs, rs)
    87  			if err != nil {
    88  				return nil, err
    89  			}
    90  		}
    91  		return vector.NewWithFixed(rtyp, rs, nsp, proc.Mp()), nil
    92  	}
    93  	return nil, moerr.NewInternalError(proc.Ctx, "unexpected case for LIKE operator")
    94  }
    95  
    96  func ILike(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    97  	lv, rv := vectors[0], vectors[1]
    98  	lvs, rvs := vector.MustStrCols(lv), vector.MustBytesCols(rv)
    99  	for i := range lvs {
   100  		lvs[i] = strings.ToLower(lvs[i])
   101  	}
   102  	for i := range rvs {
   103  		rvs[i] = []byte(strings.ToLower(string(rvs[i])))
   104  	}
   105  	rtyp := types.T_bool.ToType()
   106  
   107  	if lv.IsScalarNull() || rv.IsScalarNull() {
   108  		return proc.AllocConstNullVector(rtyp, lv.Length()), nil
   109  	}
   110  
   111  	var err error
   112  	rs := make([]bool, lv.Length())
   113  
   114  	switch {
   115  	case !lv.IsScalar() && rv.IsScalar():
   116  		if nulls.Any(lv.Nsp) {
   117  			rs, err = like.BtSliceNullAndConst(lvs, rvs[0], lv.Nsp, rs)
   118  			if err != nil {
   119  				return nil, err
   120  			}
   121  		} else {
   122  			rs, err = like.BtSliceAndConst(lvs, rvs[0], rs)
   123  			if err != nil {
   124  				return nil, err
   125  			}
   126  		}
   127  		return vector.NewWithFixed(rtyp, rs, lv.Nsp, proc.Mp()), nil
   128  	case lv.IsScalar() && rv.IsScalar(): // in our design, this case should deal while pruning extends.
   129  		ok, err := like.BtConstAndConst(lvs[0], rvs[0])
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  		return vector.NewConstFixed(rtyp, lv.Length(), ok, proc.Mp()), nil
   134  	case lv.IsScalar() && !rv.IsScalar():
   135  		rs, err = like.BtConstAndSliceNull(lvs[0], rvs, rv.Nsp, rs)
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  		return vector.NewWithFixed(rtyp, rs, lv.Nsp, proc.Mp()), nil
   140  	case !lv.IsScalar() && !rv.IsScalar():
   141  		var nsp *nulls.Nulls
   142  		if nulls.Any(rv.Nsp) && nulls.Any(lv.Nsp) {
   143  			nulls.Or(lv.Nsp, rv.Nsp, nsp)
   144  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
   145  			if err != nil {
   146  				return nil, err
   147  			}
   148  		} else if nulls.Any(rv.Nsp) && !nulls.Any(lv.Nsp) {
   149  			nsp = rv.Nsp
   150  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
   151  			if err != nil {
   152  				return nil, err
   153  			}
   154  		} else if !nulls.Any(rv.Nsp) && nulls.Any(lv.Nsp) {
   155  			nsp = lv.Nsp
   156  			rs, err = like.BtSliceNullAndSliceNull(lvs, rvs, nsp, rs)
   157  			if err != nil {
   158  				return nil, err
   159  			}
   160  		} else {
   161  			rs, err = like.BtSliceAndSlice(lvs, rvs, rs)
   162  			if err != nil {
   163  				return nil, err
   164  			}
   165  		}
   166  		return vector.NewWithFixed(rtyp, rs, nsp, proc.Mp()), nil
   167  	}
   168  	return nil, moerr.NewInternalError(proc.Ctx, "unexpected case for LIKE operator")
   169  }