github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/regexp_like_test.go (about) 1 // Copyright 2021 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 function 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/stretchr/testify/require" 22 23 "github.com/dolthub/go-mysql-server/sql" 24 "github.com/dolthub/go-mysql-server/sql/expression" 25 "github.com/dolthub/go-mysql-server/sql/types" 26 ) 27 28 // Tests taken from https://dev.mysql.com/doc/refman/8.0/en/regexp.html#regexp-syntax 29 func TestRegexpLikeWithoutFlags(t *testing.T) { 30 testCases := []struct { 31 text string 32 pattern string 33 expected int8 34 }{ 35 { 36 "fo\nfo", 37 "^fo$", 38 0, 39 }, 40 { 41 "fofo", 42 "^fo", 43 1, 44 }, 45 { 46 "fo\no", 47 "^fo", 48 1, 49 }, 50 { 51 "fo\no", 52 "^fo\no$", 53 1, 54 }, 55 { 56 "fo\no", 57 "^fo$", 58 0, 59 }, 60 { 61 "fofo", 62 "^f.*$", 63 1, 64 }, 65 { 66 "fo\r\nfo", 67 "^f.*$", 68 0, 69 }, 70 { 71 "fo\r\nfo", 72 "(?m)^f.*$", 73 1, 74 }, 75 { 76 "Ban", 77 "^Ba*n", 78 1, 79 }, 80 { 81 "Baaan", 82 "^Ba*n", 83 1, 84 }, 85 { 86 "Bn", 87 "^Ba*n", 88 1, 89 }, 90 { 91 "Ban", 92 "^Ba+n", 93 1, 94 }, 95 { 96 "Bn", 97 "^Ba+n", 98 0, 99 }, 100 { 101 "Bn", 102 "^Ba?n", 103 1, 104 }, 105 { 106 "Ban", 107 "^Ba?n", 108 1, 109 }, 110 { 111 "Baan", 112 "^Ba?n", 113 0, 114 }, 115 { 116 "pi", 117 "pi|apa", 118 1, 119 }, 120 { 121 "axe", 122 "pi|apa", 123 0, 124 }, 125 { 126 "apa", 127 "pi|apa", 128 1, 129 }, 130 { 131 "apa", 132 "^(pi|apa)$", 133 1, 134 }, 135 { 136 "pi", 137 "^(pi|apa)$", 138 1, 139 }, 140 { 141 "pix", 142 "^(pi|apa)$", 143 0, 144 }, 145 { 146 "pi", 147 "^(pi)*$", 148 1, 149 }, 150 { 151 "pip", 152 "^(pi)*$", 153 0, 154 }, 155 { 156 "pipi", 157 "^(pi)*$", 158 1, 159 }, 160 { 161 "abcde", 162 "a[bcd]{2}e", 163 0, 164 }, 165 { 166 "abcde", 167 "a[bcd]{3}e", 168 1, 169 }, 170 { 171 "abcde", 172 "a[bcd]{1,10}e", 173 1, 174 }, 175 { 176 "aXbc", 177 "[a-dXYZ]", 178 1, 179 }, 180 { 181 "aXbc", 182 "^[a-dXYZ]$", 183 0, 184 }, 185 { 186 "aXbc", 187 "^[a-dXYZ]+$", 188 1, 189 }, 190 { 191 "aXbc", 192 "^[^a-dXYZ]+$", 193 0, 194 }, 195 { 196 "gheis", 197 "^[^a-dXYZ]+$", 198 1, 199 }, 200 { 201 "gheisa", 202 "^[^a-dXYZ]+$", 203 0, 204 }, 205 { 206 "justalnums", 207 "[[:alnum:]]+", 208 1, 209 }, 210 { 211 "!!", 212 "[[:alnum:]]+", 213 0, 214 }, 215 } 216 217 for _, test := range testCases { 218 t.Run(fmt.Sprintf("%s|%s", test.text, test.pattern), func(t *testing.T) { 219 ctx := sql.NewEmptyContext() 220 f, err := NewRegexpLike( 221 expression.NewLiteral(test.text, types.LongText), 222 expression.NewLiteral(test.pattern, types.LongText), 223 ) 224 require.NoError(t, err) 225 defer f.(*RegexpLike).Close(ctx) 226 res, err := f.Eval(ctx, nil) 227 require.Equal(t, test.expected, res) 228 }) 229 } 230 } 231 232 func TestRegexpLikeWithFlags(t *testing.T) { 233 testCases := []struct { 234 text string 235 pattern string 236 flags string 237 expected int8 238 }{ 239 { 240 "fo\r\nfo", 241 "^f.*$", 242 "m", 243 1, 244 }, 245 { 246 "fofo", 247 "FOFO", 248 "i", 249 1, 250 }, 251 { 252 "fofo", 253 "FOFo", 254 "c", 255 0, 256 }, 257 { 258 "fofo", 259 "FOfO", 260 "ci", 261 1, 262 }, 263 { 264 "fofo", 265 "FoFO", 266 "ic", 267 0, 268 }, 269 } 270 271 for _, test := range testCases { 272 t.Run(fmt.Sprintf("%v|%v", test.text, test.pattern), func(t *testing.T) { 273 ctx := sql.NewEmptyContext() 274 f, err := NewRegexpLike( 275 expression.NewLiteral(test.text, types.LongText), 276 expression.NewLiteral(test.pattern, types.LongText), 277 expression.NewLiteral(test.flags, types.LongText), 278 ) 279 require.NoError(t, err) 280 defer f.(*RegexpLike).Close(ctx) 281 res, err := f.Eval(ctx, nil) 282 require.Equal(t, test.expected, res) 283 }) 284 } 285 } 286 287 func TestRegexpLikeNilAndErrors(t *testing.T) { 288 ctx := sql.NewEmptyContext() 289 290 f, err := NewRegexpLike( 291 expression.NewLiteral("", types.LongText), 292 ) 293 require.True(t, sql.ErrInvalidArgumentNumber.Is(err)) 294 295 f, err = NewRegexpLike( 296 expression.NewLiteral("", types.LongText), 297 expression.NewLiteral("", types.LongText), 298 expression.NewLiteral("", types.LongText), 299 expression.NewLiteral("", types.LongText), 300 ) 301 require.True(t, sql.ErrInvalidArgumentNumber.Is(err)) 302 303 f, err = NewRegexpLike( 304 expression.NewLiteral("foo", types.LongText), 305 expression.NewLiteral("foo", types.LongText), 306 expression.NewLiteral("z", types.LongText), 307 ) 308 require.NoError(t, err) 309 _, err = f.Eval(ctx, nil) 310 require.True(t, sql.ErrInvalidArgument.Is(err)) 311 require.NoError(t, f.(*RegexpLike).Close(ctx)) 312 313 f, err = NewRegexpLike( 314 expression.NewLiteral(nil, types.Null), 315 expression.NewLiteral("foo", types.LongText), 316 expression.NewLiteral("i", types.LongText), 317 ) 318 require.NoError(t, err) 319 res, err := f.Eval(ctx, nil) 320 require.NoError(t, err) 321 require.Equal(t, nil, res) 322 require.NoError(t, f.(*RegexpLike).Close(ctx)) 323 324 f, err = NewRegexpLike( 325 expression.NewLiteral("foo", types.LongText), 326 expression.NewLiteral(nil, types.Null), 327 expression.NewLiteral("i", types.LongText), 328 ) 329 require.NoError(t, err) 330 res, err = f.Eval(ctx, nil) 331 require.NoError(t, err) 332 require.Equal(t, nil, res) 333 require.NoError(t, f.(*RegexpLike).Close(ctx)) 334 335 f, err = NewRegexpLike( 336 expression.NewLiteral("foo", types.LongText), 337 expression.NewLiteral("foo", types.LongText), 338 expression.NewLiteral(nil, types.Null), 339 ) 340 require.NoError(t, err) 341 res, err = f.Eval(ctx, nil) 342 require.NoError(t, err) 343 require.Equal(t, nil, res) 344 require.NoError(t, f.(*RegexpLike).Close(ctx)) 345 346 f, err = NewRegexpLike( 347 expression.NewLiteral(nil, types.Null), 348 expression.NewLiteral("foo", types.LongText), 349 ) 350 require.NoError(t, err) 351 res, err = f.Eval(ctx, nil) 352 require.NoError(t, err) 353 require.Equal(t, nil, res) 354 require.NoError(t, f.(*RegexpLike).Close(ctx)) 355 356 f, err = NewRegexpLike( 357 expression.NewLiteral("foo", types.LongText), 358 expression.NewLiteral(nil, types.Null), 359 ) 360 require.NoError(t, err) 361 res, err = f.Eval(ctx, nil) 362 require.NoError(t, err) 363 require.Equal(t, nil, res) 364 require.NoError(t, f.(*RegexpLike).Close(ctx)) 365 }