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 }