-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
Copy pathexplain_factory.go
158 lines (137 loc) · 4.35 KB
/
explain_factory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2020 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package explain
import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/colinfo"
"github.com/cockroachdb/cockroach/pkg/sql/opt/exec"
)
// Factory implements exec.ExplainFactory. It wraps another factory and forwards
// all factory calls, while also recording the calls and arguments. The product
// of the factory is the Plan returned by ConstructPlan, which can be used to
// access the wrapped plan, as well as a parallel Node tree which can be used to
// produce EXPLAIN information.
type Factory struct {
wrappedFactory exec.Factory
}
var _ exec.ExplainFactory = &Factory{}
// Node in a plan tree; records the operation and arguments passed to the
// factory method and provides access to the corresponding exec.Node (produced
// by the wrapped factory).
type Node struct {
f *Factory
op execOperator
args interface{}
columns colinfo.ResultColumns
ordering colinfo.ColumnOrdering
children []*Node
annotations map[exec.ExplainAnnotationID]interface{}
wrappedNode exec.Node
}
var _ exec.Node = &Node{}
// ChildCount returns the number of children nodes.
func (n *Node) ChildCount() int {
return len(n.children)
}
// Child returns the i-th child.
func (n *Node) Child(idx int) *Node {
return n.children[idx]
}
// Columns returns the ResultColumns for this node.
func (n *Node) Columns() colinfo.ResultColumns {
return n.columns
}
// Ordering returns the required output ordering for this node; columns
// correspond to Columns().
func (n *Node) Ordering() colinfo.ColumnOrdering {
return n.ordering
}
// WrappedNode returns the corresponding exec.Node produced by the wrapped
// factory.
func (n *Node) WrappedNode() exec.Node {
return n.wrappedNode
}
func (f *Factory) newNode(
op execOperator, args interface{}, ordering exec.OutputOrdering, children ...*Node,
) (*Node, error) {
inputNodeCols := make([]colinfo.ResultColumns, len(children))
for i := range children {
inputNodeCols[i] = children[i].Columns()
}
columns, err := getResultColumns(op, args, inputNodeCols...)
if err != nil {
return nil, err
}
return &Node{
f: f,
op: op,
args: args,
columns: columns,
ordering: colinfo.ColumnOrdering(ordering),
children: children,
}, nil
}
// Plan is the result of ConstructPlan; provides access to the exec.Plan
// produced by the wrapped factory.
type Plan struct {
Root *Node
Subqueries []exec.Subquery
Cascades []exec.Cascade
Checks []*Node
WrappedPlan exec.Plan
}
var _ exec.Plan = &Plan{}
// NewFactory creates a new explain factory.
func NewFactory(wrappedFactory exec.Factory) *Factory {
return &Factory{
wrappedFactory: wrappedFactory,
}
}
// AnnotateNode is part of the exec.ExplainFactory interface.
func (f *Factory) AnnotateNode(execNode exec.Node, id exec.ExplainAnnotationID, value interface{}) {
n := execNode.(*Node)
if n.annotations == nil {
n.annotations = make(map[exec.ExplainAnnotationID]interface{})
}
n.annotations[id] = value
}
// ConstructPlan is part of the exec.Factory interface.
func (f *Factory) ConstructPlan(
root exec.Node, subqueries []exec.Subquery, cascades []exec.Cascade, checks []exec.Node,
) (exec.Plan, error) {
p := &Plan{
Root: root.(*Node),
Subqueries: subqueries,
Cascades: cascades,
Checks: make([]*Node, len(checks)),
}
for i := range checks {
p.Checks[i] = checks[i].(*Node)
}
wrappedSubqueries := append([]exec.Subquery(nil), subqueries...)
for i := range wrappedSubqueries {
wrappedSubqueries[i].Root = wrappedSubqueries[i].Root.(*Node).WrappedNode()
}
wrappedCascades := append([]exec.Cascade(nil), cascades...)
for i := range wrappedCascades {
wrappedCascades[i].Buffer = wrappedCascades[i].Buffer.(*Node).WrappedNode()
}
wrappedChecks := make([]exec.Node, len(checks))
for i := range wrappedChecks {
wrappedChecks[i] = checks[i].(*Node).WrappedNode()
}
var err error
p.WrappedPlan, err = f.wrappedFactory.ConstructPlan(
p.Root.WrappedNode(), wrappedSubqueries, wrappedCascades, wrappedChecks,
)
if err != nil {
return nil, err
}
return p, nil
}