github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/like_ops_test.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package colexec
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"regexp"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/col/coldata"
    20  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/colexecbase"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/cockroachdb/cockroach/pkg/util/randutil"
    26  )
    27  
    28  func TestLikeOperators(t *testing.T) {
    29  	defer leaktest.AfterTest(t)()
    30  	for _, tc := range []struct {
    31  		pattern  string
    32  		negate   bool
    33  		tups     tuples
    34  		expected tuples
    35  	}{
    36  		{
    37  			pattern:  "def",
    38  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    39  			expected: tuples{{"def"}},
    40  		},
    41  		{
    42  			pattern:  "def",
    43  			negate:   true,
    44  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    45  			expected: tuples{{"abc"}, {"ghi"}},
    46  		},
    47  		{
    48  			pattern:  "de%",
    49  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    50  			expected: tuples{{"def"}},
    51  		},
    52  		{
    53  			pattern:  "de%",
    54  			negate:   true,
    55  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    56  			expected: tuples{{"abc"}, {"ghi"}},
    57  		},
    58  		{
    59  			pattern:  "%ef",
    60  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    61  			expected: tuples{{"def"}},
    62  		},
    63  		{
    64  			pattern:  "%ef",
    65  			negate:   true,
    66  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    67  			expected: tuples{{"abc"}, {"ghi"}},
    68  		},
    69  		{
    70  			pattern:  "_e_",
    71  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    72  			expected: tuples{{"def"}},
    73  		},
    74  		{
    75  			pattern:  "_e_",
    76  			negate:   true,
    77  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    78  			expected: tuples{{"abc"}, {"ghi"}},
    79  		},
    80  		{
    81  			pattern:  "%e%",
    82  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    83  			expected: tuples{{"def"}},
    84  		},
    85  		{
    86  			pattern:  "%e%",
    87  			negate:   true,
    88  			tups:     tuples{{"abc"}, {"def"}, {"ghi"}},
    89  			expected: tuples{{"abc"}, {"ghi"}},
    90  		},
    91  	} {
    92  		runTests(
    93  			t, []tuples{tc.tups}, tc.expected, orderedVerifier,
    94  			func(input []colexecbase.Operator) (colexecbase.Operator, error) {
    95  				ctx := tree.MakeTestingEvalContext(cluster.MakeTestingClusterSettings())
    96  				return GetLikeOperator(&ctx, input[0], 0, tc.pattern, tc.negate)
    97  			})
    98  	}
    99  }
   100  
   101  func BenchmarkLikeOps(b *testing.B) {
   102  	rng, _ := randutil.NewPseudoRand()
   103  	ctx := context.Background()
   104  
   105  	typs := []*types.T{types.Bytes}
   106  	batch := testAllocator.NewMemBatch(typs)
   107  	col := batch.ColVec(0).Bytes()
   108  	width := 64
   109  	for i := 0; i < coldata.BatchSize(); i++ {
   110  		col.Set(i, randutil.RandBytes(rng, width))
   111  	}
   112  
   113  	// Set a known prefix and suffix on half the batch so we're not filtering
   114  	// everything out.
   115  	prefix := "abc"
   116  	suffix := "xyz"
   117  	for i := 0; i < coldata.BatchSize()/2; i++ {
   118  		copy(col.Get(i)[:3], prefix)
   119  		copy(col.Get(i)[width-3:], suffix)
   120  	}
   121  
   122  	batch.SetLength(coldata.BatchSize())
   123  	source := colexecbase.NewRepeatableBatchSource(testAllocator, batch, typs)
   124  	source.Init()
   125  
   126  	base := selConstOpBase{
   127  		OneInputNode: NewOneInputNode(source),
   128  		colIdx:       0,
   129  	}
   130  	prefixOp := &selPrefixBytesBytesConstOp{
   131  		selConstOpBase: base,
   132  		constArg:       []byte(prefix),
   133  	}
   134  	suffixOp := &selSuffixBytesBytesConstOp{
   135  		selConstOpBase: base,
   136  		constArg:       []byte(suffix),
   137  	}
   138  	pattern := fmt.Sprintf("^%s.*%s$", prefix, suffix)
   139  	regexpOp := &selRegexpBytesBytesConstOp{
   140  		selConstOpBase: base,
   141  		constArg:       regexp.MustCompile(pattern),
   142  	}
   143  
   144  	testCases := []struct {
   145  		name string
   146  		op   colexecbase.Operator
   147  	}{
   148  		{name: "selPrefixBytesBytesConstOp", op: prefixOp},
   149  		{name: "selSuffixBytesBytesConstOp", op: suffixOp},
   150  		{name: "selRegexpBytesBytesConstOp", op: regexpOp},
   151  	}
   152  	for _, tc := range testCases {
   153  		b.Run(tc.name, func(b *testing.B) {
   154  			tc.op.Init()
   155  			b.SetBytes(int64(width * coldata.BatchSize()))
   156  			for i := 0; i < b.N; i++ {
   157  				tc.op.Next(ctx)
   158  			}
   159  		})
   160  	}
   161  }