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  }