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 }