github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/compile/operator.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 compile
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"strings"
    21  
    22  	"github.com/google/uuid"
    23  	"github.com/matrixorigin/matrixone/pkg/catalog"
    24  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    25  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    26  	"github.com/matrixorigin/matrixone/pkg/container/types"
    27  	"github.com/matrixorigin/matrixone/pkg/defines"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    29  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    30  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/agg"
    31  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/anti"
    32  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/connector"
    33  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/deletion"
    34  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/dispatch"
    35  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/external"
    36  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/group"
    37  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/hashbuild"
    38  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/insert"
    39  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/intersect"
    40  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/intersectall"
    41  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/join"
    42  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/left"
    43  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/limit"
    44  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopanti"
    45  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopjoin"
    46  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopleft"
    47  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopmark"
    48  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopsemi"
    49  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/loopsingle"
    50  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mark"
    51  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/merge"
    52  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mergegroup"
    53  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mergelimit"
    54  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mergeoffset"
    55  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mergeorder"
    56  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/mergetop"
    57  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/minus"
    58  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/multi_col/group_concat"
    59  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/offset"
    60  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/order"
    61  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/product"
    62  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/projection"
    63  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/restrict"
    64  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/semi"
    65  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/single"
    66  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/table_function"
    67  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/top"
    68  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/update"
    69  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    70  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    71  	"github.com/matrixorigin/matrixone/pkg/vm"
    72  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    73  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    74  )
    75  
    76  var constBat *batch.Batch
    77  
    78  func init() {
    79  	constBat = batch.NewWithSize(0)
    80  	constBat.Zs = []int64{1}
    81  }
    82  
    83  func dupInstruction(sourceIns *vm.Instruction, regMap map[*process.WaitRegister]*process.WaitRegister) vm.Instruction {
    84  	res := vm.Instruction{Op: sourceIns.Op, Idx: sourceIns.Idx, IsFirst: sourceIns.IsFirst, IsLast: sourceIns.IsLast}
    85  	switch sourceIns.Op {
    86  	case vm.Anti:
    87  		t := sourceIns.Arg.(*anti.Argument)
    88  		res.Arg = &anti.Argument{
    89  			Ibucket:    t.Ibucket,
    90  			Nbucket:    t.Nbucket,
    91  			Cond:       t.Cond,
    92  			Typs:       t.Typs,
    93  			Conditions: t.Conditions,
    94  			Result:     t.Result,
    95  		}
    96  	case vm.Group:
    97  		t := sourceIns.Arg.(*group.Argument)
    98  		res.Arg = &group.Argument{
    99  			NeedEval: t.NeedEval,
   100  			Ibucket:  t.Ibucket,
   101  			Nbucket:  t.Nbucket,
   102  			Exprs:    t.Exprs,
   103  			Types:    t.Types,
   104  			Aggs:     t.Aggs,
   105  		}
   106  	case vm.Join:
   107  		t := sourceIns.Arg.(*join.Argument)
   108  		res.Arg = &join.Argument{
   109  			Ibucket:    t.Ibucket,
   110  			Nbucket:    t.Nbucket,
   111  			Result:     t.Result,
   112  			Cond:       t.Cond,
   113  			Typs:       t.Typs,
   114  			Conditions: t.Conditions,
   115  		}
   116  	case vm.Left:
   117  		t := sourceIns.Arg.(*left.Argument)
   118  		res.Arg = &left.Argument{
   119  			Ibucket:    t.Ibucket,
   120  			Nbucket:    t.Nbucket,
   121  			Cond:       t.Cond,
   122  			Result:     t.Result,
   123  			Typs:       t.Typs,
   124  			Conditions: t.Conditions,
   125  		}
   126  	case vm.Limit:
   127  		t := sourceIns.Arg.(*limit.Argument)
   128  		res.Arg = &limit.Argument{
   129  			Limit: t.Limit,
   130  		}
   131  	case vm.LoopAnti:
   132  		t := sourceIns.Arg.(*loopanti.Argument)
   133  		res.Arg = &loopanti.Argument{
   134  			Result: t.Result,
   135  			Cond:   t.Cond,
   136  			Typs:   t.Typs,
   137  		}
   138  	case vm.LoopJoin:
   139  		t := sourceIns.Arg.(*loopanti.Argument)
   140  		res.Arg = &loopanti.Argument{
   141  			Result: t.Result,
   142  			Cond:   t.Cond,
   143  			Typs:   t.Typs,
   144  		}
   145  	case vm.LoopLeft:
   146  		t := sourceIns.Arg.(*loopleft.Argument)
   147  		res.Arg = &loopleft.Argument{
   148  			Cond:   t.Cond,
   149  			Typs:   t.Typs,
   150  			Result: t.Result,
   151  		}
   152  	case vm.LoopSemi:
   153  		t := sourceIns.Arg.(*loopsemi.Argument)
   154  		res.Arg = &loopsemi.Argument{
   155  			Result: t.Result,
   156  			Cond:   t.Cond,
   157  			Typs:   t.Typs,
   158  		}
   159  	case vm.LoopSingle:
   160  		t := sourceIns.Arg.(*loopsingle.Argument)
   161  		res.Arg = &loopsingle.Argument{
   162  			Result: t.Result,
   163  			Cond:   t.Cond,
   164  			Typs:   t.Typs,
   165  		}
   166  	case vm.LoopMark:
   167  		t := sourceIns.Arg.(*loopmark.Argument)
   168  		res.Arg = &loopmark.Argument{
   169  			Result: t.Result,
   170  			Cond:   t.Cond,
   171  			Typs:   t.Typs,
   172  		}
   173  	case vm.Offset:
   174  		t := sourceIns.Arg.(*offset.Argument)
   175  		res.Arg = &offset.Argument{
   176  			Offset: t.Offset,
   177  		}
   178  	case vm.Order:
   179  		t := sourceIns.Arg.(*order.Argument)
   180  		res.Arg = &order.Argument{
   181  			Fs: t.Fs,
   182  		}
   183  	case vm.Product:
   184  		t := sourceIns.Arg.(*product.Argument)
   185  		res.Arg = &product.Argument{
   186  			Result: t.Result,
   187  			Typs:   t.Typs,
   188  		}
   189  	case vm.Projection:
   190  		t := sourceIns.Arg.(*projection.Argument)
   191  		res.Arg = &projection.Argument{
   192  			Es: t.Es,
   193  		}
   194  	case vm.Restrict:
   195  		t := sourceIns.Arg.(*restrict.Argument)
   196  		res.Arg = &restrict.Argument{
   197  			E: t.E,
   198  		}
   199  	case vm.Semi:
   200  		t := sourceIns.Arg.(*semi.Argument)
   201  		res.Arg = &semi.Argument{
   202  			Ibucket:    t.Ibucket,
   203  			Nbucket:    t.Nbucket,
   204  			Result:     t.Result,
   205  			Cond:       t.Cond,
   206  			Typs:       t.Typs,
   207  			Conditions: t.Conditions,
   208  		}
   209  	case vm.Single:
   210  		t := sourceIns.Arg.(*single.Argument)
   211  		res.Arg = &single.Argument{
   212  			Ibucket:    t.Ibucket,
   213  			Nbucket:    t.Nbucket,
   214  			Result:     t.Result,
   215  			Cond:       t.Cond,
   216  			Typs:       t.Typs,
   217  			Conditions: t.Conditions,
   218  		}
   219  	case vm.Top:
   220  		t := sourceIns.Arg.(*top.Argument)
   221  		res.Arg = &top.Argument{
   222  			Limit: t.Limit,
   223  			Fs:    t.Fs,
   224  		}
   225  	case vm.Intersect:
   226  		t := sourceIns.Arg.(*intersect.Argument)
   227  		res.Arg = &intersect.Argument{
   228  			IBucket: t.IBucket,
   229  			NBucket: t.NBucket,
   230  		}
   231  	case vm.Minus: // 2
   232  		t := sourceIns.Arg.(*minus.Argument)
   233  		res.Arg = &minus.Argument{
   234  			IBucket: t.IBucket,
   235  			NBucket: t.NBucket,
   236  		}
   237  	case vm.IntersectAll:
   238  		t := sourceIns.Arg.(*intersectall.Argument)
   239  		res.Arg = &intersectall.Argument{
   240  			IBucket: t.IBucket,
   241  			NBucket: t.NBucket,
   242  		}
   243  	case vm.Merge:
   244  		res.Arg = &merge.Argument{}
   245  	case vm.MergeGroup:
   246  		t := sourceIns.Arg.(*mergegroup.Argument)
   247  		res.Arg = &mergegroup.Argument{
   248  			NeedEval: t.NeedEval,
   249  		}
   250  	case vm.MergeLimit:
   251  		t := sourceIns.Arg.(*mergelimit.Argument)
   252  		res.Arg = &mergelimit.Argument{
   253  			Limit: t.Limit,
   254  		}
   255  	case vm.MergeOffset:
   256  		t := sourceIns.Arg.(*mergeoffset.Argument)
   257  		res.Arg = &mergeoffset.Argument{
   258  			Offset: t.Offset,
   259  		}
   260  	case vm.MergeTop:
   261  		t := sourceIns.Arg.(*mergetop.Argument)
   262  		res.Arg = &mergetop.Argument{
   263  			Limit: t.Limit,
   264  			Fs:    t.Fs,
   265  		}
   266  	case vm.MergeOrder:
   267  		t := sourceIns.Arg.(*mergeorder.Argument)
   268  		res.Arg = &mergeorder.Argument{
   269  			Fs: t.Fs,
   270  		}
   271  	case vm.Mark:
   272  		t := sourceIns.Arg.(*mark.Argument)
   273  		res.Arg = &mark.Argument{
   274  			Ibucket:    t.Ibucket,
   275  			Nbucket:    t.Nbucket,
   276  			Result:     t.Result,
   277  			Conditions: t.Conditions,
   278  			Typs:       t.Typs,
   279  			Cond:       t.Cond,
   280  			OnList:     t.OnList,
   281  		}
   282  	case vm.TableFunction:
   283  		t := sourceIns.Arg.(*table_function.Argument)
   284  		res.Arg = &table_function.Argument{
   285  			Name:   t.Name,
   286  			Args:   t.Args,
   287  			Rets:   t.Rets,
   288  			Attrs:  t.Attrs,
   289  			Params: t.Params,
   290  		}
   291  
   292  	case vm.HashBuild:
   293  		t := sourceIns.Arg.(*hashbuild.Argument)
   294  		res.Arg = &hashbuild.Argument{
   295  			NeedHashMap:    t.NeedHashMap,
   296  			NeedExpr:       t.NeedExpr,
   297  			NeedSelectList: t.NeedSelectList,
   298  			Ibucket:        t.Ibucket,
   299  			Nbucket:        t.Nbucket,
   300  			Typs:           t.Typs,
   301  			Conditions:     t.Conditions,
   302  		}
   303  	case vm.External:
   304  		t := sourceIns.Arg.(*external.Argument)
   305  		res.Arg = &external.Argument{
   306  			Es: &external.ExternalParam{
   307  				ExParamConst: external.ExParamConst{
   308  					Attrs:         t.Es.Attrs,
   309  					Cols:          t.Es.Cols,
   310  					Name2ColIndex: t.Es.Name2ColIndex,
   311  					CreateSql:     t.Es.CreateSql,
   312  					FileList:      t.Es.FileList,
   313  					OriginCols:    t.Es.OriginCols,
   314  					Extern:        t.Es.Extern,
   315  				},
   316  				ExParam: external.ExParam{
   317  					Filter: t.Es.Filter,
   318  					Fileparam: &external.ExFileparam{
   319  						End:       t.Es.Fileparam.End,
   320  						FileCnt:   t.Es.Fileparam.FileCnt,
   321  						FileFin:   t.Es.Fileparam.FileFin,
   322  						FileIndex: t.Es.Fileparam.FileIndex,
   323  					},
   324  				},
   325  			},
   326  		}
   327  	case vm.Connector:
   328  		ok := false
   329  		if regMap != nil {
   330  			arg := &connector.Argument{}
   331  			sourceReg := sourceIns.Arg.(*connector.Argument).Reg
   332  			if arg.Reg, ok = regMap[sourceReg]; !ok {
   333  				panic("nonexistent wait register")
   334  			}
   335  			res.Arg = arg
   336  		}
   337  	case vm.Dispatch:
   338  		ok := false
   339  		if regMap != nil {
   340  			sourceArg := sourceIns.Arg.(*dispatch.Argument)
   341  			arg := &dispatch.Argument{
   342  				FuncId:     sourceArg.FuncId,
   343  				LocalRegs:  make([]*process.WaitRegister, len(sourceArg.LocalRegs)),
   344  				RemoteRegs: make([]colexec.ReceiveInfo, len(sourceArg.RemoteRegs)),
   345  			}
   346  			for j := range arg.LocalRegs {
   347  				sourceReg := sourceArg.LocalRegs[j]
   348  				if arg.LocalRegs[j], ok = regMap[sourceReg]; !ok {
   349  					panic("nonexistent wait register")
   350  				}
   351  			}
   352  			for j := range arg.RemoteRegs {
   353  				arg.RemoteRegs[j] = sourceArg.RemoteRegs[j]
   354  			}
   355  			res.Arg = arg
   356  		}
   357  	case vm.Insert:
   358  		t := sourceIns.Arg.(*insert.Argument)
   359  		res.Arg = &insert.Argument{
   360  			Ts: t.Ts,
   361  			// TargetTable:          t.TargetTable,
   362  			// TargetColDefs:        t.TargetColDefs,
   363  			Affected: t.Affected,
   364  			Engine:   t.Engine,
   365  			// DB:                   t.DB,
   366  			// TableID:              t.TableID,
   367  			// CPkeyColDef:          t.CPkeyColDef,
   368  			// DBName:               t.DBName,
   369  			// TableName:            t.TableName,
   370  			// UniqueIndexTables:    t.UniqueIndexTables,
   371  			// UniqueIndexDef:       t.UniqueIndexDef,
   372  			// SecondaryIndexTables: t.SecondaryIndexTables,
   373  			// SecondaryIndexDef:    t.SecondaryIndexDef,
   374  			// ClusterTable:         t.ClusterTable,
   375  			// ClusterByDef:         t.ClusterByDef,
   376  			IsRemote:  t.IsRemote,
   377  			InsertCtx: t.InsertCtx,
   378  			// HasAutoCol:           t.HasAutoCol,
   379  		}
   380  	default:
   381  		panic(fmt.Sprintf("unexpected instruction type '%d' to dup", sourceIns.Op))
   382  	}
   383  	return res
   384  }
   385  
   386  func constructRestrict(n *plan.Node) *restrict.Argument {
   387  	return &restrict.Argument{
   388  		E: colexec.RewriteFilterExprList(n.FilterList),
   389  	}
   390  }
   391  
   392  func constructDeletion(n *plan.Node, eg engine.Engine, proc *process.Process) (*deletion.Argument, error) {
   393  	oldCtx := n.DeleteCtx
   394  	delCtx := &deletion.DeleteCtx{
   395  		DelSource: make([]engine.Relation, len(oldCtx.Ref)),
   396  		DelRef:    oldCtx.Ref,
   397  
   398  		IdxSource: make([]engine.Relation, len(oldCtx.IdxRef)),
   399  		IdxIdx:    oldCtx.IdxIdx,
   400  
   401  		OnRestrictIdx: oldCtx.OnRestrictIdx,
   402  
   403  		OnCascadeIdx:    oldCtx.OnCascadeIdx,
   404  		OnCascadeSource: make([]engine.Relation, len(oldCtx.OnCascadeRef)),
   405  
   406  		OnSetSource:       make([]engine.Relation, len(oldCtx.OnSetRef)),
   407  		OnSetUniqueSource: make([][]engine.Relation, len(oldCtx.Ref)),
   408  		OnSetIdx:          make([][]int32, len(oldCtx.OnSetIdx)),
   409  		OnSetTableDef:     oldCtx.OnSetDef,
   410  		OnSetRef:          oldCtx.OnSetRef,
   411  		OnSetUpdateCol:    make([]map[string]int32, len(oldCtx.OnSetUpdateCol)),
   412  
   413  		CanTruncate: oldCtx.CanTruncate,
   414  	}
   415  
   416  	if delCtx.CanTruncate {
   417  		for i, ref := range oldCtx.Ref {
   418  			rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil)
   419  			if err != nil {
   420  				return nil, err
   421  			}
   422  			delCtx.DelSource[i] = rel
   423  		}
   424  	} else {
   425  		for i, list := range oldCtx.OnSetIdx {
   426  			delCtx.OnSetIdx[i] = make([]int32, len(list.List))
   427  			for j, id := range list.List {
   428  				delCtx.OnSetIdx[i][j] = int32(id)
   429  			}
   430  		}
   431  		for i, ref := range oldCtx.Ref {
   432  			rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil)
   433  			if err != nil {
   434  				return nil, err
   435  			}
   436  			delCtx.DelSource[i] = rel
   437  		}
   438  		for i, ref := range oldCtx.IdxRef {
   439  			rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil)
   440  			if err != nil {
   441  				return nil, err
   442  			}
   443  			delCtx.IdxSource[i] = rel
   444  		}
   445  		for i, ref := range oldCtx.OnCascadeRef {
   446  			rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil)
   447  			if err != nil {
   448  				return nil, err
   449  			}
   450  			delCtx.OnCascadeSource[i] = rel
   451  		}
   452  		for i, ref := range oldCtx.OnSetRef {
   453  			rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnSetDef[i])
   454  			if err != nil {
   455  				return nil, err
   456  			}
   457  			delCtx.OnSetSource[i] = rel
   458  			delCtx.OnSetUniqueSource[i] = uniqueRels
   459  		}
   460  		for i, idxMap := range oldCtx.OnSetUpdateCol {
   461  			delCtx.OnSetUpdateCol[i] = idxMap.Map
   462  		}
   463  	}
   464  
   465  	return &deletion.Argument{
   466  		DeleteCtx: delCtx,
   467  		Engine:    eg,
   468  	}, nil
   469  }
   470  
   471  func constructInsert(n *plan.Node, eg engine.Engine, proc *process.Process) (*insert.Argument, error) {
   472  	oldCtx := n.InsertCtx
   473  	ctx := proc.Ctx
   474  	if oldCtx.GetClusterTable().GetIsClusterTable() {
   475  		ctx = context.WithValue(ctx, defines.TenantIDKey{}, catalog.System_Account)
   476  	}
   477  	newCtx := &insert.InsertCtx{
   478  		Idx:      oldCtx.Idx,
   479  		Ref:      oldCtx.Ref,
   480  		TableDef: oldCtx.TableDef,
   481  
   482  		ParentIdx:    oldCtx.ParentIdx,
   483  		ClusterTable: oldCtx.ClusterTable,
   484  	}
   485  
   486  	originRel, indexRels, err := getRel(ctx, proc, eg, oldCtx.Ref, oldCtx.TableDef)
   487  	if err != nil {
   488  		return nil, err
   489  	}
   490  	newCtx.Source = originRel
   491  	newCtx.UniqueSource = indexRels
   492  
   493  	return &insert.Argument{
   494  		InsertCtx: newCtx,
   495  		Engine:    eg,
   496  	}, nil
   497  }
   498  
   499  func constructUpdate(n *plan.Node, eg engine.Engine, proc *process.Process) (*update.Argument, error) {
   500  	oldCtx := n.UpdateCtx
   501  	updateCtx := &update.UpdateCtx{
   502  		Source:       make([]engine.Relation, len(oldCtx.Ref)),
   503  		Idxs:         make([][]int32, len(oldCtx.Idx)),
   504  		TableDefs:    oldCtx.TableDefs,
   505  		Ref:          oldCtx.Ref,
   506  		UpdateCol:    make([]map[string]int32, len(oldCtx.UpdateCol)),
   507  		UniqueSource: make([][]engine.Relation, len(oldCtx.Ref)),
   508  
   509  		IdxSource: make([]engine.Relation, len(oldCtx.IdxRef)),
   510  		IdxIdx:    oldCtx.IdxIdx,
   511  
   512  		OnRestrictIdx: oldCtx.OnRestrictIdx,
   513  
   514  		OnCascadeIdx:          make([][]int32, len(oldCtx.OnCascadeIdx)),
   515  		OnCascadeSource:       make([]engine.Relation, len(oldCtx.OnCascadeRef)),
   516  		OnCascadeUniqueSource: make([][]engine.Relation, len(oldCtx.OnCascadeRef)),
   517  		OnCascadeRef:          oldCtx.OnCascadeRef,
   518  		OnCascadeTableDef:     oldCtx.OnCascadeDef,
   519  		OnCascadeUpdateCol:    make([]map[string]int32, len(oldCtx.OnCascadeUpdateCol)),
   520  
   521  		OnSetSource:       make([]engine.Relation, len(oldCtx.OnSetRef)),
   522  		OnSetUniqueSource: make([][]engine.Relation, len(oldCtx.OnSetRef)),
   523  		OnSetIdx:          make([][]int32, len(oldCtx.OnSetIdx)),
   524  		OnSetRef:          oldCtx.OnSetRef,
   525  		OnSetTableDef:     oldCtx.OnSetDef,
   526  		OnSetUpdateCol:    make([]map[string]int32, len(oldCtx.OnSetUpdateCol)),
   527  
   528  		ParentIdx: make([]map[string]int32, len(oldCtx.ParentIdx)),
   529  	}
   530  
   531  	for i, idxMap := range oldCtx.UpdateCol {
   532  		updateCtx.UpdateCol[i] = idxMap.Map
   533  	}
   534  	for i, list := range oldCtx.Idx {
   535  		updateCtx.Idxs[i] = make([]int32, len(list.List))
   536  		for j, id := range list.List {
   537  			updateCtx.Idxs[i][j] = int32(id)
   538  		}
   539  	}
   540  	for i, list := range oldCtx.OnSetIdx {
   541  		updateCtx.OnSetIdx[i] = make([]int32, len(list.List))
   542  		for j, id := range list.List {
   543  			updateCtx.OnSetIdx[i][j] = int32(id)
   544  		}
   545  	}
   546  	for i, list := range oldCtx.OnCascadeIdx {
   547  		updateCtx.OnCascadeIdx[i] = make([]int32, len(list.List))
   548  		for j, id := range list.List {
   549  			updateCtx.OnCascadeIdx[i][j] = int32(id)
   550  		}
   551  	}
   552  	for i, ref := range oldCtx.Ref {
   553  		rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.TableDefs[i])
   554  		if err != nil {
   555  			return nil, err
   556  		}
   557  		updateCtx.Source[i] = rel
   558  		updateCtx.UniqueSource[i] = uniqueRels
   559  	}
   560  	for i, ref := range oldCtx.IdxRef {
   561  		rel, _, err := getRel(proc.Ctx, proc, eg, ref, nil)
   562  		if err != nil {
   563  			return nil, err
   564  		}
   565  		updateCtx.IdxSource[i] = rel
   566  	}
   567  	for i, ref := range oldCtx.OnCascadeRef {
   568  		rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnCascadeDef[i])
   569  		if err != nil {
   570  			return nil, err
   571  		}
   572  		updateCtx.OnCascadeSource[i] = rel
   573  		updateCtx.OnCascadeUniqueSource[i] = uniqueRels
   574  	}
   575  	for i, ref := range oldCtx.OnSetRef {
   576  		rel, uniqueRels, err := getRel(proc.Ctx, proc, eg, ref, oldCtx.OnSetDef[i])
   577  		if err != nil {
   578  			return nil, err
   579  		}
   580  		updateCtx.OnSetSource[i] = rel
   581  		updateCtx.OnSetUniqueSource[i] = uniqueRels
   582  	}
   583  	for i, idxMap := range oldCtx.OnCascadeUpdateCol {
   584  		updateCtx.OnCascadeUpdateCol[i] = idxMap.Map
   585  	}
   586  	for i, idxMap := range oldCtx.OnSetUpdateCol {
   587  		updateCtx.OnSetUpdateCol[i] = idxMap.Map
   588  	}
   589  	for i, idxMap := range oldCtx.ParentIdx {
   590  		updateCtx.ParentIdx[i] = idxMap.Map
   591  	}
   592  
   593  	return &update.Argument{
   594  		UpdateCtx: updateCtx,
   595  		Engine:    eg,
   596  	}, nil
   597  }
   598  
   599  func constructProjection(n *plan.Node) *projection.Argument {
   600  	return &projection.Argument{
   601  		Es: n.ProjectList,
   602  	}
   603  }
   604  
   605  func constructExternal(n *plan.Node, param *tree.ExternParam, ctx context.Context, fileList []string, FileSize []int64, fileOffset [][2]int) *external.Argument {
   606  	attrs := make([]string, len(n.TableDef.Cols))
   607  	for j, col := range n.TableDef.Cols {
   608  		attrs[j] = col.Name
   609  	}
   610  	return &external.Argument{
   611  		Es: &external.ExternalParam{
   612  			ExParamConst: external.ExParamConst{
   613  				Attrs:         attrs,
   614  				Cols:          n.TableDef.Cols,
   615  				Extern:        param,
   616  				Name2ColIndex: n.TableDef.Name2ColIndex,
   617  				FileOffset:    fileOffset,
   618  				CreateSql:     n.TableDef.Createsql,
   619  				Ctx:           ctx,
   620  				FileList:      fileList,
   621  				FileSize:      FileSize,
   622  				OriginCols:    n.TableDef.OriginCols,
   623  				ClusterTable:  n.GetClusterTable(),
   624  			},
   625  			ExParam: external.ExParam{
   626  				Fileparam: new(external.ExFileparam),
   627  				Filter: &external.FilterParam{
   628  					FilterExpr: colexec.RewriteFilterExprList(n.FilterList),
   629  				},
   630  			},
   631  		},
   632  	}
   633  }
   634  func constructTableFunction(n *plan.Node, ctx context.Context, name string) *table_function.Argument {
   635  	attrs := make([]string, len(n.TableDef.Cols))
   636  	for j, col := range n.TableDef.Cols {
   637  		attrs[j] = col.Name
   638  	}
   639  	return &table_function.Argument{
   640  		Attrs:  attrs,
   641  		Rets:   n.TableDef.Cols,
   642  		Args:   n.TblFuncExprList,
   643  		Name:   name,
   644  		Params: n.TableDef.TblFunc.Param,
   645  	}
   646  }
   647  
   648  func constructTop(n *plan.Node, topN int64) *top.Argument {
   649  	return &top.Argument{
   650  		Fs:    n.OrderBy,
   651  		Limit: topN,
   652  	}
   653  }
   654  
   655  func constructJoin(n *plan.Node, typs []types.Type, proc *process.Process) *join.Argument {
   656  	result := make([]colexec.ResultPos, len(n.ProjectList))
   657  	for i, expr := range n.ProjectList {
   658  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
   659  	}
   660  	cond, conds := extraJoinConditions(n.OnList)
   661  	return &join.Argument{
   662  		Typs:       typs,
   663  		Result:     result,
   664  		Cond:       cond,
   665  		Conditions: constructJoinConditions(conds, proc),
   666  	}
   667  }
   668  
   669  func constructSemi(n *plan.Node, typs []types.Type, proc *process.Process) *semi.Argument {
   670  	result := make([]int32, len(n.ProjectList))
   671  	for i, expr := range n.ProjectList {
   672  		rel, pos := constructJoinResult(expr, proc)
   673  		if rel != 0 {
   674  			panic(moerr.NewNYI(proc.Ctx, "semi result '%s'", expr))
   675  		}
   676  		result[i] = pos
   677  	}
   678  	cond, conds := extraJoinConditions(n.OnList)
   679  	return &semi.Argument{
   680  		Typs:       typs,
   681  		Result:     result,
   682  		Cond:       cond,
   683  		Conditions: constructJoinConditions(conds, proc),
   684  	}
   685  }
   686  
   687  func constructLeft(n *plan.Node, typs []types.Type, proc *process.Process) *left.Argument {
   688  	result := make([]colexec.ResultPos, len(n.ProjectList))
   689  	for i, expr := range n.ProjectList {
   690  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
   691  	}
   692  	cond, conds := extraJoinConditions(n.OnList)
   693  	return &left.Argument{
   694  		Typs:       typs,
   695  		Result:     result,
   696  		Cond:       cond,
   697  		Conditions: constructJoinConditions(conds, proc),
   698  	}
   699  }
   700  
   701  func constructSingle(n *plan.Node, typs []types.Type, proc *process.Process) *single.Argument {
   702  	result := make([]colexec.ResultPos, len(n.ProjectList))
   703  	for i, expr := range n.ProjectList {
   704  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
   705  	}
   706  	cond, conds := extraJoinConditions(n.OnList)
   707  	return &single.Argument{
   708  		Typs:       typs,
   709  		Result:     result,
   710  		Cond:       cond,
   711  		Conditions: constructJoinConditions(conds, proc),
   712  	}
   713  }
   714  
   715  func constructProduct(n *plan.Node, typs []types.Type, proc *process.Process) *product.Argument {
   716  	result := make([]colexec.ResultPos, len(n.ProjectList))
   717  	for i, expr := range n.ProjectList {
   718  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
   719  	}
   720  	return &product.Argument{Typs: typs, Result: result}
   721  }
   722  
   723  func constructAnti(n *plan.Node, typs []types.Type, proc *process.Process) *anti.Argument {
   724  	result := make([]int32, len(n.ProjectList))
   725  	for i, expr := range n.ProjectList {
   726  		rel, pos := constructJoinResult(expr, proc)
   727  		if rel != 0 {
   728  			panic(moerr.NewNYI(proc.Ctx, "anti result '%s'", expr))
   729  		}
   730  		result[i] = pos
   731  	}
   732  	cond, conds := extraJoinConditions(n.OnList)
   733  	return &anti.Argument{
   734  		Typs:       typs,
   735  		Result:     result,
   736  		Cond:       cond,
   737  		Conditions: constructJoinConditions(conds, proc),
   738  	}
   739  }
   740  
   741  /*
   742  func constructMark(n *plan.Node, typs []types.Type, proc *process.Process) *mark.Argument {
   743  	result := make([]int32, len(n.ProjectList))
   744  	for i, expr := range n.ProjectList {
   745  		rel, pos := constructJoinResult(expr, proc)
   746  		if rel == 0 {
   747  			result[i] = pos
   748  		} else if rel == -1 {
   749  			result[i] = -1
   750  		} else {
   751  			panic(moerr.NewNYI(proc.Ctx, "loop mark result '%s'", expr))
   752  		}
   753  	}
   754  	cond, conds := extraJoinConditions(n.OnList)
   755  	return &mark.Argument{
   756  		Typs:       typs,
   757  		Result:     result,
   758  		Cond:       cond,
   759  		Conditions: constructJoinConditions(conds, proc),
   760  		OnList:     n.OnList,
   761  	}
   762  }
   763  */
   764  
   765  func constructOrder(n *plan.Node, proc *process.Process) *order.Argument {
   766  	return &order.Argument{
   767  		Fs: n.OrderBy,
   768  	}
   769  }
   770  
   771  /*
   772  func constructOffset(n *plan.Node, proc *process.Process) *offset.Argument {
   773  	vec, err := colexec.EvalExpr(constBat, proc, n.Offset)
   774  	if err != nil {
   775  		panic(err)
   776  	}
   777  	return &offset.Argument{
   778  		Offset: uint64(vec.Col.([]int64)[0]),
   779  	}
   780  }
   781  */
   782  
   783  func constructLimit(n *plan.Node, proc *process.Process) *limit.Argument {
   784  	vec, err := colexec.EvalExpr(constBat, proc, n.Limit)
   785  	if err != nil {
   786  		panic(err)
   787  	}
   788  	defer vec.Free(proc.Mp())
   789  	return &limit.Argument{
   790  		Limit: uint64(vec.Col.([]int64)[0]),
   791  	}
   792  }
   793  
   794  func constructGroup(ctx context.Context, n, cn *plan.Node, ibucket, nbucket int, needEval bool, proc *process.Process) *group.Argument {
   795  	var lenAggs, lenMultiAggs int
   796  	aggs := make([]agg.Aggregate, len(n.AggList))
   797  	// multiaggs: is not like the normal agg funcs which have only one arg exclude 'distinct'
   798  	// for now, we have group_concat
   799  	multiaggs := make([]group_concat.Argument, len(n.AggList))
   800  	for _, expr := range n.AggList {
   801  		if f, ok := expr.Expr.(*plan.Expr_F); ok {
   802  			distinct := (uint64(f.F.Func.Obj) & function.Distinct) != 0
   803  			if len(f.F.Args) > 1 {
   804  				// vec is separator
   805  				vec, _ := colexec.EvalExpr(constBat, proc, f.F.Args[len(f.F.Args)-1])
   806  				sepa := vec.GetString(0)
   807  				multiaggs[lenMultiAggs] = group_concat.Argument{
   808  					Dist:      distinct,
   809  					GroupExpr: f.F.Args[:len(f.F.Args)-1],
   810  					Separator: sepa,
   811  				}
   812  				lenMultiAggs++
   813  				continue
   814  			}
   815  			obj := int64(uint64(f.F.Func.Obj) & function.DistinctMask)
   816  			fun, err := function.GetFunctionByID(ctx, obj)
   817  			if err != nil {
   818  				panic(err)
   819  			}
   820  			aggs[lenAggs] = agg.Aggregate{
   821  				E:    f.F.Args[0],
   822  				Dist: distinct,
   823  				Op:   fun.AggregateInfo,
   824  			}
   825  			lenAggs++
   826  		}
   827  	}
   828  	aggs = aggs[:lenAggs]
   829  	multiaggs = multiaggs[:lenMultiAggs]
   830  	typs := make([]types.Type, len(cn.ProjectList))
   831  	for i, e := range cn.ProjectList {
   832  		typs[i].Oid = types.T(e.Typ.Id)
   833  		typs[i].Width = e.Typ.Width
   834  		typs[i].Size = e.Typ.Size
   835  		typs[i].Scale = e.Typ.Scale
   836  		typs[i].Precision = e.Typ.Precision
   837  	}
   838  	return &group.Argument{
   839  		Aggs:      aggs,
   840  		MultiAggs: multiaggs,
   841  		Types:     typs,
   842  		NeedEval:  needEval,
   843  		Exprs:     n.GroupBy,
   844  		Ibucket:   uint64(ibucket),
   845  		Nbucket:   uint64(nbucket),
   846  	}
   847  }
   848  
   849  // ibucket: bucket number
   850  // nbucket:
   851  // construct operator argument
   852  func constructIntersectAll(_ *plan.Node, proc *process.Process, ibucket, nbucket int) *intersectall.Argument {
   853  	return &intersectall.Argument{
   854  		IBucket: uint64(ibucket),
   855  		NBucket: uint64(nbucket),
   856  	}
   857  }
   858  
   859  func constructMinus(n *plan.Node, proc *process.Process, ibucket, nbucket int) *minus.Argument {
   860  	return &minus.Argument{
   861  		IBucket: uint64(ibucket),
   862  		NBucket: uint64(nbucket),
   863  	}
   864  }
   865  
   866  func constructIntersect(n *plan.Node, proc *process.Process, ibucket, nbucket int) *intersect.Argument {
   867  	return &intersect.Argument{
   868  		IBucket: uint64(ibucket),
   869  		NBucket: uint64(nbucket),
   870  	}
   871  }
   872  
   873  func constructDispatchLocal(all bool, regs []*process.WaitRegister) *dispatch.Argument {
   874  	arg := new(dispatch.Argument)
   875  	arg.LocalRegs = regs
   876  	if all {
   877  		arg.FuncId = dispatch.SendToAllLocalFunc
   878  	} else {
   879  		arg.FuncId = dispatch.SendToAnyLocalFunc
   880  	}
   881  
   882  	return arg
   883  }
   884  
   885  // ShuffleJoinDispatch is a cross-cn dispath
   886  // and it will send same batch to all register
   887  func constructBroadcastJoinDispatch(idx int, ss []*Scope, currentCNAddr string, proc *process.Process) *dispatch.Argument {
   888  	arg := new(dispatch.Argument)
   889  
   890  	scopeLen := len(ss)
   891  	arg.LocalRegs = make([]*process.WaitRegister, 0, scopeLen)
   892  	arg.RemoteRegs = make([]colexec.ReceiveInfo, 0, scopeLen)
   893  
   894  	hasRemote := false
   895  	for _, s := range ss {
   896  		if s.IsEnd {
   897  			continue
   898  		}
   899  
   900  		if len(s.NodeInfo.Addr) == 0 || len(currentCNAddr) == 0 ||
   901  			strings.Split(currentCNAddr, ":")[0] == strings.Split(s.NodeInfo.Addr, ":")[0] {
   902  			// Local reg.
   903  			// Put them into arg.LocalRegs
   904  			arg.LocalRegs = append(arg.LocalRegs, s.Proc.Reg.MergeReceivers[idx])
   905  		} else {
   906  			// Remote reg.
   907  			// Generate uuid for them and put into arg.RemoteRegs & scope. receive info
   908  			hasRemote = true
   909  			newUuid := uuid.New()
   910  
   911  			arg.RemoteRegs = append(arg.RemoteRegs, colexec.ReceiveInfo{
   912  				Uuid:     newUuid,
   913  				NodeAddr: s.NodeInfo.Addr,
   914  			})
   915  
   916  			s.RemoteReceivRegInfos = append(s.RemoteReceivRegInfos, RemoteReceivRegInfo{
   917  				Idx:      idx,
   918  				Uuid:     newUuid,
   919  				FromAddr: currentCNAddr,
   920  			})
   921  		}
   922  	}
   923  
   924  	if hasRemote {
   925  		arg.FuncId = dispatch.SendToAllFunc
   926  	} else {
   927  		arg.FuncId = dispatch.SendToAllLocalFunc
   928  	}
   929  
   930  	return arg
   931  }
   932  
   933  func constructMergeGroup(_ *plan.Node, needEval bool) *mergegroup.Argument {
   934  	return &mergegroup.Argument{
   935  		NeedEval: needEval,
   936  	}
   937  }
   938  
   939  func constructMergeTop(n *plan.Node, topN int64) *mergetop.Argument {
   940  	return &mergetop.Argument{
   941  		Fs:    n.OrderBy,
   942  		Limit: topN,
   943  	}
   944  }
   945  
   946  func constructMergeOffset(n *plan.Node, proc *process.Process) *mergeoffset.Argument {
   947  	vec, err := colexec.EvalExpr(constBat, proc, n.Offset)
   948  	if err != nil {
   949  		panic(err)
   950  	}
   951  	defer vec.Free(proc.Mp())
   952  	return &mergeoffset.Argument{
   953  		Offset: uint64(vec.Col.([]int64)[0]),
   954  	}
   955  }
   956  
   957  func constructMergeLimit(n *plan.Node, proc *process.Process) *mergelimit.Argument {
   958  	vec, err := colexec.EvalExpr(constBat, proc, n.Limit)
   959  	if err != nil {
   960  		panic(err)
   961  	}
   962  	defer vec.Free(proc.Mp())
   963  	return &mergelimit.Argument{
   964  		Limit: uint64(vec.Col.([]int64)[0]),
   965  	}
   966  }
   967  
   968  func constructMergeOrder(n *plan.Node, proc *process.Process) *mergeorder.Argument {
   969  	return &mergeorder.Argument{
   970  		Fs: n.OrderBy,
   971  	}
   972  }
   973  
   974  func constructLoopJoin(n *plan.Node, typs []types.Type, proc *process.Process) *loopjoin.Argument {
   975  	result := make([]colexec.ResultPos, len(n.ProjectList))
   976  	for i, expr := range n.ProjectList {
   977  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
   978  	}
   979  	return &loopjoin.Argument{
   980  		Typs:   typs,
   981  		Result: result,
   982  		Cond:   colexec.RewriteFilterExprList(n.OnList),
   983  	}
   984  }
   985  
   986  func constructLoopSemi(n *plan.Node, typs []types.Type, proc *process.Process) *loopsemi.Argument {
   987  	result := make([]int32, len(n.ProjectList))
   988  	for i, expr := range n.ProjectList {
   989  		rel, pos := constructJoinResult(expr, proc)
   990  		if rel != 0 {
   991  			panic(moerr.NewNYI(proc.Ctx, "loop semi result '%s'", expr))
   992  		}
   993  		result[i] = pos
   994  	}
   995  	return &loopsemi.Argument{
   996  		Typs:   typs,
   997  		Result: result,
   998  		Cond:   colexec.RewriteFilterExprList(n.OnList),
   999  	}
  1000  }
  1001  
  1002  func constructLoopLeft(n *plan.Node, typs []types.Type, proc *process.Process) *loopleft.Argument {
  1003  	result := make([]colexec.ResultPos, len(n.ProjectList))
  1004  	for i, expr := range n.ProjectList {
  1005  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
  1006  	}
  1007  	return &loopleft.Argument{
  1008  		Typs:   typs,
  1009  		Result: result,
  1010  		Cond:   colexec.RewriteFilterExprList(n.OnList),
  1011  	}
  1012  }
  1013  
  1014  func constructLoopSingle(n *plan.Node, typs []types.Type, proc *process.Process) *loopsingle.Argument {
  1015  	result := make([]colexec.ResultPos, len(n.ProjectList))
  1016  	for i, expr := range n.ProjectList {
  1017  		result[i].Rel, result[i].Pos = constructJoinResult(expr, proc)
  1018  	}
  1019  	return &loopsingle.Argument{
  1020  		Result: result,
  1021  		Cond:   colexec.RewriteFilterExprList(n.OnList),
  1022  	}
  1023  }
  1024  
  1025  func constructLoopAnti(n *plan.Node, typs []types.Type, proc *process.Process) *loopanti.Argument {
  1026  	result := make([]int32, len(n.ProjectList))
  1027  	for i, expr := range n.ProjectList {
  1028  		rel, pos := constructJoinResult(expr, proc)
  1029  		if rel != 0 {
  1030  			panic(moerr.NewNYI(proc.Ctx, "loop anti result '%s'", expr))
  1031  		}
  1032  		result[i] = pos
  1033  	}
  1034  	return &loopanti.Argument{
  1035  		Typs:   typs,
  1036  		Result: result,
  1037  		Cond:   colexec.RewriteFilterExprList(n.OnList),
  1038  	}
  1039  }
  1040  
  1041  func constructLoopMark(n *plan.Node, typs []types.Type, proc *process.Process) *loopmark.Argument {
  1042  	result := make([]int32, len(n.ProjectList))
  1043  	for i, expr := range n.ProjectList {
  1044  		rel, pos := constructJoinResult(expr, proc)
  1045  		if rel == 0 {
  1046  			result[i] = pos
  1047  		} else if rel == -1 {
  1048  			result[i] = -1
  1049  		} else {
  1050  			panic(moerr.NewNYI(proc.Ctx, "loop mark result '%s'", expr))
  1051  		}
  1052  	}
  1053  	return &loopmark.Argument{
  1054  		Typs:   typs,
  1055  		Result: result,
  1056  		Cond:   colexec.RewriteFilterExprList(n.OnList),
  1057  	}
  1058  }
  1059  
  1060  func constructHashBuild(in vm.Instruction, proc *process.Process) *hashbuild.Argument {
  1061  	switch in.Op {
  1062  	case vm.Anti:
  1063  		arg := in.Arg.(*anti.Argument)
  1064  		return &hashbuild.Argument{
  1065  			NeedHashMap: true,
  1066  			Typs:        arg.Typs,
  1067  			Conditions:  arg.Conditions[1],
  1068  		}
  1069  	case vm.Mark:
  1070  		arg := in.Arg.(*mark.Argument)
  1071  		return &hashbuild.Argument{
  1072  			NeedHashMap:    true,
  1073  			NeedSelectList: true,
  1074  			Typs:           arg.Typs,
  1075  			Conditions:     arg.Conditions[1],
  1076  		}
  1077  	case vm.Join:
  1078  		arg := in.Arg.(*join.Argument)
  1079  		return &hashbuild.Argument{
  1080  			NeedHashMap:    true,
  1081  			NeedSelectList: true,
  1082  			Typs:           arg.Typs,
  1083  			Conditions:     arg.Conditions[1],
  1084  		}
  1085  	case vm.Left:
  1086  		arg := in.Arg.(*left.Argument)
  1087  		return &hashbuild.Argument{
  1088  			NeedHashMap:    true,
  1089  			NeedSelectList: true,
  1090  			Typs:           arg.Typs,
  1091  			Conditions:     arg.Conditions[1],
  1092  		}
  1093  	case vm.Semi:
  1094  		arg := in.Arg.(*semi.Argument)
  1095  		return &hashbuild.Argument{
  1096  			NeedHashMap: true,
  1097  			Typs:        arg.Typs,
  1098  			Conditions:  arg.Conditions[1],
  1099  		}
  1100  	case vm.Single:
  1101  		arg := in.Arg.(*single.Argument)
  1102  		return &hashbuild.Argument{
  1103  			NeedHashMap:    true,
  1104  			NeedSelectList: true,
  1105  			Typs:           arg.Typs,
  1106  			Conditions:     arg.Conditions[1],
  1107  		}
  1108  	case vm.Product:
  1109  		arg := in.Arg.(*product.Argument)
  1110  		return &hashbuild.Argument{
  1111  			NeedHashMap:    false,
  1112  			NeedSelectList: true,
  1113  			Typs:           arg.Typs,
  1114  		}
  1115  	case vm.LoopAnti:
  1116  		arg := in.Arg.(*loopanti.Argument)
  1117  		return &hashbuild.Argument{
  1118  			NeedHashMap:    false,
  1119  			NeedSelectList: true,
  1120  			Typs:           arg.Typs,
  1121  		}
  1122  	case vm.LoopJoin:
  1123  		arg := in.Arg.(*loopjoin.Argument)
  1124  		return &hashbuild.Argument{
  1125  			NeedHashMap:    false,
  1126  			NeedSelectList: true,
  1127  			Typs:           arg.Typs,
  1128  		}
  1129  	case vm.LoopLeft:
  1130  		arg := in.Arg.(*loopleft.Argument)
  1131  		return &hashbuild.Argument{
  1132  			NeedHashMap:    false,
  1133  			NeedSelectList: true,
  1134  			Typs:           arg.Typs,
  1135  		}
  1136  	case vm.LoopSemi:
  1137  		arg := in.Arg.(*loopsemi.Argument)
  1138  		return &hashbuild.Argument{
  1139  			NeedHashMap:    false,
  1140  			NeedSelectList: true,
  1141  			Typs:           arg.Typs,
  1142  		}
  1143  	case vm.LoopSingle:
  1144  		arg := in.Arg.(*loopsingle.Argument)
  1145  		return &hashbuild.Argument{
  1146  			NeedHashMap:    false,
  1147  			NeedSelectList: true,
  1148  			Typs:           arg.Typs,
  1149  		}
  1150  	case vm.LoopMark:
  1151  		arg := in.Arg.(*loopmark.Argument)
  1152  		return &hashbuild.Argument{
  1153  			NeedHashMap:    false,
  1154  			NeedSelectList: true,
  1155  			Typs:           arg.Typs,
  1156  		}
  1157  
  1158  	default:
  1159  		panic(moerr.NewInternalError(proc.Ctx, "unsupport join type '%v'", in.Op))
  1160  	}
  1161  }
  1162  
  1163  func constructJoinResult(expr *plan.Expr, proc *process.Process) (int32, int32) {
  1164  	e, ok := expr.Expr.(*plan.Expr_Col)
  1165  	if !ok {
  1166  		panic(moerr.NewNYI(proc.Ctx, "join result '%s'", expr))
  1167  	}
  1168  	return e.Col.RelPos, e.Col.ColPos
  1169  }
  1170  
  1171  func constructJoinConditions(exprs []*plan.Expr, proc *process.Process) [][]*plan.Expr {
  1172  	conds := make([][]*plan.Expr, 2)
  1173  	conds[0] = make([]*plan.Expr, len(exprs))
  1174  	conds[1] = make([]*plan.Expr, len(exprs))
  1175  	for i, expr := range exprs {
  1176  		conds[0][i], conds[1][i] = constructJoinCondition(expr, proc)
  1177  	}
  1178  	return conds
  1179  }
  1180  
  1181  func constructJoinCondition(expr *plan.Expr, proc *process.Process) (*plan.Expr, *plan.Expr) {
  1182  	if e, ok := expr.Expr.(*plan.Expr_C); ok { // constant bool
  1183  		b, ok := e.C.Value.(*plan.Const_Bval)
  1184  		if !ok {
  1185  			panic(moerr.NewNYI(proc.Ctx, "join condition '%s'", expr))
  1186  		}
  1187  		if b.Bval {
  1188  			return expr, expr
  1189  		}
  1190  		return expr, &plan.Expr{
  1191  			Typ: expr.Typ,
  1192  			Expr: &plan.Expr_C{
  1193  				C: &plan.Const{
  1194  					Value: &plan.Const_Bval{Bval: true},
  1195  				},
  1196  			},
  1197  		}
  1198  	}
  1199  	e, ok := expr.Expr.(*plan.Expr_F)
  1200  	if !ok || !supportedJoinCondition(e.F.Func.GetObj()) {
  1201  		panic(moerr.NewNYI(proc.Ctx, "join condition '%s'", expr))
  1202  	}
  1203  	if exprRelPos(e.F.Args[0]) == 1 {
  1204  		return e.F.Args[1], e.F.Args[0]
  1205  	}
  1206  	return e.F.Args[0], e.F.Args[1]
  1207  }
  1208  
  1209  func isEquiJoin(exprs []*plan.Expr) bool {
  1210  	for _, expr := range exprs {
  1211  		if e, ok := expr.Expr.(*plan.Expr_F); ok {
  1212  			if !supportedJoinCondition(e.F.Func.GetObj()) {
  1213  				continue
  1214  			}
  1215  			lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1)
  1216  			if lpos == -1 || rpos == -1 || (lpos == rpos) {
  1217  				continue
  1218  			}
  1219  			return true
  1220  		}
  1221  	}
  1222  	return false || isEquiJoin0(exprs)
  1223  }
  1224  
  1225  func isEquiJoin0(exprs []*plan.Expr) bool {
  1226  	for _, expr := range exprs {
  1227  		if e, ok := expr.Expr.(*plan.Expr_F); ok {
  1228  			if !supportedJoinCondition(e.F.Func.GetObj()) {
  1229  				return false
  1230  			}
  1231  			lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1)
  1232  			if lpos == -1 || rpos == -1 || (lpos == rpos) {
  1233  				return false
  1234  			}
  1235  		}
  1236  	}
  1237  	return true
  1238  }
  1239  
  1240  func extraJoinConditions(exprs []*plan.Expr) (*plan.Expr, []*plan.Expr) {
  1241  	exprs = colexec.SplitAndExprs(exprs)
  1242  	eqConds := make([]*plan.Expr, 0, len(exprs))
  1243  	notEqConds := make([]*plan.Expr, 0, len(exprs))
  1244  	for i, expr := range exprs {
  1245  		if e, ok := expr.Expr.(*plan.Expr_F); ok {
  1246  			if !supportedJoinCondition(e.F.Func.GetObj()) {
  1247  				notEqConds = append(notEqConds, exprs[i])
  1248  				continue
  1249  			}
  1250  			lpos, rpos := hasColExpr(e.F.Args[0], -1), hasColExpr(e.F.Args[1], -1)
  1251  			if lpos == -1 || rpos == -1 || (lpos == rpos) {
  1252  				notEqConds = append(notEqConds, exprs[i])
  1253  				continue
  1254  			}
  1255  			eqConds = append(eqConds, exprs[i])
  1256  		}
  1257  	}
  1258  	if len(notEqConds) == 0 {
  1259  		return nil, eqConds
  1260  	}
  1261  	return colexec.RewriteFilterExprList(notEqConds), eqConds
  1262  }
  1263  
  1264  func supportedJoinCondition(id int64) bool {
  1265  	fid, _ := function.DecodeOverloadID(id)
  1266  	return fid == function.EQUAL
  1267  }
  1268  
  1269  func hasColExpr(expr *plan.Expr, pos int32) int32 {
  1270  	switch e := expr.Expr.(type) {
  1271  	case *plan.Expr_Col:
  1272  		if pos == -1 {
  1273  			return e.Col.RelPos
  1274  		}
  1275  		if pos != e.Col.RelPos {
  1276  			return -1
  1277  		}
  1278  		return pos
  1279  	case *plan.Expr_F:
  1280  		for i := range e.F.Args {
  1281  			pos0 := hasColExpr(e.F.Args[i], pos)
  1282  			switch {
  1283  			case pos0 == -1:
  1284  			case pos == -1:
  1285  				pos = pos0
  1286  			case pos != pos0:
  1287  				return -1
  1288  			}
  1289  		}
  1290  		return pos
  1291  	default:
  1292  		return pos
  1293  	}
  1294  }
  1295  
  1296  func exprRelPos(expr *plan.Expr) int32 {
  1297  	switch e := expr.Expr.(type) {
  1298  	case *plan.Expr_Col:
  1299  		return e.Col.RelPos
  1300  	case *plan.Expr_F:
  1301  		for i := range e.F.Args {
  1302  			if relPos := exprRelPos(e.F.Args[i]); relPos >= 0 {
  1303  				return relPos
  1304  			}
  1305  		}
  1306  	}
  1307  	return -1
  1308  }
  1309  
  1310  // Get the 'engine.Relation' of the table by using 'ObjectRef' and 'TableDef', if 'TableDef' is nil, the relations of its index table will not be obtained
  1311  // the first return value is Relation of the original table
  1312  // the second return value is Relations of index tables
  1313  func getRel(ctx context.Context, proc *process.Process, eg engine.Engine, ref *plan.ObjectRef, tableDef *plan.TableDef) (engine.Relation, []engine.Relation, error) {
  1314  	var dbSource engine.Database
  1315  	var relation engine.Relation
  1316  	var err error
  1317  	var isTemp bool
  1318  	oldDbName := ref.SchemaName
  1319  	if ref.SchemaName != "" {
  1320  		dbSource, err = eg.Database(ctx, ref.SchemaName, proc.TxnOperator)
  1321  		if err != nil {
  1322  			return nil, nil, err
  1323  		}
  1324  		relation, err = dbSource.Relation(ctx, ref.ObjName)
  1325  		if err == nil {
  1326  			isTemp = false
  1327  		} else {
  1328  			dbSource, err = eg.Database(ctx, defines.TEMPORARY_DBNAME, proc.TxnOperator)
  1329  			if err != nil {
  1330  				return nil, nil, err
  1331  			}
  1332  			newObjeName := engine.GetTempTableName(ref.SchemaName, ref.ObjName)
  1333  			newSchemaName := defines.TEMPORARY_DBNAME
  1334  			ref.SchemaName = newSchemaName
  1335  			ref.ObjName = newObjeName
  1336  			relation, err = dbSource.Relation(ctx, newObjeName)
  1337  			if err != nil {
  1338  				return nil, nil, err
  1339  			}
  1340  			isTemp = true
  1341  		}
  1342  	} else {
  1343  		_, _, relation, err = eg.GetRelationById(ctx, proc.TxnOperator, uint64(ref.Obj))
  1344  		if err != nil {
  1345  			return nil, nil, err
  1346  		}
  1347  	}
  1348  
  1349  	var uniqueIndexTables []engine.Relation
  1350  	if tableDef != nil {
  1351  		uniqueIndexTables = make([]engine.Relation, 0)
  1352  		if tableDef.Indexes != nil {
  1353  			for _, indexdef := range tableDef.Indexes {
  1354  				if indexdef.Unique {
  1355  					var indexTable engine.Relation
  1356  					if indexdef.TableExist {
  1357  						if isTemp {
  1358  							indexTable, err = dbSource.Relation(ctx, engine.GetTempTableName(oldDbName, indexdef.IndexTableName))
  1359  						} else {
  1360  							indexTable, err = dbSource.Relation(ctx, indexdef.IndexTableName)
  1361  						}
  1362  						if err != nil {
  1363  							return nil, nil, err
  1364  						}
  1365  						uniqueIndexTables = append(uniqueIndexTables, indexTable)
  1366  					}
  1367  				} else {
  1368  					continue
  1369  				}
  1370  			}
  1371  		}
  1372  	}
  1373  	return relation, uniqueIndexTables, err
  1374  }