github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/alter_default.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/go-mysql-server/sql" 21 "github.com/dolthub/go-mysql-server/sql/expression" 22 "github.com/dolthub/go-mysql-server/sql/transform" 23 ) 24 25 // AlterDefaultSet represents the ALTER COLUMN SET DEFAULT statement. 26 type AlterDefaultSet struct { 27 ddlNode 28 Table sql.Node 29 ColumnName string 30 Default *sql.ColumnDefaultValue 31 targetSchema sql.Schema 32 } 33 34 var _ sql.Node = (*AlterDefaultSet)(nil) 35 var _ sql.Expressioner = (*AlterDefaultSet)(nil) 36 var _ sql.SchemaTarget = (*AlterDefaultSet)(nil) 37 var _ sql.CollationCoercible = (*AlterDefaultSet)(nil) 38 39 // AlterDefaultDrop represents the ALTER COLUMN DROP DEFAULT statement. 40 type AlterDefaultDrop struct { 41 ddlNode 42 Table sql.Node 43 ColumnName string 44 targetSchema sql.Schema 45 } 46 47 var _ sql.Node = (*AlterDefaultDrop)(nil) 48 var _ sql.SchemaTarget = (*AlterDefaultDrop)(nil) 49 var _ sql.CollationCoercible = (*AlterDefaultDrop)(nil) 50 51 // NewAlterDefaultSet returns a *AlterDefaultSet node. 52 func NewAlterDefaultSet(database sql.Database, table sql.Node, columnName string, defVal *sql.ColumnDefaultValue) *AlterDefaultSet { 53 return &AlterDefaultSet{ 54 ddlNode: ddlNode{Db: database}, 55 Table: table, 56 ColumnName: columnName, 57 Default: defVal, 58 } 59 } 60 61 // String implements the sql.Node interface. 62 func (d *AlterDefaultSet) String() string { 63 return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT %s", d.Table.String(), d.ColumnName, d.Default.String()) 64 } 65 66 func (d *AlterDefaultSet) IsReadOnly() bool { 67 return false 68 } 69 70 // Resolved implements the sql.Node interface. 71 func (d *AlterDefaultDrop) Resolved() bool { 72 return d.ddlNode.Resolved() && d.Table.Resolved() && d.targetSchema.Resolved() 73 } 74 75 func (d *AlterDefaultDrop) IsReadOnly() bool { 76 return false 77 } 78 79 // WithChildren implements the sql.Node interface. 80 func (d *AlterDefaultSet) WithChildren(children ...sql.Node) (sql.Node, error) { 81 if len(children) != 1 { 82 return nil, sql.ErrInvalidChildrenNumber.New(d, len(children), 1) 83 } 84 ret := *d 85 ret.Table = children[0] 86 return &ret, nil 87 } 88 89 // Children implements the sql.Node interface. 90 func (d *AlterDefaultSet) Children() []sql.Node { 91 return []sql.Node{d.Table} 92 } 93 94 // CheckPrivileges implements the interface sql.Node. 95 func (d *AlterDefaultSet) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 96 subject := sql.PrivilegeCheckSubject{ 97 Database: d.Database().Name(), 98 Table: getTableName(d.Table), 99 } 100 return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Alter)) 101 } 102 103 // CollationCoercibility implements the interface sql.CollationCoercible. 104 func (d *AlterDefaultSet) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 105 return sql.Collation_binary, 7 106 } 107 108 // Resolved implements the sql.Node interface. 109 func (d *AlterDefaultSet) Resolved() bool { 110 return d.ddlNode.Resolved() && d.Table.Resolved() && d.Default.Resolved() && d.targetSchema.Resolved() 111 } 112 113 func (d *AlterDefaultSet) Expressions() []sql.Expression { 114 return append(transform.WrappedColumnDefaults(d.targetSchema), expression.WrapExpressions(d.Default)...) 115 } 116 117 func (d AlterDefaultSet) WithExpressions(exprs ...sql.Expression) (sql.Node, error) { 118 if len(exprs) != 1+len(d.targetSchema) { 119 return nil, sql.ErrInvalidChildrenNumber.New(d, len(exprs), 1+len(d.targetSchema)) 120 } 121 122 sch, err := transform.SchemaWithDefaults(d.targetSchema, exprs[:len(d.targetSchema)]) 123 if err != nil { 124 return nil, err 125 } 126 d.targetSchema = sch 127 128 unwrappedColDefVal, ok := exprs[len(exprs)-1].(*expression.Wrapper).Unwrap().(*sql.ColumnDefaultValue) 129 if ok { 130 d.Default = unwrappedColDefVal 131 } else { // nil fails type check 132 d.Default = nil 133 } 134 return &d, nil 135 } 136 137 func (d AlterDefaultSet) WithTargetSchema(schema sql.Schema) (sql.Node, error) { 138 d.targetSchema = schema 139 return &d, nil 140 } 141 142 func (d *AlterDefaultSet) TargetSchema() sql.Schema { 143 return d.targetSchema 144 } 145 146 func (d *AlterDefaultSet) WithDatabase(database sql.Database) (sql.Node, error) { 147 na := *d 148 na.Db = database 149 return &na, nil 150 } 151 152 func (d AlterDefaultSet) WithDefault(expr sql.Expression) (sql.Node, error) { 153 newDefault := expr.(*expression.Wrapper).Unwrap().(*sql.ColumnDefaultValue) 154 d.Default = newDefault 155 return &d, nil 156 } 157 158 // NewAlterDefaultDrop returns a *AlterDefaultDrop node. 159 func NewAlterDefaultDrop(database sql.Database, table sql.Node, columnName string) *AlterDefaultDrop { 160 return &AlterDefaultDrop{ 161 ddlNode: ddlNode{Db: database}, 162 Table: table, 163 ColumnName: columnName, 164 } 165 } 166 167 // String implements the sql.Node interface. 168 func (d *AlterDefaultDrop) String() string { 169 return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT", getTableName(d.Table), d.ColumnName) 170 } 171 172 // WithChildren implements the sql.Node interface. 173 func (d *AlterDefaultDrop) WithChildren(children ...sql.Node) (sql.Node, error) { 174 if len(children) != 1 { 175 return nil, sql.ErrInvalidChildrenNumber.New(d, len(children), 1) 176 } 177 ret := *d 178 ret.Table = children[0] 179 return &ret, nil 180 } 181 182 // Children implements the sql.Node interface. 183 func (d *AlterDefaultDrop) Children() []sql.Node { 184 return []sql.Node{d.Table} 185 } 186 187 func (d AlterDefaultDrop) WithTargetSchema(schema sql.Schema) (sql.Node, error) { 188 d.targetSchema = schema 189 return &d, nil 190 } 191 192 func (d *AlterDefaultDrop) TargetSchema() sql.Schema { 193 return d.targetSchema 194 } 195 196 func (d *AlterDefaultDrop) Expressions() []sql.Expression { 197 return transform.WrappedColumnDefaults(d.targetSchema) 198 } 199 200 func (d AlterDefaultDrop) WithExpressions(exprs ...sql.Expression) (sql.Node, error) { 201 if len(exprs) != len(d.targetSchema) { 202 return nil, sql.ErrInvalidChildrenNumber.New(d, len(exprs), len(d.targetSchema)) 203 } 204 205 sch, err := transform.SchemaWithDefaults(d.targetSchema, exprs[:len(d.targetSchema)]) 206 if err != nil { 207 return nil, err 208 } 209 d.targetSchema = sch 210 211 return &d, nil 212 } 213 214 // CheckPrivileges implements the interface sql.Node. 215 func (d *AlterDefaultDrop) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 216 subject := sql.PrivilegeCheckSubject{ 217 Database: d.Db.Name(), 218 Table: getTableName(d.Table), 219 Column: d.ColumnName, 220 } 221 222 return opChecker.UserHasPrivileges(ctx, 223 sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Alter)) 224 } 225 226 // CollationCoercibility implements the interface sql.CollationCoercible. 227 func (d *AlterDefaultDrop) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 228 return sql.Collation_binary, 7 229 } 230 231 // WithDatabase implements the sql.Databaser interface. 232 func (d *AlterDefaultDrop) WithDatabase(db sql.Database) (sql.Node, error) { 233 nd := *d 234 nd.Db = db 235 return &nd, nil 236 } 237 238 // getTableFromDatabase returns the related sql.Table from a database in the case of a sql.Databasw 239 func getTableFromDatabase(ctx *sql.Context, db sql.Database, tableNode sql.Node) (sql.Table, error) { 240 // Grab the table fresh from the database. 241 tableName := getTableName(tableNode) 242 243 table, ok, err := db.GetTableInsensitive(ctx, tableName) 244 if err != nil { 245 return nil, err 246 } 247 if !ok { 248 return nil, sql.ErrTableNotFound.New(tableName) 249 } 250 251 return table, nil 252 }