github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/mark/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 mark 16 17 import ( 18 "bytes" 19 "context" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/common/mpool" 23 "github.com/matrixorigin/matrixone/pkg/container/batch" 24 "github.com/matrixorigin/matrixone/pkg/container/nulls" 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/process" 31 "github.com/stretchr/testify/require" 32 ) 33 34 const ( 35 Rows = 10 // default rows 36 BenchmarkRows = 100000 // default rows for benchmark 37 ) 38 39 // add unit tests for cases 40 type markTestCase struct { 41 arg *Argument 42 flgs []bool // flgs[i] == true: nullable 43 types []types.Type 44 proc *process.Process 45 cancel context.CancelFunc 46 barg *hashbuild.Argument 47 } 48 49 var ( 50 tcs []markTestCase 51 ) 52 53 func init() { 54 tcs = []markTestCase{ 55 newTestCase([]bool{false}, []types.Type{{Oid: types.T_int8}}, []int32{0}, 56 [][]*plan.Expr{ 57 { 58 newExpr(0, types.Type{Oid: types.T_int8}), 59 }, 60 { 61 newExpr(0, types.Type{Oid: types.T_int8}), 62 }, 63 }), 64 newTestCase([]bool{true}, []types.Type{{Oid: types.T_int8}}, []int32{0}, 65 [][]*plan.Expr{ 66 { 67 newExpr(0, types.Type{Oid: types.T_int8}), 68 }, 69 { 70 newExpr(0, types.Type{Oid: types.T_int8}), 71 }, 72 }), 73 } 74 } 75 76 func TestString(t *testing.T) { 77 buf := new(bytes.Buffer) 78 for _, tc := range tcs { 79 String(tc.arg, buf) 80 } 81 } 82 83 func TestMark(t *testing.T) { 84 /* XXX There are some problems with the mark join code for handling null. Modify later 85 for _, tc := range tcs { 86 bat := hashBuild(t, tc) 87 err := Prepare(tc.proc, tc.arg) 88 require.NoError(t, err) 89 batWithNull := newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 90 batWithNull.Vecs[0].Nsp.Np.Add(0) 91 tc.proc.Reg.MergeReceivers[0].Ch <- batWithNull 92 tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{} 93 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 94 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 95 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 96 tc.proc.Reg.MergeReceivers[0].Ch <- nil 97 tc.proc.Reg.MergeReceivers[1].Ch <- bat 98 for { 99 if ok, err := Call(0, tc.proc, tc.arg); ok || err != nil { 100 break 101 } 102 tc.proc.Reg.InputBatch.Clean(tc.proc.Mp()) 103 } 104 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 105 } 106 */ 107 for _, tc := range tcs { 108 err := Prepare(tc.proc, tc.arg) 109 require.NoError(t, err) 110 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 111 tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{} 112 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 113 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 114 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 115 tc.proc.Reg.MergeReceivers[0].Ch <- nil 116 tc.proc.Reg.MergeReceivers[1].Ch <- nil 117 for { 118 if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil { 119 break 120 } 121 tc.proc.Reg.InputBatch.Clean(tc.proc.Mp()) 122 } 123 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 124 } 125 } 126 127 func TestHandleResultType(t *testing.T) { 128 ctr := new(container) 129 ctr.markVals = make([]bool, 3) 130 ctr.markNulls = nulls.NewWithSize(3) 131 ctr.handleResultType(0, condTrue) 132 ctr.handleResultType(1, condFalse) 133 ctr.handleResultType(2, condUnkown) 134 } 135 136 func BenchmarkMark(b *testing.B) { 137 for i := 0; i < b.N; i++ { 138 tcs = []markTestCase{ 139 newTestCase([]bool{false}, []types.Type{{Oid: types.T_int8}}, []int32{0}, 140 [][]*plan.Expr{ 141 { 142 newExpr(0, types.Type{Oid: types.T_int8}), 143 }, 144 { 145 newExpr(0, types.Type{Oid: types.T_int8}), 146 }, 147 }), 148 newTestCase([]bool{true}, []types.Type{{Oid: types.T_int8}}, []int32{0}, 149 [][]*plan.Expr{ 150 { 151 newExpr(0, types.Type{Oid: types.T_int8}), 152 }, 153 { 154 newExpr(0, types.Type{Oid: types.T_int8}), 155 }, 156 }), 157 } 158 t := new(testing.T) 159 for _, tc := range tcs { 160 bat := hashBuild(t, tc) 161 err := Prepare(tc.proc, tc.arg) 162 require.NoError(t, err) 163 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 164 tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{} 165 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 166 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 167 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 168 tc.proc.Reg.MergeReceivers[0].Ch <- nil 169 tc.proc.Reg.MergeReceivers[1].Ch <- bat 170 for { 171 if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil { 172 break 173 } 174 tc.proc.Reg.InputBatch.Clean(tc.proc.Mp()) 175 } 176 } 177 } 178 } 179 180 func newExpr(pos int32, typ types.Type) *plan.Expr { 181 return &plan.Expr{ 182 Typ: &plan.Type{ 183 Size: typ.Size, 184 Scale: typ.Scale, 185 Width: typ.Width, 186 Id: int32(typ.Oid), 187 }, 188 Expr: &plan.Expr_Col{ 189 Col: &plan.ColRef{ 190 ColPos: pos, 191 }, 192 }, 193 } 194 } 195 196 func newTestCase(flgs []bool, ts []types.Type, rp []int32, cs [][]*plan.Expr) markTestCase { 197 proc := testutil.NewProcessWithMPool(mpool.MustNewZero()) 198 proc.Reg.MergeReceivers = make([]*process.WaitRegister, 2) 199 ctx, cancel := context.WithCancel(context.Background()) 200 proc.Reg.MergeReceivers[0] = &process.WaitRegister{ 201 Ctx: ctx, 202 Ch: make(chan *batch.Batch, 10), 203 } 204 proc.Reg.MergeReceivers[1] = &process.WaitRegister{ 205 Ctx: ctx, 206 Ch: make(chan *batch.Batch, 3), 207 } 208 fid := function.EncodeOverloadID(function.EQUAL, 4) 209 args := make([]*plan.Expr, 0, 2) 210 args = append(args, &plan.Expr{ 211 Typ: &plan.Type{ 212 Size: ts[0].Size, 213 Id: int32(ts[0].Oid), 214 }, 215 Expr: &plan.Expr_Col{ 216 Col: &plan.ColRef{ 217 RelPos: 0, 218 ColPos: 0, 219 }, 220 }, 221 }) 222 args = append(args, &plan.Expr{ 223 Typ: &plan.Type{ 224 Size: ts[0].Size, 225 Id: int32(ts[0].Oid), 226 }, 227 Expr: &plan.Expr_Col{ 228 Col: &plan.ColRef{ 229 RelPos: 1, 230 ColPos: 0, 231 }, 232 }, 233 }) 234 cond := &plan.Expr{ 235 Typ: &plan.Type{ 236 Size: 1, 237 Id: int32(types.T_bool), 238 }, 239 Expr: &plan.Expr_F{ 240 F: &plan.Function{ 241 Args: args, 242 Func: &plan.ObjectRef{Obj: fid, ObjName: "="}, 243 }, 244 }, 245 } 246 247 c := markTestCase{ 248 types: ts, 249 flgs: flgs, 250 proc: proc, 251 cancel: cancel, 252 arg: &Argument{ 253 Typs: ts, 254 Result: rp, 255 Conditions: cs, 256 Cond: cond, 257 OnList: []*plan.Expr{cond}, 258 }, 259 barg: &hashbuild.Argument{ 260 Typs: ts, 261 NeedHashMap: true, 262 Conditions: cs[1], 263 }, 264 } 265 return c 266 } 267 268 func hashBuild(t *testing.T, tc markTestCase) *batch.Batch { 269 err := hashbuild.Prepare(tc.proc, tc.barg) 270 require.NoError(t, err) 271 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 272 tc.proc.Reg.MergeReceivers[0].Ch <- nil 273 ok, err := hashbuild.Call(0, tc.proc, tc.barg, false, false) 274 require.NoError(t, err) 275 require.Equal(t, true, ok) 276 return tc.proc.Reg.InputBatch 277 } 278 279 // create a new block based on the type information, flgs[i] == ture: has null 280 func newBatch(t *testing.T, flgs []bool, ts []types.Type, proc *process.Process, rows int64) *batch.Batch { 281 return testutil.NewBatch(ts, true, int(rows), proc.Mp()) 282 }