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  }