github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/insert/insert.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 insert 16 17 import ( 18 "bytes" 19 "sync/atomic" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/container/batch" 23 "github.com/matrixorigin/matrixone/pkg/container/vector" 24 "github.com/matrixorigin/matrixone/pkg/pb/plan" 25 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 26 "github.com/matrixorigin/matrixone/pkg/vm/process" 27 ) 28 29 func String(_ any, buf *bytes.Buffer) { 30 buf.WriteString("insert select") 31 } 32 33 func Prepare(proc *process.Process, arg any) error { 34 ap := arg.(*Argument) 35 if ap.IsRemote { 36 container := colexec.NewWriteS3Container(ap.InsertCtx.TableDef) 37 ap.Container = container 38 } 39 return nil 40 } 41 42 func Call(idx int, proc *process.Process, arg any, isFirst bool, isLast bool) (bool, error) { 43 var err error 44 var affectedRows uint64 45 t1 := time.Now() 46 insertArg := arg.(*Argument) 47 bat := proc.Reg.InputBatch 48 if bat == nil { 49 if insertArg.IsRemote { 50 // handle the last Batch that batchSize less than DefaultBlockMaxRows 51 // for more info, refer to the comments about reSizeBatch 52 err = insertArg.Container.WriteS3CacheBatch(proc) 53 if err != nil { 54 return false, err 55 } 56 } 57 return true, nil 58 } 59 if len(bat.Zs) == 0 { 60 return false, nil 61 } 62 63 insertCtx := insertArg.InsertCtx 64 clusterTable := insertCtx.ClusterTable 65 66 var insertBat *batch.Batch 67 defer func() { 68 bat.Clean(proc.Mp()) 69 if insertBat != nil { 70 insertBat.Clean(proc.Mp()) 71 } 72 anal := proc.GetAnalyze(idx) 73 anal.AddInsertTime(t1) 74 }() 75 76 insertRows := func() error { 77 var affectedRow uint64 78 79 affectedRow, err = colexec.InsertBatch(insertArg.Container, insertArg.Engine, proc, bat, insertCtx.Source, 80 insertCtx.Ref, insertCtx.TableDef, insertCtx.ParentIdx, insertCtx.UniqueSource) 81 if err != nil { 82 return err 83 } 84 85 affectedRows = affectedRows + affectedRow 86 return nil 87 } 88 89 if clusterTable.GetIsClusterTable() { 90 accountIdColumnDef := insertCtx.TableDef.Cols[clusterTable.GetColumnIndexOfAccountId()] 91 accountIdExpr := accountIdColumnDef.GetDefault().GetExpr() 92 accountIdConst := accountIdExpr.GetC() 93 94 vecLen := vector.Length(bat.Vecs[0]) 95 tmpBat := batch.NewWithSize(0) 96 tmpBat.Zs = []int64{1} 97 //save auto_increment column if necessary 98 savedAutoIncrVectors := make([]*vector.Vector, 0) 99 defer func() { 100 for _, vec := range savedAutoIncrVectors { 101 vector.Clean(vec, proc.Mp()) 102 } 103 }() 104 for i, colDef := range insertCtx.TableDef.Cols { 105 if colDef.GetTyp().GetAutoIncr() { 106 vec2, err := vector.Dup(bat.Vecs[i], proc.Mp()) 107 if err != nil { 108 return false, err 109 } 110 savedAutoIncrVectors = append(savedAutoIncrVectors, vec2) 111 } 112 } 113 for idx, accountId := range clusterTable.GetAccountIDs() { 114 //update accountId in the accountIdExpr 115 accountIdConst.Value = &plan.Const_U32Val{U32Val: accountId} 116 accountIdVec := bat.Vecs[clusterTable.GetColumnIndexOfAccountId()] 117 //clean vector before fill it 118 vector.Clean(accountIdVec, proc.Mp()) 119 //the i th row 120 for i := 0; i < vecLen; i++ { 121 err := fillRow(tmpBat, accountIdExpr, accountIdVec, proc) 122 if err != nil { 123 return false, err 124 } 125 } 126 if idx != 0 { //refill the auto_increment column vector 127 j := 0 128 for colIdx, colDef := range insertCtx.TableDef.Cols { 129 if colDef.GetTyp().GetAutoIncr() { 130 targetVec := bat.Vecs[colIdx] 131 vector.Clean(targetVec, proc.Mp()) 132 for k := int64(0); k < int64(vecLen); k++ { 133 err := vector.UnionOne(targetVec, savedAutoIncrVectors[j], k, proc.Mp()) 134 if err != nil { 135 return false, err 136 } 137 } 138 j++ 139 } 140 } 141 } 142 143 err := insertRows() 144 if err != nil { 145 return false, err 146 } 147 } 148 } else { 149 err := insertRows() 150 if err != nil { 151 return false, err 152 } 153 } 154 155 if insertArg.IsRemote { 156 insertArg.Container.WriteEnd(proc) 157 } 158 atomic.AddUint64(&insertArg.Affected, affectedRows) 159 return false, nil 160 } 161 162 /* 163 fillRow evaluates the expression and put the result into the targetVec. 164 tmpBat: store temporal vector 165 expr: the expression to be evaluated at the position (colIdx,rowIdx) 166 targetVec: the destination where the evaluated result of expr saved into 167 */ 168 func fillRow(tmpBat *batch.Batch, 169 expr *plan.Expr, 170 targetVec *vector.Vector, 171 proc *process.Process) error { 172 vec, err := colexec.EvalExpr(tmpBat, proc, expr) 173 if err != nil { 174 return err 175 } 176 if vec.Size() == 0 { 177 vec = vec.ConstExpand(false, proc.Mp()) 178 } 179 if err := vector.UnionOne(targetVec, vec, 0, proc.Mp()); err != nil { 180 vec.Free(proc.Mp()) 181 return err 182 } 183 vec.Free(proc.Mp()) 184 return err 185 }