github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/mergecte/mergecte.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 mergecte 16 17 import ( 18 "bytes" 19 20 "github.com/matrixorigin/matrixone/pkg/container/batch" 21 "github.com/matrixorigin/matrixone/pkg/container/types" 22 "github.com/matrixorigin/matrixone/pkg/container/vector" 23 "github.com/matrixorigin/matrixone/pkg/vm" 24 "github.com/matrixorigin/matrixone/pkg/vm/process" 25 ) 26 27 const argName = "merge_cte" 28 29 func (arg *Argument) String(buf *bytes.Buffer) { 30 buf.WriteString(argName) 31 buf.WriteString(": merge cte ") 32 } 33 34 func (arg *Argument) Prepare(proc *process.Process) error { 35 ap := arg 36 ap.ctr = new(container) 37 ap.ctr.InitReceiver(proc, true) 38 ap.ctr.nodeCnt = int32(len(proc.Reg.MergeReceivers)) - 1 39 ap.ctr.curNodeCnt = ap.ctr.nodeCnt 40 ap.ctr.status = sendInitial 41 return nil 42 } 43 44 func (arg *Argument) Call(proc *process.Process) (vm.CallResult, error) { 45 if err, isCancel := vm.CancelCheck(proc); isCancel { 46 return vm.CancelResult, err 47 } 48 49 anal := proc.GetAnalyze(arg.GetIdx(), arg.GetParallelIdx(), arg.GetParallelMajor()) 50 anal.Start() 51 defer anal.Stop() 52 var end bool 53 var err error 54 result := vm.NewCallResult() 55 if arg.buf != nil { 56 proc.PutBatch(arg.buf) 57 arg.buf = nil 58 } 59 switch arg.ctr.status { 60 case sendInitial: 61 arg.buf, _, err = arg.ctr.ReceiveFromSingleReg(0, anal) 62 if err != nil { 63 result.Status = vm.ExecStop 64 return result, err 65 } 66 if arg.buf == nil { 67 arg.ctr.status = sendLastTag 68 } 69 fallthrough 70 case sendLastTag: 71 if arg.ctr.status == sendLastTag { 72 arg.ctr.status = sendRecursive 73 arg.buf = makeRecursiveBatch(proc) 74 arg.ctr.RemoveChosen(1) 75 } 76 case sendRecursive: 77 for { 78 arg.buf, end, _ = arg.ctr.ReceiveFromAllRegs(anal) 79 if arg.buf == nil || end { 80 result.Batch = nil 81 result.Status = vm.ExecStop 82 return result, nil 83 } 84 if !arg.buf.Last() { 85 break 86 } 87 88 arg.buf.SetLast() 89 arg.ctr.curNodeCnt-- 90 if arg.ctr.curNodeCnt == 0 { 91 arg.ctr.curNodeCnt = arg.ctr.nodeCnt 92 break 93 } else { 94 proc.PutBatch(arg.buf) 95 } 96 } 97 } 98 99 anal.Input(arg.buf, arg.GetIsFirst()) 100 anal.Output(arg.buf, arg.GetIsLast()) 101 result.Batch = arg.buf 102 return result, nil 103 } 104 105 func makeRecursiveBatch(proc *process.Process) *batch.Batch { 106 b := batch.NewWithSize(1) 107 b.Attrs = []string{ 108 "recursive_col", 109 } 110 b.SetVector(0, proc.GetVector(types.T_varchar.ToType())) 111 vector.AppendBytes(b.GetVector(0), []byte("check recursive status"), false, proc.GetMPool()) 112 batch.SetLength(b, 1) 113 b.SetLast() 114 return b 115 }