vitess.io/vitess@v0.16.2/go/vt/schemadiff/view.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package schemadiff 18 19 import ( 20 "strings" 21 22 "vitess.io/vitess/go/vt/sqlparser" 23 ) 24 25 type AlterViewEntityDiff struct { 26 from *CreateViewEntity 27 to *CreateViewEntity 28 alterView *sqlparser.AlterView 29 } 30 31 // IsEmpty implements EntityDiff 32 func (d *AlterViewEntityDiff) IsEmpty() bool { 33 return d.Statement() == nil 34 } 35 36 // Entities implements EntityDiff 37 func (d *AlterViewEntityDiff) Entities() (from Entity, to Entity) { 38 return d.from, d.to 39 } 40 41 // Statement implements EntityDiff 42 func (d *AlterViewEntityDiff) Statement() sqlparser.Statement { 43 if d == nil { 44 return nil 45 } 46 return d.alterView 47 } 48 49 // AlterView returns the underlying sqlparser.AlterView that was generated for the diff. 50 func (d *AlterViewEntityDiff) AlterView() *sqlparser.AlterView { 51 if d == nil { 52 return nil 53 } 54 return d.alterView 55 } 56 57 // StatementString implements EntityDiff 58 func (d *AlterViewEntityDiff) StatementString() (s string) { 59 if stmt := d.Statement(); stmt != nil { 60 s = sqlparser.String(stmt) 61 } 62 return s 63 } 64 65 // CanonicalStatementString implements EntityDiff 66 func (d *AlterViewEntityDiff) CanonicalStatementString() (s string) { 67 if stmt := d.Statement(); stmt != nil { 68 s = sqlparser.CanonicalString(stmt) 69 } 70 return s 71 } 72 73 // SubsequentDiff implements EntityDiff 74 func (d *AlterViewEntityDiff) SubsequentDiff() EntityDiff { 75 return nil 76 } 77 78 // SetSubsequentDiff implements EntityDiff 79 func (d *AlterViewEntityDiff) SetSubsequentDiff(EntityDiff) { 80 } 81 82 type CreateViewEntityDiff struct { 83 createView *sqlparser.CreateView 84 } 85 86 // IsEmpty implements EntityDiff 87 func (d *CreateViewEntityDiff) IsEmpty() bool { 88 return d.Statement() == nil 89 } 90 91 // Entities implements EntityDiff 92 func (d *CreateViewEntityDiff) Entities() (from Entity, to Entity) { 93 return nil, &CreateViewEntity{CreateView: d.createView} 94 } 95 96 // Statement implements EntityDiff 97 func (d *CreateViewEntityDiff) Statement() sqlparser.Statement { 98 if d == nil { 99 return nil 100 } 101 return d.createView 102 } 103 104 // CreateView returns the underlying sqlparser.CreateView that was generated for the diff. 105 func (d *CreateViewEntityDiff) CreateView() *sqlparser.CreateView { 106 if d == nil { 107 return nil 108 } 109 return d.createView 110 } 111 112 // StatementString implements EntityDiff 113 func (d *CreateViewEntityDiff) StatementString() (s string) { 114 if stmt := d.Statement(); stmt != nil { 115 s = sqlparser.String(stmt) 116 } 117 return s 118 } 119 120 // CanonicalStatementString implements EntityDiff 121 func (d *CreateViewEntityDiff) CanonicalStatementString() (s string) { 122 if stmt := d.Statement(); stmt != nil { 123 s = sqlparser.CanonicalString(stmt) 124 } 125 return s 126 } 127 128 // SubsequentDiff implements EntityDiff 129 func (d *CreateViewEntityDiff) SubsequentDiff() EntityDiff { 130 return nil 131 } 132 133 // SetSubsequentDiff implements EntityDiff 134 func (d *CreateViewEntityDiff) SetSubsequentDiff(EntityDiff) { 135 } 136 137 type DropViewEntityDiff struct { 138 from *CreateViewEntity 139 dropView *sqlparser.DropView 140 } 141 142 // IsEmpty implements EntityDiff 143 func (d *DropViewEntityDiff) IsEmpty() bool { 144 return d.Statement() == nil 145 } 146 147 // Entities implements EntityDiff 148 func (d *DropViewEntityDiff) Entities() (from Entity, to Entity) { 149 return d.from, nil 150 } 151 152 // Statement implements EntityDiff 153 func (d *DropViewEntityDiff) Statement() sqlparser.Statement { 154 if d == nil { 155 return nil 156 } 157 return d.dropView 158 } 159 160 // DropView returns the underlying sqlparser.DropView that was generated for the diff. 161 func (d *DropViewEntityDiff) DropView() *sqlparser.DropView { 162 if d == nil { 163 return nil 164 } 165 return d.dropView 166 } 167 168 // CanonicalStatementString implements EntityDiff 169 func (d *DropViewEntityDiff) CanonicalStatementString() (s string) { 170 if stmt := d.Statement(); stmt != nil { 171 s = sqlparser.CanonicalString(stmt) 172 } 173 return s 174 } 175 176 // StatementString implements EntityDiff 177 func (d *DropViewEntityDiff) StatementString() (s string) { 178 if stmt := d.Statement(); stmt != nil { 179 s = sqlparser.String(stmt) 180 } 181 return s 182 } 183 184 // SubsequentDiff implements EntityDiff 185 func (d *DropViewEntityDiff) SubsequentDiff() EntityDiff { 186 return nil 187 } 188 189 // SetSubsequentDiff implements EntityDiff 190 func (d *DropViewEntityDiff) SetSubsequentDiff(EntityDiff) { 191 } 192 193 // CreateViewEntity stands for a VIEW construct. It contains the view's CREATE statement. 194 type CreateViewEntity struct { 195 *sqlparser.CreateView 196 } 197 198 func NewCreateViewEntity(c *sqlparser.CreateView) (*CreateViewEntity, error) { 199 if !c.IsFullyParsed() { 200 return nil, &NotFullyParsedError{Entity: c.ViewName.Name.String(), Statement: sqlparser.CanonicalString(c)} 201 } 202 entity := &CreateViewEntity{CreateView: c} 203 entity.normalize() 204 return entity, nil 205 } 206 207 func (c *CreateViewEntity) normalize() { 208 // Drop the default algorithm 209 if strings.EqualFold(c.CreateView.Algorithm, "undefined") { 210 c.CreateView.Algorithm = "" 211 } 212 // Drop the default security model 213 if strings.EqualFold(c.CreateView.Security, "definer") { 214 c.CreateView.Security = "" 215 } 216 } 217 218 // Name implements Entity interface 219 func (c *CreateViewEntity) Name() string { 220 return c.CreateView.GetTable().Name.String() 221 } 222 223 // Diff implements Entity interface function 224 func (c *CreateViewEntity) Diff(other Entity, hints *DiffHints) (EntityDiff, error) { 225 otherCreateView, ok := other.(*CreateViewEntity) 226 if !ok { 227 return nil, ErrEntityTypeMismatch 228 } 229 return c.ViewDiff(otherCreateView, hints) 230 } 231 232 // ViewDiff compares this view statement with another view statement, and sees what it takes to 233 // change this view to look like the other view. 234 // It returns an AlterView statement if changes are found, or nil if not. 235 // the other view may be of different name; its name is ignored. 236 func (c *CreateViewEntity) ViewDiff(other *CreateViewEntity, _ *DiffHints) (*AlterViewEntityDiff, error) { 237 if !c.IsFullyParsed() { 238 return nil, &NotFullyParsedError{Entity: c.Name(), Statement: sqlparser.CanonicalString(c.CreateView)} 239 } 240 if !other.CreateView.IsFullyParsed() { 241 return nil, &NotFullyParsedError{Entity: c.Name(), Statement: sqlparser.CanonicalString(other.CreateView)} 242 } 243 244 if c.identicalOtherThanName(other) { 245 return nil, nil 246 } 247 248 alterView := &sqlparser.AlterView{ 249 ViewName: c.CreateView.ViewName, 250 Algorithm: other.CreateView.Algorithm, 251 Definer: other.CreateView.Definer, 252 Security: other.CreateView.Security, 253 Columns: other.CreateView.Columns, 254 Select: other.CreateView.Select, 255 CheckOption: other.CreateView.CheckOption, 256 } 257 return &AlterViewEntityDiff{alterView: alterView, from: c, to: other}, nil 258 } 259 260 // Create implements Entity interface 261 func (c *CreateViewEntity) Create() EntityDiff { 262 return &CreateViewEntityDiff{createView: c.CreateView} 263 } 264 265 // Drop implements Entity interface 266 func (c *CreateViewEntity) Drop() EntityDiff { 267 dropView := &sqlparser.DropView{ 268 FromTables: []sqlparser.TableName{c.ViewName}, 269 } 270 return &DropViewEntityDiff{from: c, dropView: dropView} 271 } 272 273 // apply attempts to apply an ALTER VIEW diff onto this entity's view definition. 274 // supported modifications are only those created by schemadiff's Diff() function. 275 func (c *CreateViewEntity) apply(diff *AlterViewEntityDiff) error { 276 c.CreateView = diff.to.CreateView 277 return nil 278 } 279 280 // Apply attempts to apply given ALTER VIEW diff onto the view defined by this entity. 281 // This entity is unmodified. If successful, a new CREATE VIEW entity is returned. 282 func (c *CreateViewEntity) Apply(diff EntityDiff) (Entity, error) { 283 alterDiff, ok := diff.(*AlterViewEntityDiff) 284 if !ok { 285 return nil, ErrEntityTypeMismatch 286 } 287 dup := c.Clone().(*CreateViewEntity) 288 if err := dup.apply(alterDiff); err != nil { 289 return nil, err 290 } 291 dup.normalize() 292 return dup, nil 293 } 294 295 func (c *CreateViewEntity) Clone() Entity { 296 return &CreateViewEntity{CreateView: sqlparser.CloneRefOfCreateView(c.CreateView)} 297 } 298 299 func (c *CreateViewEntity) identicalOtherThanName(other *CreateViewEntity) bool { 300 if other == nil { 301 return false 302 } 303 return c.Algorithm == other.Algorithm && 304 c.Security == other.Security && 305 c.CheckOption == other.CheckOption && 306 c.IsReplace == other.IsReplace && 307 sqlparser.Equals.RefOfDefiner(c.Definer, other.Definer) && 308 sqlparser.Equals.Columns(c.Columns, other.Columns) && 309 sqlparser.Equals.SelectStatement(c.Select, other.Select) && 310 sqlparser.Equals.RefOfParsedComments(c.Comments, other.Comments) 311 }