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 }