github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/partition/partition.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 partition
    16  
    17  import (
    18  	"bytes"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/compare"
    21  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    22  	"github.com/matrixorigin/matrixone/pkg/container/types"
    23  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    24  	plan2 "github.com/matrixorigin/matrixone/pkg/pb/plan"
    25  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    26  	"github.com/matrixorigin/matrixone/pkg/sql/plan"
    27  	"github.com/matrixorigin/matrixone/pkg/vm"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    29  )
    30  
    31  const argName = "partition"
    32  
    33  func (arg *Argument) String(buf *bytes.Buffer) {
    34  	buf.WriteString(argName)
    35  	ap := arg
    36  	buf.WriteString(": partition([")
    37  	for i, f := range ap.OrderBySpecs {
    38  		if i > 0 {
    39  			buf.WriteString(", ")
    40  		}
    41  		buf.WriteString(f.String())
    42  	}
    43  	buf.WriteString("])")
    44  }
    45  
    46  func (arg *Argument) Prepare(proc *process.Process) (err error) {
    47  	ap := arg
    48  	ap.ctr = new(container)
    49  	ctr := ap.ctr
    50  	ap.ctr.InitReceiver(proc, true)
    51  
    52  	length := 2 * len(proc.Reg.MergeReceivers)
    53  	ctr.batchList = make([]*batch.Batch, 0, length)
    54  	ctr.orderCols = make([][]*vector.Vector, 0, length)
    55  
    56  	ap.ctr.executors = make([]colexec.ExpressionExecutor, len(ap.OrderBySpecs))
    57  	for i := range ap.ctr.executors {
    58  		ap.ctr.executors[i], err = colexec.NewExpressionExecutor(proc, ap.OrderBySpecs[i].Expr)
    59  		if err != nil {
    60  			return err
    61  		}
    62  	}
    63  	ctr.generateCompares(ap.OrderBySpecs)
    64  	return nil
    65  }
    66  
    67  func (arg *Argument) Call(proc *process.Process) (vm.CallResult, error) {
    68  	if err, isCancel := vm.CancelCheck(proc); isCancel {
    69  		return vm.CancelResult, err
    70  	}
    71  
    72  	ap := arg
    73  	ctr := ap.ctr
    74  
    75  	anal := proc.GetAnalyze(arg.GetIdx(), arg.GetParallelIdx(), arg.GetParallelMajor())
    76  	anal.Start()
    77  	defer anal.Stop()
    78  	result := vm.NewCallResult()
    79  
    80  	for {
    81  		switch ctr.status {
    82  		case receive:
    83  			bat, end, err := ctr.ReceiveFromAllRegs(anal)
    84  			if err != nil {
    85  				return result, err
    86  			}
    87  			if end {
    88  				ctr.indexList = make([]int64, len(ctr.batchList))
    89  				ctr.status = eval
    90  			} else {
    91  				if err = ctr.mergeAndEvaluateOrderColumn(proc, bat); err != nil {
    92  					return result, err
    93  				}
    94  			}
    95  
    96  		case eval:
    97  
    98  			if len(ctr.batchList) == 0 {
    99  				result.Status = vm.ExecStop
   100  				return result, nil
   101  			}
   102  
   103  			ok, err := ctr.pickAndSend(proc, &result)
   104  			if ok {
   105  				result.Status = vm.ExecStop
   106  				return result, err
   107  			}
   108  			return result, err
   109  
   110  		}
   111  	}
   112  }
   113  
   114  func (ctr *container) mergeAndEvaluateOrderColumn(proc *process.Process, bat *batch.Batch) error {
   115  	ctr.batchList = append(ctr.batchList, bat)
   116  	ctr.orderCols = append(ctr.orderCols, nil)
   117  	return ctr.evaluateOrderColumn(proc, len(ctr.orderCols)-1)
   118  }
   119  
   120  func (ctr *container) evaluateOrderColumn(proc *process.Process, index int) error {
   121  	inputs := []*batch.Batch{ctr.batchList[index]}
   122  
   123  	ctr.orderCols[index] = make([]*vector.Vector, len(ctr.executors))
   124  	for i := 0; i < len(ctr.executors); i++ {
   125  		vec, err := ctr.executors[i].EvalWithoutResultReusing(proc, inputs)
   126  		if err != nil {
   127  			return err
   128  		}
   129  		ctr.orderCols[index][i] = vec
   130  	}
   131  	return nil
   132  }
   133  
   134  func (ctr *container) generateCompares(fs []*plan.OrderBySpec) {
   135  	var desc, nullsLast bool
   136  
   137  	ctr.compares = make([]compare.Compare, len(fs))
   138  	for i := range ctr.compares {
   139  		desc = fs[i].Flag&plan2.OrderBySpec_DESC != 0
   140  		if fs[i].Flag&plan2.OrderBySpec_NULLS_FIRST != 0 {
   141  			nullsLast = false
   142  		} else if fs[i].Flag&plan2.OrderBySpec_NULLS_LAST != 0 {
   143  			nullsLast = true
   144  		} else {
   145  			nullsLast = desc
   146  		}
   147  
   148  		exprTyp := fs[i].Expr.Typ
   149  		typ := types.New(types.T(exprTyp.Id), exprTyp.Width, exprTyp.Scale)
   150  		ctr.compares[i] = compare.New(typ, desc, nullsLast)
   151  	}
   152  }
   153  
   154  func (ctr *container) pickAndSend(proc *process.Process, result *vm.CallResult) (sendOver bool, err error) {
   155  	if ctr.buf != nil {
   156  		proc.PutBatch(ctr.buf)
   157  		ctr.buf = nil
   158  	}
   159  	ctr.buf = batch.NewWithSize(ctr.batchList[0].VectorCount())
   160  	mp := proc.Mp()
   161  
   162  	for i := range ctr.buf.Vecs {
   163  		ctr.buf.Vecs[i] = proc.GetVector(*ctr.batchList[0].Vecs[i].GetType())
   164  	}
   165  
   166  	wholeLength, choice := 0, 0
   167  	hasSame := false
   168  	var row int64
   169  	var cols []*vector.Vector
   170  	for {
   171  
   172  		if wholeLength == 0 {
   173  			choice = ctr.pickFirstRow()
   174  		} else {
   175  			if choice, hasSame = ctr.pickSameRow(row, cols); !hasSame {
   176  				break
   177  			}
   178  		}
   179  
   180  		row = ctr.indexList[choice]
   181  		cols = ctr.orderCols[choice]
   182  
   183  		for j := range ctr.buf.Vecs {
   184  			err = ctr.buf.Vecs[j].UnionOne(ctr.batchList[choice].Vecs[j], row, mp)
   185  			if err != nil {
   186  				return false, err
   187  			}
   188  		}
   189  		wholeLength++
   190  
   191  		ctr.indexList[choice]++
   192  		if ctr.indexList[choice] == int64(ctr.batchList[choice].RowCount()) {
   193  			ctr.removeBatch(proc, choice)
   194  		}
   195  
   196  		if len(ctr.indexList) == 0 {
   197  			sendOver = true
   198  			break
   199  		}
   200  	}
   201  	ctr.buf.SetRowCount(wholeLength)
   202  	result.Batch = ctr.buf
   203  	return sendOver, nil
   204  }
   205  
   206  func (ctr *container) pickFirstRow() (batIndex int) {
   207  	l := len(ctr.indexList)
   208  
   209  	i, j := 0, 1
   210  	for j < l {
   211  		for k := 0; k < len(ctr.compares); k++ {
   212  			ctr.compares[k].Set(0, ctr.orderCols[i][k])
   213  			ctr.compares[k].Set(1, ctr.orderCols[j][k])
   214  			result := ctr.compares[k].Compare(0, 1, ctr.indexList[i], ctr.indexList[j])
   215  			if result < 0 {
   216  				break
   217  			} else if result > 0 {
   218  				i = j
   219  				break
   220  			} else if k == len(ctr.compares)-1 {
   221  				break
   222  			}
   223  		}
   224  		j++
   225  	}
   226  	return i
   227  }
   228  
   229  func (ctr *container) pickSameRow(row int64, cols []*vector.Vector) (batIndex int, hasSame bool) {
   230  	l := len(ctr.indexList)
   231  
   232  	j := 0
   233  	for ; j < l; j++ {
   234  		hasSame = true
   235  		for k := 0; k < len(ctr.compares); k++ {
   236  			ctr.compares[k].Set(0, cols[k])
   237  			ctr.compares[k].Set(1, ctr.orderCols[j][k])
   238  			result := ctr.compares[k].Compare(0, 1, row, ctr.indexList[j])
   239  			if result != 0 {
   240  				hasSame = false
   241  				break
   242  			}
   243  		}
   244  		if hasSame {
   245  			break
   246  		}
   247  	}
   248  	return j, hasSame
   249  }
   250  
   251  func (ctr *container) removeBatch(_ *process.Process, index int) {
   252  	//bat := ctr.batchList[index]
   253  	//cols := ctr.orderCols[index]
   254  
   255  	//alreadyPut := make(map[*vector.Vector]bool, len(bat.Vecs))
   256  	//for i := range bat.Vecs {
   257  	//	proc.PutVector(bat.Vecs[i])
   258  	//	alreadyPut[bat.Vecs[i]] = true
   259  	//}
   260  	ctr.batchList = append(ctr.batchList[:index], ctr.batchList[index+1:]...)
   261  	ctr.indexList = append(ctr.indexList[:index], ctr.indexList[index+1:]...)
   262  
   263  	//for i := range cols {
   264  	//	if _, ok := alreadyPut[cols[i]]; ok {
   265  	//		continue
   266  	//	}
   267  	//	proc.PutVector(cols[i])
   268  	//}
   269  	ctr.orderCols = append(ctr.orderCols[:index], ctr.orderCols[index+1:]...)
   270  }