()
| 186 | } |
| 187 | |
| 188 | func (n *Node) String() string { |
| 189 | metadataFields := n.PlanNode.GetMetadata().GetFields() |
| 190 | |
| 191 | var operator string |
| 192 | { |
| 193 | var components []string |
| 194 | for _, s := range []string{ |
| 195 | metadataFields["call_type"].GetStringValue(), |
| 196 | metadataFields["iterator_type"].GetStringValue(), |
| 197 | strings.TrimSuffix(metadataFields["scan_type"].GetStringValue(), "Scan"), |
| 198 | n.PlanNode.GetDisplayName(), |
| 199 | } { |
| 200 | if s != "" { |
| 201 | components = append(components, s) |
| 202 | } |
| 203 | } |
| 204 | operator = strings.Join(components, " ") |
| 205 | } |
| 206 | |
| 207 | var metadata string |
| 208 | { |
| 209 | fields := make([]string, 0) |
| 210 | for k, v := range metadataFields { |
| 211 | switch k { |
| 212 | case "call_type", "iterator_type": // Skip because it is displayed in node title |
| 213 | continue |
| 214 | case "scan_target": // Skip because it is combined with scan_type |
| 215 | continue |
| 216 | case "subquery_cluster_node": // Skip because it is useless without displaying node id |
| 217 | continue |
| 218 | case "scan_type": |
| 219 | fields = append(fields, fmt.Sprintf("%s: %s", |
| 220 | strings.TrimSuffix(v.GetStringValue(), "Scan"), |
| 221 | metadataFields["scan_target"].GetStringValue())) |
| 222 | default: |
| 223 | fields = append(fields, fmt.Sprintf("%s: %s", k, v.GetStringValue())) |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | sort.Strings(fields) |
| 228 | |
| 229 | if len(fields) != 0 { |
| 230 | metadata = fmt.Sprintf(`(%s)`, strings.Join(fields, ", ")) |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | if metadata == "" { |
| 235 | return operator |
| 236 | } |
| 237 | return operator + " " + metadata |
| 238 | } |
| 239 | |
| 240 | func renderTreeWithStats(tree treeprint.Tree, linkType string, node *Node) { |
| 241 | // Scalar operator is rendered if and only if it is linked as Scalar type(Scalar/Array Subquery) |
no outgoing calls