forked from dolthub/go-mysql-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
create_view.go
146 lines (128 loc) · 4.24 KB
/
create_view.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
// Copyright 2020-2021 Dolthub, Inc.
//
// 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.
package plan
import (
"fmt"
"strings"
"github.com/Sndav/go-mysql-server/sql"
)
// CreateView is a node representing the creation (or replacement) of a view,
// which is defined by the Child node. The Columns member represent the
// explicit columns specified by the query, if any.
type CreateView struct {
UnaryNode
database sql.Database
Name string
Columns []string
Catalog *sql.Catalog
IsReplace bool
Definition *SubqueryAlias
}
// NewCreateView creates a CreateView node with the specified parameters,
// setting its catalog to nil.
func NewCreateView(
database sql.Database,
name string,
columns []string,
definition *SubqueryAlias,
isReplace bool,
) *CreateView {
return &CreateView{
UnaryNode{Child: definition},
database,
name,
columns,
nil,
isReplace,
definition,
}
}
// View returns the view that will be created by this node.
func (cv *CreateView) View() sql.View {
return cv.Definition.AsView()
}
// Children implements the Node interface. It returns the Child of the
// CreateView node; i.e., the definition of the view that will be created.
func (cv *CreateView) Children() []sql.Node {
return []sql.Node{cv.Child}
}
// Resolved implements the Node interface. This node is resolved if and only if
// the database and the Child are both resolved.
func (cv *CreateView) Resolved() bool {
_, ok := cv.database.(sql.UnresolvedDatabase)
return !ok && cv.Child.Resolved()
}
// RowIter implements the Node interface. When executed, this function creates
// (or replaces) the view. It can error if the CraeteView's IsReplace member is
// set to false and the view already exists. The RowIter returned is always
// empty.
func (cv *CreateView) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) {
view := cv.View()
registry := ctx.ViewRegistry
if cv.IsReplace {
err := registry.Delete(cv.database.Name(), view.Name())
if err != nil && !sql.ErrNonExistingView.Is(err) {
return sql.RowsToRowIter(), err
}
if dropper, ok := cv.database.(sql.ViewDropper); ok {
err := dropper.DropView(ctx, cv.Name)
if err != nil && !sql.ErrNonExistingView.Is(err) {
return sql.RowsToRowIter(), err
}
}
}
creator, ok := cv.database.(sql.ViewCreator)
if ok {
err := creator.CreateView(ctx, cv.Name, cv.Definition.TextDefinition)
if err != nil {
return sql.RowsToRowIter(), err
}
}
return sql.RowsToRowIter(), registry.Register(cv.database.Name(), view)
}
// Schema implements the Node interface. It always returns nil.
func (cv *CreateView) Schema() sql.Schema { return nil }
// String implements the fmt.Stringer interface, using sql.TreePrinter to
// generate the string.
func (cv *CreateView) String() string {
pr := sql.NewTreePrinter()
_ = pr.WriteNode("CreateView(%s)", cv.Name)
_ = pr.WriteChildren(
fmt.Sprintf("Columns (%s)", strings.Join(cv.Columns, ", ")),
cv.Child.String(),
)
return pr.String()
}
// WithChildren implements the Node interface. It only succeeds if the length
// of the specified children equals 1.
func (cv *CreateView) WithChildren(children ...sql.Node) (sql.Node, error) {
if len(children) != 1 {
return nil, sql.ErrInvalidChildrenNumber.New(cv, len(children), 1)
}
newCreate := *cv
newCreate.Child = children[0]
return &newCreate, nil
}
// Database implements the Databaser interface, and it returns the database in
// which CreateView will create the view.
func (cv *CreateView) Database() sql.Database {
return cv.database
}
// Database implements the Databaser interface, and it returns a copy of this
// node with the specified database.
func (cv *CreateView) WithDatabase(database sql.Database) (sql.Node, error) {
newCreate := *cv
newCreate.database = database
return &newCreate, nil
}