github.com/dolthub/go-mysql-server@v0.18.0/sql/viewregistry.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 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 sql 16 17 import ( 18 "strings" 19 "sync" 20 ) 21 22 // View is the parsed version of ViewDefinition 23 // Not meant to be used externally 24 type View struct { 25 name string 26 definition Node 27 textDefinition string 28 createViewStmt string 29 } 30 31 // NewView creates a View with the specified name and definition. 32 func NewView(name string, definition Node, textDefinition, createViewStmt string) *View { 33 return &View{name, definition, textDefinition, createViewStmt} 34 } 35 36 // Name returns the name of the view. 37 func (v *View) Name() string { 38 return v.name 39 } 40 41 // WithDefinition returns a new view with the updated definition 42 func (v *View) WithDefinition(def Node) *View { 43 ret := *v 44 ret.definition = def 45 return &ret 46 } 47 48 // Definition returns the definition of the view. 49 func (v *View) Definition() Node { 50 return v.definition 51 } 52 53 // TextDefinition returns the text definition of the view as originally defined. 54 func (v *View) TextDefinition() string { 55 return v.textDefinition 56 } 57 58 // CreateStatement returns the text create view statement of the view as originally defined. 59 func (v *View) CreateStatement() string { 60 return v.createViewStmt 61 } 62 63 // ViewKey is the key used to store view definitions 64 type ViewKey struct { 65 dbName, viewName string 66 } 67 68 // NewViewKey creates a ViewKey ensuring both names are lowercase. 69 func NewViewKey(databaseName, viewName string) ViewKey { 70 return ViewKey{strings.ToLower(databaseName), strings.ToLower(viewName)} 71 } 72 73 // ViewRegistry stores session-local views for databases that don't implement view storage. Each session gets a new 74 // view registry by default. Integrators that want views to persist across sessions should either implement 75 // sql.ViewDatabase, or construct their sessions to reuse the same ViewRegistry for each session. 76 type ViewRegistry struct { 77 mutex sync.RWMutex 78 views map[ViewKey]*View 79 } 80 81 // NewViewRegistry creates an empty ViewRegistry. 82 func NewViewRegistry() *ViewRegistry { 83 return &ViewRegistry{ 84 views: make(map[ViewKey]*View), 85 } 86 } 87 88 // Register adds the view specified by the pair {database, view.Name()}, 89 // returning an error if there is already an element with that key. 90 func (r *ViewRegistry) Register(database string, view *View) error { 91 r.mutex.Lock() 92 defer r.mutex.Unlock() 93 94 key := NewViewKey(database, view.Name()) 95 96 if _, ok := r.views[key]; ok { 97 return ErrExistingView.New(database, view.Name()) 98 } 99 100 r.views[key] = view 101 return nil 102 } 103 104 // Delete deletes the view specified by the pair {databaseName, viewName}, 105 // returning an error if it does not exist. 106 func (r *ViewRegistry) Delete(databaseName, viewName string) error { 107 r.mutex.Lock() 108 defer r.mutex.Unlock() 109 110 key := NewViewKey(databaseName, viewName) 111 112 if _, ok := r.views[key]; !ok { 113 return ErrViewDoesNotExist.New(databaseName, viewName) 114 } 115 116 delete(r.views, key) 117 return nil 118 } 119 120 // View returns a pointer to the view specified by the pair {databaseName, 121 // viewName}, returning an error if it does not exist. 122 func (r *ViewRegistry) View(databaseName, viewName string) (*View, bool) { 123 r.mutex.RLock() 124 defer r.mutex.RUnlock() 125 126 key := NewViewKey(databaseName, viewName) 127 128 view, ok := r.views[key] 129 return view, ok 130 } 131 132 // ViewsInDatabase returns an array of all the views registered under the 133 // specified database. 134 func (r *ViewRegistry) ViewsInDatabase(databaseName string) (views []*View) { 135 r.mutex.RLock() 136 defer r.mutex.RUnlock() 137 138 for key, value := range r.views { 139 if key.dbName == databaseName { 140 views = append(views, value) 141 } 142 } 143 144 return views 145 } 146 147 func (r *ViewRegistry) exists(databaseName, viewName string) bool { 148 key := NewViewKey(databaseName, viewName) 149 _, ok := r.views[key] 150 151 return ok 152 } 153 154 // Exists returns whether the specified key is already registered 155 func (r *ViewRegistry) Exists(databaseName, viewName string) bool { 156 r.mutex.RLock() 157 defer r.mutex.RUnlock() 158 159 return r.exists(databaseName, viewName) 160 }