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 }