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  }