github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/model/schema_storage_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package model 15 16 import ( 17 "github.com/pingcap/check" 18 timodel "github.com/pingcap/parser/model" 19 "github.com/pingcap/parser/mysql" 20 parser_types "github.com/pingcap/parser/types" 21 "github.com/pingcap/ticdc/pkg/util/testleak" 22 ) 23 24 type schemaStorageSuite struct{} 25 26 var _ = check.Suite(&schemaStorageSuite{}) 27 28 func (s *schemaStorageSuite) TestPKShouldBeInTheFirstPlaceWhenPKIsNotHandle(c *check.C) { 29 defer testleak.AfterTest(c)() 30 t := timodel.TableInfo{ 31 Columns: []*timodel.ColumnInfo{ 32 { 33 Name: timodel.CIStr{O: "group"}, 34 FieldType: parser_types.FieldType{ 35 Flag: mysql.NotNullFlag, 36 }, 37 State: timodel.StatePublic, 38 }, 39 { 40 Name: timodel.CIStr{O: "name"}, 41 FieldType: parser_types.FieldType{ 42 Flag: mysql.NotNullFlag, 43 }, 44 State: timodel.StatePublic, 45 }, 46 { 47 Name: timodel.CIStr{O: "id"}, 48 State: timodel.StatePublic, 49 }, 50 }, 51 Indices: []*timodel.IndexInfo{ 52 { 53 Name: timodel.CIStr{ 54 O: "group", 55 }, 56 Columns: []*timodel.IndexColumn{ 57 { 58 Name: timodel.CIStr{O: "group"}, 59 Offset: 0, 60 }, 61 }, 62 Unique: false, 63 }, 64 { 65 Name: timodel.CIStr{ 66 O: "name", 67 }, 68 Columns: []*timodel.IndexColumn{ 69 { 70 Name: timodel.CIStr{O: "name"}, 71 Offset: 0, 72 }, 73 }, 74 Unique: true, 75 }, 76 { 77 Name: timodel.CIStr{ 78 O: "PRIMARY", 79 }, 80 Columns: []*timodel.IndexColumn{ 81 { 82 Name: timodel.CIStr{O: "id"}, 83 Offset: 1, 84 }, 85 }, 86 Primary: true, 87 }, 88 }, 89 IsCommonHandle: true, 90 PKIsHandle: false, 91 } 92 info := WrapTableInfo(1, "", 0, &t) 93 cols := info.GetUniqueKeys() 94 c.Assert(cols, check.DeepEquals, [][]string{ 95 {"id"}, {"name"}, 96 }) 97 } 98 99 func (s *schemaStorageSuite) TestPKShouldBeInTheFirstPlaceWhenPKIsHandle(c *check.C) { 100 defer testleak.AfterTest(c)() 101 t := timodel.TableInfo{ 102 Indices: []*timodel.IndexInfo{ 103 { 104 Name: timodel.CIStr{ 105 O: "uniq_job", 106 }, 107 Columns: []*timodel.IndexColumn{ 108 {Name: timodel.CIStr{O: "job"}}, 109 }, 110 Unique: true, 111 }, 112 }, 113 Columns: []*timodel.ColumnInfo{ 114 { 115 Name: timodel.CIStr{ 116 O: "job", 117 }, 118 FieldType: parser_types.FieldType{ 119 Flag: mysql.NotNullFlag, 120 }, 121 State: timodel.StatePublic, 122 }, 123 { 124 Name: timodel.CIStr{ 125 O: "uid", 126 }, 127 FieldType: parser_types.FieldType{ 128 Flag: mysql.PriKeyFlag, 129 }, 130 State: timodel.StatePublic, 131 }, 132 }, 133 PKIsHandle: true, 134 } 135 info := WrapTableInfo(1, "", 0, &t) 136 cols := info.GetUniqueKeys() 137 c.Assert(cols, check.DeepEquals, [][]string{ 138 {"uid"}, {"job"}, 139 }) 140 } 141 142 func (s *schemaStorageSuite) TestUniqueKeyIsHandle(c *check.C) { 143 defer testleak.AfterTest(c)() 144 t := timodel.TableInfo{ 145 Columns: []*timodel.ColumnInfo{ 146 { 147 Name: timodel.CIStr{O: "group"}, 148 FieldType: parser_types.FieldType{ 149 Flag: mysql.NotNullFlag, 150 }, 151 State: timodel.StatePublic, 152 }, 153 { 154 Name: timodel.CIStr{O: "name"}, 155 FieldType: parser_types.FieldType{ 156 Flag: mysql.NotNullFlag, 157 }, 158 State: timodel.StatePublic, 159 }, 160 }, 161 Indices: []*timodel.IndexInfo{ 162 { 163 Name: timodel.CIStr{ 164 O: "group", 165 }, 166 Columns: []*timodel.IndexColumn{ 167 { 168 Name: timodel.CIStr{O: "group"}, 169 Offset: 0, 170 }, 171 }, 172 Unique: false, 173 }, 174 { 175 Name: timodel.CIStr{ 176 O: "name", 177 }, 178 Columns: []*timodel.IndexColumn{ 179 { 180 Name: timodel.CIStr{O: "name"}, 181 Offset: 0, 182 }, 183 }, 184 Unique: true, 185 }, 186 }, 187 IsCommonHandle: false, 188 PKIsHandle: false, 189 } 190 info := WrapTableInfo(1, "", 0, &t) 191 cols := info.GetUniqueKeys() 192 c.Assert(cols, check.DeepEquals, [][]string{{"name"}}) 193 } 194 195 func (s *schemaStorageSuite) TestHandleKeyPriority(c *check.C) { 196 defer testleak.AfterTest(c)() 197 t := timodel.TableInfo{ 198 Columns: []*timodel.ColumnInfo{ 199 { 200 Name: timodel.CIStr{O: "a"}, 201 FieldType: parser_types.FieldType{ 202 Flag: mysql.NotNullFlag | mysql.MultipleKeyFlag, 203 }, 204 State: timodel.StatePublic, 205 }, 206 { 207 Name: timodel.CIStr{O: "b"}, 208 FieldType: parser_types.FieldType{ 209 Flag: mysql.NotNullFlag | mysql.MultipleKeyFlag, 210 }, 211 State: timodel.StatePublic, 212 }, 213 { 214 Name: timodel.CIStr{O: "c"}, 215 FieldType: parser_types.FieldType{ 216 Flag: mysql.NotNullFlag | mysql.UniqueKeyFlag, 217 }, 218 State: timodel.StatePublic, 219 }, 220 { 221 Name: timodel.CIStr{O: "d"}, 222 FieldType: parser_types.FieldType{ 223 // test not null unique index 224 // Flag: mysql.NotNullFlag, 225 }, 226 State: timodel.StatePublic, 227 }, 228 { 229 Name: timodel.CIStr{O: "e"}, 230 FieldType: parser_types.FieldType{ 231 Flag: mysql.NotNullFlag, 232 }, 233 State: timodel.StatePublic, 234 // test virtual generated column is not treated as unique key 235 GeneratedExprString: "as d", 236 GeneratedStored: false, 237 }, 238 }, 239 Indices: []*timodel.IndexInfo{ 240 { 241 ID: 10, 242 Name: timodel.CIStr{ 243 O: "a,b", 244 }, 245 Columns: []*timodel.IndexColumn{ 246 {Name: timodel.CIStr{O: "a"}, Offset: 0}, 247 {Name: timodel.CIStr{O: "b"}, Offset: 1}, 248 }, 249 Unique: true, 250 }, 251 { 252 ID: 9, 253 Name: timodel.CIStr{ 254 O: "c", 255 }, 256 Columns: []*timodel.IndexColumn{ 257 {Name: timodel.CIStr{O: "c"}, Offset: 2}, 258 }, 259 Unique: true, 260 }, 261 { 262 ID: 8, 263 Name: timodel.CIStr{ 264 O: "b", 265 }, 266 Columns: []*timodel.IndexColumn{ 267 {Name: timodel.CIStr{O: "b"}, Offset: 1}, 268 }, 269 Unique: true, 270 }, 271 { 272 ID: 7, 273 Name: timodel.CIStr{ 274 O: "d", 275 }, 276 Columns: []*timodel.IndexColumn{ 277 {Name: timodel.CIStr{O: "d"}, Offset: 3}, 278 }, 279 Unique: true, 280 }, 281 { 282 ID: 6, 283 Name: timodel.CIStr{ 284 O: "e", 285 }, 286 Columns: []*timodel.IndexColumn{ 287 {Name: timodel.CIStr{O: "e"}, Offset: 4}, 288 }, 289 Unique: true, 290 }, 291 }, 292 IsCommonHandle: false, 293 PKIsHandle: false, 294 } 295 info := WrapTableInfo(1, "", 0, &t) 296 cols := info.GetUniqueKeys() 297 c.Assert(info.HandleIndexID, check.Equals, int64(8)) 298 c.Assert(cols, check.DeepEquals, [][]string{{"a", "b"}, {"c"}, {"b"}}) 299 } 300 301 func (s *schemaStorageSuite) TestTableInfoGetterFuncs(c *check.C) { 302 defer testleak.AfterTest(c)() 303 t := timodel.TableInfo{ 304 ID: 1071, 305 Name: timodel.CIStr{O: "t1"}, 306 Columns: []*timodel.ColumnInfo{ 307 { 308 ID: 0, 309 Name: timodel.CIStr{O: "a"}, 310 FieldType: parser_types.FieldType{ 311 // test binary flag 312 Flag: mysql.NotNullFlag | mysql.BinaryFlag, 313 Charset: "binary", 314 }, 315 State: timodel.StatePublic, 316 }, 317 { 318 ID: 1, 319 Name: timodel.CIStr{O: "b"}, 320 FieldType: parser_types.FieldType{ 321 // test unsigned flag 322 Flag: mysql.NotNullFlag | mysql.UnsignedFlag, 323 }, 324 State: timodel.StatePublic, 325 }, 326 { 327 ID: 2, 328 Name: timodel.CIStr{O: "c"}, 329 FieldType: parser_types.FieldType{ 330 Flag: mysql.NotNullFlag, 331 }, 332 State: timodel.StatePublic, 333 }, 334 }, 335 Indices: []*timodel.IndexInfo{ 336 { 337 ID: 0, 338 Name: timodel.CIStr{ 339 O: "c", 340 }, 341 Columns: []*timodel.IndexColumn{ 342 {Name: timodel.CIStr{O: "c"}, Offset: 2}, 343 }, 344 Unique: true, 345 }, 346 }, 347 IsCommonHandle: false, 348 PKIsHandle: false, 349 } 350 info := WrapTableInfo(1, "test", 0, &t) 351 352 col, exists := info.GetColumnInfo(2) 353 c.Assert(exists, check.IsTrue) 354 c.Assert(col.Name.O, check.Equals, "c") 355 _, exists = info.GetColumnInfo(4) 356 c.Assert(exists, check.IsFalse) 357 358 c.Assert(info.String(), check.Equals, "TableInfo, ID: 1071, Name:test.t1, ColNum: 3, IdxNum: 1, PKIsHandle: false") 359 360 idx, exists := info.GetIndexInfo(0) 361 c.Assert(exists, check.IsTrue) 362 c.Assert(idx.Name.O, check.Equals, "c") 363 _, exists = info.GetIndexInfo(1) 364 c.Assert(exists, check.IsFalse) 365 366 handleColIDs, fts, colInfos := info.GetRowColInfos() 367 c.Assert(handleColIDs, check.DeepEquals, []int64{-1}) 368 c.Assert(len(fts), check.Equals, 3) 369 c.Assert(len(colInfos), check.Equals, 3) 370 371 c.Assert(info.IsColumnUnique(0), check.IsFalse) 372 c.Assert(info.IsColumnUnique(2), check.IsTrue) 373 c.Assert(info.ExistTableUniqueColumn(), check.IsTrue) 374 375 // check IsEligible 376 c.Assert(info.IsEligible(false), check.IsTrue) 377 t = timodel.TableInfo{ 378 ID: 1073, 379 Name: timodel.CIStr{O: "t2"}, 380 Columns: []*timodel.ColumnInfo{ 381 { 382 ID: 0, 383 Name: timodel.CIStr{O: "a"}, 384 FieldType: parser_types.FieldType{}, 385 State: timodel.StatePublic, 386 }, 387 }, 388 Indices: []*timodel.IndexInfo{ 389 { 390 ID: 0, 391 Name: timodel.CIStr{O: "a"}, 392 Columns: []*timodel.IndexColumn{ 393 {Name: timodel.CIStr{O: "a"}, Offset: 0}, 394 }, 395 Unique: true, 396 }, 397 }, 398 IsCommonHandle: false, 399 PKIsHandle: false, 400 } 401 info = WrapTableInfo(1, "test", 0, &t) 402 c.Assert(info.IsEligible(false), check.IsFalse) 403 c.Assert(info.IsEligible(true), check.IsTrue) 404 t.View = &timodel.ViewInfo{} 405 info = WrapTableInfo(1, "test", 0, &t) 406 c.Assert(info.IsEligible(false), check.IsTrue) 407 } 408 409 func (s *schemaStorageSuite) TestTableInfoClone(c *check.C) { 410 defer testleak.AfterTest(c)() 411 t := timodel.TableInfo{ 412 ID: 1071, 413 Name: timodel.CIStr{O: "t1"}, 414 Columns: []*timodel.ColumnInfo{ 415 { 416 ID: 0, 417 Name: timodel.CIStr{O: "c"}, 418 FieldType: parser_types.FieldType{ 419 Flag: mysql.NotNullFlag, 420 }, 421 State: timodel.StatePublic, 422 }, 423 }, 424 Indices: []*timodel.IndexInfo{ 425 { 426 ID: 0, 427 Name: timodel.CIStr{ 428 O: "c", 429 }, 430 Columns: []*timodel.IndexColumn{ 431 {Name: timodel.CIStr{O: "c"}, Offset: 0}, 432 }, 433 Unique: true, 434 }, 435 }, 436 } 437 info := WrapTableInfo(10, "test", 0, &t) 438 cloned := info.Clone() 439 c.Assert(cloned.SchemaID, check.Equals, info.SchemaID) 440 cloned.SchemaID = 100 441 c.Assert(info.SchemaID, check.Equals, int64(10)) 442 }