forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 2
/
plan.go
158 lines (148 loc) · 4.67 KB
/
plan.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 2015 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License. See the AUTHORS file
// for names of contributors.
//
// Author: Peter Mattis (peter@cockroachlabs.com)
package sql
import (
"fmt"
"github.com/cockroachdb/cockroach/client"
"github.com/cockroachdb/cockroach/sql/parser"
"github.com/cockroachdb/cockroach/util"
)
// planner is the centerpiece of SQL statement execution combining session
// state and database state with the logic for SQL execution.
type planner struct {
txn *client.Txn
session Session
user string
}
// makePlan creates the query plan for a single SQL statement. The returned
// plan needs to be iterated over using planNode.Next() and planNode.Values()
// in order to retrieve matching rows.
func (p *planner) makePlan(stmt parser.Statement) (planNode, error) {
// TODO(pmattis): It is somewhat premature to expand subqueries here as we
// should make sure the statement is otherwise valid first. But it is
// correct.
if err := p.expandSubqueries(stmt); err != nil {
return nil, err
}
switch n := stmt.(type) {
case *parser.BeginTransaction:
return p.BeginTransaction(n)
case *parser.CommitTransaction:
return p.CommitTransaction(n)
case *parser.CreateDatabase:
return p.CreateDatabase(n)
case *parser.CreateIndex:
return p.CreateIndex(n)
case *parser.CreateTable:
return p.CreateTable(n)
case *parser.Delete:
return p.Delete(n)
case *parser.DropDatabase:
return p.DropDatabase(n)
case *parser.DropTable:
return p.DropTable(n)
case *parser.Explain:
return p.Explain(n)
case *parser.Grant:
return p.Grant(n)
case *parser.Insert:
return p.Insert(n)
case *parser.ParenSelect:
return p.makePlan(n.Select)
case *parser.RenameColumn:
return p.RenameColumn(n)
case *parser.RenameDatabase:
return p.RenameDatabase(n)
case *parser.RenameIndex:
return p.RenameIndex(n)
case *parser.RenameTable:
return p.RenameTable(n)
case *parser.Revoke:
return p.Revoke(n)
case *parser.RollbackTransaction:
return p.RollbackTransaction(n)
case *parser.Select:
return p.Select(n)
case *parser.Set:
return p.Set(n)
case *parser.Show:
return p.Show(n)
case *parser.ShowColumns:
return p.ShowColumns(n)
case *parser.ShowDatabases:
return p.ShowDatabases(n)
case *parser.ShowGrants:
return p.ShowGrants(n)
case *parser.ShowIndex:
return p.ShowIndex(n)
case *parser.ShowTables:
return p.ShowTables(n)
case *parser.Truncate:
return p.Truncate(n)
case *parser.Update:
return p.Update(n)
case parser.Values:
return p.Values(n)
default:
return nil, fmt.Errorf("unknown statement type: %T", stmt)
}
}
func (p *planner) getAliasedTableDesc(n parser.TableExpr) (*TableDescriptor, error) {
ate, ok := n.(*parser.AliasedTableExpr)
if !ok {
return nil, util.Errorf("TODO(pmattis): unsupported FROM: %s", n)
}
table, ok := ate.Expr.(*parser.QualifiedName)
if !ok {
return nil, util.Errorf("TODO(pmattis): unsupported FROM: %s", n)
}
desc, err := p.getTableDesc(table)
if err != nil {
return nil, err
}
if ate.As != "" {
desc.Alias = string(ate.As)
} else {
desc.Alias = desc.Name
}
return desc, nil
}
// planNode defines the interface for executing a query or portion of a query.
type planNode interface {
// Columns returns the column names. The length of the returned slice is
// guaranteed to be equal to the length of the tuple returned by Values().
Columns() []string
// The indexes of the columns the output is ordered by. Indexes are 1-based
// and negative indexes indicate descending ordering. The []int result may be
// nil if no ordering has been performed.
Ordering() []int
// Values returns the values at the current row. The result is only valid
// until the next call to Next().
Values() parser.DTuple
// Next advances to the next row, returning false if an error is encountered
// or if there is no next row.
Next() bool
// Err returns the error, if any, encountered during iteration.
Err() error
// ExplainPlan returns a name and description and a list of child nodes.
ExplainPlan() (name, description string, children []planNode)
}
var _ planNode = &groupNode{}
var _ planNode = &scanNode{}
var _ planNode = &sortNode{}
var _ planNode = &valuesNode{}
// TODO(pmattis): joinNode.