github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/vm.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 vm
    16  
    17  import (
    18  	"bytes"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  	"github.com/matrixorigin/matrixone/pkg/logutil"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    23  )
    24  
    25  func (ins *Instruction) MarshalBinary() ([]byte, error) {
    26  	return nil, nil
    27  }
    28  
    29  func (ins *Instruction) UnmarshalBinary(_ []byte) error {
    30  	return nil
    31  }
    32  
    33  // String range instructions and call each operator's string function to show a query plan
    34  func String(ins Instructions, buf *bytes.Buffer) {
    35  	for i, in := range ins {
    36  		if i > 0 {
    37  			buf.WriteString(" -> ")
    38  		}
    39  		in.Arg.String(buf)
    40  	}
    41  }
    42  
    43  // Prepare range instructions and do init work for each operator's argument by calling its prepare function
    44  func Prepare(ins Instructions, proc *process.Process) error {
    45  	for _, in := range ins {
    46  		if err := in.Arg.Prepare(proc); err != nil {
    47  			return err
    48  		}
    49  	}
    50  	return nil
    51  }
    52  
    53  func setAnalyzeInfo(ins Instructions, proc *process.Process) {
    54  	for i := 0; i < len(ins); i++ {
    55  		switch ins[i].Op {
    56  		case Output:
    57  			ins[i].Idx = -1
    58  		case TableScan:
    59  			ins[i].Idx = ins[i+1].Idx
    60  		}
    61  	}
    62  
    63  	idxMapMajor := make(map[int]int, 0)
    64  	idxMapMinor := make(map[int]int, 0)
    65  	for i := 0; i < len(ins); i++ {
    66  		info := &OperatorInfo{
    67  			Idx:     ins[i].Idx,
    68  			IsFirst: ins[i].IsFirst,
    69  			IsLast:  ins[i].IsLast,
    70  
    71  			CnAddr:      ins[i].CnAddr,
    72  			OperatorID:  ins[i].OperatorID,
    73  			ParallelID:  ins[i].ParallelID,
    74  			MaxParallel: ins[i].MaxParallel,
    75  		}
    76  		switch ins[i].Op {
    77  		case HashBuild, Restrict, MergeGroup, MergeOrder:
    78  			isMinor := true
    79  			if ins[i].Op == Restrict {
    80  				if ins[0].Op != TableScan && ins[0].Op != External {
    81  					isMinor = false // restrict operator is minor only for scan
    82  				}
    83  			}
    84  
    85  			if isMinor {
    86  				if info.Idx >= 0 && info.Idx < len(proc.AnalInfos) {
    87  					info.ParallelMajor = false
    88  					if pidx, ok := idxMapMinor[info.Idx]; ok {
    89  						info.ParallelIdx = pidx
    90  					} else {
    91  						pidx = proc.AnalInfos[info.Idx].AddNewParallel(false)
    92  						idxMapMinor[info.Idx] = pidx
    93  						info.ParallelIdx = pidx
    94  					}
    95  				}
    96  			} else {
    97  				info.ParallelIdx = -1
    98  			}
    99  
   100  		case TableScan, External, Order, Window, Group, Join, LoopJoin, Left, LoopLeft, Single, LoopSingle, Semi, RightSemi, LoopSemi, Anti, RightAnti, LoopAnti, Mark, LoopMark, Product:
   101  			info.ParallelMajor = true
   102  			if info.Idx >= 0 && info.Idx < len(proc.AnalInfos) {
   103  				if pidx, ok := idxMapMajor[info.Idx]; ok {
   104  					info.ParallelIdx = pidx
   105  				} else {
   106  					pidx = proc.AnalInfos[info.Idx].AddNewParallel(true)
   107  					idxMapMajor[info.Idx] = pidx
   108  					info.ParallelIdx = pidx
   109  				}
   110  			}
   111  		default:
   112  			info.ParallelIdx = -1 // do nothing for parallel analyze info
   113  		}
   114  		ins[i].Arg.SetInfo(info)
   115  	}
   116  }
   117  
   118  func Run(ins Instructions, proc *process.Process) (end bool, err error) {
   119  	defer func() {
   120  		if e := recover(); e != nil {
   121  			err = moerr.ConvertPanicError(proc.Ctx, e)
   122  			logutil.Errorf("panic in vm.Run: %v", err)
   123  		}
   124  	}()
   125  
   126  	setAnalyzeInfo(ins, proc)
   127  
   128  	for i := 1; i < len(ins); i++ {
   129  		ins[i].Arg.AppendChild(ins[i-1].Arg)
   130  	}
   131  
   132  	root := ins[len(ins)-1].Arg
   133  	end = false
   134  	for !end {
   135  		result, err := root.Call(proc)
   136  		if err != nil {
   137  			return true, err
   138  		}
   139  		end = result.Status == ExecStop || result.Batch == nil
   140  	}
   141  	return end, nil
   142  }