github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/compile/debugTools.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  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/connector"
    22  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/dispatch"
    23  	"github.com/matrixorigin/matrixone/pkg/vm"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    25  )
    26  
    27  var debugInstructionNames = map[int]string{
    28  	vm.Top:          "top",
    29  	vm.Join:         "join",
    30  	vm.Semi:         "semi",
    31  	vm.Left:         "left",
    32  	vm.Limit:        "limit",
    33  	vm.Merge:        "merge",
    34  	vm.Order:        "order",
    35  	vm.Group:        "group",
    36  	vm.Output:       "output",
    37  	vm.Offset:       "offset",
    38  	vm.Product:      "product",
    39  	vm.Restrict:     "restrict",
    40  	vm.Dispatch:     "dispatch",
    41  	vm.Connector:    "connect",
    42  	vm.Projection:   "projection",
    43  	vm.Anti:         "anti",
    44  	vm.Single:       "single",
    45  	vm.Mark:         "mark",
    46  	vm.LoopJoin:     "loop join",
    47  	vm.LoopLeft:     "loop left",
    48  	vm.LoopSemi:     "loop semi",
    49  	vm.LoopAnti:     "loop anti",
    50  	vm.LoopSingle:   "loop single",
    51  	vm.LoopMark:     "loop mark",
    52  	vm.MergeTop:     "merge top",
    53  	vm.MergeLimit:   "merge limit",
    54  	vm.MergeOrder:   "merge order",
    55  	vm.MergeGroup:   "merge group",
    56  	vm.MergeOffset:  "merge offset",
    57  	vm.Deletion:     "delete",
    58  	vm.Insert:       "insert",
    59  	vm.Update:       "update",
    60  	vm.External:     "external",
    61  	vm.Minus:        "minus",
    62  	vm.Intersect:    "intersect",
    63  	vm.IntersectAll: "intersect all",
    64  	vm.HashBuild:    "hash build",
    65  }
    66  
    67  var debugMagicNames = map[int]string{
    68  	Merge:          "Merge",
    69  	Normal:         "Normal",
    70  	Remote:         "Remote",
    71  	Parallel:       "Parallel",
    72  	Pushdown:       "Pushdown",
    73  	CreateDatabase: "CreateDatabase",
    74  	CreateTable:    "CreateTable",
    75  	CreateIndex:    "CreateIndex",
    76  	DropDatabase:   "DropDatabase",
    77  	DropTable:      "DropTable",
    78  	DropIndex:      "DropIndex",
    79  	Deletion:       "Deletion",
    80  	Insert:         "Insert",
    81  	Update:         "Update",
    82  	InsertValues:   "InsertValues",
    83  }
    84  
    85  var _ = DebugShowScopes
    86  
    87  // DebugShowScopes show information of a scope structure.
    88  func DebugShowScopes(ss []*Scope) string {
    89  	var generateReceiverMap func(*Scope, map[*process.WaitRegister]int)
    90  	generateReceiverMap = func(s *Scope, mp map[*process.WaitRegister]int) {
    91  		for i := range s.PreScopes {
    92  			generateReceiverMap(s.PreScopes[i], mp)
    93  		}
    94  		if s.Proc == nil {
    95  			return
    96  		}
    97  		for i := range s.Proc.Reg.MergeReceivers {
    98  			mp[s.Proc.Reg.MergeReceivers[i]] = len(mp)
    99  		}
   100  	}
   101  
   102  	receiverMap := make(map[*process.WaitRegister]int)
   103  	for i := range ss {
   104  		generateReceiverMap(ss[i], receiverMap)
   105  	}
   106  
   107  	return debugShowScopes(ss, 0, receiverMap)
   108  }
   109  
   110  func debugShowScopes(ss []*Scope, gap int, rmp map[*process.WaitRegister]int) string {
   111  	// new line and start with n space
   112  	gapNextLine := func() string {
   113  		str := "\n"
   114  		for i := 0; i < gap; i++ {
   115  			str += " "
   116  		}
   117  		return str
   118  	}
   119  
   120  	// return n space
   121  	addGap := func() string {
   122  		str := ""
   123  		for i := 0; i < gap; i++ {
   124  			str += " "
   125  		}
   126  		return str
   127  	}
   128  
   129  	// get receiver id string
   130  	getReceiverStr := func(s *Scope, rs []*process.WaitRegister) string {
   131  		str := "["
   132  		for i := range rs {
   133  			remote := ""
   134  			for _, u := range s.RemoteReceivRegInfos {
   135  				if u.Idx == i {
   136  					remote = fmt.Sprintf("(%s)", u.Uuid)
   137  					break
   138  				}
   139  			}
   140  			if i != 0 {
   141  				str += ", "
   142  			}
   143  			if id, ok := rmp[rs[i]]; ok {
   144  				str += fmt.Sprintf("%d%s", id, remote)
   145  			} else {
   146  				str += "unknown"
   147  			}
   148  		}
   149  		str += "]"
   150  		return str
   151  	}
   152  
   153  	// convert magic to its string name
   154  	magicShow := func(magic int) string {
   155  		name, ok := debugMagicNames[magic]
   156  		if ok {
   157  			return name
   158  		}
   159  		return "unknown"
   160  	}
   161  
   162  	// explain the datasource
   163  	showDataSource := func(source *Source) string {
   164  		if source == nil {
   165  			return "nil"
   166  		}
   167  		s := fmt.Sprintf("%s.%s%s", source.SchemaName, source.RelationName, source.Attributes)
   168  		return strings.TrimLeft(s, ".")
   169  	}
   170  
   171  	// explain the operator information
   172  	showInstruction := func(instruction vm.Instruction, mp map[*process.WaitRegister]int) string {
   173  		id := instruction.Op
   174  		name, ok := debugInstructionNames[id]
   175  		if ok {
   176  			str := name
   177  			if id == vm.Connector {
   178  				var receiver = "unknown"
   179  				arg := instruction.Arg.(*connector.Argument)
   180  				if receiverId, okk := mp[arg.Reg]; okk {
   181  					receiver = fmt.Sprintf("%d", receiverId)
   182  				}
   183  				str += fmt.Sprintf(" to MergeReceiver %s", receiver)
   184  			}
   185  			if id == vm.Dispatch {
   186  				arg := instruction.Arg.(*dispatch.Argument)
   187  				chs := ""
   188  				for i := range arg.LocalRegs {
   189  					if i != 0 {
   190  						chs += ", "
   191  					}
   192  					if receiverId, okk := mp[arg.LocalRegs[i]]; okk {
   193  						chs += fmt.Sprintf("%d", receiverId)
   194  					} else {
   195  						chs += "unknown"
   196  					}
   197  				}
   198  				switch arg.FuncId {
   199  				case dispatch.SendToAllFunc, dispatch.SendToAllLocalFunc:
   200  					str += fmt.Sprintf(" to all of MergeReceiver [%s].", chs)
   201  				case dispatch.SendToAnyLocalFunc:
   202  					str += fmt.Sprintf(" to any of MergeReceiver [%s].", chs)
   203  				default:
   204  					str += fmt.Sprintf(" unknow type dispatch [%s].", chs)
   205  				}
   206  
   207  				if arg.FuncId == dispatch.SendToAllFunc && len(arg.RemoteRegs) != 0 {
   208  					remoteChs := ""
   209  					for i, reg := range arg.RemoteRegs {
   210  						if i != 0 {
   211  							remoteChs += ", "
   212  						}
   213  						remoteChs += fmt.Sprintf("[addr: %s, uuid %s]", reg.NodeAddr, reg.Uuid)
   214  					}
   215  					str += fmt.Sprintf(" cross-cn receiver info: %s", remoteChs)
   216  				}
   217  			}
   218  			return str
   219  		}
   220  		return "unknown"
   221  	}
   222  
   223  	var result string
   224  	for i := range ss {
   225  		str := addGap()
   226  		receiverStr := "nil"
   227  		if ss[i].Proc != nil {
   228  			receiverStr = getReceiverStr(ss[i], ss[i].Proc.Reg.MergeReceivers)
   229  		}
   230  		str += fmt.Sprintf("Scope %d (Magic: %s, Receiver: %s): [", i+1, magicShow(ss[i].Magic), receiverStr)
   231  		for j, instruction := range ss[i].Instructions {
   232  			if j != 0 {
   233  				str += " -> "
   234  			}
   235  			str += showInstruction(instruction, rmp)
   236  		}
   237  		str += "]"
   238  		if ss[i].DataSource != nil {
   239  			str += gapNextLine()
   240  			str += fmt.Sprintf("DataSource: %s,", showDataSource(ss[i].DataSource))
   241  		}
   242  		if len(ss[i].PreScopes) > 0 {
   243  			str += gapNextLine()
   244  			str += "  PreScopes: {"
   245  			str += debugShowScopes(ss[i].PreScopes, gap+2, rmp)
   246  			str += gapNextLine()
   247  			str += "}"
   248  		}
   249  		result += "\n"
   250  		result += str
   251  	}
   252  	return result
   253  }