github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/dbddl.go (about) 1 // Copyright 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 plan 16 17 import ( 18 "fmt" 19 20 "github.com/dolthub/vitess/go/vt/sqlparser" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/types" 24 ) 25 26 // CreateDB creates an in memory database that lasts the length of the process only. 27 type CreateDB struct { 28 Catalog sql.Catalog 29 DbName string 30 IfNotExists bool 31 Collation sql.CollationID 32 } 33 34 var _ sql.Node = (*CreateDB)(nil) 35 var _ sql.CollationCoercible = (*CreateDB)(nil) 36 37 func (c *CreateDB) Resolved() bool { 38 return true 39 } 40 41 func (c *CreateDB) IsReadOnly() bool { 42 return false 43 } 44 45 func (c *CreateDB) String() string { 46 ifNotExists := "" 47 if c.IfNotExists { 48 ifNotExists = " if not exists" 49 } 50 return fmt.Sprintf("%s database%s %v", sqlparser.CreateStr, ifNotExists, c.DbName) 51 } 52 53 func (c *CreateDB) Schema() sql.Schema { 54 return types.OkResultSchema 55 } 56 57 func (c *CreateDB) Children() []sql.Node { 58 return nil 59 } 60 61 func (c *CreateDB) WithChildren(children ...sql.Node) (sql.Node, error) { 62 return NillaryWithChildren(c, children...) 63 } 64 65 // CheckPrivileges implements the interface sql.Node. 66 func (c *CreateDB) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 67 return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(sql.PrivilegeCheckSubject{}, sql.PrivilegeType_Create)) 68 } 69 70 // CollationCoercibility implements the interface sql.CollationCoercible. 71 func (*CreateDB) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 72 return sql.Collation_binary, 7 73 } 74 75 // Database returns the name of the database that will be used. 76 func (c *CreateDB) Database() string { 77 return c.DbName 78 } 79 80 func NewCreateDatabase(dbName string, ifNotExists bool, collation sql.CollationID) *CreateDB { 81 return &CreateDB{ 82 DbName: dbName, 83 IfNotExists: ifNotExists, 84 Collation: collation, 85 } 86 } 87 88 // DropDB removes a databases from the Catalog and updates the active database if it gets removed itself. 89 type DropDB struct { 90 Catalog sql.Catalog 91 DbName string 92 IfExists bool 93 // EventScheduler is used to notify EventSchedulerStatus of database deletion, 94 // so the events of this database in the scheduler will be removed. 95 EventScheduler sql.EventScheduler 96 } 97 98 var _ sql.Node = (*DropDB)(nil) 99 var _ sql.CollationCoercible = (*DropDB)(nil) 100 var _ sql.EventSchedulerStatement = (*DropDB)(nil) 101 102 func (d *DropDB) Resolved() bool { 103 return true 104 } 105 106 func (d *DropDB) IsReadOnly() bool { 107 return false 108 } 109 110 func (d *DropDB) String() string { 111 ifExists := "" 112 if d.IfExists { 113 ifExists = " if exists" 114 } 115 return fmt.Sprintf("%s database%s %v", sqlparser.DropStr, ifExists, d.DbName) 116 } 117 118 func (d *DropDB) Schema() sql.Schema { 119 return types.OkResultSchema 120 } 121 122 func (d *DropDB) Children() []sql.Node { 123 return nil 124 } 125 126 func (d *DropDB) WithChildren(children ...sql.Node) (sql.Node, error) { 127 return NillaryWithChildren(d, children...) 128 } 129 130 // WithEventScheduler is used to drop all events from EventSchedulerStatus for DROP DATABASE. 131 func (d *DropDB) WithEventScheduler(scheduler sql.EventScheduler) sql.Node { 132 na := *d 133 na.EventScheduler = scheduler 134 return &na 135 } 136 137 // CheckPrivileges implements the interface sql.Node. 138 func (d *DropDB) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 139 return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(sql.PrivilegeCheckSubject{}, sql.PrivilegeType_Drop)) 140 } 141 142 // CollationCoercibility implements the interface sql.CollationCoercible. 143 func (*DropDB) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 144 return sql.Collation_binary, 7 145 } 146 147 func NewDropDatabase(dbName string, ifExists bool) *DropDB { 148 return &DropDB{ 149 DbName: dbName, 150 IfExists: ifExists, 151 } 152 } 153 154 // AlterDB alters a database from the Catalog. 155 type AlterDB struct { 156 Catalog sql.Catalog 157 dbName string 158 Collation sql.CollationID 159 } 160 161 var _ sql.Node = (*AlterDB)(nil) 162 var _ sql.CollationCoercible = (*AlterDB)(nil) 163 164 // Resolved implements the interface sql.Node. 165 func (c *AlterDB) Resolved() bool { 166 return true 167 } 168 169 func (c *AlterDB) IsReadOnly() bool { 170 return false 171 } 172 173 // String implements the interface sql.Node. 174 func (c *AlterDB) String() string { 175 var dbName string 176 if len(c.dbName) > 0 { 177 dbName = fmt.Sprintf(" %s", c.dbName) 178 } 179 return fmt.Sprintf("%s database%s collate %s", sqlparser.AlterStr, dbName, c.Collation.Name()) 180 } 181 182 // Schema implements the interface sql.Node. 183 func (c *AlterDB) Schema() sql.Schema { 184 return types.OkResultSchema 185 } 186 187 // Children implements the interface sql.Node. 188 func (c *AlterDB) Children() []sql.Node { 189 return nil 190 } 191 192 // WithChildren implements the interface sql.Node. 193 func (c *AlterDB) WithChildren(children ...sql.Node) (sql.Node, error) { 194 return NillaryWithChildren(c, children...) 195 } 196 197 // CheckPrivileges implements the interface sql.Node. 198 func (c *AlterDB) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 199 subject := sql.PrivilegeCheckSubject{ 200 Database: c.Database(ctx), 201 } 202 return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Alter)) 203 } 204 205 // CollationCoercibility implements the interface sql.CollationCoercible. 206 func (*AlterDB) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 207 return sql.Collation_binary, 7 208 } 209 210 // Database returns the name of the database that will be used. 211 func (c *AlterDB) Database(ctx *sql.Context) string { 212 if len(c.dbName) == 0 { 213 return ctx.GetCurrentDatabase() 214 } 215 return c.dbName 216 } 217 218 // NewAlterDatabase returns a new AlterDB. 219 func NewAlterDatabase(dbName string, collation sql.CollationID) *AlterDB { 220 return &AlterDB{ 221 dbName: dbName, 222 Collation: collation, 223 } 224 } 225 226 // GetDatabaseCollation returns a database's collation. Also handles when a database does not explicitly support collations. 227 func GetDatabaseCollation(ctx *sql.Context, db sql.Database) sql.CollationID { 228 collatedDb, ok := db.(sql.CollatedDatabase) 229 if !ok { 230 return sql.Collation_Default 231 } 232 collation := collatedDb.GetCollation(ctx) 233 if collation == sql.Collation_Unspecified { 234 return sql.Collation_Default 235 } 236 return collation 237 }