vitess.io/vitess@v0.16.2/go/vt/schemadiff/diff.go (about)

     1  package schemadiff
     2  
     3  import (
     4  	"vitess.io/vitess/go/vt/sqlparser"
     5  )
     6  
     7  // DDLActionStr returns the action implied by the given diff: CREATE", "DROP", "ALTER" or empty
     8  func DDLActionStr(diff EntityDiff) (string, error) {
     9  	if diff == nil {
    10  		return "", nil
    11  	}
    12  	if ddl, ok := diff.Statement().(sqlparser.DDLStatement); ok {
    13  		return ddl.GetAction().ToString(), nil
    14  	}
    15  	return "", ErrUnexpectedDiffAction
    16  }
    17  
    18  // AllSubsequent returns a list of diffs starting the given diff and followed by all subsequent diffs, if any
    19  func AllSubsequent(diff EntityDiff) (diffs []EntityDiff) {
    20  	for diff != nil && !diff.IsEmpty() {
    21  		diffs = append(diffs, diff)
    22  		diff = diff.SubsequentDiff()
    23  	}
    24  	return diffs
    25  }
    26  
    27  // DiffCreateTablesQueries compares two `CREATE TABLE ...` queries (in string form) and returns the diff from table1 to table2.
    28  // Either or both of the queries can be empty. Based on this, the diff could be
    29  // nil, CreateTable, DropTable or AlterTable
    30  func DiffCreateTablesQueries(query1 string, query2 string, hints *DiffHints) (EntityDiff, error) {
    31  	var fromCreateTable *sqlparser.CreateTable
    32  	var ok bool
    33  	if query1 != "" {
    34  		stmt, err := sqlparser.ParseStrictDDL(query1)
    35  		if err != nil {
    36  			return nil, err
    37  		}
    38  		fromCreateTable, ok = stmt.(*sqlparser.CreateTable)
    39  		if !ok {
    40  			return nil, ErrExpectedCreateTable
    41  		}
    42  	}
    43  	var toCreateTable *sqlparser.CreateTable
    44  	if query2 != "" {
    45  		stmt, err := sqlparser.ParseStrictDDL(query2)
    46  		if err != nil {
    47  			return nil, err
    48  		}
    49  		toCreateTable, ok = stmt.(*sqlparser.CreateTable)
    50  		if !ok {
    51  			return nil, ErrExpectedCreateTable
    52  		}
    53  	}
    54  	return DiffTables(fromCreateTable, toCreateTable, hints)
    55  }
    56  
    57  // DiffTables compares two tables and returns the diff from table1 to table2.
    58  // Either or both of the CreateTable statements can be nil. Based on this, the diff could be
    59  // nil, CreateTable, DropTable or AlterTable
    60  func DiffTables(create1 *sqlparser.CreateTable, create2 *sqlparser.CreateTable, hints *DiffHints) (EntityDiff, error) {
    61  	switch {
    62  	case create1 == nil && create2 == nil:
    63  		return nil, nil
    64  	case create1 == nil:
    65  		c2, err := NewCreateTableEntity(create2)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		return c2.Create(), nil
    70  	case create2 == nil:
    71  		c1, err := NewCreateTableEntity(create1)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		return c1.Drop(), nil
    76  	default:
    77  		c1, err := NewCreateTableEntity(create1)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  		c2, err := NewCreateTableEntity(create2)
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  		return c1.Diff(c2, hints)
    86  	}
    87  }
    88  
    89  // DiffCreateViewsQueries compares two `CREATE TABLE ...` queries (in string form) and returns the diff from table1 to table2.
    90  // Either or both of the queries can be empty. Based on this, the diff could be
    91  // nil, CreateView, DropView or AlterView
    92  func DiffCreateViewsQueries(query1 string, query2 string, hints *DiffHints) (EntityDiff, error) {
    93  	var fromCreateView *sqlparser.CreateView
    94  	var ok bool
    95  	if query1 != "" {
    96  		stmt, err := sqlparser.ParseStrictDDL(query1)
    97  		if err != nil {
    98  			return nil, err
    99  		}
   100  		fromCreateView, ok = stmt.(*sqlparser.CreateView)
   101  		if !ok {
   102  			return nil, ErrExpectedCreateView
   103  		}
   104  	}
   105  	var toCreateView *sqlparser.CreateView
   106  	if query2 != "" {
   107  		stmt, err := sqlparser.ParseStrictDDL(query2)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		toCreateView, ok = stmt.(*sqlparser.CreateView)
   112  		if !ok {
   113  			return nil, ErrExpectedCreateView
   114  		}
   115  	}
   116  	return DiffViews(fromCreateView, toCreateView, hints)
   117  }
   118  
   119  // DiffViews compares two views and returns the diff from view1 to view2
   120  // Either or both of the CreateView statements can be nil. Based on this, the diff could be
   121  // nil, CreateView, DropView or AlterView
   122  func DiffViews(create1 *sqlparser.CreateView, create2 *sqlparser.CreateView, hints *DiffHints) (EntityDiff, error) {
   123  	switch {
   124  	case create1 == nil && create2 == nil:
   125  		return nil, nil
   126  	case create1 == nil:
   127  		c2, err := NewCreateViewEntity(create2)
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  		return c2.Create(), nil
   132  	case create2 == nil:
   133  		c1, err := NewCreateViewEntity(create1)
   134  		if err != nil {
   135  			return nil, err
   136  		}
   137  		return c1.Drop(), nil
   138  	default:
   139  		c1, err := NewCreateViewEntity(create1)
   140  		if err != nil {
   141  			return nil, err
   142  		}
   143  		c2, err := NewCreateViewEntity(create2)
   144  		if err != nil {
   145  			return nil, err
   146  		}
   147  		return c1.Diff(c2, hints)
   148  	}
   149  }
   150  
   151  // DiffSchemasSQL compares two schemas and returns the list of diffs that turn
   152  // 1st schema into 2nd. Schemas are build from SQL, each of which can contain an arbitrary number of
   153  // CREATE TABLE and CREATE VIEW statements.
   154  func DiffSchemasSQL(sql1 string, sql2 string, hints *DiffHints) ([]EntityDiff, error) {
   155  	schema1, err := NewSchemaFromSQL(sql1)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	schema2, err := NewSchemaFromSQL(sql2)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  	return schema1.Diff(schema2, hints)
   164  }
   165  
   166  // DiffSchemasSQL compares two schemas and returns the list of diffs that turn
   167  // 1st schema into 2nd. Any of the schemas may be nil.
   168  func DiffSchemas(schema1 *Schema, schema2 *Schema, hints *DiffHints) ([]EntityDiff, error) {
   169  	if schema1 == nil {
   170  		schema1 = newEmptySchema()
   171  	}
   172  	if schema2 == nil {
   173  		schema2 = newEmptySchema()
   174  	}
   175  	return schema1.Diff(schema2, hints)
   176  }