vitess.io/vitess@v0.16.2/go/vt/vttablet/onlineddl/vrepl/parser.go (about)

     1  /*
     2     Copyright 2016 GitHub Inc.
     3  	 See https://github.com/github/gh-ost/blob/master/LICENSE
     4  */
     5  /*
     6  Copyright 2021 The Vitess Authors.
     7  
     8  Licensed under the Apache License, Version 2.0 (the "License");
     9  you may not use this file except in compliance with the License.
    10  You may obtain a copy of the License at
    11  
    12      http://www.apache.org/licenses/LICENSE-2.0
    13  
    14  Unless required by applicable law or agreed to in writing, software
    15  distributed under the License is distributed on an "AS IS" BASIS,
    16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17  See the License for the specific language governing permissions and
    18  limitations under the License.
    19  */
    20  
    21  package vrepl
    22  
    23  import (
    24  	"strings"
    25  
    26  	"vitess.io/vitess/go/vt/proto/vtrpc"
    27  	"vitess.io/vitess/go/vt/sqlparser"
    28  	"vitess.io/vitess/go/vt/vterrors"
    29  )
    30  
    31  // AlterTableParser is a parser tool for ALTER TABLE statements
    32  // This is imported from gh-ost. In the future, we should replace that with Vitess parsing.
    33  type AlterTableParser struct {
    34  	columnRenameMap        map[string]string
    35  	droppedColumns         map[string]bool
    36  	isRenameTable          bool
    37  	isAutoIncrementDefined bool
    38  }
    39  
    40  // NewAlterTableParser creates a new parser
    41  func NewAlterTableParser() *AlterTableParser {
    42  	return &AlterTableParser{
    43  		columnRenameMap: make(map[string]string),
    44  		droppedColumns:  make(map[string]bool),
    45  	}
    46  }
    47  
    48  // NewParserFromAlterStatement creates a new parser with a ALTER TABLE statement
    49  func NewParserFromAlterStatement(alterTable *sqlparser.AlterTable) *AlterTableParser {
    50  	parser := NewAlterTableParser()
    51  	parser.analyzeAlter(alterTable)
    52  	return parser
    53  }
    54  
    55  // analyzeAlter looks for specific changes in the AlterTable statement, that are relevant
    56  // to OnlineDDL/VReplication
    57  func (p *AlterTableParser) analyzeAlter(alterTable *sqlparser.AlterTable) {
    58  	for _, opt := range alterTable.AlterOptions {
    59  		switch opt := opt.(type) {
    60  		case *sqlparser.RenameTableName:
    61  			p.isRenameTable = true
    62  		case *sqlparser.DropColumn:
    63  			p.droppedColumns[opt.Name.Name.String()] = true
    64  		case *sqlparser.ChangeColumn:
    65  			if opt.OldColumn != nil && opt.NewColDefinition != nil {
    66  				oldName := opt.OldColumn.Name.String()
    67  				newName := opt.NewColDefinition.Name.String()
    68  				p.columnRenameMap[oldName] = newName
    69  			}
    70  		case sqlparser.TableOptions:
    71  			for _, tableOption := range opt {
    72  				if strings.ToUpper(tableOption.Name) == "AUTO_INCREMENT" {
    73  					p.isAutoIncrementDefined = true
    74  				}
    75  			}
    76  		}
    77  	}
    78  }
    79  
    80  // ParseAlterStatement is the main function of th eparser, and parses an ALTER TABLE statement
    81  func (p *AlterTableParser) ParseAlterStatement(alterQuery string) (err error) {
    82  	stmt, err := sqlparser.ParseStrictDDL(alterQuery)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	alterTable, ok := stmt.(*sqlparser.AlterTable)
    87  	if !ok {
    88  		return vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "expected AlterTable statement, got %v", sqlparser.CanonicalString(stmt))
    89  	}
    90  	p.analyzeAlter(alterTable)
    91  	return nil
    92  }
    93  
    94  // GetNonTrivialRenames gets a list of renamed column
    95  func (p *AlterTableParser) GetNonTrivialRenames() map[string]string {
    96  	result := make(map[string]string)
    97  	for column, renamed := range p.columnRenameMap {
    98  		if column != renamed {
    99  			result[column] = renamed
   100  		}
   101  	}
   102  	return result
   103  }
   104  
   105  // HasNonTrivialRenames is true when columns have been renamed
   106  func (p *AlterTableParser) HasNonTrivialRenames() bool {
   107  	return len(p.GetNonTrivialRenames()) > 0
   108  }
   109  
   110  // DroppedColumnsMap returns list of dropped columns
   111  func (p *AlterTableParser) DroppedColumnsMap() map[string]bool {
   112  	return p.droppedColumns
   113  }
   114  
   115  // IsRenameTable returns true when the ALTER TABLE statement inclusdes renaming the table
   116  func (p *AlterTableParser) IsRenameTable() bool {
   117  	return p.isRenameTable
   118  }
   119  
   120  // IsAutoIncrementDefined returns true when alter options include an explicit AUTO_INCREMENT value
   121  func (p *AlterTableParser) IsAutoIncrementDefined() bool {
   122  	return p.isAutoIncrementDefined
   123  }
   124  
   125  // ColumnRenameMap returns the renamed column mapping
   126  func (p *AlterTableParser) ColumnRenameMap() map[string]string {
   127  	return p.columnRenameMap
   128  }