func (r *ViewRegistry) View(databaseName, viewName string) (*View, error) {
	r.mutex.RLock()
	defer r.mutex.RUnlock()
	key := NewViewKey(databaseName, viewName)
	if view, ok := r.views[key]; ok {
		return view, nil
	}
	return nil, ErrViewDoesNotExist.New(databaseName, viewName)
}
View returns a pointer to the view specified by the pair {databaseName,
viewName}, returning an error if it does not exist.
package sql
import (
	"strings"
	"sync"
)
type View struct {
	name           string
	definition     Node
	textDefinition string
}
func NewView(name string, definition Node, textDefinition string) *View {
	return &View{name, definition, textDefinition}
}
func (v *View) Name() string {
	return v.name
}
func (v *View) Definition() Node {
	return v.definition
}
func (v *View) TextDefinition() string {
	return v.textDefinition
}
type ViewKey struct {
	dbName, viewName string
}
func NewViewKey(databaseName, viewName string) ViewKey {
	return ViewKey{strings.ToLower(databaseName), strings.ToLower(viewName)}
}
type ViewRegistry struct {
	mutex sync.RWMutex
	views map[ViewKey]*View
}
func NewViewRegistry() *ViewRegistry {
	return &ViewRegistry{
		views: make(map[ViewKey]*View),
	}
}
func (r *ViewRegistry) Register(database string, view *View) error {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	key := NewViewKey(database, view.Name())
	if _, ok := r.views[key]; ok {
		return ErrExistingView.New(database, view.Name())
	}
	r.views[key] = view
	return nil
}
func (r *ViewRegistry) Delete(databaseName, viewName string) error {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	key := NewViewKey(databaseName, viewName)
	if _, ok := r.views[key]; !ok {
		return ErrViewDoesNotExist.New(databaseName, viewName)
	}
	delete(r.views, key)
	return nil
}