github.com/matrixorigin/matrixone@v0.7.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 "time" 20 21 "github.com/matrixorigin/matrixone/pkg/container/batch" 22 "github.com/matrixorigin/matrixone/pkg/container/vector" 23 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 24 "github.com/matrixorigin/matrixone/pkg/vm/process" 25 ) 26 27 func String(_ any, buf *bytes.Buffer) { 28 buf.WriteString(" loop left join ") 29 } 30 31 func Prepare(proc *process.Process, arg any) error { 32 ap := arg.(*Argument) 33 ap.ctr = new(container) 34 ap.ctr.bat = batch.NewWithSize(len(ap.Typs)) 35 ap.ctr.bat.Zs = proc.Mp().GetSels() 36 for i, typ := range ap.Typs { 37 ap.ctr.bat.Vecs[i] = vector.New(typ) 38 } 39 return nil 40 } 41 42 func Call(idx int, proc *process.Process, arg any, isFirst bool, isLast bool) (bool, error) { 43 anal := proc.GetAnalyze(idx) 44 anal.Start() 45 defer anal.Stop() 46 ap := arg.(*Argument) 47 ctr := ap.ctr 48 for { 49 switch ctr.state { 50 case Build: 51 if err := ctr.build(ap, proc, anal); err != nil { 52 return false, err 53 } 54 ctr.state = Probe 55 56 case Probe: 57 var err error 58 start := time.Now() 59 bat := <-proc.Reg.MergeReceivers[0].Ch 60 anal.WaitStop(start) 61 62 if bat == nil { 63 ctr.state = End 64 continue 65 } 66 if bat.Length() == 0 { 67 continue 68 } 69 if ctr.bat.Length() == 0 { 70 err = ctr.emptyProbe(bat, ap, proc, anal, isFirst, isLast) 71 } else { 72 err = ctr.probe(bat, ap, proc, anal, isFirst, isLast) 73 } 74 bat.Clean(proc.Mp()) 75 return false, err 76 77 default: 78 ap.Free(proc, false) 79 proc.SetInputBatch(nil) 80 return true, nil 81 } 82 } 83 } 84 85 func (ctr *container) build(ap *Argument, proc *process.Process, anal process.Analyze) error { 86 start := time.Now() 87 bat := <-proc.Reg.MergeReceivers[1].Ch 88 anal.WaitStop(start) 89 90 if bat != nil { 91 ctr.bat = bat 92 } 93 return nil 94 } 95 96 func (ctr *container) emptyProbe(bat *batch.Batch, ap *Argument, proc *process.Process, anal process.Analyze, isFirst bool, isLast bool) error { 97 anal.Input(bat, isFirst) 98 rbat := batch.NewWithSize(len(ap.Result)) 99 count := bat.Length() 100 for i, rp := range ap.Result { 101 if rp.Rel == 0 { 102 rbat.Vecs[i] = bat.Vecs[rp.Pos] 103 bat.Vecs[rp.Pos] = nil 104 } else { 105 rbat.Vecs[i] = vector.NewConstNull(ctr.bat.Vecs[rp.Pos].Typ, count) 106 } 107 } 108 rbat.Zs = bat.Zs 109 bat.Zs = nil 110 anal.Output(rbat, isLast) 111 proc.SetInputBatch(rbat) 112 return nil 113 } 114 115 func (ctr *container) probe(bat *batch.Batch, ap *Argument, proc *process.Process, anal process.Analyze, isFirst bool, isLast bool) error { 116 anal.Input(bat, isFirst) 117 rbat := batch.NewWithSize(len(ap.Result)) 118 rbat.Zs = proc.Mp().GetSels() 119 for i, rp := range ap.Result { 120 if rp.Rel == 0 { 121 rbat.Vecs[i] = vector.New(bat.Vecs[rp.Pos].Typ) 122 } else { 123 rbat.Vecs[i] = vector.New(ctr.bat.Vecs[rp.Pos].Typ) 124 } 125 } 126 count := bat.Length() 127 for i := 0; i < count; i++ { 128 matched := false 129 vec, err := colexec.JoinFilterEvalExpr(bat, ctr.bat, i, proc, ap.Cond) 130 if err != nil { 131 rbat.Clean(proc.Mp()) 132 return err 133 } 134 bs := vector.MustTCols[bool](vec) 135 if len(bs) == 1 { 136 if bs[0] { 137 for j := 0; j < len(ctr.bat.Zs); j++ { 138 matched = true 139 for k, rp := range ap.Result { 140 if rp.Rel == 0 { 141 if err := vector.UnionOne(rbat.Vecs[k], bat.Vecs[rp.Pos], int64(i), proc.Mp()); err != nil { 142 vec.Free(proc.Mp()) 143 rbat.Clean(proc.Mp()) 144 return err 145 } 146 } else { 147 if err := vector.UnionOne(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], int64(j), proc.Mp()); err != nil { 148 vec.Free(proc.Mp()) 149 rbat.Clean(proc.Mp()) 150 return err 151 } 152 } 153 } 154 rbat.Zs = append(rbat.Zs, ctr.bat.Zs[j]) 155 156 } 157 } 158 } else { 159 for j, b := range bs { 160 if b { 161 matched = true 162 for k, rp := range ap.Result { 163 if rp.Rel == 0 { 164 if err := vector.UnionOne(rbat.Vecs[k], bat.Vecs[rp.Pos], int64(i), proc.Mp()); err != nil { 165 vec.Free(proc.Mp()) 166 rbat.Clean(proc.Mp()) 167 return err 168 } 169 } else { 170 if err := vector.UnionOne(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], int64(j), proc.Mp()); err != nil { 171 vec.Free(proc.Mp()) 172 rbat.Clean(proc.Mp()) 173 return err 174 } 175 } 176 } 177 rbat.Zs = append(rbat.Zs, ctr.bat.Zs[j]) 178 } 179 } 180 } 181 vec.Free(proc.Mp()) 182 if !matched { 183 for k, rp := range ap.Result { 184 if rp.Rel == 0 { 185 if err := vector.UnionOne(rbat.Vecs[k], bat.Vecs[rp.Pos], int64(i), proc.Mp()); err != nil { 186 rbat.Clean(proc.Mp()) 187 return err 188 } 189 } else { 190 if err := vector.UnionNull(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], proc.Mp()); err != nil { 191 rbat.Clean(proc.Mp()) 192 return err 193 } 194 } 195 } 196 rbat.Zs = append(rbat.Zs, bat.Zs[i]) 197 } 198 } 199 rbat.ExpandNulls() 200 anal.Output(rbat, isLast) 201 proc.SetInputBatch(rbat) 202 return nil 203 }