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  }