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  }