github.com/matrixorigin/matrixone@v0.7.0/pkg/vectorize/regular/regular_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 regular
    16  
    17  import (
    18  	"fmt"
    19  	"regexp"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    22  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    23  )
    24  
    25  // Support four arguments:
    26  // i: case insensitive.
    27  // c: case sensitive.
    28  // m: multiple line mode.
    29  // n: '.' can match line terminator.
    30  func getPureMatchType(input string) (string, error) {
    31  	retstring := ""
    32  	caseType := ""
    33  	foundn := false
    34  	foundm := false
    35  
    36  	for _, c := range input {
    37  		switch string(c) {
    38  		case "i":
    39  			caseType = "i"
    40  		case "c":
    41  			caseType = ""
    42  		case "m":
    43  			if !foundm {
    44  				retstring += "m"
    45  				foundm = true
    46  			}
    47  		case "n":
    48  			if !foundn {
    49  				retstring += "s"
    50  				foundn = true
    51  			}
    52  		default:
    53  			return "", moerr.NewInvalidInputNoCtx("regexp_like got invalid match_type input!")
    54  		}
    55  	}
    56  
    57  	retstring += caseType
    58  
    59  	return retstring, nil
    60  }
    61  
    62  func compileWithMatchType(pat, match_type string) (*regexp.Regexp, error) {
    63  	if len(pat) == 0 {
    64  		return nil, moerr.NewInvalidInputNoCtx("regexp_like got invalid input!")
    65  	}
    66  	match_type, err := getPureMatchType(match_type)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	re, err := regexp.Compile(fmt.Sprintf("(?%s)%s", match_type, pat))
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	return re, nil
    75  }
    76  
    77  func RegularLike(expr, pat, match_type string) (bool, error) {
    78  	re, err := compileWithMatchType(pat, match_type)
    79  	if err != nil {
    80  		return false, err
    81  	}
    82  	matchRes := re.MatchString(expr)
    83  	return matchRes, nil
    84  }
    85  
    86  func RegularLikeWithArrays(expr, pat []string, match_type []string, exprN, patN, matchN, rns *nulls.Nulls, rs []bool, maxLen int) error {
    87  	matchIndex := 0
    88  	if len(expr) == 1 && len(pat) == 1 {
    89  		for i := 0; i < maxLen; i++ {
    90  			if nulls.Contains(exprN, uint64(0)) || nulls.Contains(patN, uint64(0)) || nulls.Contains(matchN, uint64(0)) {
    91  				nulls.Add(rns, uint64(i))
    92  				continue
    93  			}
    94  			res, err := RegularLike(expr[0], pat[0], match_type[i])
    95  			if err != nil {
    96  				return err
    97  			}
    98  			rs[i] = res
    99  		}
   100  	} else if len(expr) == 1 {
   101  		for i := 0; i < maxLen; i++ {
   102  			if nulls.Contains(exprN, uint64(0)) || nulls.Contains(patN, uint64(i)) || nulls.Contains(matchN, uint64(0)) {
   103  				nulls.Add(rns, uint64(i))
   104  				continue
   105  			}
   106  			if len(match_type) != 1 {
   107  				matchIndex = i
   108  			}
   109  			res, err := RegularLike(expr[0], pat[i], match_type[matchIndex])
   110  			if err != nil {
   111  				return err
   112  			}
   113  			rs[i] = res
   114  		}
   115  	} else if len(pat) == 1 {
   116  		for i := 0; i < maxLen; i++ {
   117  			if nulls.Contains(exprN, uint64(i)) || nulls.Contains(patN, uint64(0)) || nulls.Contains(matchN, uint64(0)) {
   118  				nulls.Add(rns, uint64(i))
   119  				continue
   120  			}
   121  			if len(match_type) != 1 {
   122  				matchIndex = i
   123  			}
   124  			res, err := RegularLike(expr[i], pat[0], match_type[matchIndex])
   125  			if err != nil {
   126  				return err
   127  			}
   128  			rs[i] = res
   129  		}
   130  	} else {
   131  		for i := 0; i < maxLen; i++ {
   132  			if nulls.Contains(exprN, uint64(i)) || nulls.Contains(patN, uint64(i)) || nulls.Contains(matchN, uint64(0)) {
   133  				nulls.Add(rns, uint64(i))
   134  				continue
   135  			}
   136  			if len(match_type) != 1 {
   137  				matchIndex = i
   138  			}
   139  			res, err := RegularLike(expr[i], pat[i], match_type[matchIndex])
   140  			if err != nil {
   141  				return err
   142  			}
   143  			rs[i] = res
   144  		}
   145  	}
   146  	return nil
   147  }