github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/loopsingle/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 loopsingle 16 17 import ( 18 "bytes" 19 "time" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/container/batch" 23 "github.com/matrixorigin/matrixone/pkg/container/vector" 24 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 25 "github.com/matrixorigin/matrixone/pkg/vm/process" 26 ) 27 28 func String(_ any, buf *bytes.Buffer) { 29 buf.WriteString(" loop single join ") 30 } 31 32 func Prepare(proc *process.Process, arg any) error { 33 ap := arg.(*Argument) 34 ap.ctr = new(container) 35 ap.ctr.bat = batch.NewWithSize(len(ap.Typs)) 36 ap.ctr.bat.Zs = proc.Mp().GetSels() 37 for i, typ := range ap.Typs { 38 ap.ctr.bat.Vecs[i] = vector.New(typ) 39 } 40 return nil 41 } 42 43 func Call(idx int, proc *process.Process, arg any, isFirst bool, isLast bool) (bool, error) { 44 anal := proc.GetAnalyze(idx) 45 anal.Start() 46 defer anal.Stop() 47 ap := arg.(*Argument) 48 ctr := ap.ctr 49 for { 50 switch ctr.state { 51 case Build: 52 if err := ctr.build(ap, proc, anal); err != nil { 53 return false, err 54 } 55 ctr.state = Probe 56 57 case Probe: 58 var err error 59 start := time.Now() 60 bat := <-proc.Reg.MergeReceivers[0].Ch 61 anal.WaitStop(start) 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 for i, rp := range ap.Result { 119 if rp.Rel != 0 { 120 rbat.Vecs[i] = vector.New(ctr.bat.Vecs[rp.Pos].Typ) 121 } 122 } 123 count := bat.Length() 124 for i := 0; i < count; i++ { 125 unmatched := true 126 vec, err := colexec.JoinFilterEvalExpr(bat, ctr.bat, i, proc, ap.Cond) 127 if err != nil { 128 rbat.Clean(proc.Mp()) 129 return err 130 } 131 bs := vector.MustTCols[bool](vec) 132 if len(bs) == 1 { 133 if bs[0] { 134 if len(ctr.bat.Zs) > 1 { 135 return moerr.NewInternalError(proc.Ctx, "scalar subquery returns more than 1 row") 136 } 137 unmatched = false 138 for k, rp := range ap.Result { 139 if rp.Rel != 0 { 140 if err := vector.UnionOne(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], 0, proc.Mp()); err != nil { 141 vec.Free(proc.Mp()) 142 rbat.Clean(proc.Mp()) 143 return err 144 } 145 } 146 } 147 } 148 } else { 149 for j, b := range bs { 150 if b { 151 if !unmatched { 152 return moerr.NewInternalError(proc.Ctx, "scalar subquery returns more than 1 row") 153 } 154 unmatched = false 155 for k, rp := range ap.Result { 156 if rp.Rel != 0 { 157 if err := vector.UnionOne(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], int64(j), proc.Mp()); err != nil { 158 vec.Free(proc.Mp()) 159 rbat.Clean(proc.Mp()) 160 return err 161 } 162 } 163 } 164 } 165 } 166 } 167 if unmatched { 168 for k, rp := range ap.Result { 169 if rp.Rel != 0 { 170 if err := vector.UnionNull(rbat.Vecs[k], ctr.bat.Vecs[rp.Pos], proc.Mp()); err != nil { 171 vec.Free(proc.Mp()) 172 rbat.Clean(proc.Mp()) 173 return err 174 } 175 } 176 } 177 } 178 vec.Free(proc.Mp()) 179 } 180 for i, rp := range ap.Result { 181 if rp.Rel == 0 { 182 rbat.Vecs[i] = bat.Vecs[rp.Pos] 183 bat.Vecs[rp.Pos] = nil 184 } 185 } 186 rbat.Zs = bat.Zs 187 bat.Zs = nil 188 rbat.ExpandNulls() 189 anal.Output(rbat, isLast) 190 proc.SetInputBatch(rbat) 191 return nil 192 }