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 }