github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/descriptor_mutation_test.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql_test 12 13 import ( 14 "context" 15 gosql "database/sql" 16 "fmt" 17 "math/rand" 18 "testing" 19 20 "github.com/cockroachdb/cockroach/pkg/base" 21 "github.com/cockroachdb/cockroach/pkg/keys" 22 "github.com/cockroachdb/cockroach/pkg/kv" 23 "github.com/cockroachdb/cockroach/pkg/sql" 24 "github.com/cockroachdb/cockroach/pkg/sql/catalog/lease" 25 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 26 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 27 "github.com/cockroachdb/cockroach/pkg/sql/tests" 28 "github.com/cockroachdb/cockroach/pkg/testutils" 29 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 30 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 31 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 32 ) 33 34 type mutationTest struct { 35 // SQLRunner embeds testing.TB 36 testing.TB 37 *sqlutils.SQLRunner 38 kvDB *kv.DB 39 tableDesc *sqlbase.TableDescriptor 40 } 41 42 func makeMutationTest( 43 t *testing.T, kvDB *kv.DB, db *gosql.DB, tableDesc *sqlbase.TableDescriptor, 44 ) mutationTest { 45 return mutationTest{ 46 TB: t, 47 SQLRunner: sqlutils.MakeSQLRunner(db), 48 kvDB: kvDB, 49 tableDesc: tableDesc, 50 } 51 } 52 53 // checkTableSize checks that the number of key:value pairs stored 54 // in the table equals e. 55 func (mt mutationTest) checkTableSize(e int) { 56 // Check that there are no hidden values 57 tableStartKey := keys.SystemSQLCodec.TablePrefix(uint32(mt.tableDesc.ID)) 58 tableEndKey := tableStartKey.PrefixEnd() 59 if kvs, err := mt.kvDB.Scan(context.Background(), tableStartKey, tableEndKey, 0); err != nil { 60 mt.Error(err) 61 } else if len(kvs) != e { 62 mt.Errorf("expected %d key value pairs, but got %d", e, len(kvs)) 63 } 64 } 65 66 // Convert all the mutations into live descriptors for the table 67 // and write the updated table descriptor to the DB. 68 func (mt mutationTest) makeMutationsActive() { 69 // Remove mutation to check real values in DB using SQL 70 if mt.tableDesc.Mutations == nil || len(mt.tableDesc.Mutations) == 0 { 71 mt.Fatal("No mutations to make active") 72 } 73 for _, m := range mt.tableDesc.Mutations { 74 if col := m.GetColumn(); col != nil { 75 mt.tableDesc.Columns = append(mt.tableDesc.Columns, *col) 76 } else if index := m.GetIndex(); index != nil { 77 mt.tableDesc.Indexes = append(mt.tableDesc.Indexes, *index) 78 } else { 79 mt.Fatalf("no descriptor in mutation: %v", m) 80 } 81 } 82 mt.tableDesc.Mutations = nil 83 mt.tableDesc.Version++ 84 if err := mt.tableDesc.ValidateTable(); err != nil { 85 mt.Fatal(err) 86 } 87 if err := mt.kvDB.Put( 88 context.Background(), 89 sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, mt.tableDesc.ID), 90 sqlbase.WrapDescriptor(mt.tableDesc), 91 ); err != nil { 92 mt.Fatal(err) 93 } 94 } 95 96 // writeColumnMutation adds column as a mutation and writes the 97 // descriptor to the DB. 98 func (mt mutationTest) writeColumnMutation(column string, m sqlbase.DescriptorMutation) { 99 col, _, err := mt.tableDesc.FindColumnByName(tree.Name(column)) 100 if err != nil { 101 mt.Fatal(err) 102 } 103 for i := range mt.tableDesc.Columns { 104 if col.ID == mt.tableDesc.Columns[i].ID { 105 // Use [:i:i] to prevent reuse of existing slice, or outstanding refs 106 // to ColumnDescriptors may unexpectedly change. 107 mt.tableDesc.Columns = append(mt.tableDesc.Columns[:i:i], mt.tableDesc.Columns[i+1:]...) 108 break 109 } 110 } 111 m.Descriptor_ = &sqlbase.DescriptorMutation_Column{Column: col} 112 mt.writeMutation(m) 113 } 114 115 // writeMutation writes the mutation to the table descriptor. If the 116 // State or the Direction is undefined, these values are populated via 117 // picking random values before the mutation is written. 118 func (mt mutationTest) writeMutation(m sqlbase.DescriptorMutation) { 119 if m.Direction == sqlbase.DescriptorMutation_NONE { 120 // randomly pick ADD/DROP mutation if this is the first mutation, or 121 // pick the direction already chosen for the first mutation. 122 if len(mt.tableDesc.Mutations) > 0 { 123 m.Direction = mt.tableDesc.Mutations[0].Direction 124 } else { 125 m.Direction = sqlbase.DescriptorMutation_DROP 126 if rand.Intn(2) == 0 { 127 m.Direction = sqlbase.DescriptorMutation_ADD 128 } 129 } 130 } 131 if m.State == sqlbase.DescriptorMutation_UNKNOWN { 132 // randomly pick DELETE_ONLY/DELETE_AND_WRITE_ONLY state. 133 r := rand.Intn(2) 134 if r == 0 { 135 m.State = sqlbase.DescriptorMutation_DELETE_ONLY 136 } else { 137 m.State = sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY 138 } 139 } 140 mt.tableDesc.Mutations = append(mt.tableDesc.Mutations, m) 141 mt.tableDesc.Version++ 142 if err := mt.tableDesc.ValidateTable(); err != nil { 143 mt.Fatal(err) 144 } 145 if err := mt.kvDB.Put( 146 context.Background(), 147 sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, mt.tableDesc.ID), 148 sqlbase.WrapDescriptor(mt.tableDesc), 149 ); err != nil { 150 mt.Fatal(err) 151 } 152 } 153 154 // Test that UPSERT with a column mutation that has a default value with a 155 // NOT NULL constraint can handle the null input to its row fetcher, and 156 // produces output rows of the correct shape. 157 // Regression test for #29436. 158 func TestUpsertWithColumnMutationAndNotNullDefault(t *testing.T) { 159 defer leaktest.AfterTest(t)() 160 // NB: This test manually adds mutations to a table descriptor to test that 161 // other schema changes work in the presence of those mutations. Since there's 162 // no job associated with the added mutations, those mutations stay on the 163 // table descriptor but don't do anything, which is what we want. 164 165 // The descriptor changes made must have an immediate effect 166 // so disable leases on tables. 167 defer lease.TestingDisableTableLeases()() 168 // Disable external processing of mutations. 169 params, _ := tests.CreateTestServerParams() 170 server, sqlDB, kvDB := serverutils.StartServer(t, params) 171 defer server.Stopper().Stop(context.Background()) 172 173 if _, err := sqlDB.Exec(` 174 CREATE DATABASE t; 175 CREATE TABLE t.test (k VARCHAR PRIMARY KEY DEFAULT 'default', v VARCHAR); 176 INSERT INTO t.test VALUES('a', 'foo'); 177 ALTER TABLE t.test ADD COLUMN i VARCHAR NOT NULL DEFAULT 'i'; 178 `); err != nil { 179 t.Fatal(err) 180 } 181 182 // read table descriptor 183 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 184 185 mTest := makeMutationTest(t, kvDB, sqlDB, tableDesc) 186 // Add column "i" as a mutation in delete/write. 187 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY}) 188 189 // This row will conflict with the original row, and should insert an `i` 190 // into the new column. 191 mTest.Exec(t, `UPSERT INTO t.test VALUES('a', 'bar') RETURNING k`) 192 193 // These rows will not conflict. 194 mTest.Exec(t, `UPSERT INTO t.test VALUES('b', 'bar') RETURNING k`) 195 mTest.Exec(t, `INSERT INTO t.test VALUES('c', 'bar') RETURNING k, v`) 196 mTest.Exec(t, `INSERT INTO t.test VALUES('c', 'bar') ON CONFLICT(k) DO UPDATE SET v='qux' RETURNING k`) 197 198 mTest.CheckQueryResults(t, `SELECT * FROM t.test`, [][]string{ 199 {"a", "bar"}, 200 {"b", "bar"}, 201 {"c", "qux"}, 202 }) 203 204 mTest.makeMutationsActive() 205 206 mTest.CheckQueryResults(t, `SELECT * FROM t.test`, [][]string{ 207 {"a", "bar", "i"}, 208 {"b", "bar", "i"}, 209 {"c", "qux", "i"}, 210 }) 211 } 212 213 // Test INSERT, UPDATE, UPSERT, and DELETE operations with a column schema 214 // change. 215 func TestOperationsWithColumnMutation(t *testing.T) { 216 defer leaktest.AfterTest(t)() 217 // NB: This test manually adds mutations to a table descriptor to test that 218 // other schema changes work in the presence of those mutations. Since there's 219 // no job associated with the added mutations, those mutations stay on the 220 // table descriptor but don't do anything, which is what we want. 221 222 // The descriptor changes made must have an immediate effect 223 // so disable leases on tables. 224 defer lease.TestingDisableTableLeases()() 225 // Disable external processing of mutations. 226 params, _ := tests.CreateTestServerParams() 227 server, sqlDB, kvDB := serverutils.StartServer(t, params) 228 defer server.Stopper().Stop(context.Background()) 229 230 // Fix the column families so the key counts below don't change if the 231 // family heuristics are updated. 232 // Add an index so that we test adding a column when a table has an index. 233 if _, err := sqlDB.Exec(` 234 CREATE DATABASE t; 235 CREATE TABLE t.test (k VARCHAR PRIMARY KEY DEFAULT 'default', v VARCHAR, i VARCHAR DEFAULT 'i', FAMILY (k), FAMILY (v), FAMILY (i)); 236 CREATE INDEX allidx ON t.test (k, v); 237 `); err != nil { 238 t.Fatal(err) 239 } 240 241 // read table descriptor 242 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 243 244 mTest := makeMutationTest(t, kvDB, sqlDB, tableDesc) 245 246 starQuery := `SELECT * FROM t.test` 247 for _, useUpsert := range []bool{true, false} { 248 // Run the tests for both states. 249 for _, state := range []sqlbase.DescriptorMutation_State{sqlbase.DescriptorMutation_DELETE_ONLY, 250 sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY} { 251 t.Run(fmt.Sprintf("useUpsert=%t/state=%v", useUpsert, state), 252 func(t *testing.T) { 253 254 // Init table to start state. 255 mTest.Exec(t, `TRUNCATE TABLE t.test`) 256 // read table descriptor 257 mTest.tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 258 259 initRows := [][]string{{"a", "z", "q"}} 260 for _, row := range initRows { 261 if useUpsert { 262 mTest.Exec(t, `UPSERT INTO t.test VALUES ($1, $2, $3)`, row[0], row[1], row[2]) 263 } else { 264 mTest.Exec(t, `INSERT INTO t.test VALUES ($1, $2, $3)`, row[0], row[1], row[2]) 265 } 266 } 267 // Check that the table only contains the initRows. 268 mTest.CheckQueryResults(t, starQuery, initRows) 269 270 // Add column "i" as a mutation. 271 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 272 // A direct read of column "i" fails. 273 if _, err := sqlDB.Query(`SELECT i FROM t.test`); err == nil { 274 t.Fatalf("Read succeeded despite column being in %v state", sqlbase.DescriptorMutation{State: state}) 275 } 276 // The table only contains columns "k" and "v". 277 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "z"}}) 278 279 // The column backfill uses Put instead of CPut because it depends on 280 // an INSERT of a column in the DELETE_AND_WRITE_ONLY state failing. These two 281 // tests guarantee that. 282 283 var err error 284 // Inserting a row into the table while specifying column "i" results in an error. 285 if useUpsert { 286 _, err = sqlDB.Exec(`UPSERT INTO t.test (k, v, i) VALUES ('b', 'y', 'i')`) 287 } else { 288 _, err = sqlDB.Exec(`INSERT INTO t.test (k, v, i) VALUES ('b', 'y', 'i')`) 289 } 290 if !testutils.IsError(err, `column "i" does not exist`) && 291 !testutils.IsError(err, `column "i" is being backfilled`) { 292 t.Fatal(err) 293 } 294 if useUpsert { 295 _, err = sqlDB.Exec(`UPSERT INTO t.test (k, v) VALUES ('b', 'y') RETURNING i`) 296 } else { 297 _, err = sqlDB.Exec(`INSERT INTO t.test (k, v) VALUES ('b', 'y') RETURNING i`) 298 } 299 if !testutils.IsError(err, `column "i" does not exist`) { 300 t.Fatal(err) 301 } 302 303 // Repeating the same without specifying the columns results in a different error. 304 if useUpsert { 305 _, err = sqlDB.Exec(`UPSERT INTO t.test VALUES ('b', 'y', 'i')`) 306 } else { 307 _, err = sqlDB.Exec(`INSERT INTO t.test VALUES ('b', 'y', 'i')`) 308 } 309 if !testutils.IsError(err, "(IN|UP)SERT has more expressions than target columns, 3 expressions for 2 targets") && 310 !testutils.IsError(err, `column "i" is being backfilled`) { 311 t.Fatal(err) 312 } 313 314 // Make column "i" live so that it is read. 315 mTest.makeMutationsActive() 316 // Check that we can read all the rows and columns. 317 mTest.CheckQueryResults(t, starQuery, initRows) 318 319 var afterDefaultInsert, afterInsert, afterUpdate, afterPKUpdate, afterDelete [][]string 320 var afterDeleteKeys int 321 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 322 // The default value of "i" for column "i" is not written. 323 afterDefaultInsert = [][]string{{"a", "z", "q"}, {"default", "NULL", "NULL"}} 324 // The default value of "i" for column "i" is not written. 325 afterInsert = [][]string{{"a", "z", "q"}, {"c", "x", "NULL"}} 326 // Update is a noop for column "i". 327 afterUpdate = [][]string{{"a", "u", "q"}, {"c", "x", "NULL"}} 328 // Update the pk of the second tuple from c to d 329 afterPKUpdate = [][]string{{"a", "u", "q"}, {"d", "x", "NULL"}} 330 // Delete also deletes column "i". 331 afterDelete = [][]string{{"d", "x", "NULL"}} 332 afterDeleteKeys = 3 333 } else { 334 // The default value of "i" for column "i" is written. 335 afterDefaultInsert = [][]string{{"a", "z", "q"}, {"default", "NULL", "i"}} 336 // The default value of "i" for column "i" is written. 337 afterInsert = [][]string{{"a", "z", "q"}, {"c", "x", "i"}} 338 // Upsert/update sets column "i" to default value of "i". 339 afterUpdate = [][]string{{"a", "u", "i"}, {"c", "x", "i"}} 340 afterPKUpdate = [][]string{{"a", "u", "i"}, {"d", "x", "i"}} 341 // Delete also deletes column "i". 342 afterDelete = [][]string{{"d", "x", "i"}} 343 afterDeleteKeys = 4 344 } 345 // Make column "i" a mutation. 346 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 347 // Insert an all-defaults row into the table. 348 if useUpsert { 349 mTest.Exec(t, `UPSERT INTO t.test DEFAULT VALUES`) 350 } else { 351 mTest.Exec(t, `INSERT INTO t.test DEFAULT VALUES`) 352 } 353 // Make column "i" live so that it is read. 354 mTest.makeMutationsActive() 355 // Notice that the default value of "i" is only written when the 356 // descriptor is in the DELETE_AND_WRITE_ONLY state. 357 mTest.CheckQueryResults(t, starQuery, afterDefaultInsert) 358 // Clean up the all-defaults row 359 mTest.Exec(t, `DELETE FROM t.test WHERE k = 'default'`) 360 361 // Make column "i" a mutation. 362 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 363 // Insert a row into the table. 364 if useUpsert { 365 mTest.Exec(t, `UPSERT INTO t.test VALUES ('c', 'x')`) 366 } else { 367 mTest.Exec(t, `INSERT INTO t.test VALUES ('c', 'x')`) 368 } 369 // Make column "i" live so that it is read. 370 mTest.makeMutationsActive() 371 // Notice that the default value of "i" is only written when the 372 // descriptor is in the DELETE_AND_WRITE_ONLY state. 373 mTest.CheckQueryResults(t, starQuery, afterInsert) 374 375 // The column backfill uses Put instead of CPut because it depends on 376 // an UPDATE of a column in the DELETE_AND_WRITE_ONLY state failing. This test 377 // guarantees that. 378 379 // Make column "i" a mutation. 380 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 381 // Updating column "i" for a row fails. 382 if useUpsert { 383 _, err := sqlDB.Exec(`UPSERT INTO t.test VALUES ('a', 'u', 'u')`) 384 if !testutils.IsError(err, `UPSERT has more expressions than target columns, 3 expressions for 2 targets`) { 385 t.Fatal(err) 386 } 387 } else { 388 _, err := sqlDB.Exec(`UPDATE t.test SET (v, i) = ('u', 'u') WHERE k = 'a'`) 389 if !testutils.IsError(err, `column "i" does not exist`) && 390 !testutils.IsError(err, `column "i" is being backfilled`) { 391 t.Fatal(err) 392 } 393 } 394 // Make column "i" live so that it is read. 395 mTest.makeMutationsActive() 396 // The above failed update was a noop. 397 mTest.CheckQueryResults(t, starQuery, afterInsert) 398 399 // Make column "i" a mutation. 400 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 401 // Update a row without specifying mutation column "i". 402 if useUpsert { 403 mTest.Exec(t, `UPSERT INTO t.test VALUES ('a', 'u')`) 404 } else { 405 mTest.Exec(t, `UPDATE t.test SET v = 'u' WHERE k = 'a'`) 406 } 407 // Make column "i" live so that it is read. 408 mTest.makeMutationsActive() 409 // The update to column "v" is seen; there is no effect on column "i". 410 mTest.CheckQueryResults(t, starQuery, afterUpdate) 411 412 // Make column "i" a mutation. 413 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 414 // Update primary key of row "c" to be "d" 415 mTest.Exec(t, `UPDATE t.test SET k = 'd' WHERE v = 'x'`) 416 // Make column "i" live so that it is read. 417 mTest.makeMutationsActive() 418 mTest.CheckQueryResults(t, starQuery, afterPKUpdate) 419 420 // Make column "i" a mutation. 421 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 422 // Delete row "a". 423 mTest.Exec(t, `DELETE FROM t.test WHERE k = 'a'`) 424 // Make column "i" live so that it is read. 425 mTest.makeMutationsActive() 426 // Row "a" is deleted. 427 mTest.CheckQueryResults(t, starQuery, afterDelete) 428 // Check that there are no hidden KV values for row "a", 429 // and column "i" for row "a" was deleted. 430 mTest.checkTableSize(afterDeleteKeys) 431 }) 432 } 433 } 434 435 // Check that a mutation can only be inserted with an explicit mutation state, and direction. 436 tableDesc = mTest.tableDesc 437 tableDesc.Mutations = []sqlbase.DescriptorMutation{{}} 438 if err := tableDesc.ValidateTable(); !testutils.IsError(err, "mutation in state UNKNOWN, direction NONE, and no column/index descriptor") { 439 t.Fatal(err) 440 } 441 tableDesc.Mutations = []sqlbase.DescriptorMutation{{Descriptor_: &sqlbase.DescriptorMutation_Column{Column: &tableDesc.Columns[len(tableDesc.Columns)-1]}}} 442 tableDesc.Columns = tableDesc.Columns[:len(tableDesc.Columns)-1] 443 if err := tableDesc.ValidateTable(); !testutils.IsError(err, `mutation in state UNKNOWN, direction NONE, col "i", id 3`) { 444 t.Fatal(err) 445 } 446 tableDesc.Mutations[0].State = sqlbase.DescriptorMutation_DELETE_ONLY 447 if err := tableDesc.ValidateTable(); !testutils.IsError(err, `mutation in state DELETE_ONLY, direction NONE, col "i", id 3`) { 448 t.Fatal(err) 449 } 450 tableDesc.Mutations[0].State = sqlbase.DescriptorMutation_UNKNOWN 451 tableDesc.Mutations[0].Direction = sqlbase.DescriptorMutation_DROP 452 if err := tableDesc.ValidateTable(); !testutils.IsError(err, `mutation in state UNKNOWN, direction DROP, col "i", id 3`) { 453 t.Fatal(err) 454 } 455 } 456 457 // writeIndexMutation adds index as a mutation and writes the 458 // descriptor to the DB. 459 func (mt mutationTest) writeIndexMutation(index string, m sqlbase.DescriptorMutation) { 460 tableDesc := mt.tableDesc 461 idx, _, err := tableDesc.FindIndexByName(index) 462 if err != nil { 463 mt.Fatal(err) 464 } 465 // The rewrite below potentially invalidates the original object with an overwrite. 466 // Clarify what's going on. 467 idxCopy := *idx 468 for i := range tableDesc.Indexes { 469 if idxCopy.ID == tableDesc.Indexes[i].ID { 470 tableDesc.Indexes = append(tableDesc.Indexes[:i], tableDesc.Indexes[i+1:]...) 471 break 472 } 473 } 474 475 m.Descriptor_ = &sqlbase.DescriptorMutation_Index{Index: &idxCopy} 476 mt.writeMutation(m) 477 } 478 479 // Test INSERT, UPDATE, UPSERT, and DELETE operations with an index schema 480 // change. 481 func TestOperationsWithIndexMutation(t *testing.T) { 482 defer leaktest.AfterTest(t)() 483 // NB: This test manually adds mutations to a table descriptor to test that 484 // other schema changes work in the presence of those mutations. Since there's 485 // no job associated with the added mutations, those mutations stay on the 486 // table descriptor but don't do anything, which is what we want. 487 488 // The descriptor changes made must have an immediate effect. 489 defer lease.TestingDisableTableLeases()() 490 // Disable external processing of mutations. 491 params, _ := tests.CreateTestServerParams() 492 server, sqlDB, kvDB := serverutils.StartServer(t, params) 493 defer server.Stopper().Stop(context.Background()) 494 495 if _, err := sqlDB.Exec(` 496 CREATE DATABASE t; 497 CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, INDEX foo (v)); 498 `); err != nil { 499 t.Fatal(err) 500 } 501 502 // read table descriptor 503 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 504 505 mTest := makeMutationTest(t, kvDB, sqlDB, tableDesc) 506 507 starQuery := `SELECT * FROM t.test` 508 indexQuery := `SELECT v FROM t.test@foo` 509 for _, useUpsert := range []bool{true, false} { 510 // See the effect of the operations depending on the state. 511 for _, state := range []sqlbase.DescriptorMutation_State{sqlbase.DescriptorMutation_DELETE_ONLY, 512 sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY} { 513 // Init table with some entries. 514 if _, err := sqlDB.Exec(`TRUNCATE TABLE t.test`); err != nil { 515 t.Fatal(err) 516 } 517 // read table descriptor 518 mTest.tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 519 520 initRows := [][]string{{"a", "z"}, {"b", "y"}} 521 for _, row := range initRows { 522 if useUpsert { 523 mTest.Exec(t, `UPSERT INTO t.test VALUES ($1, $2)`, row[0], row[1]) 524 } else { 525 mTest.Exec(t, `INSERT INTO t.test VALUES ($1, $2)`, row[0], row[1]) 526 } 527 } 528 mTest.CheckQueryResults(t, starQuery, initRows) 529 // Index foo is visible. 530 mTest.CheckQueryResults(t, indexQuery, [][]string{{"y"}, {"z"}}) 531 532 // Index foo is invisible once it's a mutation. 533 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: state}) 534 if _, err := sqlDB.Query(indexQuery); !testutils.IsError(err, `index "foo" not found`) { 535 t.Fatal(err) 536 } 537 538 // Insert a new entry. 539 if useUpsert { 540 mTest.Exec(t, `UPSERT INTO t.test VALUES ('c', 'x')`) 541 } else { 542 mTest.Exec(t, `INSERT INTO t.test VALUES ('c', 'x')`) 543 } 544 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "z"}, {"b", "y"}, {"c", "x"}}) 545 546 // Make index "foo" live so that we can read it. 547 mTest.makeMutationsActive() 548 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 549 // "x" didn't get added to the index. 550 mTest.CheckQueryResults(t, indexQuery, [][]string{{"y"}, {"z"}}) 551 } else { 552 // "x" got added to the index. 553 mTest.CheckQueryResults(t, indexQuery, [][]string{{"x"}, {"y"}, {"z"}}) 554 } 555 556 // Make "foo" a mutation. 557 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: state}) 558 // Update. 559 if useUpsert { 560 mTest.Exec(t, `UPSERT INTO t.test VALUES ('c', 'w')`) 561 // Update "v" to its current value "z" in row "a". 562 mTest.Exec(t, `UPSERT INTO t.test VALUES ('a', 'z')`) 563 } else { 564 mTest.Exec(t, `UPDATE t.test SET v = 'w' WHERE k = 'c'`) 565 // Update "v" to its current value "z" in row "a". 566 mTest.Exec(t, `UPDATE t.test SET v = 'z' WHERE k = 'a'`) 567 } 568 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "z"}, {"b", "y"}, {"c", "w"}}) 569 570 // Make index "foo" live so that we can read it. 571 mTest.makeMutationsActive() 572 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 573 // updating "x" -> "w" will result in "x" being deleted from the index. 574 // updating "z" -> "z" results in "z" being deleted from the index. 575 mTest.CheckQueryResults(t, indexQuery, [][]string{{"y"}}) 576 } else { 577 // updating "x" -> "w" results in the index updating from "x" -> "w", 578 // updating "z" -> "z" is a noop on the index. 579 mTest.CheckQueryResults(t, indexQuery, [][]string{{"w"}, {"y"}, {"z"}}) 580 } 581 582 // Make "foo" a mutation. 583 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: state}) 584 // Update the primary key of row "a". 585 mTest.Exec(t, `UPDATE t.test SET k = 'd' WHERE v = 'z'`) 586 mTest.CheckQueryResults(t, starQuery, [][]string{{"b", "y"}, {"c", "w"}, {"d", "z"}}) 587 588 // Make index "foo" live so that we can read it. 589 mTest.makeMutationsActive() 590 // Updating the primary key for a row when we're in delete-only won't 591 // create a new index entry, and will delete the old one. Otherwise it'll 592 // create a new entry and delete the old one. 593 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 594 mTest.CheckQueryResults(t, indexQuery, [][]string{{"y"}}) 595 } else { 596 mTest.CheckQueryResults(t, indexQuery, [][]string{{"w"}, {"y"}, {"z"}}) 597 } 598 599 // Make "foo" a mutation. 600 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: state}) 601 // Delete row "b". 602 mTest.Exec(t, `DELETE FROM t.test WHERE k = 'b'`) 603 mTest.CheckQueryResults(t, starQuery, [][]string{{"c", "w"}, {"d", "z"}}) 604 605 // Make index "foo" live so that we can read it. 606 mTest.makeMutationsActive() 607 // Deleting row "b" deletes "y" from the index. 608 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 609 mTest.CheckQueryResults(t, indexQuery, [][]string{}) 610 } else { 611 mTest.CheckQueryResults(t, indexQuery, [][]string{{"w"}, {"z"}}) 612 } 613 } 614 } 615 616 // Check that a mutation can only be inserted with an explicit mutation state. 617 tableDesc = mTest.tableDesc 618 tableDesc.Mutations = []sqlbase.DescriptorMutation{{Descriptor_: &sqlbase.DescriptorMutation_Index{Index: &tableDesc.Indexes[len(tableDesc.Indexes)-1]}}} 619 tableDesc.Indexes = tableDesc.Indexes[:len(tableDesc.Indexes)-1] 620 if err := tableDesc.ValidateTable(); !testutils.IsError(err, "mutation in state UNKNOWN, direction NONE, index foo, id 2") { 621 t.Fatal(err) 622 } 623 } 624 625 // TestOperationsWithColumnAndIndexMutation tests the INSERT, UPDATE, UPSERT, 626 // and DELETE operations while an index mutation refers to a column mutation. 627 func TestOperationsWithColumnAndIndexMutation(t *testing.T) { 628 defer leaktest.AfterTest(t)() 629 // NB: This test manually adds mutations to a table descriptor to test that 630 // other schema changes work in the presence of those mutations. Since there's 631 // no job associated with the added mutations, those mutations stay on the 632 // table descriptor but don't do anything, which is what we want. 633 634 // The descriptor changes made must have an immediate effect 635 // so disable leases on tables. 636 defer lease.TestingDisableTableLeases()() 637 params, _ := tests.CreateTestServerParams() 638 server, sqlDB, kvDB := serverutils.StartServer(t, params) 639 defer server.Stopper().Stop(context.Background()) 640 641 // Create a table with column i and an index on v and i. Fix the column 642 // families so the key counts below don't change if the family heuristics 643 // are updated. 644 // Add an index so that we test adding a column when a table has an index. 645 if _, err := sqlDB.Exec(` 646 CREATE DATABASE t; 647 CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, i CHAR, INDEX foo (i, v), FAMILY (k), FAMILY (v), FAMILY (i)); 648 CREATE INDEX allidx ON t.test (k, v); 649 `); err != nil { 650 t.Fatal(err) 651 } 652 653 // read table descriptor 654 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 655 656 mTest := makeMutationTest(t, kvDB, sqlDB, tableDesc) 657 658 starQuery := `SELECT * FROM t.test` 659 indexQuery := `SELECT i FROM t.test@foo` 660 for _, useUpsert := range []bool{true, false} { 661 // Run the tests for both states for a column and an index. 662 for _, state := range []sqlbase.DescriptorMutation_State{ 663 sqlbase.DescriptorMutation_DELETE_ONLY, 664 sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY, 665 } { 666 for _, idxState := range []sqlbase.DescriptorMutation_State{ 667 sqlbase.DescriptorMutation_DELETE_ONLY, 668 sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY, 669 } { 670 // Ignore the impossible column in DELETE_ONLY state while index 671 // is in the DELETE_AND_WRITE_ONLY state. 672 if state == sqlbase.DescriptorMutation_DELETE_ONLY && 673 idxState == sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY { 674 continue 675 } 676 // Init table to start state. 677 if _, err := sqlDB.Exec(`TRUNCATE TABLE t.test`); err != nil { 678 t.Fatal(err) 679 } 680 681 // read table descriptor 682 mTest.tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 683 684 initRows := [][]string{{"a", "z", "q"}, {"b", "y", "r"}} 685 for _, row := range initRows { 686 if useUpsert { 687 mTest.Exec(t, `UPSERT INTO t.test VALUES ($1, $2, $3)`, row[0], row[1], row[2]) 688 } else { 689 mTest.Exec(t, `INSERT INTO t.test VALUES ($1, $2, $3)`, row[0], row[1], row[2]) 690 } 691 } 692 // Check that the table only contains the initRows. 693 mTest.CheckQueryResults(t, starQuery, initRows) 694 695 // Add index "foo" as a mutation. 696 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: idxState}) 697 // Make column "i" a mutation. 698 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 699 700 // Insert a row into the table. 701 if useUpsert { 702 mTest.Exec(t, `UPSERT INTO t.test VALUES ('c', 'x')`) 703 } else { 704 mTest.Exec(t, `INSERT INTO t.test VALUES ('c', 'x')`) 705 } 706 707 // Make column "i" and index "foo" live. 708 mTest.makeMutationsActive() 709 // column "i" has no entry. 710 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "z", "q"}, {"b", "y", "r"}, {"c", "x", "NULL"}}) 711 if idxState == sqlbase.DescriptorMutation_DELETE_ONLY { 712 // No index entry for row "c" 713 mTest.CheckQueryResults(t, indexQuery, [][]string{{"q"}, {"r"}}) 714 } else { 715 // Index entry for row "c" 716 mTest.CheckQueryResults(t, indexQuery, [][]string{{"NULL"}, {"q"}, {"r"}}) 717 } 718 719 // Add index "foo" as a mutation. 720 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: idxState}) 721 // Make column "i" a mutation. 722 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 723 724 // Updating column "i" for a row fails. 725 if useUpsert { 726 _, err := sqlDB.Exec(`UPSERT INTO t.test VALUES ('a', 'u', 'u')`) 727 if !testutils.IsError(err, `UPSERT has more expressions than target columns, 3 expressions for 2 targets`) { 728 t.Error(err) 729 } 730 } else { 731 _, err := sqlDB.Exec(`UPDATE t.test SET (v, i) = ('u', 'u') WHERE k = 'a'`) 732 if !testutils.IsError(err, `column "i" does not exist`) && 733 !testutils.IsError(err, `column "i" is being backfilled`) { 734 t.Error(err) 735 } 736 } 737 738 // Using the mutation column as an index expression is disallowed. 739 _, err := sqlDB.Exec(`UPDATE t.test SET v = 'u' WHERE i < 'a'`) 740 if !testutils.IsError(err, `column "i" is being backfilled`) { 741 t.Error(err) 742 } 743 // TODO(vivek): Fix this error to return the same is being 744 // backfilled error. 745 _, err = sqlDB.Exec(`UPDATE t.test SET i = 'u' WHERE k = 'a'`) 746 if !testutils.IsError(err, `column "i" does not exist`) && 747 !testutils.IsError(err, `column "i" is being backfilled`) { 748 t.Error(err) 749 } 750 _, err = sqlDB.Exec(`DELETE FROM t.test WHERE i < 'a'`) 751 if !testutils.IsError(err, `column "i" is being backfilled`) { 752 t.Error(err) 753 } 754 755 // Update a row without specifying mutation column "i". 756 if useUpsert { 757 mTest.Exec(t, `UPSERT INTO t.test VALUES ('a', 'u')`) 758 } else { 759 mTest.Exec(t, `UPDATE t.test SET v = 'u' WHERE k = 'a'`) 760 } 761 // Make column "i" and index "foo" live. 762 mTest.makeMutationsActive() 763 764 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 765 // Mutation column "i" is not updated. 766 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "u", "q"}, {"b", "y", "r"}, {"c", "x", "NULL"}}) 767 } else { 768 // Mutation column "i" is set to its default value (NULL). 769 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "u", "NULL"}, {"b", "y", "r"}, {"c", "x", "NULL"}}) 770 } 771 772 if idxState == sqlbase.DescriptorMutation_DELETE_ONLY { 773 // Index entry for row "a" is deleted. 774 mTest.CheckQueryResults(t, indexQuery, [][]string{{"r"}}) 775 } else { 776 // Index "foo" has NULL "i" value for row "a". 777 mTest.CheckQueryResults(t, indexQuery, [][]string{{"NULL"}, {"NULL"}, {"r"}}) 778 } 779 780 // Add index "foo" as a mutation. 781 mTest.writeIndexMutation("foo", sqlbase.DescriptorMutation{State: idxState}) 782 // Make column "i" a mutation. 783 mTest.writeColumnMutation("i", sqlbase.DescriptorMutation{State: state}) 784 785 // Delete row "b". 786 mTest.Exec(t, `DELETE FROM t.test WHERE k = 'b'`) 787 // Make column "i" and index "foo" live. 788 mTest.makeMutationsActive() 789 // Row "b" is deleted. 790 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 791 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "u", "q"}, {"c", "x", "NULL"}}) 792 } else { 793 mTest.CheckQueryResults(t, starQuery, [][]string{{"a", "u", "NULL"}, {"c", "x", "NULL"}}) 794 } 795 796 // numKVs is the number of expected key-values. We start with the number 797 // of non-NULL values above. 798 numKVs := 6 799 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 800 // In DELETE_ONLY case, the "q" value is not set to NULL above. 801 numKVs++ 802 } 803 804 if idxState == sqlbase.DescriptorMutation_DELETE_ONLY { 805 // Index entry for row "a" is deleted. 806 mTest.CheckQueryResults(t, indexQuery, [][]string{}) 807 } else { 808 // Index entry for row "a" is deleted. 809 if state == sqlbase.DescriptorMutation_DELETE_ONLY { 810 mTest.CheckQueryResults(t, indexQuery, [][]string{{"NULL"}, {"q"}}) 811 } else { 812 mTest.CheckQueryResults(t, indexQuery, [][]string{{"NULL"}, {"NULL"}}) 813 } 814 // We have two index values. 815 numKVs += 2 816 } 817 818 // Check that there are no hidden KV values for row "b", and column 819 // "i" for row "b" was deleted. Also check that the index values are 820 // all accounted for. 821 mTest.checkTableSize(numKVs) 822 } 823 } 824 } 825 } 826 827 // TestSchemaChangeCommandsWithPendingMutations tests how schema change 828 // commands behave when they are referencing schema elements that are 829 // mutations that are not yet live. 830 func TestSchemaChangeCommandsWithPendingMutations(t *testing.T) { 831 defer leaktest.AfterTest(t)() 832 // The descriptor changes made must have an immediate effect 833 // so disable leases on tables. 834 defer lease.TestingDisableTableLeases()() 835 // Disable external processing of mutations. 836 params, _ := tests.CreateTestServerParams() 837 params.Knobs = base.TestingKnobs{ 838 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 839 SchemaChangeJobNoOp: func() bool { 840 return true 841 }, 842 }, 843 } 844 server, sqlDB, kvDB := serverutils.StartServer(t, params) 845 defer server.Stopper().Stop(context.Background()) 846 847 if _, err := sqlDB.Exec(` 848 CREATE DATABASE t; 849 CREATE TABLE t.test (a STRING PRIMARY KEY, b STRING, c STRING, INDEX foo (c)); 850 `); err != nil { 851 t.Fatal(err) 852 } 853 854 // Read table descriptor 855 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 856 857 mt := makeMutationTest(t, kvDB, sqlDB, tableDesc) 858 859 // Test CREATE INDEX in the presence of mutations. 860 861 // Add index DROP mutation "foo"" 862 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 863 if _, err := sqlDB.Exec(`CREATE INDEX foo ON t.test (c)`); !testutils.IsError(err, `index "foo" being dropped, try again later`) { 864 t.Fatal(err) 865 } 866 // Make "foo" live. 867 mt.makeMutationsActive() 868 869 // "foo" is being added. 870 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 871 if _, err := sqlDB.Exec(`CREATE INDEX foo ON t.test (c)`); !testutils.IsError(err, 872 `relation "foo" already exists`) { 873 t.Fatal(err) 874 } 875 // Make "foo" live. 876 mt.makeMutationsActive() 877 // Add column DROP mutation "b" 878 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 879 if _, err := sqlDB.Exec(`CREATE INDEX bar ON t.test (b)`); !testutils.IsError(err, `column "b" does not exist`) { 880 t.Fatal(err) 881 } 882 // Make "b" live. 883 mt.makeMutationsActive() 884 // "b" is being added. 885 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 886 // An index referencing a column mutation that is being added 887 // is allowed to be added. 888 mt.Exec(t, `CREATE INDEX bar ON t.test (b)`) 889 // Make "b" live. 890 mt.makeMutationsActive() 891 892 // Test DROP INDEX in the presence of mutations. 893 894 // Add index DROP mutation "foo"" 895 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 896 // Noop. 897 mt.Exec(t, `DROP INDEX t.test@foo`) 898 // Make "foo" live. 899 mt.makeMutationsActive() 900 // "foo" is being added. 901 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 902 if _, err := sqlDB.Exec(`DROP INDEX t.test@foo`); !testutils.IsError(err, `index "foo" in the middle of being added, try again later`) { 903 t.Fatal(err) 904 } 905 // Make "foo" live. 906 mt.makeMutationsActive() 907 // Test ALTER TABLE ADD/DROP column in the presence of mutations. 908 909 // Add column DROP mutation "b" 910 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 911 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD b CHAR`); !testutils.IsError(err, `column "b" being dropped, try again later`) { 912 t.Fatal(err) 913 } 914 // Noop. 915 mt.Exec(t, `ALTER TABLE t.test DROP b`) 916 // Make "b" live. 917 mt.makeMutationsActive() 918 // "b" is being added. 919 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 920 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD b CHAR`); !testutils.IsError(err, 921 `pq: duplicate: column "b" in the middle of being added, not yet public`) { 922 t.Fatal(err) 923 } 924 if _, err := sqlDB.Exec(`ALTER TABLE t.test DROP b`); !testutils.IsError(err, `column "b" in the middle of being added, try again later`) { 925 t.Fatal(err) 926 } 927 // Make "b" live. 928 mt.makeMutationsActive() 929 930 // Test ALTER TABLE ADD CONSTRAINT in the presence of mutations. 931 932 // Add index DROP mutation "foo"" 933 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 934 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD CONSTRAINT foo UNIQUE (c)`); !testutils.IsError(err, `index "foo" being dropped, try again later`) { 935 t.Fatal(err) 936 } 937 // Make "foo" live. 938 mt.makeMutationsActive() 939 // "foo" is being added. 940 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 941 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD CONSTRAINT foo UNIQUE (c)`); !testutils.IsError(err, 942 `duplicate: index "foo" in the middle of being added, not yet public`) { 943 t.Fatal(err) 944 } 945 // Make "foo" live. 946 mt.makeMutationsActive() 947 // Add column mutation "b" 948 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 949 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD CONSTRAINT bar UNIQUE (b)`); !testutils.IsError(err, `index "bar" contains unknown column "b"`) { 950 t.Fatal(err) 951 } 952 // Make "b" live. 953 mt.makeMutationsActive() 954 // "b" is being added. 955 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 956 // Noop. 957 mt.Exec(t, `ALTER TABLE t.test ADD CONSTRAINT bar UNIQUE (b)`) 958 // Make "b" live. 959 mt.makeMutationsActive() 960 961 // Test DROP CONSTRAINT in the presence of mutations. 962 963 // Add index mutation "foo"" 964 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 965 // Noop. 966 mt.Exec(t, `DROP INDEX t.test@foo`) 967 // Make "foo" live. 968 mt.makeMutationsActive() 969 // "foo" is being added. 970 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 971 if _, err := sqlDB.Exec(`DROP INDEX t.test@foo`); !testutils.IsError(err, `index "foo" in the middle of being added, try again later`) { 972 t.Fatal(err) 973 } 974 // Make "foo" live. 975 mt.makeMutationsActive() 976 977 // Rename column/index, while index is under mutation. 978 979 // Add index mutation "foo"" 980 mt.writeIndexMutation("foo", sqlbase.DescriptorMutation{}) 981 mt.Exec(t, `ALTER INDEX t.test@foo RENAME to ufo`) 982 mt.Exec(t, `ALTER TABLE t.test RENAME COLUMN c TO d`) 983 // The mutation in the table descriptor has changed and we would like 984 // to update our copy to make it live. 985 mt.tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 986 987 // Make "ufo" live. 988 mt.makeMutationsActive() 989 // The index has been renamed to ufo, and the column to d. 990 mt.CheckQueryResults(t, 991 "SHOW INDEXES FROM t.test", 992 [][]string{ 993 {"test", "primary", "false", "1", "a", "ASC", "false", "false"}, 994 {"test", "ufo", "true", "1", "d", "ASC", "false", "false"}, 995 {"test", "ufo", "true", "2", "a", "ASC", "false", "true"}, 996 }, 997 ) 998 999 // Rename column under mutation works properly. 1000 1001 // Add column mutation "b". 1002 mt.writeColumnMutation("b", sqlbase.DescriptorMutation{}) 1003 if _, err := sqlDB.Exec(`ALTER TABLE t.test RENAME COLUMN b TO e`); err != nil { 1004 mt.Fatal(err) 1005 } 1006 1007 // The mutation in the table descriptor has changed and we would like 1008 // to update our copy to make it live. 1009 mt.tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1010 1011 // Make column "e" live. 1012 mt.makeMutationsActive() 1013 // Column b changed to d. 1014 mt.CheckQueryResults(t, 1015 "SHOW COLUMNS FROM t.test", 1016 [][]string{ 1017 {"a", "STRING", "false", "NULL", "", "{primary,ufo}", "false"}, 1018 {"e", "STRING", "true", "NULL", "", "{}", "false"}, 1019 {"d", "STRING", "true", "NULL", "", "{ufo}", "false"}, 1020 }, 1021 ) 1022 1023 // Try to change column defaults while column is under mutation. 1024 mt.writeColumnMutation("e", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_ADD}) 1025 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER COLUMN e SET DEFAULT 'a'`); err != nil { 1026 t.Fatal(err) 1027 } 1028 mt.makeMutationsActive() 1029 mt.writeColumnMutation("e", sqlbase.DescriptorMutation{Direction: sqlbase.DescriptorMutation_DROP}) 1030 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER COLUMN e SET DEFAULT 'a'`); !testutils.IsError( 1031 err, `column "e" in the middle of being dropped`) { 1032 t.Fatal(err) 1033 } 1034 mt.makeMutationsActive() 1035 } 1036 1037 // TestTableMutationQueue tests that schema elements when added are 1038 // assigned the correct start state and mutation id. 1039 func TestTableMutationQueue(t *testing.T) { 1040 defer leaktest.AfterTest(t)() 1041 // Disable synchronous and asynchronous schema change processing so that 1042 // the mutations get queued up. 1043 params, _ := tests.CreateTestServerParams() 1044 params.Knobs = base.TestingKnobs{ 1045 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1046 SchemaChangeJobNoOp: func() bool { 1047 return true 1048 }, 1049 }, 1050 } 1051 server, sqlDB, kvDB := serverutils.StartServer(t, params) 1052 defer server.Stopper().Stop(context.Background()) 1053 1054 // Create a table with column i and an index on v and i. 1055 if _, err := sqlDB.Exec(` 1056 CREATE DATABASE t; 1057 CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR UNIQUE); 1058 `); err != nil { 1059 t.Fatal(err) 1060 } 1061 1062 // Run some schema changes. 1063 1064 // This single command creates three columns and two indexes sharing the 1065 // same mutation ID. 1066 if _, err := sqlDB.Exec( 1067 `ALTER TABLE t.test ADD d INT UNIQUE, ADD e INT UNIQUE, ADD f INT`, 1068 ); err != nil { 1069 t.Fatal(err) 1070 } 1071 1072 // This command creates two mutations sharing the same mutation ID. 1073 if _, err := sqlDB.Exec( 1074 `ALTER TABLE t.test ADD g INT, ADD CONSTRAINT idx_f UNIQUE (f)`, 1075 ); err != nil { 1076 t.Fatal(err) 1077 } 1078 1079 // This command creates a single mutation. 1080 if _, err := sqlDB.Exec(`CREATE UNIQUE INDEX idx_g ON t.test (g)`); err != nil { 1081 t.Fatal(err) 1082 } 1083 1084 // This command created a drop mutation. 1085 if _, err := sqlDB.Exec(`ALTER TABLE t.test DROP v`); err != nil { 1086 t.Fatal(err) 1087 } 1088 1089 // read table descriptor 1090 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1091 1092 expected := []struct { 1093 name string 1094 id sqlbase.MutationID 1095 state sqlbase.DescriptorMutation_State 1096 }{ 1097 {"d", 1, sqlbase.DescriptorMutation_DELETE_ONLY}, 1098 {"test_d_key", 1, sqlbase.DescriptorMutation_DELETE_ONLY}, 1099 {"e", 1, sqlbase.DescriptorMutation_DELETE_ONLY}, 1100 {"test_e_key", 1, sqlbase.DescriptorMutation_DELETE_ONLY}, 1101 {"f", 1, sqlbase.DescriptorMutation_DELETE_ONLY}, 1102 // Second schema change. 1103 {"g", 2, sqlbase.DescriptorMutation_DELETE_ONLY}, 1104 {"idx_f", 2, sqlbase.DescriptorMutation_DELETE_ONLY}, 1105 // Third. 1106 {"idx_g", 3, sqlbase.DescriptorMutation_DELETE_ONLY}, 1107 // Drop mutations start off in the DELETE_AND_WRITE_ONLY state. 1108 // UNIQUE column deletion gets split into two mutations with the same ID. 1109 {"test_v_key", 4, sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY}, 1110 {"v", 4, sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY}, 1111 } 1112 1113 if len(tableDesc.Mutations) != len(expected) { 1114 t.Fatalf("%d mutations, instead of expected %d", len(tableDesc.Mutations), len(expected)) 1115 } 1116 1117 for i, m := range tableDesc.Mutations { 1118 name := expected[i].name 1119 if col := m.GetColumn(); col != nil { 1120 if col.Name != name { 1121 t.Errorf("%d entry: name %s, expected %s", i, col.Name, name) 1122 } 1123 } 1124 if idx := m.GetIndex(); idx != nil { 1125 if idx.Name != name { 1126 t.Errorf("%d entry: name %s, expected %s", i, idx.Name, name) 1127 } 1128 } 1129 if id := expected[i].id; m.MutationID != id { 1130 t.Errorf("%d entry: id %d, expected %d", i, m.MutationID, id) 1131 } 1132 if state := expected[i].state; m.State != state { 1133 t.Errorf("%d entry: state %s, expected %s", i, m.State, state) 1134 } 1135 } 1136 } 1137 1138 // TestAddingFKs checks the behavior of a table in the non-public `ADD` state. 1139 // Being non-public, it should not be visible to clients, and is therefore 1140 // assumed to be empty (e.g. by foreign key checks), since no one could have 1141 // written to it yet. 1142 func TestAddingFKs(t *testing.T) { 1143 defer leaktest.AfterTest(t)() 1144 1145 params, _ := tests.CreateTestServerParams() 1146 s, sqlDB, kvDB := serverutils.StartServer(t, params) 1147 defer s.Stopper().Stop(context.Background()) 1148 1149 if _, err := sqlDB.Exec(` 1150 CREATE DATABASE t; 1151 CREATE TABLE t.products (id INT PRIMARY KEY); 1152 INSERT INTO t.products VALUES (1), (2); 1153 CREATE TABLE t.orders (id INT PRIMARY KEY, product INT REFERENCES t.products, INDEX (product)); 1154 `); err != nil { 1155 t.Fatal(err) 1156 } 1157 1158 // Step the referencing table back to the ADD state. 1159 ordersDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "orders") 1160 ordersDesc.State = sqlbase.TableDescriptor_ADD 1161 ordersDesc.Version++ 1162 if err := kvDB.Put( 1163 context.Background(), 1164 sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, ordersDesc.ID), 1165 sqlbase.WrapDescriptor(ordersDesc), 1166 ); err != nil { 1167 t.Fatal(err) 1168 } 1169 1170 // Generally a referenced table needs to lookup referencing tables to check 1171 // FKs during delete operations, but referencing tables in the ADD state are 1172 // given special treatment. 1173 if _, err := sqlDB.Exec(`DELETE FROM t.products`); err != nil { 1174 t.Fatal(err) 1175 } 1176 1177 // Client should not see the orders table. 1178 if _, err := sqlDB.Exec( 1179 `SELECT * FROM t.orders`, 1180 ); !testutils.IsError(err, `table is being added`) { 1181 t.Fatal(err) 1182 } 1183 }