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  }