vitess.io/vitess@v0.16.2/go/vt/vttablet/onlineddl/analysis_test.go (about) 1 /* 2 Copyright 2021 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 /* 18 Functionality of this Executor is tested in go/test/endtoend/onlineddl/... 19 */ 20 21 package onlineddl 22 23 import ( 24 "testing" 25 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 29 "vitess.io/vitess/go/mysql" 30 "vitess.io/vitess/go/vt/sqlparser" 31 ) 32 33 func TestAnalyzeInstantDDL(t *testing.T) { 34 tt := []struct { 35 version string 36 create string 37 alter string 38 expectError bool 39 instant bool 40 }{ 41 // add/drop columns 42 { 43 version: "5.7.28", 44 create: "create table t(id int, i1 int not null, primary key(id))", 45 alter: "alter table t add column i2 int not null", 46 instant: false, 47 }, 48 { 49 version: "8.0.21", 50 create: "create table t(id int, i1 int not null, primary key(id))", 51 alter: "alter table t add column i2 int not null", 52 instant: true, 53 }, 54 { 55 version: "8.0.21", 56 create: "create table t(id int, i1 int not null, primary key(id))", 57 alter: "alter table t add column i2 int not null, add column i3 int not null", 58 instant: true, 59 }, 60 { 61 // fail add mid column in older versions 62 version: "8.0.21", 63 create: "create table t(id int, i1 int not null, primary key(id))", 64 alter: "alter table t add column i2 int not null after id", 65 instant: false, 66 }, 67 { 68 version: "8.0.21", 69 create: "create table t(id int, i1 int not null, primary key(id))", 70 alter: "alter table t drop column i1", 71 instant: false, 72 }, 73 { 74 // drop virtual column 75 version: "8.0.21", 76 create: "create table t(id int, i1 int not null, i2 int generated always as (i1 + 1) virtual, primary key(id))", 77 alter: "alter table t drop column i2", 78 instant: true, 79 }, 80 { 81 version: "8.0.21", 82 create: "create table t(id int, i1 int not null, i2 int generated always as (i1 + 1) stored, primary key(id))", 83 alter: "alter table t drop column i2", 84 instant: false, 85 }, 86 { 87 // add mid column 88 version: "8.0.29", 89 create: "create table t(id int, i1 int not null, primary key(id))", 90 alter: "alter table t add column i2 int not null after id", 91 instant: true, 92 }, 93 { 94 // drop mid column 95 version: "8.0.29", 96 create: "create table t(id int, i1 int not null, i2 int not null, primary key(id))", 97 alter: "alter table t drop column i1", 98 instant: true, 99 }, 100 { 101 // fail due to row_format=compressed 102 version: "8.0.29", 103 create: "create table t(id int, i1 int not null, i2 int not null, primary key(id)) row_format=compressed", 104 alter: "alter table t drop column i1", 105 instant: false, 106 }, 107 { 108 version: "8.0.29", 109 create: "create table t(id int, i1 int not null, primary key(id))", 110 alter: "alter table t add column i2 int not null after id, add column i3 int not null", 111 instant: true, 112 }, 113 { 114 version: "8.0.29", 115 create: "create table t(id int, i1 int not null, primary key(id))", 116 alter: "alter table t add column i2 int not null after id, add column i3 int not null, drop column i1", 117 instant: true, 118 }, 119 // change/remove column default 120 { 121 // set a default value 122 version: "8.0.21", 123 create: "create table t(id int, i1 int not null, primary key(id))", 124 alter: "alter table t modify column i1 int not null default 0", 125 instant: true, 126 }, 127 { 128 // change a default value 129 version: "8.0.21", 130 create: "create table t(id int, i1 int not null, primary key(id))", 131 alter: "alter table t modify column i1 int not null default 3", 132 instant: true, 133 }, 134 { 135 // change default value to null 136 version: "8.0.21", 137 create: "create table t(id int, i1 int not null, primary key(id))", 138 alter: "alter table t modify column i1 int default null", 139 instant: false, 140 }, 141 { 142 // fail because on top of changing the default value, the datatype is changed, too 143 version: "8.0.21", 144 create: "create table t(id int, i1 int not null, primary key(id))", 145 alter: "alter table t modify column i1 bigint not null default 3", 146 instant: false, 147 }, 148 { 149 version: "8.0.21", 150 create: "create table t(id int, i1 int, primary key(id))", 151 alter: "alter table t modify column i1 int default 0", 152 instant: true, 153 }, 154 { 155 version: "8.0.21", 156 create: "create table t(id int, i1 int, primary key(id))", 157 alter: "alter table t modify column i1 int default null", 158 instant: true, 159 }, 160 // enum/set: 161 { 162 // enum same, with changed default 163 version: "8.0.21", 164 create: "create table t(id int, c1 enum('a', 'b', 'c'), primary key(id))", 165 alter: "alter table t modify column c1 enum('a', 'b', 'c') default 'b'", 166 instant: true, 167 }, 168 { 169 // enum append 170 version: "8.0.21", 171 create: "create table t(id int, c1 enum('a', 'b', 'c'), primary key(id))", 172 alter: "alter table t modify column c1 enum('a', 'b', 'c', 'd')", 173 instant: true, 174 }, 175 { 176 // enum append with changed default 177 version: "8.0.21", 178 create: "create table t(id int, c1 enum('a', 'b', 'c') default 'a', primary key(id))", 179 alter: "alter table t modify column c1 enum('a', 'b', 'c', 'd') default 'd'", 180 instant: true, 181 }, 182 { 183 // fail insert in middle 184 version: "8.0.21", 185 create: "create table t(id int, c1 enum('a', 'b', 'c'), primary key(id))", 186 alter: "alter table t modify column c1 enum('a', 'b', 'x', 'c')", 187 instant: false, 188 }, 189 { 190 // fail change 191 version: "8.0.21", 192 create: "create table t(id int, c1 enum('a', 'b', 'c'), primary key(id))", 193 alter: "alter table t modify column c1 enum('a', 'x', 'c')", 194 instant: false, 195 }, 196 { 197 // set append 198 version: "8.0.21", 199 create: "create table t(id int, c1 set('a', 'b', 'c'), primary key(id))", 200 alter: "alter table t modify column c1 set('a', 'b', 'c', 'd')", 201 instant: true, 202 }, 203 { 204 // fail set append when over threshold (increase from 8 to 9 values => storage goes from 1 byte to 2 bytes) 205 version: "8.0.21", 206 create: "create table t(id int, c1 set('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), primary key(id))", 207 alter: "alter table t modify column c1 set('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')", 208 instant: false, 209 }, 210 } 211 for _, tc := range tt { 212 name := tc.version + " " + tc.create 213 t.Run(name, func(t *testing.T) { 214 stmt, err := sqlparser.ParseStrictDDL(tc.create) 215 require.NoError(t, err) 216 createTable, ok := stmt.(*sqlparser.CreateTable) 217 require.True(t, ok) 218 219 stmt, err = sqlparser.ParseStrictDDL(tc.alter) 220 require.NoError(t, err) 221 alterTable, ok := stmt.(*sqlparser.AlterTable) 222 require.True(t, ok) 223 224 _, capableOf, _ := mysql.GetFlavor(tc.version, nil) 225 plan, err := AnalyzeInstantDDL(alterTable, createTable, capableOf) 226 if tc.expectError { 227 assert.Error(t, err) 228 } else { 229 assert.NoError(t, err) 230 if tc.instant { 231 require.NotNil(t, plan) 232 assert.Equal(t, instantDDLSpecialOperation, plan.operation) 233 } else { 234 require.Nil(t, plan) 235 } 236 } 237 }) 238 } 239 }