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  }