github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/rightanti/join_test.go (about) 1 // Copyright 2021 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 rightanti 16 17 import ( 18 "bytes" 19 "context" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/common/hashmap" 23 "github.com/matrixorigin/matrixone/pkg/common/mpool" 24 "github.com/matrixorigin/matrixone/pkg/container/batch" 25 "github.com/matrixorigin/matrixone/pkg/container/types" 26 "github.com/matrixorigin/matrixone/pkg/pb/plan" 27 "github.com/matrixorigin/matrixone/pkg/sql/colexec/hashbuild" 28 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 29 "github.com/matrixorigin/matrixone/pkg/testutil" 30 "github.com/matrixorigin/matrixone/pkg/vm" 31 "github.com/matrixorigin/matrixone/pkg/vm/process" 32 "github.com/stretchr/testify/require" 33 ) 34 35 const ( 36 Rows = 10 // default rows 37 BenchmarkRows = 100000 // default rows for benchmark 38 ) 39 40 // add unit tests for cases 41 type joinTestCase struct { 42 arg *Argument 43 flgs []bool // flgs[i] == true: nullable 44 types []types.Type 45 proc *process.Process 46 cancel context.CancelFunc 47 barg *hashbuild.Argument 48 } 49 50 var ( 51 tcs []joinTestCase 52 ) 53 54 func init() { 55 tcs = []joinTestCase{ 56 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, []int32{0}, 57 [][]*plan.Expr{ 58 { 59 newExpr(0, types.T_int8.ToType()), 60 }, 61 { 62 newExpr(0, types.T_int8.ToType()), 63 }, 64 }), 65 newTestCase([]bool{true}, []types.Type{types.T_int8.ToType()}, []int32{0}, 66 [][]*plan.Expr{ 67 { 68 newExpr(0, types.T_int8.ToType()), 69 }, 70 { 71 newExpr(0, types.T_int8.ToType()), 72 }, 73 }), 74 } 75 } 76 77 func TestString(t *testing.T) { 78 buf := new(bytes.Buffer) 79 for _, tc := range tcs { 80 tc.arg.String(buf) 81 } 82 } 83 84 func TestJoin(t *testing.T) { 85 for _, tc := range tcs { 86 nb0 := tc.proc.Mp().CurrNB() 87 bats := hashBuild(t, tc) 88 if jm, ok := bats[0].AuxData.(*hashmap.JoinMap); ok { 89 jm.SetDupCount(int64(1)) 90 } 91 err := tc.arg.Prepare(tc.proc) 92 require.NoError(t, err) 93 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 94 tc.proc.Reg.MergeReceivers[0].Ch <- batch.EmptyBatch 95 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 96 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 97 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 98 tc.proc.Reg.MergeReceivers[0].Ch <- nil 99 tc.proc.Reg.MergeReceivers[1].Ch <- bats[0] 100 tc.proc.Reg.MergeReceivers[1].Ch <- bats[1] 101 tc.proc.Reg.MergeReceivers[0].Ch <- nil 102 tc.proc.Reg.MergeReceivers[1].Ch <- nil 103 for { 104 ok, err := tc.arg.Call(tc.proc) 105 if ok.Status == vm.ExecStop || err != nil { 106 break 107 } 108 } 109 tc.proc.FreeVectors() 110 tc.arg.Free(tc.proc, false, nil) 111 tc.proc.FreeVectors() 112 nb1 := tc.proc.Mp().CurrNB() 113 require.Equal(t, nb0, nb1) 114 } 115 116 for _, tc := range tcs { 117 nb0 := tc.proc.Mp().CurrNB() 118 err := tc.arg.Prepare(tc.proc) 119 require.NoError(t, err) 120 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 121 tc.proc.Reg.MergeReceivers[0].Ch <- batch.EmptyBatch 122 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 123 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 124 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 125 tc.proc.Reg.MergeReceivers[0].Ch <- nil 126 tc.proc.Reg.MergeReceivers[1].Ch <- nil 127 tc.proc.Reg.MergeReceivers[0].Ch <- nil 128 tc.proc.Reg.MergeReceivers[1].Ch <- nil 129 for { 130 ok, err := tc.arg.Call(tc.proc) 131 if ok.Status == vm.ExecStop || err != nil { 132 break 133 } 134 } 135 tc.proc.FreeVectors() 136 tc.arg.Free(tc.proc, false, nil) 137 nb1 := tc.proc.Mp().CurrNB() 138 require.Equal(t, nb0, nb1) 139 } 140 } 141 142 func BenchmarkJoin(b *testing.B) { 143 for i := 0; i < b.N; i++ { 144 tcs = []joinTestCase{ 145 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, []int32{0}, 146 [][]*plan.Expr{ 147 { 148 newExpr(0, types.T_int8.ToType()), 149 }, 150 { 151 newExpr(0, types.T_int8.ToType()), 152 }, 153 }), 154 newTestCase([]bool{true}, []types.Type{types.T_int8.ToType()}, []int32{0}, 155 [][]*plan.Expr{ 156 { 157 newExpr(0, types.T_int8.ToType()), 158 }, 159 { 160 newExpr(0, types.T_int8.ToType()), 161 }, 162 }), 163 } 164 t := new(testing.T) 165 for _, tc := range tcs { 166 bats := hashBuild(t, tc) 167 err := tc.arg.Prepare(tc.proc) 168 require.NoError(t, err) 169 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 170 tc.proc.Reg.MergeReceivers[0].Ch <- batch.EmptyBatch 171 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 172 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 173 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 174 tc.proc.Reg.MergeReceivers[0].Ch <- nil 175 tc.proc.Reg.MergeReceivers[1].Ch <- bats[0] 176 tc.proc.Reg.MergeReceivers[1].Ch <- bats[1] 177 for { 178 ok, err := tc.arg.Call(tc.proc) 179 if ok.Status == vm.ExecStop || err != nil { 180 break 181 } 182 } 183 } 184 } 185 } 186 187 func newExpr(pos int32, typ types.Type) *plan.Expr { 188 return &plan.Expr{ 189 Typ: plan.Type{ 190 Scale: typ.Scale, 191 Width: typ.Width, 192 Id: int32(typ.Oid), 193 }, 194 Expr: &plan.Expr_Col{ 195 Col: &plan.ColRef{ 196 ColPos: pos, 197 }, 198 }, 199 } 200 } 201 202 func newTestCase(flgs []bool, ts []types.Type, rp []int32, cs [][]*plan.Expr) joinTestCase { 203 proc := testutil.NewProcessWithMPool(mpool.MustNewZero()) 204 proc.Reg.MergeReceivers = make([]*process.WaitRegister, 2) 205 ctx, cancel := context.WithCancel(context.Background()) 206 proc.Reg.MergeReceivers[0] = &process.WaitRegister{ 207 Ctx: ctx, 208 Ch: make(chan *batch.Batch, 10), 209 } 210 proc.Reg.MergeReceivers[1] = &process.WaitRegister{ 211 Ctx: ctx, 212 Ch: make(chan *batch.Batch, 3), 213 } 214 fr, _ := function.GetFunctionByName(ctx, "=", ts) 215 fid := fr.GetEncodedOverloadID() 216 args := make([]*plan.Expr, 0, 2) 217 args = append(args, &plan.Expr{ 218 Typ: plan.Type{ 219 Id: int32(ts[0].Oid), 220 }, 221 Expr: &plan.Expr_Col{ 222 Col: &plan.ColRef{ 223 RelPos: 0, 224 ColPos: 0, 225 }, 226 }, 227 }) 228 args = append(args, &plan.Expr{ 229 Typ: plan.Type{ 230 Id: int32(ts[0].Oid), 231 }, 232 Expr: &plan.Expr_Col{ 233 Col: &plan.ColRef{ 234 RelPos: 1, 235 ColPos: 0, 236 }, 237 }, 238 }) 239 cond := &plan.Expr{ 240 Typ: plan.Type{ 241 Id: int32(types.T_bool), 242 }, 243 Expr: &plan.Expr_F{ 244 F: &plan.Function{ 245 Args: args, 246 Func: &plan.ObjectRef{Obj: fid, ObjName: "="}, 247 }, 248 }, 249 } 250 return joinTestCase{ 251 types: ts, 252 flgs: flgs, 253 proc: proc, 254 cancel: cancel, 255 arg: &Argument{ 256 RightTypes: ts, 257 Result: rp, 258 Conditions: cs, 259 NumCPU: 1, 260 IsMerger: true, 261 Cond: cond, 262 OperatorBase: vm.OperatorBase{ 263 OperatorInfo: vm.OperatorInfo{ 264 Idx: 0, 265 IsFirst: false, 266 IsLast: false, 267 }, 268 }, 269 }, 270 barg: &hashbuild.Argument{ 271 Typs: ts, 272 NeedHashMap: true, 273 Conditions: cs[1], 274 OperatorBase: vm.OperatorBase{ 275 OperatorInfo: vm.OperatorInfo{ 276 Idx: 0, 277 IsFirst: false, 278 IsLast: false, 279 }, 280 }, 281 NeedAllocateSels: true, 282 }, 283 } 284 } 285 286 func hashBuild(t *testing.T, tc joinTestCase) []*batch.Batch { 287 err := tc.barg.Prepare(tc.proc) 288 require.NoError(t, err) 289 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 290 for _, r := range tc.proc.Reg.MergeReceivers { 291 r.Ch <- nil 292 } 293 ok1, err := tc.barg.Call(tc.proc) 294 require.NoError(t, err) 295 require.Equal(t, false, ok1.Status == vm.ExecStop) 296 ok2, err := tc.barg.Call(tc.proc) 297 require.NoError(t, err) 298 require.Equal(t, false, ok2.Status == vm.ExecStop) 299 return []*batch.Batch{ok1.Batch, ok2.Batch} 300 } 301 302 // create a new block based on the type information, flgs[i] == ture: has null 303 func newBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch { 304 return testutil.NewBatch(ts, false, int(rows), proc.Mp()) 305 }