github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/loopleft/join.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 loopleft 16 17 import ( 18 "bytes" 19 20 "github.com/matrixorigin/matrixone/pkg/container/batch" 21 "github.com/matrixorigin/matrixone/pkg/container/vector" 22 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 23 "github.com/matrixorigin/matrixone/pkg/vm" 24 "github.com/matrixorigin/matrixone/pkg/vm/process" 25 ) 26 27 const argName = "loop_left" 28 29 func (arg *Argument) String(buf *bytes.Buffer) { 30 buf.WriteString(argName) 31 buf.WriteString(": loop left join ") 32 } 33 34 func (arg *Argument) Prepare(proc *process.Process) error { 35 var err error 36 37 arg.ctr = new(container) 38 arg.ctr.InitReceiver(proc, false) 39 arg.ctr.bat = batch.NewWithSize(len(arg.Typs)) 40 for i, typ := range arg.Typs { 41 arg.ctr.bat.Vecs[i] = proc.GetVector(typ) 42 } 43 44 if arg.Cond != nil { 45 arg.ctr.expr, err = colexec.NewExpressionExecutor(proc, arg.Cond) 46 } 47 return err 48 } 49 50 func (arg *Argument) Call(proc *process.Process) (vm.CallResult, error) { 51 if err, isCancel := vm.CancelCheck(proc); isCancel { 52 return vm.CancelResult, err 53 } 54 55 anal := proc.GetAnalyze(arg.GetIdx(), arg.GetParallelIdx(), arg.GetParallelMajor()) 56 anal.Start() 57 defer anal.Stop() 58 ctr := arg.ctr 59 result := vm.NewCallResult() 60 var err error 61 for { 62 switch ctr.state { 63 case Build: 64 if err = ctr.build(proc, anal); err != nil { 65 return result, err 66 } 67 ctr.state = Probe 68 69 case Probe: 70 if ctr.inBat != nil { 71 err = ctr.probe(arg, proc, anal, arg.GetIsLast(), &result) 72 return result, err 73 } 74 ctr.inBat, _, err = ctr.ReceiveFromSingleReg(0, anal) 75 if err != nil { 76 return result, err 77 } 78 79 if ctr.inBat == nil { 80 ctr.state = End 81 continue 82 } 83 if ctr.inBat.IsEmpty() { 84 proc.PutBatch(ctr.inBat) 85 ctr.inBat = nil 86 continue 87 } 88 anal.Input(ctr.inBat, arg.GetIsFirst()) 89 if ctr.bat.RowCount() == 0 { 90 err = ctr.emptyProbe(arg, proc, anal, arg.GetIsLast(), &result) 91 } else { 92 err = ctr.probe(arg, proc, anal, arg.GetIsLast(), &result) 93 } 94 return result, err 95 96 default: 97 result.Batch = nil 98 result.Status = vm.ExecStop 99 return result, nil 100 } 101 } 102 } 103 104 func (ctr *container) build(proc *process.Process, anal process.Analyze) error { 105 for { 106 bat, _, err := ctr.ReceiveFromSingleReg(1, anal) 107 if err != nil { 108 return err 109 } 110 if bat == nil { 111 break 112 } 113 ctr.bat, err = ctr.bat.AppendWithCopy(proc.Ctx, proc.Mp(), bat) 114 if err != nil { 115 return err 116 } 117 proc.PutBatch(bat) 118 } 119 return nil 120 } 121 122 func (ctr *container) emptyProbe(ap *Argument, proc *process.Process, anal process.Analyze, isLast bool, result *vm.CallResult) error { 123 if ctr.rbat != nil { 124 proc.PutBatch(ctr.rbat) 125 ctr.rbat = nil 126 } 127 ctr.rbat = batch.NewWithSize(len(ap.Result)) 128 for i, rp := range ap.Result { 129 if rp.Rel == 0 { 130 // rbat.Vecs[i] = bat.Vecs[rp.Pos] 131 // bat.Vecs[rp.Pos] = nil 132 typ := *ctr.inBat.Vecs[rp.Pos].GetType() 133 ctr.rbat.Vecs[i] = proc.GetVector(typ) 134 if err := vector.GetUnionAllFunction(typ, proc.Mp())(ctr.rbat.Vecs[i], ctr.inBat.Vecs[rp.Pos]); err != nil { 135 return err 136 } 137 } else { 138 ctr.rbat.Vecs[i] = vector.NewConstNull(ap.Typs[rp.Pos], ctr.inBat.RowCount(), proc.Mp()) 139 } 140 } 141 ctr.probeIdx = 0 142 ctr.rbat.AddRowCount(ctr.inBat.RowCount()) 143 anal.Output(ctr.rbat, isLast) 144 result.Batch = ctr.rbat 145 proc.PutBatch(ctr.inBat) 146 ctr.inBat = nil 147 return nil 148 } 149 150 func (ctr *container) probe(ap *Argument, proc *process.Process, anal process.Analyze, isLast bool, result *vm.CallResult) error { 151 if ctr.rbat != nil { 152 proc.PutBatch(ctr.rbat) 153 ctr.rbat = nil 154 } 155 ctr.rbat = batch.NewWithSize(len(ap.Result)) 156 for i, rp := range ap.Result { 157 if rp.Rel == 0 { 158 ctr.rbat.Vecs[i] = proc.GetVector(*ctr.inBat.Vecs[rp.Pos].GetType()) 159 } else { 160 ctr.rbat.Vecs[i] = proc.GetVector(ap.Typs[rp.Pos]) 161 } 162 } 163 164 count := ctr.inBat.RowCount() 165 rowCountIncrease := 0 166 if ctr.joinBat == nil { 167 ctr.joinBat, ctr.cfs = colexec.NewJoinBatch(ctr.inBat, proc.Mp()) 168 } 169 for i := ctr.probeIdx; i < count; i++ { 170 if ctr.expr == nil { 171 for k, rp := range ap.Result { 172 if rp.Rel == 0 { 173 if err := ctr.rbat.Vecs[k].UnionMulti(ctr.inBat.Vecs[rp.Pos], int64(i), ctr.bat.RowCount(), proc.Mp()); err != nil { 174 return err 175 } 176 } else { 177 if err := ctr.rbat.Vecs[k].UnionBatch(ctr.bat.Vecs[rp.Pos], 0, ctr.bat.RowCount(), nil, proc.Mp()); err != nil { 178 return err 179 } 180 } 181 } 182 rowCountIncrease += ctr.bat.RowCount() 183 } else { 184 matched := false 185 if err := colexec.SetJoinBatchValues(ctr.joinBat, ctr.inBat, int64(i), 186 ctr.bat.RowCount(), ctr.cfs); err != nil { 187 return err 188 } 189 vec, err := ctr.expr.Eval(proc, []*batch.Batch{ctr.joinBat, ctr.bat}) 190 if err != nil { 191 return err 192 } 193 194 rs := vector.GenerateFunctionFixedTypeParameter[bool](vec) 195 if vec.IsConst() { 196 b, null := rs.GetValue(0) 197 if !null && b { 198 matched = true 199 for k, rp := range ap.Result { 200 if rp.Rel == 0 { 201 if err := ctr.rbat.Vecs[k].UnionMulti(ctr.inBat.Vecs[rp.Pos], int64(i), ctr.bat.RowCount(), proc.Mp()); err != nil { 202 return err 203 } 204 } else { 205 if err := ctr.rbat.Vecs[k].UnionBatch(ctr.bat.Vecs[rp.Pos], 0, ctr.bat.RowCount(), nil, proc.Mp()); err != nil { 206 return err 207 } 208 } 209 } 210 rowCountIncrease += ctr.bat.RowCount() 211 } 212 } else { 213 l := vec.Length() 214 for j := uint64(0); j < uint64(l); j++ { 215 b, null := rs.GetValue(j) 216 if !null && b { 217 matched = true 218 for k, rp := range ap.Result { 219 if rp.Rel == 0 { 220 if err := ctr.rbat.Vecs[k].UnionOne(ctr.inBat.Vecs[rp.Pos], int64(i), proc.Mp()); err != nil { 221 return err 222 } 223 } else { 224 if err := ctr.rbat.Vecs[k].UnionOne(ctr.bat.Vecs[rp.Pos], int64(j), proc.Mp()); err != nil { 225 return err 226 } 227 } 228 } 229 rowCountIncrease++ 230 } 231 } 232 } 233 if !matched { 234 for k, rp := range ap.Result { 235 if rp.Rel == 0 { 236 if err := ctr.rbat.Vecs[k].UnionOne(ctr.inBat.Vecs[rp.Pos], int64(i), proc.Mp()); err != nil { 237 return err 238 } 239 } else { 240 if err := ctr.rbat.Vecs[k].UnionNull(proc.Mp()); err != nil { 241 return err 242 } 243 } 244 } 245 rowCountIncrease++ 246 } 247 } 248 if rowCountIncrease >= colexec.DefaultBatchSize { 249 anal.Output(ctr.rbat, isLast) 250 result.Batch = ctr.rbat 251 ctr.rbat.SetRowCount(rowCountIncrease) 252 ctr.probeIdx = i + 1 253 return nil 254 } 255 } 256 ctr.probeIdx = 0 257 ctr.rbat.SetRowCount(ctr.rbat.RowCount() + rowCountIncrease) 258 anal.Output(ctr.rbat, isLast) 259 result.Batch = ctr.rbat 260 proc.PutBatch(ctr.inBat) 261 ctr.inBat = nil 262 return nil 263 }