github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/schema_changer_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 "database/sql/driver" 17 "fmt" 18 "math/rand" 19 "strings" 20 "sync" 21 "sync/atomic" 22 "testing" 23 "time" 24 25 "github.com/cockroachdb/cockroach/pkg/base" 26 "github.com/cockroachdb/cockroach/pkg/config/zonepb" 27 "github.com/cockroachdb/cockroach/pkg/jobs" 28 "github.com/cockroachdb/cockroach/pkg/jobs/jobspb" 29 "github.com/cockroachdb/cockroach/pkg/keys" 30 "github.com/cockroachdb/cockroach/pkg/kv" 31 "github.com/cockroachdb/cockroach/pkg/kv/kvclient/kvcoord" 32 "github.com/cockroachdb/cockroach/pkg/roachpb" 33 "github.com/cockroachdb/cockroach/pkg/security" 34 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 35 "github.com/cockroachdb/cockroach/pkg/sql" 36 "github.com/cockroachdb/cockroach/pkg/sql/catalog/lease" 37 "github.com/cockroachdb/cockroach/pkg/sql/execinfra" 38 "github.com/cockroachdb/cockroach/pkg/sql/gcjob" 39 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 40 "github.com/cockroachdb/cockroach/pkg/sql/sqltestutils" 41 "github.com/cockroachdb/cockroach/pkg/sql/stats" 42 "github.com/cockroachdb/cockroach/pkg/sql/tests" 43 "github.com/cockroachdb/cockroach/pkg/sqlmigrations" 44 "github.com/cockroachdb/cockroach/pkg/testutils" 45 "github.com/cockroachdb/cockroach/pkg/testutils/jobutils" 46 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 47 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 48 "github.com/cockroachdb/cockroach/pkg/util" 49 "github.com/cockroachdb/cockroach/pkg/util/ctxgroup" 50 "github.com/cockroachdb/cockroach/pkg/util/json" 51 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 52 "github.com/cockroachdb/cockroach/pkg/util/log" 53 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 54 "github.com/cockroachdb/cockroach/pkg/util/retry" 55 "github.com/cockroachdb/cockroach/pkg/util/stop" 56 "github.com/cockroachdb/cockroach/pkg/util/syncutil" 57 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 58 "github.com/cockroachdb/cockroach/pkg/util/tracing" 59 "github.com/cockroachdb/errors" 60 "github.com/stretchr/testify/require" 61 ) 62 63 // setTestJobsAdoptInterval sets a short job adoption interval for a test 64 // and returns a function to reset it after the test. The intention is that 65 // the returned function should be deferred. 66 func setTestJobsAdoptInterval() (reset func()) { 67 const testingJobsAdoptionInverval = 100 * time.Millisecond 68 old := jobs.DefaultAdoptInterval 69 jobs.DefaultAdoptInterval = testingJobsAdoptionInverval 70 return func() { 71 jobs.DefaultAdoptInterval = old 72 } 73 } 74 75 // TestSchemaChangeProcess adds mutations manually to a table descriptor and 76 // ensures that RunStateMachineBeforeBackfill processes the mutation. 77 // TODO (lucy): This is the only test that creates its own schema changer and 78 // calls methods on it. Now that every schema changer "belongs" to a single 79 // instance of a job resumer there's less of a reason to test this way. Should 80 // this test still even exist? 81 func TestSchemaChangeProcess(t *testing.T) { 82 defer leaktest.AfterTest(t)() 83 // The descriptor changes made must have an immediate effect 84 // so disable leases on tables. 85 defer lease.TestingDisableTableLeases()() 86 87 params, _ := tests.CreateTestServerParams() 88 s, sqlDB, kvDB := serverutils.StartServer(t, params) 89 defer s.Stopper().Stop(context.Background()) 90 91 var id = sqlbase.ID(keys.MinNonPredefinedUserDescID + 1 /* skip over DB ID */) 92 var instance = base.SQLInstanceID(2) 93 stopper := stop.NewStopper() 94 cfg := base.NewLeaseManagerConfig() 95 execCfg := s.ExecutorConfig().(sql.ExecutorConfig) 96 leaseMgr := lease.NewLeaseManager( 97 log.AmbientContext{Tracer: tracing.NewTracer()}, 98 execCfg.NodeID, 99 execCfg.DB, 100 execCfg.Clock, 101 execCfg.InternalExecutor, 102 execCfg.Settings, 103 execCfg.Codec, 104 lease.ManagerTestingKnobs{}, 105 stopper, 106 cfg, 107 ) 108 jobRegistry := s.JobRegistry().(*jobs.Registry) 109 defer stopper.Stop(context.Background()) 110 changer := sql.NewSchemaChangerForTesting( 111 id, 0, instance, *kvDB, leaseMgr, jobRegistry, &execCfg, cluster.MakeTestingClusterSettings()) 112 113 if _, err := sqlDB.Exec(` 114 CREATE DATABASE t; 115 CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, INDEX foo(v)); 116 INSERT INTO t.test VALUES ('a', 'b'), ('c', 'd'); 117 `); err != nil { 118 t.Fatal(err) 119 } 120 121 // Read table descriptor for version. 122 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 123 expectedVersion := tableDesc.Version 124 ctx := context.Background() 125 126 // Check that RunStateMachineBeforeBackfill doesn't do anything 127 // if there are no mutations queued. 128 if err := changer.RunStateMachineBeforeBackfill(ctx); err != nil { 129 t.Fatal(err) 130 } 131 132 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 133 newVersion := tableDesc.Version 134 if newVersion != expectedVersion { 135 t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) 136 } 137 138 // Check that RunStateMachineBeforeBackfill functions properly. 139 expectedVersion = tableDesc.Version 140 // Make a copy of the index for use in a mutation. 141 index := protoutil.Clone(&tableDesc.Indexes[0]).(*sqlbase.IndexDescriptor) 142 index.Name = "bar" 143 index.ID = tableDesc.NextIndexID 144 tableDesc.NextIndexID++ 145 changer = sql.NewSchemaChangerForTesting( 146 id, tableDesc.NextMutationID, instance, *kvDB, leaseMgr, jobRegistry, 147 &execCfg, cluster.MakeTestingClusterSettings(), 148 ) 149 tableDesc.Mutations = append(tableDesc.Mutations, sqlbase.DescriptorMutation{ 150 Descriptor_: &sqlbase.DescriptorMutation_Index{Index: index}, 151 Direction: sqlbase.DescriptorMutation_ADD, 152 State: sqlbase.DescriptorMutation_DELETE_ONLY, 153 MutationID: tableDesc.NextMutationID, 154 }) 155 tableDesc.NextMutationID++ 156 157 // Run state machine in both directions. 158 for _, direction := range []sqlbase.DescriptorMutation_Direction{sqlbase.DescriptorMutation_ADD, sqlbase.DescriptorMutation_DROP} { 159 tableDesc.Mutations[0].Direction = direction 160 expectedVersion++ 161 if err := kvDB.Put( 162 ctx, 163 sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, tableDesc.ID), 164 sqlbase.WrapDescriptor(tableDesc), 165 ); err != nil { 166 t.Fatal(err) 167 } 168 // The expected end state. 169 expectedState := sqlbase.DescriptorMutation_DELETE_AND_WRITE_ONLY 170 if direction == sqlbase.DescriptorMutation_DROP { 171 expectedState = sqlbase.DescriptorMutation_DELETE_ONLY 172 } 173 // Run two times to ensure idempotency of operations. 174 for i := 0; i < 2; i++ { 175 if err := changer.RunStateMachineBeforeBackfill(ctx); err != nil { 176 t.Fatal(err) 177 } 178 179 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 180 newVersion = tableDesc.Version 181 if newVersion != expectedVersion { 182 t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) 183 } 184 state := tableDesc.Mutations[0].State 185 if state != expectedState { 186 t.Fatalf("bad state; e = %d, v = %d", expectedState, state) 187 } 188 } 189 } 190 // RunStateMachineBeforeBackfill() doesn't complete the schema change. 191 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 192 if len(tableDesc.Mutations) == 0 { 193 t.Fatalf("table expected to have an outstanding schema change: %v", tableDesc) 194 } 195 } 196 197 // TODO (lucy): In the current state of the code it doesn't make sense to try to 198 // test the "async" path separately. This test doesn't have any special 199 // settings. Should it even still exist? 200 func TestAsyncSchemaChanger(t *testing.T) { 201 defer leaktest.AfterTest(t)() 202 // The descriptor changes made must have an immediate effect 203 // so disable leases on tables. 204 defer lease.TestingDisableTableLeases()() 205 // Disable synchronous schema change execution so the asynchronous schema 206 // changer executes all schema changes. 207 params, _ := tests.CreateTestServerParams() 208 s, sqlDB, kvDB := serverutils.StartServer(t, params) 209 defer s.Stopper().Stop(context.Background()) 210 211 if _, err := sqlDB.Exec(` 212 CREATE DATABASE t; 213 CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR); 214 INSERT INTO t.test VALUES ('a', 'b'), ('c', 'd'); 215 `); err != nil { 216 t.Fatal(err) 217 } 218 219 // Read table descriptor for version. 220 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 221 222 // A long running schema change operation runs through 223 // a state machine that increments the version by 3. 224 expectedVersion := tableDesc.Version + 3 225 226 // Run some schema change 227 if _, err := sqlDB.Exec(` 228 CREATE INDEX foo ON t.test (v) 229 `); err != nil { 230 t.Fatal(err) 231 } 232 233 retryOpts := retry.Options{ 234 InitialBackoff: 20 * time.Millisecond, 235 MaxBackoff: 200 * time.Millisecond, 236 Multiplier: 2, 237 } 238 239 // Wait until index is created. 240 for r := retry.Start(retryOpts); r.Next(); { 241 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 242 if len(tableDesc.Indexes) == 1 { 243 break 244 } 245 } 246 247 // Ensure that the indexes have been created. 248 mTest := makeMutationTest(t, kvDB, sqlDB, tableDesc) 249 indexQuery := `SELECT v FROM t.test@foo` 250 mTest.CheckQueryResults(t, indexQuery, [][]string{{"b"}, {"d"}}) 251 252 // Ensure that the version has been incremented. 253 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 254 newVersion := tableDesc.Version 255 if newVersion != expectedVersion { 256 t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) 257 } 258 259 // Apply a schema change that only sets the UpVersion bit. 260 expectedVersion = newVersion + 1 261 262 mTest.Exec(t, `ALTER INDEX t.test@foo RENAME TO ufo`) 263 264 for r := retry.Start(retryOpts); r.Next(); { 265 // Ensure that the version gets incremented. 266 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 267 name := tableDesc.Indexes[0].Name 268 if name != "ufo" { 269 t.Fatalf("bad index name %s", name) 270 } 271 newVersion = tableDesc.Version 272 if newVersion == expectedVersion { 273 break 274 } 275 } 276 277 // Run many schema changes simultaneously and check 278 // that they all get executed. 279 count := 5 280 for i := 0; i < count; i++ { 281 mTest.Exec(t, fmt.Sprintf(`CREATE INDEX foo%d ON t.test (v)`, i)) 282 } 283 // Wait until indexes are created. 284 for r := retry.Start(retryOpts); r.Next(); { 285 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 286 if len(tableDesc.Indexes) == count+1 { 287 break 288 } 289 } 290 for i := 0; i < count; i++ { 291 indexQuery := fmt.Sprintf(`SELECT v FROM t.test@foo%d`, i) 292 mTest.CheckQueryResults(t, indexQuery, [][]string{{"b"}, {"d"}}) 293 } 294 295 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 296 t.Fatal(err) 297 } 298 } 299 300 func getTableKeyCount(ctx context.Context, kvDB *kv.DB) (int, error) { 301 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 302 tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 303 tableEnd := tablePrefix.PrefixEnd() 304 kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0) 305 return len(kvs), err 306 } 307 308 func checkTableKeyCountExact(ctx context.Context, kvDB *kv.DB, e int) error { 309 if count, err := getTableKeyCount(ctx, kvDB); err != nil { 310 return err 311 } else if count != e { 312 return errors.Errorf("expected %d key value pairs, but got %d", e, count) 313 } 314 return nil 315 } 316 317 // checkTableKeyCount returns the number of KVs in the DB, the multiple should be the 318 // number of columns. 319 func checkTableKeyCount(ctx context.Context, kvDB *kv.DB, multiple int, maxValue int) error { 320 return checkTableKeyCountExact(ctx, kvDB, multiple*(maxValue+1)) 321 } 322 323 // Run a particular schema change and run some OLTP operations in parallel, as 324 // soon as the schema change starts executing its backfill. 325 func runSchemaChangeWithOperations( 326 t *testing.T, 327 sqlDB *gosql.DB, 328 kvDB *kv.DB, 329 schemaChange string, 330 maxValue int, 331 keyMultiple int, 332 backfillNotification chan struct{}, 333 useUpsert bool, 334 ) { 335 var wg sync.WaitGroup 336 wg.Add(1) 337 go func() { 338 start := timeutil.Now() 339 // Start schema change that eventually runs a backfill. 340 if _, err := sqlDB.Exec(schemaChange); err != nil { 341 t.Error(err) 342 } 343 t.Logf("schema change %s took %v", schemaChange, timeutil.Since(start)) 344 wg.Done() 345 }() 346 347 // Wait until the schema change backfill starts. 348 <-backfillNotification 349 350 // Run a variety of operations during the backfill. 351 ctx := context.Background() 352 353 // Update some rows. 354 var updatedKeys []int 355 for i := 0; i < 10; i++ { 356 k := rand.Intn(maxValue) 357 v := maxValue + i + 1 358 if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, v, k); err != nil { 359 t.Error(err) 360 } 361 updatedKeys = append(updatedKeys, k) 362 } 363 364 // Reupdate updated values back to what they were before. 365 for _, k := range updatedKeys { 366 if rand.Float32() < 0.5 || !useUpsert { 367 if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, maxValue-k, k); err != nil { 368 t.Error(err) 369 } 370 } else { 371 if _, err := sqlDB.Exec(`UPSERT INTO t.test (k,v) VALUES ($1, $2)`, k, maxValue-k); err != nil { 372 t.Error(err) 373 } 374 } 375 } 376 377 // Delete some rows. 378 deleteStartKey := rand.Intn(maxValue - 10) 379 for i := 0; i < 10; i++ { 380 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = $1`, deleteStartKey+i); err != nil { 381 t.Error(err) 382 } 383 } 384 // Reinsert deleted rows. 385 for i := 0; i < 10; i++ { 386 k := deleteStartKey + i 387 if rand.Float32() < 0.5 || !useUpsert { 388 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES($1, $2)`, k, maxValue-k); err != nil { 389 t.Error(err) 390 } 391 } else { 392 if _, err := sqlDB.Exec(`UPSERT INTO t.test VALUES($1, $2)`, k, maxValue-k); err != nil { 393 t.Error(err) 394 } 395 } 396 } 397 398 // Insert some new rows. 399 numInserts := 10 400 for i := 0; i < numInserts; i++ { 401 k := maxValue + i + 1 402 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES($1, $1)`, k); err != nil { 403 t.Error(err) 404 } 405 } 406 407 wg.Wait() // for schema change to complete. 408 409 // Verify the number of keys left behind in the table to validate schema 410 // change operations. This is wrapped in SucceedsSoon to handle cases where 411 // dropped indexes are expected to be GC'ed immediately after the schema 412 // change completes. 413 testutils.SucceedsSoon(t, func() error { 414 return checkTableKeyCount(ctx, kvDB, keyMultiple, maxValue+numInserts) 415 }) 416 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 417 t.Fatal(err) 418 } 419 420 // Delete the rows inserted. 421 for i := 0; i < numInserts; i++ { 422 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = $1`, maxValue+i+1); err != nil { 423 t.Error(err) 424 } 425 } 426 } 427 428 // bulkInsertIntoTable fills up table t.test with (maxValue + 1) rows. 429 func bulkInsertIntoTable(sqlDB *gosql.DB, maxValue int) error { 430 inserts := make([]string, maxValue+1) 431 for i := 0; i < maxValue+1; i++ { 432 inserts[i] = fmt.Sprintf(`(%d, %d)`, i, maxValue-i) 433 } 434 _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ` + strings.Join(inserts, ",")) 435 return err 436 } 437 438 // Test schema change backfills are not affected by various operations 439 // that run simultaneously. 440 func TestRaceWithBackfill(t *testing.T) { 441 defer leaktest.AfterTest(t)() 442 // protects backfillNotification 443 var mu syncutil.Mutex 444 var backfillNotification chan struct{} 445 446 const numNodes = 5 447 var chunkSize int64 = 100 448 var maxValue = 4000 449 if util.RaceEnabled { 450 // Race builds are a lot slower, so use a smaller number of rows and a 451 // correspondingly smaller chunk size. 452 chunkSize = 5 453 maxValue = 200 454 } 455 456 params, _ := tests.CreateTestServerParams() 457 initBackfillNotification := func() chan struct{} { 458 mu.Lock() 459 defer mu.Unlock() 460 backfillNotification = make(chan struct{}) 461 return backfillNotification 462 } 463 notifyBackfill := func() { 464 mu.Lock() 465 defer mu.Unlock() 466 if backfillNotification != nil { 467 // Close channel to notify that the backfill has started. 468 close(backfillNotification) 469 backfillNotification = nil 470 } 471 } 472 params.Knobs = base.TestingKnobs{ 473 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 474 BackfillChunkSize: chunkSize, 475 }, 476 // Disable GC job. 477 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { select {} }}, 478 DistSQL: &execinfra.TestingKnobs{ 479 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 480 notifyBackfill() 481 return nil 482 }, 483 }, 484 } 485 486 tc := serverutils.StartTestCluster(t, numNodes, 487 base.TestClusterArgs{ 488 ReplicationMode: base.ReplicationManual, 489 ServerArgs: params, 490 }) 491 defer tc.Stopper().Stop(context.Background()) 492 kvDB := tc.Server(0).DB() 493 sqlDB := tc.ServerConn(0) 494 495 if _, err := sqlDB.Exec(` 496 CREATE DATABASE t; 497 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 498 CREATE UNIQUE INDEX vidx ON t.test (v); 499 `); err != nil { 500 t.Fatal(err) 501 } 502 503 // Bulk insert. 504 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 505 t.Fatal(err) 506 } 507 508 // Split the table into multiple ranges. 509 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 510 var sps []sql.SplitPoint 511 for i := 1; i <= numNodes-1; i++ { 512 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / numNodes * i}}) 513 } 514 sql.SplitTable(t, tc, tableDesc, sps) 515 516 ctx := context.Background() 517 518 // number of keys == 2 * number of rows; 1 column family and 1 index entry 519 // for each row. 520 if err := checkTableKeyCount(ctx, kvDB, 2, maxValue); err != nil { 521 t.Fatal(err) 522 } 523 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 524 t.Fatal(err) 525 } 526 527 // Run some schema changes with operations. 528 529 // Add column with a check constraint. 530 runSchemaChangeWithOperations( 531 t, 532 sqlDB, 533 kvDB, 534 "ALTER TABLE t.test ADD COLUMN x DECIMAL DEFAULT (DECIMAL '1.4') CHECK (x >= 0)", 535 maxValue, 536 2, 537 initBackfillNotification(), 538 true, 539 ) 540 541 // Drop column. 542 runSchemaChangeWithOperations( 543 t, 544 sqlDB, 545 kvDB, 546 "ALTER TABLE t.test DROP pi", 547 maxValue, 548 2, 549 initBackfillNotification(), 550 true, 551 ) 552 553 // Add index. 554 runSchemaChangeWithOperations( 555 t, 556 sqlDB, 557 kvDB, 558 "CREATE UNIQUE INDEX foo ON t.test (v)", 559 maxValue, 560 3, 561 initBackfillNotification(), 562 true, 563 ) 564 565 // Add STORING index (that will have non-nil values). 566 runSchemaChangeWithOperations( 567 t, 568 sqlDB, 569 kvDB, 570 "CREATE INDEX bar ON t.test(k) STORING (v)", 571 maxValue, 572 4, 573 initBackfillNotification(), 574 true, 575 ) 576 577 // Verify that the index foo over v is consistent, and that column x has 578 // been backfilled properly. 579 rows, err := sqlDB.Query(`SELECT v, x from t.test@foo`) 580 if err != nil { 581 t.Fatal(err) 582 } 583 defer rows.Close() 584 585 count := 0 586 for ; rows.Next(); count++ { 587 var val int 588 var x float64 589 if err := rows.Scan(&val, &x); err != nil { 590 t.Errorf("row %d scan failed: %s", count, err) 591 continue 592 } 593 if count != val { 594 t.Errorf("e = %d, v = %d", count, val) 595 } 596 if x != 1.4 { 597 t.Errorf("e = %f, v = %f", 1.4, x) 598 } 599 } 600 if err := rows.Err(); err != nil { 601 t.Fatal(err) 602 } 603 eCount := maxValue + 1 604 if eCount != count { 605 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 606 } 607 } 608 609 // Test that a table drop in the middle of a backfill works properly. 610 // The backfill will terminate in the middle, and the drop will 611 // successfully complete without deleting the data. 612 func TestDropWhileBackfill(t *testing.T) { 613 defer leaktest.AfterTest(t)() 614 t.Skip("https://github.com/cockroachdb/cockroach/issues/44944") 615 // protects backfillNotification 616 var mu syncutil.Mutex 617 backfillNotification := make(chan struct{}) 618 619 var partialBackfillDone atomic.Value 620 partialBackfillDone.Store(false) 621 const numNodes, chunkSize = 5, 100 622 maxValue := 4000 623 if util.RaceEnabled { 624 // Race builds are a lot slower, so use a smaller number of rows. 625 // We expect this to also reduce the memory footprint of the test. 626 maxValue = 200 627 } 628 params, _ := tests.CreateTestServerParams() 629 notifyBackfill := func() { 630 mu.Lock() 631 defer mu.Unlock() 632 if backfillNotification != nil { 633 // Close channel to notify that the backfill has started. 634 close(backfillNotification) 635 backfillNotification = nil 636 } 637 } 638 params.Knobs = base.TestingKnobs{ 639 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 640 BackfillChunkSize: chunkSize, 641 }, 642 // Disable GC job. 643 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { select {} }}, 644 DistSQL: &execinfra.TestingKnobs{ 645 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 646 if partialBackfillDone.Load().(bool) { 647 notifyBackfill() 648 // Returning DeadlineExceeded will result in the 649 // schema change being retried. 650 return context.DeadlineExceeded 651 } 652 partialBackfillDone.Store(true) 653 return nil 654 }, 655 }, 656 // Disable backfill migrations, we still need the jobs table migration. 657 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 658 DisableBackfillMigrations: true, 659 }, 660 } 661 662 tc := serverutils.StartTestCluster(t, numNodes, 663 base.TestClusterArgs{ 664 ReplicationMode: base.ReplicationManual, 665 ServerArgs: params, 666 }) 667 defer tc.Stopper().Stop(context.Background()) 668 kvDB := tc.Server(0).DB() 669 sqlDB := tc.ServerConn(0) 670 671 if _, err := sqlDB.Exec(` 672 CREATE DATABASE t; 673 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 674 CREATE UNIQUE INDEX vidx ON t.test (v); 675 `); err != nil { 676 t.Fatal(err) 677 } 678 679 // Bulk insert. 680 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 681 t.Fatal(err) 682 } 683 684 // Split the table into multiple ranges. 685 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 686 var sps []sql.SplitPoint 687 for i := 1; i <= numNodes-1; i++ { 688 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / numNodes * i}}) 689 } 690 sql.SplitTable(t, tc, tableDesc, sps) 691 692 ctx := context.Background() 693 694 // number of keys == 2 * number of rows; 1 column family and 1 index entry 695 // for each row. 696 if err := checkTableKeyCount(ctx, kvDB, 2, maxValue); err != nil { 697 t.Fatal(err) 698 } 699 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 700 t.Fatal(err) 701 } 702 703 notification := backfillNotification 704 // Run the schema change in a separate goroutine. 705 var wg sync.WaitGroup 706 wg.Add(1) 707 go func() { 708 // Start schema change that eventually runs a partial backfill. 709 if _, err := sqlDB.Exec("CREATE UNIQUE INDEX bar ON t.test (v)"); err != nil && !testutils.IsError(err, "table is being dropped") { 710 t.Error(err) 711 } 712 wg.Done() 713 }() 714 715 // Wait until the schema change backfill is partially complete. 716 <-notification 717 718 if _, err := sqlDB.Exec("DROP TABLE t.test"); err != nil { 719 t.Fatal(err) 720 } 721 722 // Wait until the schema change is done. 723 wg.Wait() 724 725 // Ensure that the table data hasn't been deleted. 726 tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 727 tableEnd := tablePrefix.PrefixEnd() 728 if kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0); err != nil { 729 t.Fatal(err) 730 } else if e := 2 * (maxValue + 1); len(kvs) != e { 731 t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) 732 } 733 // Check that the table descriptor exists so we know the data will 734 // eventually be deleted. 735 tbDescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, tableDesc.ID) 736 if gr, err := kvDB.Get(ctx, tbDescKey); err != nil { 737 t.Fatal(err) 738 } else if !gr.Exists() { 739 t.Fatalf("table descriptor doesn't exist after table is dropped: %q", tbDescKey) 740 } 741 } 742 743 // Test that a schema change on encountering a permanent backfill error 744 // on a remote node terminates properly and returns the database to a 745 // proper state. 746 func TestBackfillErrors(t *testing.T) { 747 defer leaktest.AfterTest(t)() 748 749 const numNodes, chunkSize, maxValue = 5, 100, 4000 750 params, _ := tests.CreateTestServerParams() 751 752 blockGC := make(chan struct{}) 753 params.Knobs = base.TestingKnobs{ 754 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 755 BackfillChunkSize: chunkSize, 756 }, 757 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { <-blockGC; return nil }}, 758 } 759 760 tc := serverutils.StartTestCluster(t, numNodes, 761 base.TestClusterArgs{ 762 ReplicationMode: base.ReplicationManual, 763 ServerArgs: params, 764 }) 765 defer tc.Stopper().Stop(context.Background()) 766 kvDB := tc.Server(0).DB() 767 sqlDB := tc.ServerConn(0) 768 769 if _, err := sqlDB.Exec(` 770 CREATE DATABASE t; 771 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 772 `); err != nil { 773 t.Fatal(err) 774 } 775 776 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 777 778 // Bulk insert. 779 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 780 t.Fatal(err) 781 } 782 783 // Update v column on some rows to be the same so that the future 784 // UNIQUE index we create on it fails. 785 // 786 // Pick a set of random rows because if we pick a deterministic set 787 // we can't be sure they will end up on a remote node. We want this 788 // test to fail if an error is not reported correctly on a local or 789 // remote node and the randomness allows us to test both. 790 const numUpdatedRows = 10 791 for i := 0; i < numUpdatedRows; i++ { 792 k := rand.Intn(maxValue - numUpdatedRows) 793 if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, 1, k); err != nil { 794 t.Error(err) 795 } 796 } 797 798 // Split the table into multiple ranges. 799 var sps []sql.SplitPoint 800 for i := 1; i <= numNodes-1; i++ { 801 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / numNodes * i}}) 802 } 803 sql.SplitTable(t, tc, tableDesc, sps) 804 805 ctx := context.Background() 806 807 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 808 t.Fatal(err) 809 } 810 811 if _, err := sqlDB.Exec(` 812 CREATE UNIQUE INDEX vidx ON t.test (v); 813 `); !testutils.IsError(err, `violates unique constraint "vidx"`) { 814 t.Fatalf("got err=%s", err) 815 } 816 817 // Index backfill errors at a non-deterministic chunk and the garbage 818 // keys remain because the async schema changer for the rollback stays 819 // disabled in order to assert the next errors. Therefore we do not check 820 // the keycount from this operation and just check that the next failed 821 // operations do not add more. 822 keyCount, err := getTableKeyCount(ctx, kvDB) 823 if err != nil { 824 t.Fatal(err) 825 } 826 827 if _, err := sqlDB.Exec(` 828 ALTER TABLE t.test ADD COLUMN p DECIMAL NOT NULL DEFAULT (DECIMAL '1-3'); 829 `); !testutils.IsError(err, `could not parse "1-3" as type decimal`) { 830 t.Fatalf("got err=%s", err) 831 } 832 833 if err := checkTableKeyCountExact(ctx, kvDB, keyCount); err != nil { 834 t.Fatal(err) 835 } 836 837 if _, err := sqlDB.Exec(` 838 ALTER TABLE t.test ADD COLUMN p DECIMAL NOT NULL; 839 `); !testutils.IsError(err, `null value in column \"p\" violates not-null constraint`) { 840 t.Fatalf("got err=%s", err) 841 } 842 843 if err := checkTableKeyCountExact(ctx, kvDB, keyCount); err != nil { 844 t.Fatal(err) 845 } 846 close(blockGC) 847 } 848 849 // Test aborting a schema change backfill transaction and check that the 850 // backfill is completed correctly. The backfill transaction is aborted at a 851 // time when it thinks it has processed all the rows of the table. Later, 852 // before the transaction is retried, the table is populated with more rows 853 // that a backfill chunk, requiring the backfill to forget that it is at the 854 // end of its processing and needs to continue on to process two more chunks 855 // of data. 856 func TestAbortSchemaChangeBackfill(t *testing.T) { 857 defer leaktest.AfterTest(t)() 858 var backfillNotification, commandsDone chan struct{} 859 var dontAbortBackfill uint32 860 params, _ := tests.CreateTestServerParams() 861 const maxValue = 100 862 backfillCount := int64(0) 863 retriedBackfill := int64(0) 864 var retriedSpan roachpb.Span 865 866 params.Knobs = base.TestingKnobs{ 867 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 868 // TODO (lucy): Stress this test. This test used to require fast GC, but 869 // it passes without it. 870 BackfillChunkSize: maxValue, 871 }, 872 DistSQL: &execinfra.TestingKnobs{ 873 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 874 switch atomic.LoadInt64(&backfillCount) { 875 case 0: 876 // Keep track of the span provided with the first backfill 877 // attempt. 878 retriedSpan = sp 879 case 1: 880 // Ensure that the second backfill attempt provides the 881 // same span as the first. 882 if sp.EqualValue(retriedSpan) { 883 atomic.AddInt64(&retriedBackfill, 1) 884 } 885 } 886 return nil 887 }, 888 RunAfterBackfillChunk: func() { 889 atomic.AddInt64(&backfillCount, 1) 890 if atomic.SwapUint32(&dontAbortBackfill, 1) == 1 { 891 return 892 } 893 // Close channel to notify that the backfill has been 894 // completed but hasn't yet committed. 895 close(backfillNotification) 896 // Receive signal that the commands that push the backfill 897 // transaction have completed; The backfill will attempt 898 // to commit and will abort. 899 <-commandsDone 900 }, 901 }, 902 // Disable backfill migrations, we still need the jobs table migration. 903 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 904 DisableBackfillMigrations: true, 905 }, 906 } 907 server, sqlDB, kvDB := serverutils.StartServer(t, params) 908 defer server.Stopper().Stop(context.Background()) 909 910 // Disable strict GC TTL enforcement because we're going to shove a zero-value 911 // TTL into the system with AddImmediateGCZoneConfig. 912 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 913 914 if _, err := sqlDB.Exec(` 915 CREATE DATABASE t; 916 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 917 `); err != nil { 918 t.Fatal(err) 919 } 920 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 921 // Add a zone config for the table. 922 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 923 t.Fatal(err) 924 } 925 926 // Bulk insert enough rows to exceed the chunk size. 927 inserts := make([]string, maxValue+1) 928 for i := 0; i < maxValue+1; i++ { 929 inserts[i] = fmt.Sprintf(`(%d, %d)`, i, i) 930 } 931 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ` + strings.Join(inserts, ",")); err != nil { 932 t.Fatal(err) 933 } 934 935 // The two drop cases (column and index) do not need to be tested here 936 // because the INSERT down below will not insert an entry for a dropped 937 // column or index, however, it's still nice to have the column drop 938 // just in case INSERT gets messed up. The writes will never abort a 939 // drop index because it uses ClearRange, so it is not tested. 940 testCases := []struct { 941 sql string 942 // Each schema change adds/drops a schema element that affects the 943 // number of keys representing a table row. 944 expectedNumKeysPerRow int 945 }{ 946 {"ALTER TABLE t.test ADD COLUMN x DECIMAL DEFAULT (DECIMAL '1.4') CHECK (x >= 0)", 1}, 947 {"ALTER TABLE t.test DROP x", 1}, 948 {"CREATE UNIQUE INDEX foo ON t.test (v)", 2}, 949 } 950 951 for _, testCase := range testCases { 952 t.Run(testCase.sql, func(t *testing.T) { 953 // Delete two rows so that the table size is smaller than a backfill 954 // chunk. The two values will be added later to make the table larger 955 // than a backfill chunk after the schema change backfill is aborted. 956 for i := 0; i < 2; i++ { 957 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = $1`, i); err != nil { 958 t.Fatal(err) 959 } 960 } 961 962 backfillNotification = make(chan struct{}) 963 commandsDone = make(chan struct{}) 964 atomic.StoreUint32(&dontAbortBackfill, 0) 965 // Run the column schema change in a separate goroutine. 966 var wg sync.WaitGroup 967 wg.Add(1) 968 go func() { 969 // Start schema change that eventually runs a backfill. 970 if _, err := sqlDB.Exec(testCase.sql); err != nil { 971 t.Error(err) 972 } 973 974 wg.Done() 975 }() 976 977 // Wait until the schema change backfill has finished writing its 978 // intents. 979 <-backfillNotification 980 981 // Delete a row that will push the backfill transaction. 982 if _, err := sqlDB.Exec(` 983 BEGIN TRANSACTION PRIORITY HIGH; 984 DELETE FROM t.test WHERE k = 2; 985 COMMIT; 986 `); err != nil { 987 t.Fatal(err) 988 } 989 990 // Add missing rows so that the table exceeds the size of a 991 // backfill chunk. 992 for i := 0; i < 3; i++ { 993 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES($1, $2)`, i, i); err != nil { 994 t.Fatal(err) 995 } 996 } 997 998 // Release backfill so that it can try to commit and in the 999 // process discover that it was aborted. 1000 close(commandsDone) 1001 1002 wg.Wait() // for schema change to complete 1003 1004 ctx := context.Background() 1005 1006 // Verify the number of keys left behind in the table to validate 1007 // schema change operations. 1008 if err := checkTableKeyCount( 1009 ctx, kvDB, testCase.expectedNumKeysPerRow, maxValue, 1010 ); err != nil { 1011 t.Fatal(err) 1012 } 1013 1014 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 1015 t.Fatal(err) 1016 } 1017 }) 1018 } 1019 } 1020 1021 // Add an index and check that it succeeds. 1022 func addIndexSchemaChange( 1023 t *testing.T, sqlDB *gosql.DB, kvDB *kv.DB, maxValue int, numKeysPerRow int, 1024 ) { 1025 if _, err := sqlDB.Exec("CREATE UNIQUE INDEX foo ON t.test (v)"); err != nil { 1026 t.Fatal(err) 1027 } 1028 1029 // The schema change succeeded. Verify that the index foo over v is 1030 // consistent. 1031 rows, err := sqlDB.Query(`SELECT v from t.test@foo`) 1032 if err != nil { 1033 t.Fatal(err) 1034 } 1035 defer rows.Close() 1036 1037 count := 0 1038 for ; rows.Next(); count++ { 1039 var val int 1040 if err := rows.Scan(&val); err != nil { 1041 t.Errorf("row %d scan failed: %s", count, err) 1042 continue 1043 } 1044 if count != val { 1045 t.Errorf("e = %d, v = %d", count, val) 1046 } 1047 } 1048 if err := rows.Err(); err != nil { 1049 t.Fatal(err) 1050 } 1051 if eCount := maxValue + 1; eCount != count { 1052 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 1053 } 1054 1055 ctx := context.Background() 1056 1057 if err := checkTableKeyCount(ctx, kvDB, numKeysPerRow, maxValue); err != nil { 1058 t.Fatal(err) 1059 } 1060 } 1061 1062 // Add a column with a check constraint and check that it succeeds. 1063 func addColumnSchemaChange( 1064 t *testing.T, sqlDB *gosql.DB, kvDB *kv.DB, maxValue int, numKeysPerRow int, 1065 ) { 1066 if _, err := sqlDB.Exec("ALTER TABLE t.test ADD COLUMN x DECIMAL DEFAULT (DECIMAL '1.4') CHECK (x >= 0)"); err != nil { 1067 t.Fatal(err) 1068 } 1069 rows, err := sqlDB.Query(`SELECT x from t.test`) 1070 if err != nil { 1071 t.Fatal(err) 1072 } 1073 defer rows.Close() 1074 count := 0 1075 for ; rows.Next(); count++ { 1076 var val float64 1077 if err := rows.Scan(&val); err != nil { 1078 t.Errorf("row %d scan failed: %s", count, err) 1079 continue 1080 } 1081 if e := 1.4; e != val { 1082 t.Errorf("e = %f, v = %f", e, val) 1083 } 1084 } 1085 if err := rows.Err(); err != nil { 1086 t.Fatal(err) 1087 } 1088 if eCount := maxValue + 1; eCount != count { 1089 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 1090 } 1091 1092 ctx := context.Background() 1093 1094 if err := checkTableKeyCount(ctx, kvDB, numKeysPerRow, maxValue); err != nil { 1095 t.Fatal(err) 1096 } 1097 } 1098 1099 // Drop a column and check that it succeeds. 1100 func dropColumnSchemaChange( 1101 t *testing.T, sqlDB *gosql.DB, kvDB *kv.DB, maxValue int, numKeysPerRow int, 1102 ) { 1103 if _, err := sqlDB.Exec("ALTER TABLE t.test DROP x"); err != nil { 1104 t.Fatal(err) 1105 } 1106 1107 ctx := context.Background() 1108 1109 if err := checkTableKeyCount(ctx, kvDB, numKeysPerRow, maxValue); err != nil { 1110 t.Fatal(err) 1111 } 1112 1113 } 1114 1115 // Drop an index and check that it succeeds. 1116 func dropIndexSchemaChange( 1117 t *testing.T, sqlDB *gosql.DB, kvDB *kv.DB, maxValue int, numKeysPerRow int, 1118 ) { 1119 if _, err := sqlDB.Exec("DROP INDEX t.test@foo CASCADE"); err != nil { 1120 t.Fatal(err) 1121 } 1122 1123 if err := checkTableKeyCount(context.Background(), kvDB, numKeysPerRow, maxValue); err != nil { 1124 t.Fatal(err) 1125 } 1126 } 1127 1128 // TestDropColumn tests that dropped columns properly drop their Table's CHECK constraints, 1129 // or an error occurs if a CHECK constraint is being added on it. 1130 func TestDropColumn(t *testing.T) { 1131 defer leaktest.AfterTest(t)() 1132 params, _ := tests.CreateTestServerParams() 1133 1134 s, sqlDB, kvDB := serverutils.StartServer(t, params) 1135 defer s.Stopper().Stop(context.Background()) 1136 1137 if _, err := sqlDB.Exec(` 1138 CREATE DATABASE t; 1139 CREATE TABLE t.test ( 1140 k INT PRIMARY KEY, 1141 v INT CONSTRAINT check_v CHECK (v >= 0), 1142 a INT DEFAULT 0 CONSTRAINT check_av CHECK (a <= v), 1143 b INT DEFAULT 100 CONSTRAINT check_ab CHECK (b > a) 1144 ); 1145 `); err != nil { 1146 t.Fatal(err) 1147 } 1148 1149 // Read table descriptor. 1150 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1151 if len(tableDesc.Checks) != 3 { 1152 t.Fatalf("Expected 3 checks but got %d ", len(tableDesc.Checks)) 1153 } 1154 1155 if _, err := sqlDB.Exec("ALTER TABLE t.test DROP v"); err != nil { 1156 t.Fatal(err) 1157 } 1158 1159 // Re-read table descriptor. 1160 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1161 // Only check_ab should remain 1162 if len(tableDesc.Checks) != 1 { 1163 checkExprs := make([]string, 0) 1164 for i := range tableDesc.Checks { 1165 checkExprs = append(checkExprs, tableDesc.Checks[i].Expr) 1166 } 1167 t.Fatalf("Expected 1 check but got %d with CHECK expr %s ", len(tableDesc.Checks), strings.Join(checkExprs, ", ")) 1168 } 1169 1170 if tableDesc.Checks[0].Name != "check_ab" { 1171 t.Fatalf("Only check_ab should remain, got: %s ", tableDesc.Checks[0].Name) 1172 } 1173 1174 // Test that a constraint being added prevents the column from being dropped. 1175 txn, err := sqlDB.Begin() 1176 if err != nil { 1177 t.Fatal(err) 1178 } 1179 if _, err := txn.Exec(`ALTER TABLE t.test ADD CONSTRAINT check_bk CHECK (b >= k)`); err != nil { 1180 t.Fatal(err) 1181 } 1182 if _, err := txn.Exec(`ALTER TABLE t.test DROP b`); !testutils.IsError(err, 1183 "referencing constraint \"check_bk\" in the middle of being added") { 1184 t.Fatalf("err = %+v", err) 1185 } 1186 if err := txn.Rollback(); err != nil { 1187 t.Fatal(err) 1188 } 1189 } 1190 1191 // Test schema changes are retried and complete properly. This also checks 1192 // that a mutation checkpoint reduces the number of chunks operated on during 1193 // a retry. 1194 func TestSchemaChangeRetry(t *testing.T) { 1195 defer leaktest.AfterTest(t)() 1196 1197 // Decrease the adopt loop interval so that retries happen quickly. 1198 defer setTestJobsAdoptInterval()() 1199 1200 params, _ := tests.CreateTestServerParams() 1201 1202 currChunk := 0 1203 seenSpan := roachpb.Span{} 1204 checkSpan := func(sp roachpb.Span) error { 1205 currChunk++ 1206 // Fail somewhere in the middle. 1207 if currChunk == 3 { 1208 if rand.Intn(2) == 0 { 1209 return context.DeadlineExceeded 1210 } else { 1211 errAmbiguous := &roachpb.AmbiguousResultError{} 1212 return roachpb.NewError(errAmbiguous).GoError() 1213 } 1214 } 1215 if sp.Key != nil && seenSpan.Key != nil { 1216 // Check that the keys are never reevaluated 1217 if seenSpan.Key.Compare(sp.Key) >= 0 { 1218 t.Errorf("reprocessing span %s, already seen span %s", sp, seenSpan) 1219 } 1220 if !seenSpan.EndKey.Equal(sp.EndKey) { 1221 t.Errorf("different EndKey: span %s, already seen span %s", sp, seenSpan) 1222 } 1223 } 1224 seenSpan = sp 1225 return nil 1226 } 1227 1228 params.Knobs = base.TestingKnobs{ 1229 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1230 WriteCheckpointInterval: time.Nanosecond, 1231 }, 1232 DistSQL: &execinfra.TestingKnobs{RunBeforeBackfillChunk: checkSpan}, 1233 // Disable backfill migrations, we still need the jobs table migration. 1234 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 1235 DisableBackfillMigrations: true, 1236 }, 1237 } 1238 s, sqlDB, kvDB := serverutils.StartServer(t, params) 1239 defer s.Stopper().Stop(context.Background()) 1240 1241 if _, err := sqlDB.Exec(` 1242 CREATE DATABASE t; 1243 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 1244 `); err != nil { 1245 t.Fatal(err) 1246 } 1247 1248 // Bulk insert. 1249 const maxValue = 2000 1250 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 1251 t.Fatal(err) 1252 } 1253 1254 addIndexSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1255 1256 currChunk = 0 1257 seenSpan = roachpb.Span{} 1258 addColumnSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1259 1260 currChunk = 0 1261 seenSpan = roachpb.Span{} 1262 dropColumnSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1263 1264 currChunk = 0 1265 seenSpan = roachpb.Span{} 1266 dropIndexSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1267 } 1268 1269 // Test schema changes are retried and complete properly when the table 1270 // version changes. This also checks that a mutation checkpoint reduces 1271 // the number of chunks operated on during a retry. 1272 func TestSchemaChangeRetryOnVersionChange(t *testing.T) { 1273 defer leaktest.AfterTest(t)() 1274 1275 // Decrease the adopt loop interval so that retries happen quickly. 1276 defer setTestJobsAdoptInterval()() 1277 1278 params, _ := tests.CreateTestServerParams() 1279 var upTableVersion func() 1280 const maxValue = 2000 1281 currChunk := 0 1282 var numBackfills uint32 1283 seenSpan := roachpb.Span{} 1284 params.Knobs = base.TestingKnobs{ 1285 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1286 RunBeforeBackfill: func() error { 1287 atomic.AddUint32(&numBackfills, 1) 1288 return nil 1289 }, 1290 WriteCheckpointInterval: time.Nanosecond, 1291 BackfillChunkSize: maxValue / 10, 1292 }, 1293 DistSQL: &execinfra.TestingKnobs{ 1294 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 1295 currChunk++ 1296 // Fail somewhere in the middle. 1297 if currChunk == 3 { 1298 // Publish a new version of the table. 1299 upTableVersion() 1300 } 1301 if seenSpan.Key != nil { 1302 if !seenSpan.EndKey.Equal(sp.EndKey) { 1303 t.Errorf("different EndKey: span %s, already seen span %s", sp, seenSpan) 1304 } 1305 } 1306 seenSpan = sp 1307 return nil 1308 }, 1309 }, 1310 // Disable backfill migrations, we still need the jobs table migration. 1311 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 1312 DisableBackfillMigrations: true, 1313 }, 1314 } 1315 s, sqlDB, kvDB := serverutils.StartServer(t, params) 1316 defer s.Stopper().Stop(context.Background()) 1317 1318 if _, err := sqlDB.Exec(` 1319 CREATE DATABASE t; 1320 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 1321 `); err != nil { 1322 t.Fatal(err) 1323 } 1324 1325 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1326 id := tableDesc.ID 1327 ctx := context.Background() 1328 1329 upTableVersion = func() { 1330 leaseMgr := s.LeaseManager().(*lease.Manager) 1331 var version sqlbase.DescriptorVersion 1332 if _, err := leaseMgr.Publish(ctx, id, func(table *sqlbase.MutableTableDescriptor) error { 1333 // Publish nothing; only update the version. 1334 version = table.Version 1335 return nil 1336 }, nil); err != nil { 1337 t.Error(err) 1338 } 1339 // Grab a lease at the latest version so that we are confident 1340 // that all future leases will be taken at the latest version. 1341 table, _, err := leaseMgr.TestingAcquireAndAssertMinVersion(ctx, s.Clock().Now(), id, version+1) 1342 if err != nil { 1343 t.Error(err) 1344 } 1345 if err := leaseMgr.Release(table); err != nil { 1346 t.Error(err) 1347 } 1348 } 1349 1350 // Bulk insert. 1351 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 1352 t.Fatal(err) 1353 } 1354 1355 addIndexSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1356 if num := atomic.SwapUint32(&numBackfills, 0); num != 2 { 1357 t.Fatalf("expected %d backfills, but seen %d", 2, num) 1358 } 1359 1360 currChunk = 0 1361 seenSpan = roachpb.Span{} 1362 addColumnSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1363 if num := atomic.SwapUint32(&numBackfills, 0); num != 2 { 1364 t.Fatalf("expected %d backfills, but seen %d", 2, num) 1365 } 1366 1367 currChunk = 0 1368 seenSpan = roachpb.Span{} 1369 dropColumnSchemaChange(t, sqlDB, kvDB, maxValue, 2) 1370 if num := atomic.SwapUint32(&numBackfills, 0); num != 2 { 1371 t.Fatalf("expected %d backfills, but seen %d", 2, num) 1372 } 1373 } 1374 1375 // Test schema change purge failure doesn't leave DB in a bad state. 1376 func TestSchemaChangePurgeFailure(t *testing.T) { 1377 defer leaktest.AfterTest(t)() 1378 t.Skip("") 1379 // TODO (lucy): This test needs more complicated schema changer knobs than 1380 // currently implemented. Previously this test disabled the async schema 1381 // changer so that we don't retry the cleanup of the failed schema change 1382 // until a certain point in the test. 1383 params, _ := tests.CreateTestServerParams() 1384 const chunkSize = 200 1385 var enableAsyncSchemaChanges uint32 1386 var attempts int32 1387 // attempt 1: write the first chunk of the index. 1388 // attempt 2: write the second chunk and hit a unique constraint 1389 // violation; purge the schema change. 1390 // attempt 3: return an error while purging the schema change. 1391 var expectedAttempts int32 = 3 1392 params.Knobs = base.TestingKnobs{ 1393 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1394 BackfillChunkSize: chunkSize, 1395 }, 1396 DistSQL: &execinfra.TestingKnobs{ 1397 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 1398 // Return a deadline exceeded error during the third attempt 1399 // which attempts to clean up the schema change. 1400 if atomic.AddInt32(&attempts, 1) == expectedAttempts { 1401 // Disable the async schema changer for assertions. 1402 atomic.StoreUint32(&enableAsyncSchemaChanges, 0) 1403 return context.DeadlineExceeded 1404 } 1405 return nil 1406 }, 1407 // the backfiller flushes after every batch if RunAfterBackfillChunk is 1408 // non-nil so this noop fn means we can observe the partial-backfill that 1409 // would otherwise just be buffered. 1410 RunAfterBackfillChunk: func() {}, 1411 }, 1412 // Disable backfill migrations, we still need the jobs table migration. 1413 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 1414 DisableBackfillMigrations: true, 1415 }, 1416 } 1417 server, sqlDB, kvDB := serverutils.StartServer(t, params) 1418 defer server.Stopper().Stop(context.Background()) 1419 1420 // Disable strict GC TTL enforcement because we're going to shove a zero-value 1421 // TTL into the system with AddImmediateGCZoneConfig. 1422 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 1423 1424 if _, err := sqlDB.Exec(` 1425 CREATE DATABASE t; 1426 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 1427 `); err != nil { 1428 t.Fatal(err) 1429 } 1430 1431 // Bulk insert. 1432 const maxValue = chunkSize + 1 1433 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 1434 t.Fatal(err) 1435 } 1436 1437 // Add a row with a duplicate value=0 which is the same 1438 // value as for the key maxValue. 1439 if _, err := sqlDB.Exec( 1440 `INSERT INTO t.test VALUES ($1, $2)`, maxValue+1, 0, 1441 ); err != nil { 1442 t.Fatal(err) 1443 } 1444 1445 // A schema change that violates integrity constraints. 1446 if _, err := sqlDB.Exec( 1447 "CREATE UNIQUE INDEX foo ON t.test (v)", 1448 ); !testutils.IsError(err, `violates unique constraint "foo"`) { 1449 t.Fatal(err) 1450 } 1451 1452 // The index doesn't exist 1453 if _, err := sqlDB.Query( 1454 `SELECT v from t.test@foo`, 1455 ); !testutils.IsError(err, "index .* not found") { 1456 t.Fatal(err) 1457 } 1458 1459 // Allow async schema change purge to attempt backfill and error. 1460 atomic.StoreUint32(&enableAsyncSchemaChanges, 1) 1461 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1462 // deal with schema change knob 1463 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 1464 t.Fatal(err) 1465 } 1466 1467 // The deadline exceeded error in the schema change purge results in no 1468 // retry attempts of the purge. 1469 testutils.SucceedsSoon(t, func() error { 1470 if read := atomic.LoadInt32(&attempts); read != expectedAttempts { 1471 return errors.Errorf("%d retries, despite allowing only (schema change + reverse) = %d", read, expectedAttempts) 1472 } 1473 return nil 1474 }) 1475 1476 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1477 1478 // There is still a DROP INDEX mutation waiting for GC. 1479 if e := 1; len(tableDesc.GCMutations) != e { 1480 t.Fatalf("the table has %d instead of %d GC mutations", len(tableDesc.GCMutations), e) 1481 } else if m := tableDesc.GCMutations[0]; m.IndexID != 2 && m.DropTime == 0 && m.JobID == 0 { 1482 t.Fatalf("unexpected GC mutation %v", m) 1483 } 1484 1485 // There is still some garbage index data that needs to be purged. All the 1486 // rows from k = 0 to k = chunkSize - 1 have index values. 1487 numGarbageValues := chunkSize 1488 1489 ctx := context.Background() 1490 1491 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue+1+numGarbageValues); err != nil { 1492 t.Fatal(err) 1493 } 1494 1495 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 1496 t.Fatal(err) 1497 } 1498 1499 // Enable async schema change processing to ensure that it cleans up the 1500 // above garbage left behind. 1501 atomic.StoreUint32(&enableAsyncSchemaChanges, 1) 1502 1503 testutils.SucceedsSoon(t, func() error { 1504 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1505 if len(tableDesc.GCMutations) > 0 { 1506 return errors.Errorf("%d GC mutations remaining", len(tableDesc.GCMutations)) 1507 } 1508 return nil 1509 }) 1510 1511 // No garbage left behind. 1512 numGarbageValues = 0 1513 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue+1+numGarbageValues); err != nil { 1514 t.Fatal(err) 1515 } 1516 1517 // A new attempt cleans up a chunk of data. 1518 if attempts != expectedAttempts+1 { 1519 t.Fatalf("%d chunk ops, despite allowing only (schema change + reverse) = %d", attempts, expectedAttempts) 1520 } 1521 } 1522 1523 // Test schema change failure after a backfill checkpoint has been written 1524 // doesn't leave the DB in a bad state. 1525 func TestSchemaChangeFailureAfterCheckpointing(t *testing.T) { 1526 defer leaktest.AfterTest(t)() 1527 defer gcjob.SetSmallMaxGCIntervalForTest()() 1528 params, _ := tests.CreateTestServerParams() 1529 const chunkSize = 200 1530 attempts := 0 1531 // attempt 1: write two chunks of the column. 1532 // attempt 2: writing the third chunk returns a permanent failure 1533 // purge the schema change. 1534 expectedAttempts := 3 1535 blockGC := make(chan struct{}) 1536 params.Knobs = base.TestingKnobs{ 1537 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1538 BackfillChunkSize: chunkSize, 1539 // Aggressively checkpoint, so that a schema change 1540 // failure happens after a checkpoint has been written. 1541 WriteCheckpointInterval: time.Nanosecond, 1542 }, 1543 // Disable GC job. 1544 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { <-blockGC; return nil }}, 1545 DistSQL: &execinfra.TestingKnobs{ 1546 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 1547 attempts++ 1548 // Return a deadline exceeded error during the third attempt 1549 // which attempts to clean up the schema change. 1550 if attempts == expectedAttempts { 1551 return errors.New("permanent failure") 1552 } 1553 return nil 1554 }, 1555 }, 1556 // Disable backfill migrations so it doesn't interfere with the 1557 // backfill in this test. 1558 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 1559 DisableBackfillMigrations: true, 1560 }, 1561 } 1562 server, sqlDB, kvDB := serverutils.StartServer(t, params) 1563 defer server.Stopper().Stop(context.Background()) 1564 1565 if _, err := sqlDB.Exec(` 1566 CREATE DATABASE t; 1567 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 1568 `); err != nil { 1569 t.Fatal(err) 1570 } 1571 1572 // Bulk insert. 1573 const maxValue = 4*chunkSize + 1 1574 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 1575 t.Fatal(err) 1576 } 1577 1578 if err := checkTableKeyCount(context.Background(), kvDB, 1, maxValue); err != nil { 1579 t.Fatal(err) 1580 } 1581 1582 // A schema change that fails. 1583 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD column d INT DEFAULT 0 CREATE FAMILY F3, ADD CHECK (d >= 0)`); !testutils.IsError(err, `permanent failure`) { 1584 t.Fatalf("err = %s", err) 1585 } 1586 1587 // No garbage left behind. 1588 if err := checkTableKeyCount(context.Background(), kvDB, 1, maxValue); err != nil { 1589 t.Fatal(err) 1590 } 1591 1592 // A schema change that fails after the first mutation has completed. The 1593 // column is backfilled and the index backfill fails requiring the column 1594 // backfill to be rolled back. 1595 if _, err := sqlDB.Exec( 1596 `ALTER TABLE t.test ADD column e INT DEFAULT 0 UNIQUE CREATE FAMILY F4, ADD CHECK (e >= 0)`, 1597 ); !testutils.IsError(err, ` violates unique constraint`) { 1598 t.Fatalf("err = %s", err) 1599 } 1600 1601 // No garbage left behind. 1602 if err := checkTableKeyCount(context.Background(), kvDB, 1, maxValue); err != nil { 1603 t.Fatal(err) 1604 } 1605 1606 // Check that constraints are cleaned up. 1607 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1608 if checks := tableDesc.AllActiveAndInactiveChecks(); len(checks) > 0 { 1609 t.Fatalf("found checks %+v", checks) 1610 } 1611 close(blockGC) 1612 } 1613 1614 // TestSchemaChangeReverseMutations tests that schema changes get reversed 1615 // correctly when one of them violates a constraint. 1616 func TestSchemaChangeReverseMutations(t *testing.T) { 1617 defer leaktest.AfterTest(t)() 1618 // TODO (lucy): This test needs more complicated schema changer knobs than 1619 // currently implemented. What this test should be doing is starting a schema 1620 // change, and, before it hits a violation that requires a rollback, starting 1621 // another schema change that depends on the successful completion of the 1622 // first. At the end, all the dependent schema change jobs should have been 1623 // rolled back. Right now we're just testing that schema changes fail 1624 // correctly when run sequentially, which is not as interesting. The previous 1625 // comments are kept around to describe the intended results of the test, but 1626 // they don't reflect what's happening now. 1627 params, _ := tests.CreateTestServerParams() 1628 const chunkSize = 200 1629 // Disable synchronous schema change processing so that the mutations get 1630 // processed asynchronously. 1631 var enableAsyncSchemaChanges uint32 1632 params.Knobs = base.TestingKnobs{ 1633 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 1634 BackfillChunkSize: chunkSize, 1635 }, 1636 // Disable backfill migrations, we still need the jobs table migration. 1637 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 1638 DisableBackfillMigrations: true, 1639 }, 1640 } 1641 s, sqlDB, kvDB := serverutils.StartServer(t, params) 1642 defer s.Stopper().Stop(context.Background()) 1643 1644 // Disable strict GC TTL enforcement because we're going to shove a zero-value 1645 // TTL into the system with AddImmediateGCZoneConfig. 1646 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 1647 1648 // Create a k-v table. 1649 if _, err := sqlDB.Exec(` 1650 CREATE DATABASE t; 1651 CREATE TABLE t.test (k INT PRIMARY KEY, v INT8); 1652 `); err != nil { 1653 t.Fatal(err) 1654 } 1655 1656 // Add some data 1657 const maxValue = chunkSize + 1 1658 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 1659 t.Fatal(err) 1660 } 1661 1662 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1663 1664 testCases := []struct { 1665 sql string 1666 errString string 1667 }{ 1668 // Create a column that is not NULL. This schema change doesn't return an 1669 // error only because we've turned off the synchronous execution path; it 1670 // will eventually fail when run by the asynchronous path. 1671 {`ALTER TABLE t.public.test ADD COLUMN a INT8 UNIQUE DEFAULT 0, ADD COLUMN c INT8`, 1672 "violates unique constraint"}, 1673 // Add an index over a column that will be purged. This index will 1674 // eventually not get added. The column aa will also be dropped as 1675 // a result. 1676 {`ALTER TABLE t.public.test ADD COLUMN aa INT8, ADD CONSTRAINT foo UNIQUE (a)`, 1677 "contains unknown column"}, 1678 1679 // The purge of column 'a' doesn't influence these schema changes. 1680 1681 // Drop column 'v' moves along just fine. 1682 {`ALTER TABLE t.public.test DROP COLUMN v`, 1683 ""}, 1684 // Add unique column 'b' moves along creating column b and the index on 1685 // it. 1686 {`ALTER TABLE t.public.test ADD COLUMN b INT8 UNIQUE`, 1687 ""}, 1688 // #27033: Add a column followed by an index on the column. 1689 {`ALTER TABLE t.public.test ADD COLUMN d STRING NOT NULL DEFAULT 'something'`, 1690 ""}, 1691 1692 {`CREATE INDEX ON t.public.test (d)`, 1693 ""}, 1694 1695 // Add an index over a column 'c' that will be purged. This index will 1696 // eventually not get added. The column bb will also be dropped as 1697 // a result. 1698 {`ALTER TABLE t.public.test ADD COLUMN bb INT8, ADD CONSTRAINT bar UNIQUE (never_existed)`, 1699 "contains unknown column"}, 1700 // Cascading of purges. column 'c' -> column 'bb' -> constraint 'idx_bb'. 1701 {`ALTER TABLE t.public.test ADD CONSTRAINT idx_bb UNIQUE (bb)`, 1702 "contains unknown column"}, 1703 } 1704 1705 for _, tc := range testCases { 1706 _, err := sqlDB.Exec(tc.sql) 1707 if tc.errString == "" { 1708 if err != nil { 1709 t.Fatal(err) 1710 } 1711 } else { 1712 if err == nil { 1713 t.Fatal("expected error") 1714 } 1715 if !strings.Contains(err.Error(), tc.errString) { 1716 t.Fatal(err) 1717 } 1718 } 1719 } 1720 1721 // Enable async schema change processing for purged schema changes. 1722 atomic.StoreUint32(&enableAsyncSchemaChanges, 1) 1723 1724 expectedCols := []string{"k", "b", "d"} 1725 // Wait until all the mutations have been processed. 1726 testutils.SucceedsSoon(t, func() error { 1727 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1728 if len(tableDesc.Mutations) > 0 { 1729 return errors.Errorf("%d mutations remaining", len(tableDesc.Mutations)) 1730 } 1731 return nil 1732 }) 1733 1734 // Verify that t.public.test has the expected data. Read the table data while 1735 // ensuring that the correct table lease is in use. 1736 rows, err := sqlDB.Query(`SELECT * from t.test`) 1737 if err != nil { 1738 t.Fatal(err) 1739 } 1740 defer rows.Close() 1741 cols, err := rows.Columns() 1742 if err != nil { 1743 t.Fatal(err) 1744 } 1745 1746 // Ensure that sql is using the correct table lease. 1747 if len(cols) != len(expectedCols) { 1748 t.Fatalf("incorrect columns: %v, expected: %v", cols, expectedCols) 1749 } 1750 if cols[0] != expectedCols[0] || cols[1] != expectedCols[1] { 1751 t.Fatalf("incorrect columns: %v", cols) 1752 } 1753 1754 // rows contains the data; verify that it's the right data. 1755 vals := make([]interface{}, len(expectedCols)) 1756 for i := range vals { 1757 vals[i] = new(interface{}) 1758 } 1759 var count int64 1760 for ; rows.Next(); count++ { 1761 if err := rows.Scan(vals...); err != nil { 1762 t.Errorf("row %d scan failed: %s", count, err) 1763 continue 1764 } 1765 for j, v := range vals { 1766 switch j { 1767 case 0: 1768 if val := *v.(*interface{}); val != nil { 1769 switch k := val.(type) { 1770 case int64: 1771 if count != k { 1772 t.Errorf("k = %d, expected %d", k, count) 1773 } 1774 1775 default: 1776 t.Errorf("error input of type %T", k) 1777 } 1778 } else { 1779 t.Error("received NULL value for column 'k'") 1780 } 1781 1782 case 1: 1783 if val := *v.(*interface{}); val != nil { 1784 t.Error("received non NULL value for column 'b'") 1785 } 1786 1787 case 2: 1788 if val := *v.(*interface{}); val == nil { 1789 t.Error("received NULL value for column 'd'") 1790 } 1791 } 1792 } 1793 } 1794 if err := rows.Err(); err != nil { 1795 t.Fatal(err) 1796 } 1797 if eCount := int64(maxValue + 1); eCount != count { 1798 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 1799 } 1800 1801 // Check that the index on b eventually goes live even though a schema 1802 // change in front of it in the queue got purged. 1803 rows, err = sqlDB.Query(`SELECT * from t.test@test_b_key`) 1804 if err != nil { 1805 t.Fatal(err) 1806 } 1807 defer rows.Close() 1808 count = 0 1809 for ; rows.Next(); count++ { 1810 } 1811 if err := rows.Err(); err != nil { 1812 t.Fatal(err) 1813 } 1814 if eCount := int64(maxValue + 1); eCount != count { 1815 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 1816 } 1817 1818 // Check that the index on c gets purged. 1819 if _, err := sqlDB.Query(`SELECT * from t.test@foo`); err == nil { 1820 t.Fatal("SELECT over index 'foo' works") 1821 } 1822 1823 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 1824 t.Fatal(err) 1825 } 1826 1827 // Add immediate GC TTL to allow index creation purge to complete. 1828 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 1829 t.Fatal(err) 1830 } 1831 1832 testutils.SucceedsSoon(t, func() error { 1833 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1834 if len(tableDesc.GCMutations) > 0 { 1835 return errors.Errorf("%d gc mutations remaining", len(tableDesc.GCMutations)) 1836 } 1837 return nil 1838 }) 1839 1840 ctx := context.Background() 1841 1842 // Check that the number of k-v pairs is accurate. 1843 if err := checkTableKeyCount(ctx, kvDB, 3, maxValue); err != nil { 1844 t.Fatal(err) 1845 } 1846 1847 // State of jobs table 1848 t.Skip("TODO(pbardea): The following fails due to causes seemingly unrelated to GC") 1849 runner := sqlutils.SQLRunner{DB: sqlDB} 1850 // TODO (lucy): This test API should use an offset starting from the 1851 // most recent job instead. 1852 const migrationJobOffset = 0 1853 for i, tc := range testCases { 1854 status := jobs.StatusSucceeded 1855 if tc.errString != "" { 1856 status = jobs.StatusFailed 1857 } 1858 if err := jobutils.VerifySystemJob(t, &runner, migrationJobOffset+i, jobspb.TypeSchemaChange, status, jobs.Record{ 1859 Username: security.RootUser, 1860 Description: tc.sql, 1861 DescriptorIDs: sqlbase.IDs{ 1862 tableDesc.ID, 1863 }, 1864 }); err != nil { 1865 t.Fatal(err) 1866 } 1867 } 1868 1869 jobRolledBack := 0 1870 jobID := jobutils.GetJobID(t, &runner, jobRolledBack) 1871 1872 // Roll back job. 1873 if err := jobutils.VerifySystemJob(t, &runner, len(testCases), jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 1874 Username: security.RootUser, 1875 Description: fmt.Sprintf("ROLL BACK JOB %d: %s", jobID, testCases[jobRolledBack].sql), 1876 DescriptorIDs: sqlbase.IDs{ 1877 tableDesc.ID, 1878 }, 1879 }); err != nil { 1880 t.Fatal(err) 1881 } 1882 1883 } 1884 1885 // This test checks backward compatibility with old data that contains 1886 // sentinel kv pairs at the start of each table row. Cockroachdb used 1887 // to write table rows with sentinel values in the past. When a new column 1888 // is added to such a table with the new column included in the same 1889 // column family as the primary key columns, the sentinel kv pairs 1890 // start representing this new column. This test checks that the sentinel 1891 // values represent NULL column values, and that an UPDATE to such 1892 // a column works correctly. 1893 func TestParseSentinelValueWithNewColumnInSentinelFamily(t *testing.T) { 1894 defer leaktest.AfterTest(t)() 1895 params, _ := tests.CreateTestServerParams() 1896 server, sqlDB, kvDB := serverutils.StartServer(t, params) 1897 defer server.Stopper().Stop(context.Background()) 1898 1899 if _, err := sqlDB.Exec(` 1900 CREATE DATABASE t; 1901 CREATE TABLE t.test ( 1902 k INT PRIMARY KEY, 1903 FAMILY F1 (k) 1904 ); 1905 `); err != nil { 1906 t.Fatal(err) 1907 } 1908 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1909 if tableDesc.Families[0].DefaultColumnID != 0 { 1910 t.Fatalf("default column id not set properly: %s", tableDesc) 1911 } 1912 1913 // Add some data. 1914 const maxValue = 10 1915 inserts := make([]string, maxValue+1) 1916 for i := range inserts { 1917 inserts[i] = fmt.Sprintf(`(%d)`, i) 1918 } 1919 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ` + strings.Join(inserts, ",")); err != nil { 1920 t.Fatal(err) 1921 } 1922 1923 ctx := context.Background() 1924 1925 // Convert table data created by the above INSERT into sentinel 1926 // values. This is done to make the table appear like it were 1927 // written in the past when cockroachdb used to write sentinel 1928 // values for each table row. 1929 startKey := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 1930 kvs, err := kvDB.Scan( 1931 ctx, 1932 startKey, 1933 startKey.PrefixEnd(), 1934 maxValue+1) 1935 if err != nil { 1936 t.Fatal(err) 1937 } 1938 for _, kv := range kvs { 1939 value := roachpb.MakeValueFromBytes(nil) 1940 if err := kvDB.Put(ctx, kv.Key, &value); err != nil { 1941 t.Fatal(err) 1942 } 1943 } 1944 1945 // Add a new column that gets added to column family 0, 1946 // updating DefaultColumnID. 1947 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD COLUMN v INT FAMILY F1`); err != nil { 1948 t.Fatal(err) 1949 } 1950 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 1951 if tableDesc.Families[0].DefaultColumnID != 2 { 1952 t.Fatalf("default column id not set properly: %s", tableDesc) 1953 } 1954 1955 // Update one of the rows. 1956 const setKey = 5 1957 const setVal = maxValue - setKey 1958 if _, err := sqlDB.Exec(`UPDATE t.test SET v = $1 WHERE k = $2`, setVal, setKey); err != nil { 1959 t.Fatal(err) 1960 } 1961 1962 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 1963 t.Fatal(err) 1964 } 1965 1966 // The table contains the one updated value and remaining NULL values. 1967 rows, err := sqlDB.Query(`SELECT v from t.test`) 1968 if err != nil { 1969 t.Fatal(err) 1970 } 1971 defer rows.Close() 1972 const eCount = maxValue + 1 1973 count := 0 1974 for ; rows.Next(); count++ { 1975 var val *int 1976 if err := rows.Scan(&val); err != nil { 1977 t.Errorf("row %d scan failed: %s", count, err) 1978 continue 1979 } 1980 if count == setKey { 1981 if val != nil { 1982 if setVal != *val { 1983 t.Errorf("value = %d, expected %d", *val, setVal) 1984 } 1985 } else { 1986 t.Error("received nil value for column 'v'") 1987 } 1988 } else if val != nil { 1989 t.Error("received non NULL value for column 'v'") 1990 } 1991 } 1992 if err := rows.Err(); err != nil { 1993 t.Fatal(err) 1994 } 1995 if eCount != count { 1996 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 1997 } 1998 } 1999 2000 // This test checks whether a column can be added using the name of a column that has just been dropped. 2001 func TestAddColumnDuringColumnDrop(t *testing.T) { 2002 defer leaktest.AfterTest(t)() 2003 params, _ := tests.CreateTestServerParams() 2004 backfillNotification := make(chan struct{}) 2005 continueBackfillNotification := make(chan struct{}) 2006 params.Knobs = base.TestingKnobs{ 2007 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2008 RunBeforeBackfill: func() error { 2009 if backfillNotification != nil { 2010 // Close channel to notify that the schema change has 2011 // been queued and the backfill has started. 2012 close(backfillNotification) 2013 backfillNotification = nil 2014 <-continueBackfillNotification 2015 } 2016 return nil 2017 }, 2018 }, 2019 // Disable backfill migrations, we still need the jobs table migration. 2020 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 2021 DisableBackfillMigrations: true, 2022 }, 2023 } 2024 server, sqlDB, _ := serverutils.StartServer(t, params) 2025 defer server.Stopper().Stop(context.Background()) 2026 2027 if _, err := sqlDB.Exec(` 2028 CREATE DATABASE t; 2029 CREATE TABLE t.test ( 2030 k INT PRIMARY KEY NOT NULL, 2031 v INT NOT NULL 2032 ); 2033 `); err != nil { 2034 t.Fatal(err) 2035 } 2036 2037 if err := bulkInsertIntoTable(sqlDB, 1000); err != nil { 2038 t.Fatal(err) 2039 } 2040 // Run the column schema change in a separate goroutine. 2041 notification := backfillNotification 2042 var wg sync.WaitGroup 2043 wg.Add(1) 2044 go func() { 2045 if _, err := sqlDB.Exec(`ALTER TABLE t.test DROP column v;`); err != nil { 2046 t.Error(err) 2047 } 2048 wg.Done() 2049 }() 2050 2051 <-notification 2052 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD column v INT DEFAULT 0;`); !testutils.IsError(err, `column "v" being dropped, try again later`) { 2053 t.Fatal(err) 2054 } 2055 2056 close(continueBackfillNotification) 2057 wg.Wait() 2058 2059 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 2060 t.Fatal(err) 2061 } 2062 } 2063 2064 // Test a DROP failure on a unique column. The rollback 2065 // process might not be able to reconstruct the index and thus 2066 // purges the rollback. For now this is considered acceptable. 2067 func TestSchemaUniqueColumnDropFailure(t *testing.T) { 2068 defer leaktest.AfterTest(t)() 2069 params, _ := tests.CreateTestServerParams() 2070 const chunkSize = 200 2071 attempts := 0 2072 // DROP UNIQUE COLUMN is executed in two steps: drop index and drop column. 2073 // Dropping the index happens in a separate mutation job from the drop column 2074 // which does not perform backfilling (like adding indexes and add/drop 2075 // columns) and completes successfully. However, note that the testing knob 2076 // hooks are still run as if they were backfill attempts. The index truncation 2077 // happens as an asynchronous change after the index descriptor is removed, 2078 // and will be run after the GC TTL is passed and there are no pending 2079 // synchronous mutations. Therefore, the first two backfill attempts are from 2080 // the column drop. This part of the change errors during backfilling the 2081 // second chunk. 2082 const expectedColumnBackfillAttempts = 2 2083 const maxValue = (expectedColumnBackfillAttempts/2+1)*chunkSize + 1 2084 params.Knobs = base.TestingKnobs{ 2085 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2086 BackfillChunkSize: chunkSize, 2087 // Aggressively checkpoint, so that a schema change 2088 // failure happens after a checkpoint has been written. 2089 WriteCheckpointInterval: time.Nanosecond, 2090 }, 2091 // Disable GC job. 2092 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { select {} }}, 2093 DistSQL: &execinfra.TestingKnobs{ 2094 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 2095 attempts++ 2096 // Return a deadline exceeded error while dropping 2097 // the column after the index has been dropped. 2098 if attempts == expectedColumnBackfillAttempts { 2099 return errors.New("permanent failure") 2100 } 2101 return nil 2102 }, 2103 }, 2104 // Disable backfill migrations so it doesn't interfere with the 2105 // backfill in this test. 2106 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 2107 DisableBackfillMigrations: true, 2108 }, 2109 } 2110 server, sqlDB, kvDB := serverutils.StartServer(t, params) 2111 defer server.Stopper().Stop(context.Background()) 2112 2113 if _, err := sqlDB.Exec(` 2114 CREATE DATABASE t; 2115 CREATE TABLE t.test (k INT PRIMARY KEY, v INT UNIQUE DEFAULT 23 CREATE FAMILY F3); 2116 `); err != nil { 2117 t.Fatal(err) 2118 } 2119 2120 // Bulk insert. 2121 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 2122 t.Fatal(err) 2123 } 2124 2125 if err := checkTableKeyCount(context.Background(), kvDB, 2, maxValue); err != nil { 2126 t.Fatal(err) 2127 } 2128 2129 // A schema change that fails. 2130 if _, err := sqlDB.Exec(`ALTER TABLE t.test DROP column v`); !testutils.IsError(err, `permanent failure`) { 2131 t.Fatalf("err = %s", err) 2132 } 2133 2134 // The index is not regenerated. 2135 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2136 if len(tableDesc.Indexes) > 0 { 2137 t.Fatalf("indexes %+v", tableDesc.Indexes) 2138 } 2139 2140 // Unfortunately this is the same failure present when an index drop 2141 // fails, so the rollback never completes and leaves orphaned kvs. 2142 // TODO(erik): Ignore errors or individually drop indexes in 2143 // DELETE_AND_WRITE_ONLY which failed during the creation backfill 2144 // as a rollback from a drop. 2145 if e := 1; e != len(tableDesc.Columns) { 2146 t.Fatalf("e = %d, v = %d, columns = %+v", e, len(tableDesc.Columns), tableDesc.Columns) 2147 } else if tableDesc.Columns[0].Name != "k" { 2148 t.Fatalf("columns %+v", tableDesc.Columns) 2149 } else if len(tableDesc.Mutations) != 2 { 2150 t.Fatalf("mutations %+v", tableDesc.Mutations) 2151 } 2152 } 2153 2154 // TestVisibilityDuringPrimaryKeyChange tests visibility of different indexes 2155 // during the primary key change process. 2156 func TestVisibilityDuringPrimaryKeyChange(t *testing.T) { 2157 defer leaktest.AfterTest(t)() 2158 2159 defer setTestJobsAdoptInterval()() 2160 2161 ctx := context.Background() 2162 swapNotification := make(chan struct{}) 2163 waitBeforeContinuing := make(chan struct{}) 2164 params, _ := tests.CreateTestServerParams() 2165 params.Knobs = base.TestingKnobs{ 2166 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2167 RunBeforePrimaryKeySwap: func() { 2168 // Notify the tester that the primary key swap is about to happen. 2169 swapNotification <- struct{}{} 2170 // Wait for the tester to finish before continuing the swap. 2171 <-waitBeforeContinuing 2172 }, 2173 }, 2174 } 2175 s, sqlDB, _ := serverutils.StartServer(t, params) 2176 defer s.Stopper().Stop(ctx) 2177 2178 if _, err := sqlDB.Exec(` 2179 CREATE DATABASE t; 2180 CREATE TABLE t.test (x INT PRIMARY KEY, y INT NOT NULL, z INT, INDEX i (z)); 2181 INSERT INTO t.test VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3); 2182 `); err != nil { 2183 t.Fatal(err) 2184 } 2185 2186 var wg sync.WaitGroup 2187 wg.Add(1) 2188 go func() { 2189 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (y)`); err != nil { 2190 t.Error(err) 2191 } 2192 wg.Done() 2193 }() 2194 2195 <-swapNotification 2196 2197 row := sqlDB.QueryRow("SHOW CREATE TABLE t.test") 2198 var scanName, create string 2199 if err := row.Scan(&scanName, &create); err != nil { 2200 t.Fatal(err) 2201 } 2202 expected := `CREATE TABLE test ( 2203 x INT8 NOT NULL, 2204 y INT8 NOT NULL, 2205 z INT8 NULL, 2206 CONSTRAINT "primary" PRIMARY KEY (x ASC), 2207 INDEX i (z ASC), 2208 FAMILY "primary" (x, y, z) 2209 )` 2210 if create != expected { 2211 t.Fatalf("expected %s, found %s", expected, create) 2212 } 2213 2214 // Let the schema change process continue. 2215 waitBeforeContinuing <- struct{}{} 2216 // Wait for the primary key swap to happen. 2217 wg.Wait() 2218 2219 row = sqlDB.QueryRow("SHOW CREATE TABLE t.test") 2220 if err := row.Scan(&scanName, &create); err != nil { 2221 t.Fatal(err) 2222 } 2223 expected = `CREATE TABLE test ( 2224 x INT8 NOT NULL, 2225 y INT8 NOT NULL, 2226 z INT8 NULL, 2227 CONSTRAINT "primary" PRIMARY KEY (y ASC), 2228 UNIQUE INDEX test_x_key (x ASC), 2229 INDEX i (z ASC), 2230 FAMILY "primary" (x, y, z) 2231 )` 2232 if create != expected { 2233 t.Fatalf("expected %s, found %s", expected, create) 2234 } 2235 } 2236 2237 // TestPrimaryKeyChangeWithPrecedingIndexCreation tests that a primary key change 2238 // successfully rewrites indexes that are being created while the primary key change starts. 2239 func TestPrimaryKeyChangeWithPrecedingIndexCreation(t *testing.T) { 2240 defer leaktest.AfterTest(t)() 2241 2242 defer setTestJobsAdoptInterval()() 2243 2244 ctx := context.Background() 2245 2246 var chunkSize int64 = 100 2247 var maxValue = 4000 2248 if util.RaceEnabled { 2249 // Race builds are a lot slower, so use a smaller number of rows. 2250 maxValue = 200 2251 chunkSize = 5 2252 } 2253 2254 // Protects backfillNotification. 2255 var mu syncutil.Mutex 2256 var backfillNotification, continueNotification chan struct{} 2257 // We have to have initBackfillNotification return the new 2258 // channel rather than having later users read the original 2259 // backfillNotification to make the race detector happy. 2260 initBackfillNotification := func() (chan struct{}, chan struct{}) { 2261 mu.Lock() 2262 defer mu.Unlock() 2263 backfillNotification = make(chan struct{}) 2264 continueNotification = make(chan struct{}) 2265 return backfillNotification, continueNotification 2266 } 2267 notifyBackfill := func() { 2268 mu.Lock() 2269 defer mu.Unlock() 2270 if backfillNotification != nil { 2271 close(backfillNotification) 2272 backfillNotification = nil 2273 } 2274 if continueNotification != nil { 2275 <-continueNotification 2276 } 2277 } 2278 params, _ := tests.CreateTestServerParams() 2279 params.Knobs = base.TestingKnobs{ 2280 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2281 BackfillChunkSize: chunkSize, 2282 }, 2283 DistSQL: &execinfra.TestingKnobs{ 2284 RunBeforeBackfillChunk: func(_ roachpb.Span) error { 2285 notifyBackfill() 2286 return nil 2287 }, 2288 }, 2289 } 2290 s, sqlDB, kvDB := serverutils.StartServer(t, params) 2291 defer s.Stopper().Stop(ctx) 2292 2293 if _, err := sqlDB.Exec(`CREATE DATABASE t`); err != nil { 2294 t.Fatal(err) 2295 } 2296 2297 t.Run("create-index-before", func(t *testing.T) { 2298 t.Skip("unskip once #45510 is completed") 2299 if _, err := sqlDB.Exec(`CREATE TABLE t.test (k INT NOT NULL, v INT)`); err != nil { 2300 t.Fatal(err) 2301 } 2302 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 2303 t.Fatal(err) 2304 } 2305 2306 backfillNotif, _ := initBackfillNotification() 2307 var wg sync.WaitGroup 2308 wg.Add(1) 2309 // Create an index on the table that will need to get rewritten. 2310 go func() { 2311 if _, err := sqlDB.Exec(`CREATE INDEX i ON t.test (v)`); err != nil { 2312 t.Error(err) 2313 } 2314 wg.Done() 2315 }() 2316 2317 // Wait until the create index mutation has progressed before starting the alter primary key. 2318 <-backfillNotif 2319 2320 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`); err != nil { 2321 t.Fatal(err) 2322 } 2323 2324 wg.Wait() 2325 2326 // There should be 4 k/v pairs per row: 2327 // * the original rowid index. 2328 // * the old index on v. 2329 // * the new primary key on k. 2330 // * the new index for v with k as the unique column. 2331 testutils.SucceedsSoon(t, func() error { 2332 return checkTableKeyCount(ctx, kvDB, 4, maxValue) 2333 }) 2334 }) 2335 2336 // Repeat the prior process but with a primary key change before. 2337 t.Run("pk-change-before", func(t *testing.T) { 2338 var wg sync.WaitGroup 2339 if _, err := sqlDB.Exec(` 2340 DROP TABLE IF EXISTS t.test; 2341 CREATE TABLE t.test (k INT NOT NULL, v INT, v2 INT NOT NULL)`); err != nil { 2342 t.Fatal(err) 2343 } 2344 backfillNotif, continueNotif := initBackfillNotification() 2345 // Can't use bulkInsertIntoTable here because that only works with 2 columns. 2346 inserts := make([]string, maxValue+1) 2347 for i := 0; i < maxValue+1; i++ { 2348 inserts[i] = fmt.Sprintf(`(%d, %d, %d)`, i, maxValue-i, i) 2349 } 2350 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ` + strings.Join(inserts, ",")); err != nil { 2351 t.Fatal(err) 2352 } 2353 wg.Add(1) 2354 // Alter the primary key of the table. 2355 go func() { 2356 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (v2)`); err != nil { 2357 t.Error(err) 2358 } 2359 wg.Done() 2360 }() 2361 2362 <-backfillNotif 2363 2364 // This must be rejected, because there is a primary key change already in progress. 2365 _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`) 2366 if !testutils.IsError(err, "pq: unimplemented: table test is currently undergoing a schema change") { 2367 t.Errorf("expected to concurrent primary key change to error, but got %+v", err) 2368 } 2369 2370 // After the expected error, let the backfill continue. 2371 close(continueNotif) 2372 2373 wg.Wait() 2374 2375 // After the first primary key change is done, the follow up primary key change should succeed. 2376 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`); err != nil { 2377 t.Fatal(err) 2378 } 2379 2380 // There should be 4 k/v pairs per row: 2381 // * the original rowid index. 2382 // * the new primary index on v2. 2383 // * the new primary index on k. 2384 // * the rewritten demoted index on v2. 2385 testutils.SucceedsSoon(t, func() error { 2386 return checkTableKeyCount(ctx, kvDB, 4, maxValue) 2387 }) 2388 }) 2389 } 2390 2391 // TestSchemaChangeWhileExecutingPrimaryKeyChange tests that other schema 2392 // changes cannot be queued while a primary key change is executing. 2393 func TestSchemaChangeWhileExecutingPrimaryKeyChange(t *testing.T) { 2394 defer leaktest.AfterTest(t)() 2395 ctx := context.Background() 2396 2397 backfillNotification := make(chan struct{}) 2398 waitBeforeContinuing := make(chan struct{}) 2399 2400 params, _ := tests.CreateTestServerParams() 2401 params.Knobs = base.TestingKnobs{ 2402 DistSQL: &execinfra.TestingKnobs{ 2403 RunBeforeBackfillChunk: func(_ roachpb.Span) error { 2404 backfillNotification <- struct{}{} 2405 <-waitBeforeContinuing 2406 return nil 2407 }, 2408 }, 2409 } 2410 2411 s, sqlDB, _ := serverutils.StartServer(t, params) 2412 defer s.Stopper().Stop(ctx) 2413 2414 if _, err := sqlDB.Exec(` 2415 CREATE DATABASE t; 2416 CREATE TABLE t.test (k INT NOT NULL, v INT); 2417 `); err != nil { 2418 t.Fatal(err) 2419 } 2420 2421 var wg sync.WaitGroup 2422 wg.Add(1) 2423 go func() { 2424 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`); err != nil { 2425 t.Error(err) 2426 } 2427 wg.Done() 2428 }() 2429 2430 <-backfillNotification 2431 2432 // Test that trying different schema changes results an error. 2433 _, err := sqlDB.Exec(`ALTER TABLE t.test ADD COLUMN z INT`) 2434 expected := "pq: unimplemented: cannot perform a schema change operation while a primary key change is in progress" 2435 if !testutils.IsError(err, expected) { 2436 t.Fatalf("expected to find error %s but found %+v", expected, err) 2437 } 2438 2439 _, err = sqlDB.Exec(`CREATE INDEX ON t.test(v)`) 2440 if !testutils.IsError(err, expected) { 2441 t.Fatalf("expected to find error %s but found %+v", expected, err) 2442 } 2443 2444 waitBeforeContinuing <- struct{}{} 2445 wg.Wait() 2446 } 2447 2448 // TestPrimaryKeyChangeWithOperations ensures that different operations succeed 2449 // while a primary key change is happening. 2450 func TestPrimaryKeyChangeWithOperations(t *testing.T) { 2451 defer leaktest.AfterTest(t)() 2452 ctx := context.Background() 2453 2454 var chunkSize int64 = 100 2455 var maxValue = 4000 2456 if util.RaceEnabled { 2457 // Race builds are a lot slower, so use a smaller number of rows. 2458 maxValue = 200 2459 chunkSize = 5 2460 } 2461 2462 // protects backfillNotification 2463 var mu syncutil.Mutex 2464 backfillNotification := make(chan struct{}) 2465 2466 params, _ := tests.CreateTestServerParams() 2467 initBackfillNotification := func() chan struct{} { 2468 mu.Lock() 2469 defer mu.Unlock() 2470 backfillNotification = make(chan struct{}) 2471 return backfillNotification 2472 } 2473 notifyBackfill := func() { 2474 mu.Lock() 2475 defer mu.Unlock() 2476 if backfillNotification != nil { 2477 // Close channel to notify that the backfill has started. 2478 close(backfillNotification) 2479 backfillNotification = nil 2480 } 2481 } 2482 params.Knobs = base.TestingKnobs{ 2483 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2484 BackfillChunkSize: chunkSize, 2485 }, 2486 DistSQL: &execinfra.TestingKnobs{ 2487 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 2488 notifyBackfill() 2489 return nil 2490 }, 2491 }, 2492 } 2493 s, sqlDB, kvDB := serverutils.StartServer(t, params) 2494 defer s.Stopper().Stop(ctx) 2495 if _, err := sqlDB.Exec(` 2496 CREATE DATABASE t; 2497 CREATE TABLE t.test (k INT NOT NULL, v INT); 2498 `); err != nil { 2499 t.Fatal(err) 2500 } 2501 // GC the old indexes to be dropped after the PK change immediately. 2502 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 2503 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2504 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 2505 t.Fatal(err) 2506 } 2507 2508 // Bulk insert. 2509 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 2510 t.Fatal(err) 2511 } 2512 2513 runSchemaChangeWithOperations( 2514 t, 2515 sqlDB, 2516 kvDB, 2517 "ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)", 2518 maxValue, 2519 1, 2520 initBackfillNotification(), 2521 // We don't let runSchemaChangeWithOperations use UPSERT statements, because 2522 // way in which runSchemaChangeWithOperations uses them assumes that k is already 2523 // the primary key of the table, leading to some errors during the UPSERT 2524 // conflict handling. Since we are changing the primary key of the table to 2525 // be using k as the primary key, we disable the UPSERT statements in the test. 2526 false, 2527 ) 2528 2529 // runSchemaChangeWithOperations only performs some simple 2530 // operations on the kv table. We want to also run some 2531 // more operations against a table with more columns. 2532 // We separate the columns into multiple different families 2533 // in order to test different cases of reads, writes and 2534 // deletions operating on different sets of families. 2535 if _, err := sqlDB.Exec(` 2536 DROP TABLE t.test; 2537 CREATE TABLE t.test ( 2538 x INT PRIMARY KEY, y INT NOT NULL, z INT, a INT, b INT, 2539 c INT, d INT, FAMILY (x), FAMILY (y), FAMILY (z), 2540 FAMILY (a, b), FAMILY (c), FAMILY (d) 2541 ); 2542 `); err != nil { 2543 t.Fatal(err) 2544 } 2545 // Insert into the table. 2546 inserts := make([]string, maxValue+1) 2547 for i := 0; i < maxValue+1; i++ { 2548 inserts[i] = fmt.Sprintf( 2549 "(%d, %d, %d, %d, %d, %d, %d)", 2550 i, i, i, i, i, i, i, 2551 ) 2552 } 2553 if _, err := sqlDB.Exec( 2554 fmt.Sprintf(`INSERT INTO t.test VALUES %s`, strings.Join(inserts, ","))); err != nil { 2555 t.Fatal(err) 2556 } 2557 2558 notification := initBackfillNotification() 2559 2560 var wg sync.WaitGroup 2561 wg.Add(1) 2562 go func() { 2563 if _, err := sqlDB.Exec(` 2564 ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (y)`); err != nil { 2565 t.Error(err) 2566 } 2567 wg.Done() 2568 }() 2569 2570 // Wait until the backfill starts. 2571 <-notification 2572 2573 // Update some rows. 2574 rowsUpdated := make(map[int]struct{}) 2575 for i := 0; i < 10; i++ { 2576 // Update a row that hasn't been updated yet. 2577 for { 2578 k := rand.Intn(maxValue) 2579 if _, ok := rowsUpdated[k]; !ok { 2580 rowsUpdated[k] = struct{}{} 2581 break 2582 } 2583 } 2584 } 2585 for k := range rowsUpdated { 2586 if _, err := sqlDB.Exec(` 2587 UPDATE t.test SET z = NULL, a = $1, b = NULL, c = NULL, d = $1 WHERE y = $2`, 2*k, k); err != nil { 2588 t.Fatal(err) 2589 } 2590 } 2591 2592 // Delete some rows. 2593 rowsDeleted := make(map[int]struct{}) 2594 for i := 0; i < 10; i++ { 2595 // Delete a row that hasn't been updated. 2596 for { 2597 k := rand.Intn(maxValue) 2598 _, updated := rowsUpdated[k] 2599 _, deleted := rowsDeleted[k] 2600 if !updated && !deleted { 2601 rowsDeleted[k] = struct{}{} 2602 break 2603 } 2604 } 2605 } 2606 for k := range rowsDeleted { 2607 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE x = $1`, k); err != nil { 2608 t.Fatal(err) 2609 } 2610 } 2611 2612 // Insert some rows. 2613 inserts = make([]string, 10) 2614 for i := 0; i < 10; i++ { 2615 val := i + maxValue + 1 2616 inserts[i] = fmt.Sprintf( 2617 "(%d, %d, %d, %d, %d, %d, %d)", 2618 val, val, val, val, val, val, val, 2619 ) 2620 } 2621 if _, err := sqlDB.Exec( 2622 fmt.Sprintf(`INSERT INTO t.test VALUES %s`, strings.Join(inserts, ","))); err != nil { 2623 t.Fatal(err) 2624 } 2625 2626 // Wait for the pk change to complete. 2627 wg.Wait() 2628 2629 // Ensure that the count of rows is correct along both indexes. 2630 var count int 2631 row := sqlDB.QueryRow(`SELECT count(*) FROM t.test@primary`) 2632 if err := row.Scan(&count); err != nil { 2633 t.Fatal(err) 2634 } 2635 if count != maxValue+1 { 2636 t.Fatalf("expected %d rows, found %d", maxValue+1, count) 2637 } 2638 row = sqlDB.QueryRow(`SELECT count(x) FROM t.test@test_x_key`) 2639 if err := row.Scan(&count); err != nil { 2640 t.Fatal(err) 2641 } 2642 if count != maxValue+1 { 2643 t.Fatalf("expected %d rows, found %d", maxValue+1, count) 2644 } 2645 2646 // Verify that we cannot find our deleted rows. 2647 for k := range rowsDeleted { 2648 row := sqlDB.QueryRow(`SELECT count(*) FROM t.test WHERE x = $1`, k) 2649 if err := row.Scan(&count); err != nil { 2650 t.Fatal(err) 2651 } 2652 if count != 0 { 2653 t.Fatalf("expected %d rows, found %d", 0, count) 2654 } 2655 } 2656 2657 // Verify that we can find our inserted rows. 2658 for i := 0; i < 10; i++ { 2659 val := i + maxValue + 1 2660 row := sqlDB.QueryRow(`SELECT * FROM t.test WHERE y = $1`, val) 2661 var x, y, z, a, b, c, d int 2662 if err := row.Scan(&x, &y, &z, &a, &b, &c, &d); err != nil { 2663 t.Fatal(err) 2664 } 2665 for i, v := range []int{x, y, z, a, b, c, d} { 2666 if v != val { 2667 t.Fatalf("expected to find %d for column %d, but found %d", val, i, v) 2668 } 2669 } 2670 } 2671 2672 // Verify that our updated rows have indeed been updated. 2673 for k := range rowsUpdated { 2674 row := sqlDB.QueryRow(`SELECT * FROM t.test WHERE y = $1`, k) 2675 var ( 2676 x, y, a, d int 2677 z, b, c gosql.NullInt64 2678 ) 2679 if err := row.Scan(&x, &y, &z, &a, &b, &c, &d); err != nil { 2680 t.Fatal(err) 2681 } 2682 require.Equal(t, k, x) 2683 require.Equal(t, k, y) 2684 require.Equal(t, 2*k, a) 2685 require.Equal(t, 2*k, d) 2686 for _, v := range []gosql.NullInt64{z, b, c} { 2687 if v.Valid { 2688 t.Fatalf("expected NULL but found %d", v.Int64) 2689 } 2690 } 2691 } 2692 } 2693 2694 // TestPrimaryKeyChangeInTxn tests running a primary key 2695 // change on a table created in the same transaction. 2696 func TestPrimaryKeyChangeInTxn(t *testing.T) { 2697 defer leaktest.AfterTest(t)() 2698 ctx := context.Background() 2699 params, _ := tests.CreateTestServerParams() 2700 s, sqlDB, kvDB := serverutils.StartServer(t, params) 2701 defer s.Stopper().Stop(ctx) 2702 2703 if _, err := sqlDB.Exec(` 2704 CREATE DATABASE t; 2705 BEGIN; 2706 CREATE TABLE t.test (x INT PRIMARY KEY, y INT NOT NULL, z INT, INDEX (z)); 2707 ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (y); 2708 COMMIT; 2709 `); err != nil { 2710 t.Fatal(err) 2711 } 2712 // Ensure that t.test doesn't have any pending mutations 2713 // after the primary key change. 2714 desc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2715 if len(desc.Mutations) != 0 { 2716 t.Fatalf("expected to find 0 mutations, but found %d", len(desc.Mutations)) 2717 } 2718 } 2719 2720 // TestPrimaryKeyChangeKVOps tests sequences of k/v operations 2721 // on the new primary index while it is staged as a special 2722 // secondary index. We cannot test this in a standard logic 2723 // test because we only have control over stopping the backfill 2724 // process in a unit test like this. This test is essentially 2725 // a heavy-weight poor man's logic tests, but there doesn't 2726 // seem to be a better way to achieve what is needed here. 2727 func TestPrimaryKeyChangeKVOps(t *testing.T) { 2728 defer leaktest.AfterTest(t)() 2729 ctx := context.Background() 2730 2731 backfillNotification := make(chan struct{}) 2732 waitBeforeContinuing := make(chan struct{}) 2733 2734 params, _ := tests.CreateTestServerParams() 2735 params.Knobs = base.TestingKnobs{ 2736 DistSQL: &execinfra.TestingKnobs{ 2737 RunBeforeBackfillChunk: func(_ roachpb.Span) error { 2738 backfillNotification <- struct{}{} 2739 <-waitBeforeContinuing 2740 return nil 2741 }, 2742 }, 2743 } 2744 s, sqlDB, _ := serverutils.StartServer(t, params) 2745 defer s.Stopper().Stop(ctx) 2746 2747 if _, err := sqlDB.Exec(` 2748 CREATE DATABASE t; 2749 CREATE TABLE t.test ( 2750 x INT PRIMARY KEY, 2751 y INT NOT NULL, 2752 z INT, 2753 a INT, 2754 b INT, 2755 c INT, 2756 FAMILY (x), FAMILY (y), FAMILY (z, a), FAMILY (b), FAMILY (c) 2757 ) 2758 `); err != nil { 2759 t.Fatal(err) 2760 } 2761 2762 var wg sync.WaitGroup 2763 wg.Add(1) 2764 go func() { 2765 if _, err := sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (y)`); err != nil { 2766 t.Error(err) 2767 } 2768 wg.Done() 2769 }() 2770 2771 // Wait for the new primary index to move to the DELETE_AND_WRITE_ONLY 2772 // state, which happens right before backfilling of the index begins. 2773 <-backfillNotification 2774 2775 scanToArray := func(rows *gosql.Rows) []string { 2776 var found []string 2777 for rows.Next() { 2778 var message string 2779 if err := rows.Scan(&message); err != nil { 2780 t.Fatal(err) 2781 } 2782 found = append(found, message) 2783 } 2784 return found 2785 } 2786 2787 // Test that we only insert the necessary k/v's. 2788 rows, err := sqlDB.Query(` 2789 SET TRACING=on,kv,results; 2790 INSERT INTO t.test VALUES (1, 2, 3, NULL, NULL, 6); 2791 SET TRACING=off; 2792 SELECT message FROM [SHOW KV TRACE FOR SESSION] WHERE 2793 message LIKE 'InitPut /Table/53/2%' ORDER BY message;`) 2794 if err != nil { 2795 t.Fatal(err) 2796 } 2797 2798 expected := []string{ 2799 "InitPut /Table/53/2/2/0 -> /TUPLE/1:1:Int/1", 2800 // TODO (rohany): this k/v is spurious and should be removed 2801 // when #45343 is fixed. 2802 "InitPut /Table/53/2/2/1/1 -> /INT/2", 2803 "InitPut /Table/53/2/2/2/1 -> /TUPLE/3:3:Int/3", 2804 "InitPut /Table/53/2/2/4/1 -> /INT/6", 2805 } 2806 require.Equal(t, expected, scanToArray(rows)) 2807 2808 // Test that we remove all families when deleting. 2809 rows, err = sqlDB.Query(` 2810 SET TRACING=on, kv, results; 2811 DELETE FROM t.test WHERE y = 2; 2812 SET TRACING=off; 2813 SELECT message FROM [SHOW KV TRACE FOR SESSION] WHERE 2814 message LIKE 'Del /Table/53/2%' ORDER BY message;`) 2815 if err != nil { 2816 t.Fatal(err) 2817 } 2818 2819 expected = []string{ 2820 "Del /Table/53/2/2/0", 2821 "Del /Table/53/2/2/1/1", 2822 "Del /Table/53/2/2/2/1", 2823 "Del /Table/53/2/2/3/1", 2824 "Del /Table/53/2/2/4/1", 2825 } 2826 require.Equal(t, expected, scanToArray(rows)) 2827 2828 // Test that we update all families when the key changes. 2829 rows, err = sqlDB.Query(` 2830 INSERT INTO t.test VALUES (1, 2, 3, NULL, NULL, 6); 2831 SET TRACING=on, kv, results; 2832 UPDATE t.test SET y = 3 WHERE y = 2; 2833 SET TRACING=off; 2834 SELECT message FROM [SHOW KV TRACE FOR SESSION] WHERE 2835 message LIKE 'Put /Table/53/2%' OR 2836 message LIKE 'Del /Table/53/2%' OR 2837 message LIKE 'CPut /Table/53/2%';`) 2838 if err != nil { 2839 t.Fatal(err) 2840 } 2841 2842 expected = []string{ 2843 "Del /Table/53/2/2/0", 2844 "CPut /Table/53/2/3/0 -> /TUPLE/1:1:Int/1 (expecting does not exist)", 2845 // TODO (rohany): this k/v is spurious and should be removed 2846 // when #45343 is fixed. 2847 "Del /Table/53/2/2/1/1", 2848 "CPut /Table/53/2/3/1/1 -> /INT/3 (expecting does not exist)", 2849 "Del /Table/53/2/2/2/1", 2850 "CPut /Table/53/2/3/2/1 -> /TUPLE/3:3:Int/3 (expecting does not exist)", 2851 "Del /Table/53/2/2/4/1", 2852 "CPut /Table/53/2/3/4/1 -> /INT/6 (expecting does not exist)", 2853 } 2854 require.Equal(t, expected, scanToArray(rows)) 2855 2856 // Test that we only update necessary families when the key doesn't change. 2857 rows, err = sqlDB.Query(` 2858 SET TRACING=on, kv, results; 2859 UPDATE t.test SET z = NULL, b = 5, c = NULL WHERE y = 3; 2860 SET TRACING=off; 2861 SELECT message FROM [SHOW KV TRACE FOR SESSION] WHERE 2862 message LIKE 'Put /Table/53/2%' OR 2863 message LIKE 'Del /Table/53/2%' OR 2864 message LIKE 'CPut /Table/53/2%';`) 2865 if err != nil { 2866 t.Fatal(err) 2867 } 2868 2869 expected = []string{ 2870 "Del /Table/53/2/3/2/1", 2871 "CPut /Table/53/2/3/3/1 -> /INT/5 (expecting does not exist)", 2872 "Del /Table/53/2/3/4/1", 2873 } 2874 require.Equal(t, expected, scanToArray(rows)) 2875 2876 waitBeforeContinuing <- struct{}{} 2877 2878 wg.Wait() 2879 } 2880 2881 // TestPrimaryKeyIndexRewritesGetRemoved ensures that the old versions of 2882 // indexes that are being rewritten eventually get cleaned up and removed. 2883 func TestPrimaryKeyIndexRewritesGetRemoved(t *testing.T) { 2884 defer leaktest.AfterTest(t)() 2885 ctx := context.Background() 2886 2887 // Decrease the adopt loop interval so that retries happen quickly. 2888 defer setTestJobsAdoptInterval()() 2889 2890 params, _ := tests.CreateTestServerParams() 2891 2892 s, sqlDB, kvDB := serverutils.StartServer(t, params) 2893 defer s.Stopper().Stop(ctx) 2894 2895 // Disable strict GC TTL enforcement because we're going to shove a zero-value 2896 // TTL into the system with AddImmediateGCZoneConfig. 2897 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 2898 2899 if _, err := sqlDB.Exec(` 2900 CREATE DATABASE t; 2901 CREATE TABLE t.test (k INT PRIMARY KEY, v INT NOT NULL, w INT, INDEX i (w)); 2902 INSERT INTO t.test VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3); 2903 ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (v); 2904 `); err != nil { 2905 t.Fatal(err) 2906 } 2907 2908 // Wait for the async schema changer to run. 2909 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2910 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 2911 t.Fatal(err) 2912 } 2913 testutils.SucceedsSoon(t, func() error { 2914 // We expect to have 3 (one for each row) * 3 (new primary key, old primary key and i rewritten). 2915 return checkTableKeyCountExact(ctx, kvDB, 9) 2916 }) 2917 } 2918 2919 func TestPrimaryKeyChangeWithCancel(t *testing.T) { 2920 defer leaktest.AfterTest(t)() 2921 2922 // Decrease the adopt loop interval so that retries happen quickly. 2923 defer setTestJobsAdoptInterval()() 2924 2925 var chunkSize int64 = 100 2926 var maxValue = 4000 2927 if util.RaceEnabled { 2928 // Race builds are a lot slower, so use a smaller number of rows. 2929 maxValue = 200 2930 chunkSize = 5 2931 } 2932 2933 ctx := context.Background() 2934 var db *gosql.DB 2935 shouldCancel := true 2936 params, _ := tests.CreateTestServerParams() 2937 params.Knobs = base.TestingKnobs{ 2938 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 2939 BackfillChunkSize: chunkSize, 2940 }, 2941 DistSQL: &execinfra.TestingKnobs{ 2942 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 2943 if !shouldCancel { 2944 return nil 2945 } 2946 if _, err := db.Exec(`CANCEL JOB ( 2947 SELECT job_id FROM [SHOW JOBS] 2948 WHERE 2949 job_type = 'SCHEMA CHANGE' AND 2950 status = $1 AND 2951 description NOT LIKE 'ROLL BACK%' 2952 )`, jobs.StatusRunning); err != nil { 2953 t.Error(err) 2954 } 2955 return nil 2956 }, 2957 }, 2958 } 2959 s, sqlDB, kvDB := serverutils.StartServer(t, params) 2960 db = sqlDB 2961 defer s.Stopper().Stop(ctx) 2962 2963 // Disable strict GC TTL enforcement because we're going to shove a zero-value 2964 // TTL into the system with AddImmediateGCZoneConfig. 2965 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 2966 2967 if _, err := sqlDB.Exec(` 2968 CREATE DATABASE t; 2969 CREATE TABLE t.test (k INT NOT NULL, v INT); 2970 `); err != nil { 2971 t.Fatal(err) 2972 } 2973 2974 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 2975 t.Fatal(err) 2976 } 2977 2978 // This will fail, so we don't want to check the error. 2979 _, _ = sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`) 2980 2981 // Ensure that the mutations corresponding to the primary key change are cleaned up and 2982 // that the job did not succeed even though it was canceled. 2983 testutils.SucceedsSoon(t, func() error { 2984 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2985 if len(tableDesc.Mutations) != 0 { 2986 return errors.Errorf("expected 0 mutations after cancellation, found %d", len(tableDesc.Mutations)) 2987 } 2988 if len(tableDesc.PrimaryIndex.ColumnNames) != 1 || tableDesc.PrimaryIndex.ColumnNames[0] != "rowid" { 2989 return errors.Errorf("expected primary key change to not succeed after cancellation") 2990 } 2991 return nil 2992 }) 2993 2994 // Stop any further attempts at cancellation, so the GC jobs don't fail. 2995 shouldCancel = false 2996 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 2997 if _, err := sqltestutils.AddImmediateGCZoneConfig(db, tableDesc.ID); err != nil { 2998 t.Fatal(err) 2999 } 3000 // Ensure that the writes from the partial new indexes are cleaned up. 3001 testutils.SucceedsSoon(t, func() error { 3002 return checkTableKeyCount(ctx, kvDB, 1, maxValue) 3003 }) 3004 } 3005 3006 // TestPrimaryKeyDropIndexNotCancelable tests that the job to drop indexes after 3007 // a primary key change is not cancelable. 3008 func TestPrimaryKeyDropIndexNotCancelable(t *testing.T) { 3009 defer leaktest.AfterTest(t)() 3010 3011 ctx := context.Background() 3012 var db *gosql.DB 3013 shouldAttemptCancel := true 3014 hasAttemptedCancel := make(chan struct{}) 3015 params, _ := tests.CreateTestServerParams() 3016 params.Knobs = base.TestingKnobs{ 3017 GCJob: &sql.GCJobTestingKnobs{ 3018 RunBeforeResume: func(jobID int64) error { 3019 if !shouldAttemptCancel { 3020 return nil 3021 } 3022 _, err := db.Exec(`CANCEL JOB ($1)`, jobID) 3023 require.Regexp(t, "not cancelable", err) 3024 shouldAttemptCancel = false 3025 close(hasAttemptedCancel) 3026 return nil 3027 }, 3028 }, 3029 } 3030 s, sqlDB, kvDB := serverutils.StartServer(t, params) 3031 db = sqlDB 3032 defer s.Stopper().Stop(ctx) 3033 3034 _, err := sqlDB.Exec(` 3035 CREATE DATABASE t; 3036 CREATE TABLE t.test (k INT NOT NULL, v INT); 3037 `) 3038 require.NoError(t, err) 3039 3040 _, err = sqlDB.Exec(`ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (k)`) 3041 require.NoError(t, err) 3042 3043 // Wait until the testing knob has notified that canceling the job has been 3044 // attempted before continuing. 3045 <-hasAttemptedCancel 3046 3047 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 3048 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3049 testutils.SucceedsSoon(t, func() error { 3050 return jobutils.VerifySystemJob(t, sqlRun, 1, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 3051 Description: "CLEANUP JOB for 'ALTER TABLE t.public.test ALTER PRIMARY KEY USING COLUMNS (k)'", 3052 Username: security.RootUser, 3053 DescriptorIDs: sqlbase.IDs{tableDesc.ID}, 3054 }) 3055 }) 3056 } 3057 3058 // TestMultiplePrimaryKeyChanges ensures that we can run many primary key 3059 // changes back to back. We cannot run this in a logic test because we need to 3060 // set a low job registry adopt interval, so that each successive schema change 3061 // can run immediately without waiting too long for a retry due to being second 3062 // in line after the mutation to drop indexes for the previous primary key 3063 // change. 3064 func TestMultiplePrimaryKeyChanges(t *testing.T) { 3065 defer leaktest.AfterTest(t)() 3066 3067 // Decrease the adopt loop interval so that retries happen quickly. 3068 defer setTestJobsAdoptInterval()() 3069 3070 ctx := context.Background() 3071 params, _ := tests.CreateTestServerParams() 3072 params.Knobs = base.TestingKnobs{ 3073 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{}, 3074 } 3075 s, sqlDB, _ := serverutils.StartServer(t, params) 3076 defer s.Stopper().Stop(ctx) 3077 if _, err := sqlDB.Exec(` 3078 CREATE DATABASE t; 3079 CREATE TABLE t.test (x INT NOT NULL, y INT NOT NULL, z INT NOT NULL, w int, INDEX i (w)); 3080 INSERT INTO t.test VALUES (1, 1, 1, 1), (2, 2, 2, 2), (3, 3, 3, 3); 3081 `); err != nil { 3082 t.Fatal(err) 3083 } 3084 for _, col := range []string{"x", "y", "z"} { 3085 query := fmt.Sprintf("ALTER TABLE t.test ALTER PRIMARY KEY USING COLUMNS (%s)", col) 3086 if _, err := sqlDB.Exec(query); err != nil { 3087 t.Fatal(err) 3088 } 3089 rows, err := sqlDB.Query("SELECT * FROM t.test") 3090 if err != nil { 3091 t.Fatal(err) 3092 } 3093 for i := 1; rows.Next(); i++ { 3094 var x, y, z, w int 3095 if err := rows.Scan(&x, &y, &z, &w); err != nil { 3096 t.Fatal(err) 3097 } 3098 if !(x == i && y == i && z == i && w == i) { 3099 t.Errorf("expected all columns to be %d, but found (%d, %d, %d, %d)", i, x, y, z, w) 3100 } 3101 } 3102 } 3103 } 3104 3105 // Test CRUD operations can read NULL values for NOT NULL columns 3106 // in the middle of a column backfill. 3107 func TestCRUDWhileColumnBackfill(t *testing.T) { 3108 defer leaktest.AfterTest(t)() 3109 3110 defer setTestJobsAdoptInterval()() 3111 backfillNotification := make(chan bool) 3112 3113 backfillCompleteNotification := make(chan bool) 3114 continueSchemaChangeNotification := make(chan bool) 3115 3116 params, _ := tests.CreateTestServerParams() 3117 params.Knobs = base.TestingKnobs{ 3118 DistSQL: &execinfra.TestingKnobs{ 3119 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 3120 if backfillNotification != nil { 3121 // Close channel to notify that the schema change has 3122 // been queued and the backfill has started. 3123 close(backfillNotification) 3124 backfillNotification = nil 3125 <-continueSchemaChangeNotification 3126 } 3127 return nil 3128 }, 3129 RunAfterBackfillChunk: func() { 3130 if backfillCompleteNotification != nil { 3131 // Close channel to notify that the schema change 3132 // backfill is complete and not finalized. 3133 close(backfillCompleteNotification) 3134 backfillCompleteNotification = nil 3135 <-continueSchemaChangeNotification 3136 } 3137 }, 3138 }, 3139 // Disable backfill migrations, we still need the jobs table migration. 3140 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 3141 DisableBackfillMigrations: true, 3142 }, 3143 } 3144 server, sqlDB, kvDB := serverutils.StartServer(t, params) 3145 defer server.Stopper().Stop(context.Background()) 3146 3147 if _, err := sqlDB.Exec(` 3148 CREATE DATABASE t; 3149 CREATE TABLE t.test ( 3150 k INT8 NOT NULL, 3151 v INT8, 3152 length INT8 NOT NULL, 3153 CONSTRAINT "primary" PRIMARY KEY (k), 3154 INDEX v_idx (v), 3155 FAMILY "primary" (k, v, length) 3156 ); 3157 INSERT INTO t.test (k, v, length) VALUES (0, 1, 1); 3158 INSERT INTO t.test (k, v, length) VALUES (1, 2, 1); 3159 INSERT INTO t.test (k, v, length) VALUES (2, 3, 1); 3160 `); err != nil { 3161 t.Fatal(err) 3162 } 3163 3164 // Run the column schema change in a separate goroutine. 3165 notification := backfillNotification 3166 doneNotification := backfillCompleteNotification 3167 var wg sync.WaitGroup 3168 wg.Add(2) 3169 go func() { 3170 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD id INT8 NOT NULL DEFAULT 2, ADD u INT8 NOT NULL AS (v+1) STORED;`); err != nil { 3171 t.Error(err) 3172 } 3173 wg.Done() 3174 }() 3175 3176 // Wait until the first mutation has processed through the state machine 3177 // and has started backfilling. 3178 <-notification 3179 3180 go func() { 3181 // Create a column that uses the above column in an expression. 3182 if _, err := sqlDB.Exec(`ALTER TABLE t.test ADD z INT8 AS (k + id) STORED;`); err != nil { 3183 t.Error(err) 3184 } 3185 wg.Done() 3186 }() 3187 3188 // Wait until both mutations are queued up. 3189 testutils.SucceedsSoon(t, func() error { 3190 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3191 if l := len(tableDesc.Mutations); l != 3 { 3192 return errors.Errorf("number of mutations = %d", l) 3193 } 3194 return nil 3195 }) 3196 3197 // UPDATE the row using the secondary index. 3198 if _, err := sqlDB.Exec(`UPDATE t.test SET length = 27000 WHERE v = 1`); err != nil { 3199 t.Error(err) 3200 } 3201 3202 // UPDATE the row using the primary index. 3203 if _, err := sqlDB.Exec(`UPDATE t.test SET length = 27001 WHERE k = 1`); err != nil { 3204 t.Error(err) 3205 } 3206 3207 // Use UPSERT instead of UPDATE. 3208 if _, err := sqlDB.Exec(`UPSERT INTO t.test(k, v, length) VALUES (2, 3, 27000)`); err != nil { 3209 t.Error(err) 3210 } 3211 3212 // UPSERT inserts a new row. 3213 if _, err := sqlDB.Exec(`UPSERT INTO t.test(k, v, length) VALUES (3, 4, 27000)`); err != nil { 3214 t.Error(err) 3215 } 3216 3217 // INSERT inserts a new row. 3218 if _, err := sqlDB.Exec(`INSERT INTO t.test(k, v, length) VALUES (4, 5, 270)`); err != nil { 3219 t.Error(err) 3220 } 3221 3222 // DELETE. 3223 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE k = 1`); err != nil { 3224 t.Error(err) 3225 } 3226 3227 // DELETE using the secondary index. 3228 if _, err := sqlDB.Exec(`DELETE FROM t.test WHERE v = 4`); err != nil { 3229 t.Error(err) 3230 } 3231 3232 // Ensure that the newly added column cannot be supplied with any values. 3233 if _, err := sqlDB.Exec(`UPDATE t.test SET id = 27000 WHERE k = 2`); !testutils.IsError(err, 3234 `column "id" does not exist`) && !testutils.IsError(err, `column "id" is being backfilled`) { 3235 t.Errorf("err = %+v", err) 3236 } 3237 if _, err := sqlDB.Exec(`UPDATE t.test SET id = NULL WHERE k = 2`); !testutils.IsError(err, 3238 `column "id" does not exist`) && !testutils.IsError(err, `column "id" is being backfilled`) { 3239 t.Errorf("err = %+v", err) 3240 } 3241 if _, err := sqlDB.Exec(`UPSERT INTO t.test(k, v, id) VALUES (2, 3, 234)`); !testutils.IsError( 3242 err, `column "id" does not exist`) { 3243 t.Errorf("err = %+v", err) 3244 } 3245 if _, err := sqlDB.Exec(`UPSERT INTO t.test(k, v, id) VALUES (2, 3, NULL)`); !testutils.IsError( 3246 err, `column "id" does not exist`) { 3247 t.Errorf("err = %+v", err) 3248 } 3249 if _, err := sqlDB.Exec(`INSERT INTO t.test(k, v, id) VALUES (4, 5, 270)`); !testutils.IsError( 3250 err, `column "id" does not exist`) && !testutils.IsError( 3251 err, `column "id" is being backfilled`) { 3252 t.Errorf("err = %+v", err) 3253 } 3254 if _, err := sqlDB.Exec(`INSERT INTO t.test(k, v, id) VALUES (4, 5, NULL)`); !testutils.IsError( 3255 err, `column "id" does not exist`) && !testutils.IsError( 3256 err, `column "id" is being backfilled`) { 3257 t.Errorf("err = %+v", err) 3258 } 3259 3260 // Use column in an expression. 3261 if _, err := sqlDB.Exec( 3262 `INSERT INTO t.test (k, v, length) VALUES (2, 1, 3) ON CONFLICT (k) DO UPDATE SET (k, v, length) = (id + 1, 1, 3)`, 3263 ); err != nil { 3264 t.Error(err) 3265 } 3266 3267 // SHOW CREATE TABLE doesn't show new columns. 3268 row := sqlDB.QueryRow(`SHOW CREATE TABLE t.test`) 3269 var scanName, create string 3270 if err := row.Scan(&scanName, &create); err != nil { 3271 t.Fatal(err) 3272 } 3273 if scanName != `t.public.test` { 3274 t.Fatalf("expected table name %s, got %s", `test`, scanName) 3275 } 3276 expect := `CREATE TABLE test ( 3277 k INT8 NOT NULL, 3278 v INT8 NULL, 3279 length INT8 NOT NULL, 3280 CONSTRAINT "primary" PRIMARY KEY (k ASC), 3281 INDEX v_idx (v ASC), 3282 FAMILY "primary" (k, v, length) 3283 )` 3284 if create != expect { 3285 t.Fatalf("got: %s\nexpected: %s", create, expect) 3286 } 3287 3288 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3289 if l := len(tableDesc.Mutations); l != 3 { 3290 t.Fatalf("number of mutations = %d", l) 3291 } 3292 3293 continueSchemaChangeNotification <- true 3294 3295 <-doneNotification 3296 3297 expectedErr := "\"u\" violates not-null constraint" 3298 if _, err := sqlDB.Exec(`INSERT INTO t.test(k, v, length) VALUES (5, NULL, 8)`); !testutils.IsError(err, expectedErr) { 3299 t.Fatal(err) 3300 } 3301 3302 if _, err := sqlDB.Exec(`UPDATE t.test SET v = NULL WHERE k = 0`); !testutils.IsError(err, expectedErr) { 3303 t.Fatal(err) 3304 } 3305 3306 close(continueSchemaChangeNotification) 3307 3308 wg.Wait() 3309 3310 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3311 t.Fatal(err) 3312 } 3313 // Check data! 3314 rows, err := sqlDB.Query(`SELECT k, v, length, id, u, z FROM t.test`) 3315 if err != nil { 3316 t.Fatal(err) 3317 } 3318 defer rows.Close() 3319 expected := [][]int{ 3320 {0, 1, 27000, 2, 2, 2}, 3321 {3, 1, 3, 2, 2, 5}, 3322 {4, 5, 270, 2, 6, 6}, 3323 } 3324 count := 0 3325 for ; rows.Next(); count++ { 3326 var i1, i2, i3, i4, i5, i6 *int 3327 if err := rows.Scan(&i1, &i2, &i3, &i4, &i5, &i6); err != nil { 3328 t.Errorf("row %d scan failed: %s", count, err) 3329 continue 3330 } 3331 row := fmt.Sprintf("%d %d %d %d %d %d", *i1, *i2, *i3, *i4, *i5, *i6) 3332 exp := expected[count] 3333 expRow := fmt.Sprintf("%d %d %d %d %d %d", exp[0], exp[1], exp[2], exp[3], exp[4], exp[5]) 3334 if row != expRow { 3335 t.Errorf("expected %q but read %q", expRow, row) 3336 } 3337 } 3338 if err := rows.Err(); err != nil { 3339 t.Error(err) 3340 } else if count != 3 { 3341 t.Errorf("expected 3 rows but read %d", count) 3342 } 3343 } 3344 3345 // Test that a schema change backfill that completes on a 3346 // backfill chunk boundary works correctly. A backfill is done 3347 // by scanning a table in chunks and backfilling the schema 3348 // element for each chunk. Normally the last chunk is smaller 3349 // than the other chunks (configured chunk size), but it can 3350 // sometimes be equal in size. This test deliberately runs a 3351 // schema change where the last chunk size is equal to the 3352 // configured chunk size. 3353 func TestBackfillCompletesOnChunkBoundary(t *testing.T) { 3354 defer leaktest.AfterTest(t)() 3355 const numNodes = 5 3356 const chunkSize = 100 3357 // The number of rows in the table is a multiple of chunkSize. 3358 // [0...maxValue], so that the backfill processing ends on 3359 // a chunk boundary. 3360 const maxValue = 3*chunkSize - 1 3361 params, _ := tests.CreateTestServerParams() 3362 params.Knobs = base.TestingKnobs{ 3363 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 3364 BackfillChunkSize: chunkSize, 3365 }, 3366 } 3367 3368 tc := serverutils.StartTestCluster(t, numNodes, 3369 base.TestClusterArgs{ 3370 ReplicationMode: base.ReplicationManual, 3371 ServerArgs: params, 3372 }) 3373 defer tc.Stopper().Stop(context.Background()) 3374 kvDB := tc.Server(0).DB() 3375 sqlDB := tc.ServerConn(0) 3376 3377 if _, err := sqlDB.Exec(` 3378 CREATE DATABASE t; 3379 CREATE TABLE t.test (k INT8 PRIMARY KEY, v INT8, pi DECIMAL DEFAULT (DECIMAL '3.14')); 3380 CREATE UNIQUE INDEX vidx ON t.test (v); 3381 `); err != nil { 3382 t.Fatal(err) 3383 } 3384 3385 // Bulk insert. 3386 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3387 t.Fatal(err) 3388 } 3389 3390 // Split the table into multiple ranges. 3391 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3392 var sps []sql.SplitPoint 3393 for i := 1; i <= numNodes-1; i++ { 3394 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / numNodes * i}}) 3395 } 3396 sql.SplitTable(t, tc, tableDesc, sps) 3397 3398 // Run some schema changes. 3399 testCases := []struct { 3400 sql string 3401 numKeysPerRow int 3402 }{ 3403 {sql: "ALTER TABLE t.test ADD COLUMN x DECIMAL DEFAULT (DECIMAL '1.4')", numKeysPerRow: 2}, 3404 {sql: "ALTER TABLE t.test DROP pi", numKeysPerRow: 2}, 3405 {sql: "CREATE UNIQUE INDEX foo ON t.test (v)", numKeysPerRow: 3}, 3406 {sql: "DROP INDEX t.test@vidx CASCADE", numKeysPerRow: 3}, 3407 } 3408 3409 for _, tc := range testCases { 3410 t.Run(tc.sql, func(t *testing.T) { 3411 // Start schema change that eventually runs a backfill. 3412 if _, err := sqlDB.Exec(tc.sql); err != nil { 3413 t.Error(err) 3414 } 3415 3416 ctx := context.Background() 3417 3418 // Verify the number of keys left behind in the table to 3419 // validate schema change operations. 3420 if err := checkTableKeyCount(ctx, kvDB, tc.numKeysPerRow, maxValue); err != nil { 3421 t.Fatal(err) 3422 } 3423 3424 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3425 t.Fatal(err) 3426 } 3427 }) 3428 } 3429 } 3430 3431 func TestSchemaChangeInTxn(t *testing.T) { 3432 defer leaktest.AfterTest(t)() 3433 params, _ := tests.CreateTestServerParams() 3434 s, sqlDB, _ := serverutils.StartServer(t, params) 3435 defer s.Stopper().Stop(context.Background()) 3436 3437 if _, err := sqlDB.Exec(` 3438 CREATE DATABASE t; 3439 CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR); 3440 INSERT INTO t.kv VALUES ('a', 'b'); 3441 `); err != nil { 3442 t.Fatal(err) 3443 } 3444 3445 testCases := []struct { 3446 name string 3447 firstStmt string 3448 secondStmt string 3449 expectedErr string 3450 }{ 3451 // DROP TABLE followed by CREATE TABLE case. 3452 { 3453 name: `drop-create`, 3454 firstStmt: `DROP TABLE t.kv`, 3455 secondStmt: `CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR)`, 3456 expectedErr: `relation "kv" already exists`, 3457 }, 3458 // schema change followed by another statement works. 3459 { 3460 name: `createindex-insert`, 3461 firstStmt: `CREATE INDEX foo ON t.kv (v)`, 3462 secondStmt: `INSERT INTO t.kv VALUES ('c', 'd')`, 3463 expectedErr: ``, 3464 }, 3465 // CREATE TABLE followed by INSERT works. 3466 { 3467 name: `createtable-insert`, 3468 firstStmt: `CREATE TABLE t.origin (k CHAR PRIMARY KEY, v CHAR);`, 3469 secondStmt: `INSERT INTO t.origin VALUES ('c', 'd')`, 3470 expectedErr: ``}, 3471 // Support multiple schema changes for ORMs: #15269 3472 // Support insert into another table after schema changes: #15297 3473 { 3474 name: `multiple-schema-change`, 3475 firstStmt: `CREATE TABLE t.orm1 (k CHAR PRIMARY KEY, v CHAR); CREATE TABLE t.orm2 (k CHAR PRIMARY KEY, v CHAR);`, 3476 secondStmt: `CREATE INDEX foo ON t.orm1 (v); CREATE INDEX foo ON t.orm2 (v); INSERT INTO t.origin VALUES ('e', 'f')`, 3477 expectedErr: ``, 3478 }, 3479 // schema change at the end of a transaction that has written. 3480 { 3481 name: `insert-create`, 3482 firstStmt: `INSERT INTO t.kv VALUES ('e', 'f')`, 3483 secondStmt: `CREATE INDEX foo2 ON t.kv (v)`, 3484 expectedErr: `schema change statement cannot follow a statement that has written in the same transaction`, 3485 }, 3486 // schema change at the end of a read only transaction. 3487 { 3488 name: `select-create`, 3489 firstStmt: `SELECT * FROM t.kv`, 3490 secondStmt: `CREATE INDEX bar ON t.kv (v)`, 3491 expectedErr: ``, 3492 }, 3493 { 3494 name: `index-on-add-col`, 3495 firstStmt: `ALTER TABLE t.kv ADD i INT`, 3496 secondStmt: `CREATE INDEX foobar ON t.kv (i)`, 3497 expectedErr: ``, 3498 }, 3499 { 3500 name: `check-on-add-col`, 3501 firstStmt: `ALTER TABLE t.kv ADD j INT`, 3502 secondStmt: `ALTER TABLE t.kv ADD CONSTRAINT ck_j CHECK (j >= 0)`, 3503 expectedErr: ``, 3504 }, 3505 } 3506 3507 for _, testCase := range testCases { 3508 t.Run(testCase.name, func(t *testing.T) { 3509 tx, err := sqlDB.Begin() 3510 if err != nil { 3511 t.Fatal(err) 3512 } 3513 3514 if _, err := tx.Exec(testCase.firstStmt); err != nil { 3515 t.Fatal(err) 3516 } 3517 3518 _, err = tx.Exec(testCase.secondStmt) 3519 3520 if testCase.expectedErr != "" { 3521 // Can't commit after ALTER errored, so we ROLLBACK. 3522 if rollbackErr := tx.Rollback(); rollbackErr != nil { 3523 t.Fatal(rollbackErr) 3524 } 3525 3526 if !testutils.IsError(err, testCase.expectedErr) { 3527 t.Fatalf("different error than expected: %v", err) 3528 } 3529 } else { 3530 if err != nil { 3531 t.Fatal(err) 3532 } 3533 if err := tx.Commit(); err != nil { 3534 t.Fatal(err) 3535 } 3536 3537 if err := sqlutils.RunScrub(sqlDB, "t", "kv"); err != nil { 3538 t.Fatal(err) 3539 } 3540 } 3541 }) 3542 } 3543 } 3544 3545 func TestSecondaryIndexWithOldStoringEncoding(t *testing.T) { 3546 defer leaktest.AfterTest(t)() 3547 params, _ := tests.CreateTestServerParams() 3548 server, sqlDB, kvDB := serverutils.StartServer(t, params) 3549 defer server.Stopper().Stop(context.Background()) 3550 3551 if _, err := sqlDB.Exec(` 3552 CREATE DATABASE d; 3553 CREATE TABLE d.t ( 3554 k INT PRIMARY KEY, 3555 a INT, 3556 b INT, 3557 INDEX i (a) STORING (b), 3558 UNIQUE INDEX u (a) STORING (b) 3559 ); 3560 `); err != nil { 3561 t.Fatal(err) 3562 } 3563 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "d", "t") 3564 // Verify that this descriptor uses the new STORING encoding. Overwrite it 3565 // with one that uses the old encoding. 3566 for i, index := range tableDesc.Indexes { 3567 if len(index.ExtraColumnIDs) != 1 { 3568 t.Fatalf("ExtraColumnIDs not set properly: %s", tableDesc) 3569 } 3570 if len(index.StoreColumnIDs) != 1 { 3571 t.Fatalf("StoreColumnIDs not set properly: %s", tableDesc) 3572 } 3573 index.ExtraColumnIDs = append(index.ExtraColumnIDs, index.StoreColumnIDs...) 3574 index.StoreColumnIDs = nil 3575 tableDesc.Indexes[i] = index 3576 } 3577 if err := kvDB.Put( 3578 context.Background(), 3579 sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, tableDesc.GetID()), 3580 sqlbase.WrapDescriptor(tableDesc), 3581 ); err != nil { 3582 t.Fatal(err) 3583 } 3584 if _, err := sqlDB.Exec(`INSERT INTO d.t VALUES (11, 1, 2);`); err != nil { 3585 t.Fatal(err) 3586 } 3587 // Force another ID allocation to ensure that the old encoding persists. 3588 if _, err := sqlDB.Exec(`ALTER TABLE d.t ADD COLUMN c INT;`); err != nil { 3589 t.Fatal(err) 3590 } 3591 // Ensure that the decoder sees the old encoding. 3592 for indexName, expExplainRow := range map[string]string{ 3593 "i": "fetched: /t/i/1/11/2 -> NULL", 3594 "u": "fetched: /t/u/1 -> /11/2", 3595 } { 3596 t.Run("index scan", func(t *testing.T) { 3597 if _, err := sqlDB.Exec(fmt.Sprintf(`SET tracing = on,kv; SELECT k, a, b FROM d.t@%s; SET tracing = off`, indexName)); err != nil { 3598 t.Fatal(err) 3599 } 3600 3601 rows, err := sqlDB.Query( 3602 `SELECT message FROM [SHOW KV TRACE FOR SESSION] ` + 3603 `WHERE message LIKE 'fetched:%'`) 3604 if err != nil { 3605 t.Fatal(err) 3606 } 3607 defer rows.Close() 3608 count := 0 3609 for ; rows.Next(); count++ { 3610 var msg string 3611 if err := rows.Scan(&msg); err != nil { 3612 t.Errorf("row %d scan failed: %s", count, err) 3613 continue 3614 } 3615 if msg != expExplainRow { 3616 t.Errorf("expected %q but read %q", expExplainRow, msg) 3617 } 3618 } 3619 if err := rows.Err(); err != nil { 3620 t.Error(err) 3621 } else if count != 1 { 3622 t.Errorf("expected one row but read %d", count) 3623 } 3624 }) 3625 t.Run("data scan", func(t *testing.T) { 3626 rows, err := sqlDB.Query(fmt.Sprintf(`SELECT k, a, b FROM d.t@%s;`, indexName)) 3627 if err != nil { 3628 t.Fatal(err) 3629 } 3630 defer rows.Close() 3631 count := 0 3632 for ; rows.Next(); count++ { 3633 var i1, i2, i3 *int 3634 if err := rows.Scan(&i1, &i2, &i3); err != nil { 3635 t.Errorf("row %d scan failed: %s", count, err) 3636 continue 3637 } 3638 row := fmt.Sprintf("%d %d %d", *i1, *i2, *i3) 3639 const expRow = "11 1 2" 3640 if row != expRow { 3641 t.Errorf("expected %q but read %q", expRow, row) 3642 } 3643 } 3644 if err := rows.Err(); err != nil { 3645 t.Error(err) 3646 } else if count != 1 { 3647 t.Errorf("expected one row but read %d", count) 3648 } 3649 3650 if err := sqlutils.RunScrub(sqlDB, "d", "t"); err != nil { 3651 t.Fatal(err) 3652 } 3653 }) 3654 } 3655 } 3656 3657 // Test that a backfill is executed with an EvalContext generated on the 3658 // gateway. We assert that by checking that the same timestamp is used by all 3659 // the backfilled columns. 3660 func TestSchemaChangeEvalContext(t *testing.T) { 3661 defer leaktest.AfterTest(t)() 3662 const numNodes = 3 3663 const chunkSize = 200 3664 const maxValue = 5000 3665 params, _ := tests.CreateTestServerParams() 3666 // Disable asynchronous schema change execution. 3667 params.Knobs = base.TestingKnobs{ 3668 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 3669 BackfillChunkSize: chunkSize, 3670 }, 3671 } 3672 3673 tc := serverutils.StartTestCluster(t, numNodes, 3674 base.TestClusterArgs{ 3675 ReplicationMode: base.ReplicationManual, 3676 ServerArgs: params, 3677 }) 3678 defer tc.Stopper().Stop(context.Background()) 3679 kvDB := tc.Server(0).DB() 3680 sqlDB := tc.ServerConn(0) 3681 3682 if _, err := sqlDB.Exec(` 3683 CREATE DATABASE t; 3684 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 3685 `); err != nil { 3686 t.Fatal(err) 3687 } 3688 3689 // Bulk insert. 3690 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3691 t.Fatal(err) 3692 } 3693 3694 // Split the table into multiple ranges. 3695 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3696 var sps []sql.SplitPoint 3697 for i := 1; i <= numNodes-1; i++ { 3698 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / numNodes * i}}) 3699 } 3700 sql.SplitTable(t, tc, tableDesc, sps) 3701 3702 testCases := []struct { 3703 sql string 3704 column string 3705 }{ 3706 {"ALTER TABLE t.test ADD COLUMN x TIMESTAMP DEFAULT current_timestamp;", "x"}, 3707 } 3708 3709 for _, testCase := range testCases { 3710 t.Run(testCase.sql, func(t *testing.T) { 3711 3712 if _, err := sqlDB.Exec(testCase.sql); err != nil { 3713 t.Fatal(err) 3714 } 3715 3716 rows, err := sqlDB.Query(fmt.Sprintf(`SELECT DISTINCT %s from t.test`, testCase.column)) 3717 if err != nil { 3718 t.Fatal(err) 3719 } 3720 defer rows.Close() 3721 3722 count := 0 3723 for rows.Next() { 3724 count++ 3725 } 3726 if err := rows.Err(); err != nil { 3727 t.Fatal(err) 3728 } 3729 if count != 1 { 3730 t.Fatalf("read the wrong number of rows: e = %d, v = %d", 1, count) 3731 } 3732 3733 }) 3734 } 3735 } 3736 3737 // Tests that a schema change that is queued behind another schema change 3738 // is executed through the synchronous execution path properly even if it 3739 // gets to run before the first schema change. 3740 func TestSchemaChangeCompletion(t *testing.T) { 3741 defer leaktest.AfterTest(t)() 3742 t.Skip("") 3743 // TODO (lucy): This test needs more complicated schema changer knobs than is 3744 // currently implemented. 3745 params, _ := tests.CreateTestServerParams() 3746 var notifySchemaChange chan struct{} 3747 var restartSchemaChange chan struct{} 3748 params.Knobs = base.TestingKnobs{ 3749 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{}, 3750 } 3751 s, sqlDB, kvDB := serverutils.StartServer(t, params) 3752 ctx := context.Background() 3753 defer s.Stopper().Stop(ctx) 3754 3755 if _, err := sqlDB.Exec(` 3756 CREATE DATABASE t; 3757 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 3758 `); err != nil { 3759 t.Fatal(err) 3760 } 3761 3762 // Add some data 3763 const maxValue = 200 3764 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3765 t.Fatal(err) 3766 } 3767 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 3768 t.Fatal(err) 3769 } 3770 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3771 t.Fatal(err) 3772 } 3773 3774 // Do not execute the first schema change so that the second schema 3775 // change gets queued up behind it. The second schema change will be 3776 // given the green signal to execute before the first one. 3777 var wg sync.WaitGroup 3778 wg.Add(2) 3779 notifySchemaChange = make(chan struct{}) 3780 restartSchemaChange = make(chan struct{}) 3781 restart := restartSchemaChange 3782 go func() { 3783 if _, err := sqlDB.Exec(`CREATE UNIQUE INDEX foo ON t.test (v)`); err != nil { 3784 t.Error(err) 3785 } 3786 wg.Done() 3787 }() 3788 3789 <-notifySchemaChange 3790 3791 notifySchemaChange = make(chan struct{}) 3792 restartSchemaChange = make(chan struct{}) 3793 go func() { 3794 if _, err := sqlDB.Exec(`CREATE UNIQUE INDEX bar ON t.test (v)`); err != nil { 3795 t.Error(err) 3796 } 3797 wg.Done() 3798 }() 3799 3800 <-notifySchemaChange 3801 // Allow second schema change to execute. 3802 close(restartSchemaChange) 3803 3804 // Allow first schema change to execute after a bit. 3805 time.Sleep(time.Millisecond) 3806 close(restart) 3807 3808 // Check that both schema changes have completed. 3809 wg.Wait() 3810 if err := checkTableKeyCount(ctx, kvDB, 3, maxValue); err != nil { 3811 t.Fatal(err) 3812 } 3813 3814 // The notify schema change channel must be nil-ed out, or else 3815 // running scrub will cause it to trigger again on an already closed 3816 // channel when we run another statement. 3817 notifySchemaChange = nil 3818 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3819 t.Fatal(err) 3820 } 3821 } 3822 3823 // Test that a table TRUNCATE leaves the database in the correct state 3824 // for the asynchronous schema changer to eventually execute it. 3825 func TestTruncateInternals(t *testing.T) { 3826 defer leaktest.AfterTest(t)() 3827 const maxValue = 2000 3828 params, _ := tests.CreateTestServerParams() 3829 // Disable schema changes. 3830 blockGC := make(chan struct{}) 3831 params.Knobs = base.TestingKnobs{ 3832 GCJob: &sql.GCJobTestingKnobs{RunBeforeResume: func(_ int64) error { <-blockGC; return nil }}, 3833 } 3834 3835 s, sqlDB, kvDB := serverutils.StartServer(t, params) 3836 ctx := context.Background() 3837 defer s.Stopper().Stop(ctx) 3838 3839 if _, err := sqlDB.Exec(` 3840 CREATE DATABASE t; 3841 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 3842 `); err != nil { 3843 t.Fatal(err) 3844 } 3845 3846 // Bulk insert. 3847 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3848 t.Fatal(err) 3849 } 3850 3851 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 3852 t.Fatal(err) 3853 } 3854 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3855 t.Fatal(err) 3856 } 3857 3858 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3859 3860 // Add a zone config. 3861 cfg := zonepb.DefaultZoneConfig() 3862 buf, err := protoutil.Marshal(&cfg) 3863 if err != nil { 3864 t.Fatal(err) 3865 } 3866 if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, tableDesc.ID, buf); err != nil { 3867 t.Fatal(err) 3868 } 3869 3870 if err := zoneExists(sqlDB, &cfg, tableDesc.ID); err != nil { 3871 t.Fatal(err) 3872 } 3873 3874 if _, err := sqlDB.Exec("TRUNCATE TABLE t.test"); err != nil { 3875 t.Error(err) 3876 } 3877 3878 // Check that SQL thinks the table is empty. 3879 if err := checkTableKeyCount(ctx, kvDB, 0, 0); err != nil { 3880 t.Fatal(err) 3881 } 3882 3883 newTableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3884 if newTableDesc.Adding() { 3885 t.Fatalf("bad state = %s", newTableDesc.State) 3886 } 3887 if err := zoneExists(sqlDB, &cfg, newTableDesc.ID); err != nil { 3888 t.Fatal(err) 3889 } 3890 3891 // Ensure that the table data hasn't been deleted. 3892 tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 3893 tableEnd := tablePrefix.PrefixEnd() 3894 if kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0); err != nil { 3895 t.Fatal(err) 3896 } else if e := maxValue + 1; len(kvs) != e { 3897 t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) 3898 } 3899 // Check that the table descriptor exists so we know the data will 3900 // eventually be deleted. 3901 var droppedDesc *sqlbase.TableDescriptor 3902 if err := kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 3903 var err error 3904 droppedDesc, err = sqlbase.GetTableDescFromID(ctx, txn, keys.SystemSQLCodec, tableDesc.ID) 3905 return err 3906 }); err != nil { 3907 t.Fatal(err) 3908 } 3909 if droppedDesc == nil { 3910 t.Fatalf("table descriptor doesn't exist after table is truncated: %d", tableDesc.ID) 3911 } 3912 if !droppedDesc.Dropped() { 3913 t.Fatalf("bad state = %s", droppedDesc.State) 3914 } 3915 3916 close(blockGC) 3917 3918 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 3919 testutils.SucceedsSoon(t, func() error { 3920 return jobutils.VerifySystemJob(t, sqlRun, 0, jobspb.TypeSchemaChangeGC, jobs.StatusRunning, jobs.Record{ 3921 Description: "GC for TRUNCATE TABLE t.public.test", 3922 Username: security.RootUser, 3923 DescriptorIDs: sqlbase.IDs{tableDesc.ID}, 3924 }) 3925 }) 3926 } 3927 3928 // Test that a table truncation completes properly. 3929 func TestTruncateCompletion(t *testing.T) { 3930 defer leaktest.AfterTest(t)() 3931 const maxValue = 2000 3932 3933 defer setTestJobsAdoptInterval()() 3934 defer gcjob.SetSmallMaxGCIntervalForTest()() 3935 3936 params, _ := tests.CreateTestServerParams() 3937 3938 s, sqlDB, kvDB := serverutils.StartServer(t, params) 3939 ctx := context.Background() 3940 defer s.Stopper().Stop(ctx) 3941 3942 // Disable strict GC TTL enforcement because we're going to shove a zero-value 3943 // TTL into the system with AddImmediateGCZoneConfig. 3944 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 3945 3946 if _, err := sqlDB.Exec(` 3947 CREATE DATABASE t; 3948 CREATE TABLE t.pi (d DECIMAL PRIMARY KEY); 3949 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL REFERENCES t.pi (d) DEFAULT (DECIMAL '3.14')); 3950 `); err != nil { 3951 t.Fatal(err) 3952 } 3953 3954 if _, err := sqlDB.Exec(`INSERT INTO t.pi VALUES (3.14)`); err != nil { 3955 t.Fatal(err) 3956 } 3957 3958 // Bulk insert. 3959 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3960 t.Fatal(err) 3961 } 3962 3963 if err := checkTableKeyCount(ctx, kvDB, 2, maxValue); err != nil { 3964 t.Fatal(err) 3965 } 3966 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 3967 t.Fatal(err) 3968 } 3969 3970 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 3971 3972 // Add a zone config. 3973 var cfg zonepb.ZoneConfig 3974 cfg, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID) 3975 if err != nil { 3976 t.Fatal(err) 3977 } 3978 3979 if err := zoneExists(sqlDB, &cfg, tableDesc.ID); err != nil { 3980 t.Fatal(err) 3981 } 3982 3983 if _, err := sqlDB.Exec("TRUNCATE TABLE t.test"); err != nil { 3984 t.Error(err) 3985 } 3986 3987 // Check that SQL thinks the table is empty. 3988 if err := checkTableKeyCount(ctx, kvDB, 0, 0); err != nil { 3989 t.Fatal(err) 3990 } 3991 3992 // Bulk insert. 3993 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 3994 t.Fatal(err) 3995 } 3996 3997 if err := checkTableKeyCount(ctx, kvDB, 2, maxValue); err != nil { 3998 t.Fatal(err) 3999 } 4000 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 4001 t.Fatal(err) 4002 } 4003 4004 // Ensure that the FK property still holds. 4005 if _, err := sqlDB.Exec( 4006 `INSERT INTO t.test VALUES ($1 , $2, $3)`, maxValue+2, maxValue+2, 3.15, 4007 ); !testutils.IsError(err, "foreign key violation|violates foreign key") { 4008 t.Fatalf("err = %v", err) 4009 } 4010 4011 newTableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4012 if newTableDesc.Adding() { 4013 t.Fatalf("bad state = %s", newTableDesc.State) 4014 } 4015 if err := zoneExists(sqlDB, &cfg, newTableDesc.ID); err != nil { 4016 t.Fatal(err) 4017 } 4018 4019 // Wait until the older descriptor has been deleted. 4020 testutils.SucceedsSoon(t, func() error { 4021 if err := kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 4022 var err error 4023 _, err = sqlbase.GetTableDescFromID(ctx, txn, keys.SystemSQLCodec, tableDesc.ID) 4024 return err 4025 }); err != nil { 4026 if errors.Is(err, sqlbase.ErrDescriptorNotFound) { 4027 return nil 4028 } 4029 return err 4030 } 4031 return errors.Errorf("table descriptor exists after table is truncated: %d", tableDesc.ID) 4032 }) 4033 4034 if err := zoneExists(sqlDB, nil, tableDesc.ID); err != nil { 4035 t.Fatal(err) 4036 } 4037 4038 // Ensure that the table data has been deleted. 4039 tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 4040 tableEnd := tablePrefix.PrefixEnd() 4041 if kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0); err != nil { 4042 t.Fatal(err) 4043 } else if e := 0; len(kvs) != e { 4044 t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) 4045 } 4046 4047 fkTableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "pi") 4048 tablePrefix = keys.SystemSQLCodec.TablePrefix(uint32(fkTableDesc.ID)) 4049 tableEnd = tablePrefix.PrefixEnd() 4050 if kvs, err := kvDB.Scan(ctx, tablePrefix, tableEnd, 0); err != nil { 4051 t.Fatal(err) 4052 } else if e := 1; len(kvs) != e { 4053 t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) 4054 } 4055 4056 // Ensure that the job is marked as succeeded. 4057 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 4058 4059 // TODO (lucy): This test API should use an offset starting from the 4060 // most recent job instead. 4061 schemaChangeJobOffset := 0 4062 if err := jobutils.VerifySystemJob(t, sqlRun, schemaChangeJobOffset+2, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 4063 Username: security.RootUser, 4064 Description: "TRUNCATE TABLE t.public.test", 4065 DescriptorIDs: sqlbase.IDs{ 4066 tableDesc.ID, 4067 }, 4068 }); err != nil { 4069 t.Fatal(err) 4070 } 4071 } 4072 4073 // Test TRUNCATE during a column backfill. 4074 func TestTruncateWhileColumnBackfill(t *testing.T) { 4075 defer leaktest.AfterTest(t)() 4076 4077 t.Skip("https://github.com/cockroachdb/cockroach/issues/43990") 4078 4079 backfillNotification := make(chan struct{}) 4080 backfillCount := int64(0) 4081 params, _ := tests.CreateTestServerParams() 4082 params.Knobs = base.TestingKnobs{ 4083 // Runs schema changes asynchronously. 4084 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4085 // TODO (lucy): if/when this test gets reinstated, figure out what knobs are 4086 // needed. 4087 }, 4088 DistSQL: &execinfra.TestingKnobs{ 4089 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 4090 switch atomic.LoadInt64(&backfillCount) { 4091 case 3: 4092 // Notify in the middle of a backfill. 4093 if backfillNotification != nil { 4094 close(backfillNotification) 4095 backfillNotification = nil 4096 } 4097 // Never complete the backfill. 4098 return context.DeadlineExceeded 4099 default: 4100 atomic.AddInt64(&backfillCount, 1) 4101 } 4102 return nil 4103 }, 4104 }, 4105 } 4106 s, sqlDB, kvDB := serverutils.StartServer(t, params) 4107 defer s.Stopper().Stop(context.Background()) 4108 4109 if _, err := sqlDB.Exec(` 4110 CREATE DATABASE t; 4111 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4112 `); err != nil { 4113 t.Fatal(err) 4114 } 4115 4116 // Bulk insert. 4117 const maxValue = 5000 4118 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 4119 t.Fatal(err) 4120 } 4121 4122 notify := backfillNotification 4123 4124 const add_column = `ALTER TABLE t.public.test ADD COLUMN x DECIMAL NOT NULL DEFAULT 1.4::DECIMAL, ADD CHECK (x >= 0)` 4125 if _, err := sqlDB.Exec(add_column); err != nil { 4126 t.Fatal(err) 4127 } 4128 4129 const drop_column = `ALTER TABLE t.public.test DROP COLUMN v` 4130 if _, err := sqlDB.Exec(drop_column); err != nil { 4131 t.Fatal(err) 4132 } 4133 4134 // Check that an outstanding schema change exists. 4135 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4136 oldID := tableDesc.ID 4137 if lenMutations := len(tableDesc.Mutations); lenMutations != 3 { 4138 t.Fatalf("%d outstanding schema change", lenMutations) 4139 } 4140 4141 // Run TRUNCATE. 4142 var wg sync.WaitGroup 4143 wg.Add(1) 4144 go func() { 4145 <-notify 4146 if _, err := sqlDB.Exec("TRUNCATE TABLE t.test"); err != nil { 4147 t.Error(err) 4148 } 4149 wg.Done() 4150 }() 4151 wg.Wait() 4152 4153 // The new table is truncated. 4154 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4155 tablePrefix := keys.SystemSQLCodec.TablePrefix(uint32(tableDesc.ID)) 4156 tableEnd := tablePrefix.PrefixEnd() 4157 if kvs, err := kvDB.Scan(context.Background(), tablePrefix, tableEnd, 0); err != nil { 4158 t.Fatal(err) 4159 } else if e := 0; len(kvs) != e { 4160 t.Fatalf("expected %d key value pairs, but got %d", e, len(kvs)) 4161 } 4162 4163 // Col "x" is public and col "v" is dropped. 4164 if num := len(tableDesc.Mutations); num > 0 { 4165 t.Fatalf("%d outstanding mutation", num) 4166 } 4167 if lenCols := len(tableDesc.Columns); lenCols != 2 { 4168 t.Fatalf("%d columns", lenCols) 4169 } 4170 if k, x := tableDesc.Columns[0].Name, tableDesc.Columns[1].Name; k != "k" && x != "x" { 4171 t.Fatalf("columns %q, %q in descriptor", k, x) 4172 } 4173 if checks := tableDesc.AllActiveAndInactiveChecks(); len(checks) != 1 { 4174 t.Fatalf("expected 1 check, found %d", len(checks)) 4175 } 4176 4177 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 4178 if err := jobutils.VerifySystemJob(t, sqlRun, 0, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 4179 Username: security.RootUser, 4180 Description: add_column, 4181 DescriptorIDs: sqlbase.IDs{ 4182 oldID, 4183 }, 4184 }); err != nil { 4185 t.Fatal(err) 4186 } 4187 if err := jobutils.VerifySystemJob(t, sqlRun, 1, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 4188 Username: security.RootUser, 4189 Description: drop_column, 4190 DescriptorIDs: sqlbase.IDs{ 4191 oldID, 4192 }, 4193 }); err != nil { 4194 t.Fatal(err) 4195 } 4196 } 4197 4198 // Test that, when DDL statements are run in a transaction, their errors are 4199 // received as the results of the commit statement. 4200 func TestSchemaChangeErrorOnCommit(t *testing.T) { 4201 defer leaktest.AfterTest(t)() 4202 params, _ := tests.CreateTestServerParams() 4203 s, sqlDB, _ := serverutils.StartServer(t, params) 4204 defer s.Stopper().Stop(context.Background()) 4205 4206 if _, err := sqlDB.Exec(` 4207 CREATE DATABASE t; 4208 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4209 INSERT INTO t.test (k, v) VALUES (1, 99), (2, 99); 4210 `); err != nil { 4211 t.Fatal(err) 4212 } 4213 4214 tx, err := sqlDB.Begin() 4215 if err != nil { 4216 t.Fatal(err) 4217 } 4218 4219 // This schema change is invalid because of the duplicate v, but its error is 4220 // only reported later. 4221 if _, err := tx.Exec("ALTER TABLE t.test ADD CONSTRAINT v_unique UNIQUE (v)"); err != nil { 4222 t.Fatal(err) 4223 } 4224 4225 if err := tx.Commit(); !testutils.IsError( 4226 err, `duplicate key value`, 4227 ) { 4228 t.Fatal(err) 4229 } 4230 } 4231 4232 // TestIndexBackfillAfterGC verifies that if a GC is done after an index 4233 // backfill has started, it will move past the error and complete. 4234 func TestIndexBackfillAfterGC(t *testing.T) { 4235 defer leaktest.AfterTest(t)() 4236 4237 // Decrease the adopt loop interval so that retries happen quickly. 4238 defer setTestJobsAdoptInterval()() 4239 4240 var tc serverutils.TestClusterInterface 4241 ctx := context.Background() 4242 runGC := func(sp roachpb.Span) error { 4243 if tc == nil { 4244 return nil 4245 } 4246 gcr := roachpb.GCRequest{ 4247 RequestHeader: roachpb.RequestHeaderFromSpan(sp), 4248 Threshold: tc.Server(0).Clock().Now(), 4249 } 4250 _, err := kv.SendWrapped(ctx, tc.Server(0).DistSenderI().(*kvcoord.DistSender), &gcr) 4251 if err != nil { 4252 panic(err) 4253 } 4254 return nil 4255 } 4256 4257 params, _ := tests.CreateTestServerParams() 4258 params.Knobs = base.TestingKnobs{ 4259 DistSQL: &execinfra.TestingKnobs{ 4260 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 4261 if fn := runGC; fn != nil { 4262 runGC = nil 4263 return fn(sp) 4264 } 4265 return nil 4266 }, 4267 }, 4268 } 4269 4270 tc = serverutils.StartTestCluster(t, 1, base.TestClusterArgs{ServerArgs: params}) 4271 defer tc.Stopper().Stop(context.Background()) 4272 db := tc.ServerConn(0) 4273 kvDB := tc.Server(0).DB() 4274 sqlDB := sqlutils.MakeSQLRunner(db) 4275 4276 sqlDB.Exec(t, `CREATE DATABASE t`) 4277 sqlDB.Exec(t, `CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14'))`) 4278 sqlDB.Exec(t, `INSERT INTO t.test VALUES (1, 1)`) 4279 if _, err := db.Exec(`CREATE UNIQUE INDEX foo ON t.test (v)`); err != nil { 4280 t.Fatal(err) 4281 } 4282 4283 if err := checkTableKeyCount(context.Background(), kvDB, 2, 0); err != nil { 4284 t.Fatal(err) 4285 } 4286 } 4287 4288 // TestAddComputedColumn verifies that while a column backfill is happening 4289 // for a computed column, INSERTs and UPDATEs for that column are correct. 4290 func TestAddComputedColumn(t *testing.T) { 4291 defer leaktest.AfterTest(t)() 4292 4293 var db *gosql.DB 4294 done := false 4295 params, _ := tests.CreateTestServerParams() 4296 params.Knobs = base.TestingKnobs{ 4297 DistSQL: &execinfra.TestingKnobs{ 4298 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 4299 if db == nil || done { 4300 return nil 4301 } 4302 done = true 4303 if _, err := db.Exec(`INSERT INTO t.test VALUES (10)`); err != nil { 4304 panic(err) 4305 } 4306 if _, err := db.Exec(`UPDATE t.test SET a = a + 1 WHERE a < 10`); err != nil { 4307 panic(err) 4308 } 4309 return nil 4310 }, 4311 }, 4312 } 4313 4314 tc := serverutils.StartTestCluster(t, 1, base.TestClusterArgs{ServerArgs: params}) 4315 defer tc.Stopper().Stop(context.Background()) 4316 db = tc.ServerConn(0) 4317 sqlDB := sqlutils.MakeSQLRunner(db) 4318 4319 sqlDB.Exec(t, `CREATE DATABASE t`) 4320 sqlDB.Exec(t, `CREATE TABLE t.test (a INT PRIMARY KEY)`) 4321 sqlDB.Exec(t, `INSERT INTO t.test VALUES (1)`) 4322 sqlDB.Exec(t, `ALTER TABLE t.test ADD COLUMN b INT AS (a + 5) STORED`) 4323 sqlDB.CheckQueryResults(t, `SELECT * FROM t.test ORDER BY a`, [][]string{{"2", "7"}, {"10", "15"}}) 4324 } 4325 4326 func TestSchemaChangeAfterCreateInTxn(t *testing.T) { 4327 defer leaktest.AfterTest(t)() 4328 params, _ := tests.CreateTestServerParams() 4329 s, sqlDB, kvDB := serverutils.StartServer(t, params) 4330 defer s.Stopper().Stop(context.Background()) 4331 4332 // The schema change below can occasionally take more than 4333 // 5 seconds and gets pushed by the closed timestamp mechanism 4334 // in the timestamp cache. Setting the closed timestamp 4335 // target duration to a higher value. 4336 // TODO(vivek): Remove the need to do this by removing the use of 4337 // txn.CommitTimestamp() in schema changes. 4338 if _, err := sqlDB.Exec(` 4339 SET CLUSTER SETTING kv.closed_timestamp.target_duration = '20s' 4340 `); err != nil { 4341 t.Fatal(err) 4342 } 4343 4344 // A large enough value that the backfills run as part of the 4345 // schema change run in many chunks. 4346 var maxValue = 4001 4347 if util.RaceEnabled { 4348 // Race builds are a lot slower, so use a smaller number of rows. 4349 maxValue = 200 4350 } 4351 4352 if _, err := sqlDB.Exec(` 4353 CREATE DATABASE t; 4354 `); err != nil { 4355 t.Fatal(err) 4356 } 4357 4358 tx, err := sqlDB.Begin() 4359 if err != nil { 4360 t.Fatal(err) 4361 } 4362 4363 if _, err := tx.Exec(`CREATE TABLE t.testing (k INT PRIMARY KEY, v INT, INDEX foo(v), CONSTRAINT ck_k CHECK (k >= 0));`); err != nil { 4364 t.Fatal(err) 4365 } 4366 4367 inserts := make([]string, maxValue+1) 4368 for i := 0; i < maxValue+1; i++ { 4369 inserts[i] = fmt.Sprintf(`(%d, %d)`, i, maxValue-i) 4370 } 4371 4372 if _, err := tx.Exec(`INSERT INTO t.testing VALUES ` + strings.Join(inserts, ",")); err != nil { 4373 t.Fatal(err) 4374 } 4375 4376 if _, err := tx.Exec(`ALTER TABLE t.testing RENAME TO t.test`); err != nil { 4377 t.Fatal(err) 4378 } 4379 4380 // Run schema changes that execute Column, Check and Index backfills. 4381 if _, err := tx.Exec(` 4382 ALTER TABLE t.test ADD COLUMN c INT AS (v + 4) STORED, ADD COLUMN d INT DEFAULT 23, ADD CONSTRAINT bar UNIQUE (c), DROP CONSTRAINT ck_k, ADD CONSTRAINT ck_c CHECK (c >= 4) 4383 `); err != nil { 4384 t.Fatal(err) 4385 } 4386 4387 if _, err := tx.Exec(`DROP INDEX t.test@foo`); err != nil { 4388 t.Fatal(err) 4389 } 4390 4391 if err := tx.Commit(); err != nil { 4392 t.Fatal(err) 4393 } 4394 4395 if err := checkTableKeyCount(context.Background(), kvDB, 2, maxValue); err != nil { 4396 t.Fatal(err) 4397 } 4398 4399 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 4400 t.Fatal(err) 4401 } 4402 4403 // Verify that the index bar over is consistent, and that columns c, d 4404 // have been backfilled properly. 4405 rows, err := sqlDB.Query(`SELECT c, d from t.test@bar`) 4406 if err != nil { 4407 t.Fatal(err) 4408 } 4409 defer rows.Close() 4410 4411 count := 0 4412 for ; rows.Next(); count++ { 4413 var c int 4414 var d int 4415 if err := rows.Scan(&c, &d); err != nil { 4416 t.Errorf("row %d scan failed: %s", count, err) 4417 continue 4418 } 4419 if count+4 != c { 4420 t.Errorf("e = %d, v = %d", count, c) 4421 } 4422 if d != 23 { 4423 t.Errorf("e = %d, v = %d", 23, d) 4424 } 4425 } 4426 if err := rows.Err(); err != nil { 4427 t.Fatal(err) 4428 } 4429 eCount := maxValue + 1 4430 if eCount != count { 4431 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 4432 } 4433 4434 // Constraint ck_k dropped, ck_c public. 4435 if _, err := sqlDB.Exec(fmt.Sprintf("INSERT INTO t.test (k, v) VALUES (-1, %d)", maxValue+10)); err != nil { 4436 t.Fatal(err) 4437 } 4438 q := fmt.Sprintf("INSERT INTO t.test (k, v) VALUES (%d, -1)", maxValue+10) 4439 if _, err := sqlDB.Exec(q); !testutils.IsError(err, 4440 `failed to satisfy CHECK constraint \(c >= 4:::INT8\)`) { 4441 t.Fatalf("err = %+v", err) 4442 } 4443 4444 // The descriptor version hasn't changed. 4445 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4446 if tableDesc.Version != 1 { 4447 t.Fatalf("invalid version = %d", tableDesc.Version) 4448 } 4449 } 4450 4451 // TestCancelSchemaChange tests that a CANCEL JOB run midway through column 4452 // and index backfills is canceled. 4453 func TestCancelSchemaChange(t *testing.T) { 4454 defer leaktest.AfterTest(t)() 4455 t.Skip("") 4456 4457 const ( 4458 numNodes = 3 4459 maxValue = 100 4460 ) 4461 4462 var sqlDB *sqlutils.SQLRunner 4463 var db *gosql.DB 4464 params, _ := tests.CreateTestServerParams() 4465 doCancel := false 4466 var enableAsyncSchemaChanges uint32 4467 params.Knobs = base.TestingKnobs{ 4468 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4469 WriteCheckpointInterval: time.Nanosecond, // checkpoint after every chunk. 4470 BackfillChunkSize: 10, 4471 }, 4472 DistSQL: &execinfra.TestingKnobs{ 4473 RunBeforeBackfillChunk: func(sp roachpb.Span) error { 4474 if !doCancel { 4475 return nil 4476 } 4477 if _, err := db.Exec(`CANCEL JOB ( 4478 SELECT job_id FROM [SHOW JOBS] 4479 WHERE 4480 job_type = 'SCHEMA CHANGE' AND 4481 status = $1 AND 4482 description NOT LIKE 'ROLL BACK%' 4483 )`, jobs.StatusRunning); err != nil { 4484 panic(err) 4485 } 4486 return nil 4487 }, 4488 }, 4489 } 4490 4491 tc := serverutils.StartTestCluster(t, numNodes, base.TestClusterArgs{ 4492 ReplicationMode: base.ReplicationManual, 4493 ServerArgs: params, 4494 }) 4495 defer tc.Stopper().Stop(context.Background()) 4496 db = tc.ServerConn(0) 4497 kvDB := tc.Server(0).DB() 4498 sqlDB = sqlutils.MakeSQLRunner(db) 4499 4500 // Disable strict GC TTL enforcement because we're going to shove a zero-value 4501 // TTL into the system with AddImmediateGCZoneConfig. 4502 defer sqltestutils.DisableGCTTLStrictEnforcement(t, db)() 4503 4504 sqlDB.Exec(t, ` 4505 CREATE DATABASE t; 4506 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 4507 `) 4508 4509 // Bulk insert. 4510 if err := bulkInsertIntoTable(db, maxValue); err != nil { 4511 t.Fatal(err) 4512 } 4513 4514 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4515 // Split the table into multiple ranges. 4516 var sps []sql.SplitPoint 4517 const numSplits = numNodes * 2 4518 for i := 1; i <= numSplits-1; i++ { 4519 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i % numNodes, Vals: []interface{}{maxValue / numSplits * i}}) 4520 } 4521 sql.SplitTable(t, tc, tableDesc, sps) 4522 4523 ctx := context.Background() 4524 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 4525 t.Fatal(err) 4526 } 4527 4528 testCases := []struct { 4529 sql string 4530 // Set to true if this schema change is to be canceled. 4531 cancel bool 4532 // Set to true if the rollback returns in a running, waiting status. 4533 isGC bool 4534 }{ 4535 {`ALTER TABLE t.public.test ADD COLUMN x DECIMAL DEFAULT 1.4::DECIMAL CREATE FAMILY f2, ADD CHECK (x >= 0)`, 4536 true, false}, 4537 {`CREATE INDEX foo ON t.public.test (v)`, 4538 true, true}, 4539 {`ALTER TABLE t.public.test ADD COLUMN x DECIMAL DEFAULT 1.2::DECIMAL CREATE FAMILY f3, ADD CHECK (x >= 0)`, 4540 false, false}, 4541 {`CREATE INDEX foo ON t.public.test (v)`, 4542 false, true}, 4543 } 4544 4545 idx := 0 4546 for _, tc := range testCases { 4547 doCancel = tc.cancel 4548 if doCancel { 4549 if _, err := db.Exec(tc.sql); !testutils.IsError(err, "job canceled") { 4550 t.Fatalf("unexpected %v", err) 4551 } 4552 if err := jobutils.VerifySystemJob(t, sqlDB, idx, jobspb.TypeSchemaChange, jobs.StatusCanceled, jobs.Record{ 4553 Username: security.RootUser, 4554 Description: tc.sql, 4555 DescriptorIDs: sqlbase.IDs{ 4556 tableDesc.ID, 4557 }, 4558 }); err != nil { 4559 t.Fatal(err) 4560 } 4561 jobID := jobutils.GetJobID(t, sqlDB, idx) 4562 idx++ 4563 jobRecord := jobs.Record{ 4564 Username: security.RootUser, 4565 Description: fmt.Sprintf("ROLL BACK JOB %d: %s", jobID, tc.sql), 4566 DescriptorIDs: sqlbase.IDs{ 4567 tableDesc.ID, 4568 }, 4569 } 4570 var err error 4571 if tc.isGC { 4572 err = jobutils.VerifyRunningSystemJob(t, sqlDB, idx, jobspb.TypeSchemaChange, sql.RunningStatusWaitingGC, jobRecord) 4573 } else { 4574 err = jobutils.VerifySystemJob(t, sqlDB, idx, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobRecord) 4575 } 4576 if err != nil { 4577 t.Fatal(err) 4578 } 4579 } else { 4580 sqlDB.Exec(t, tc.sql) 4581 if err := jobutils.VerifySystemJob(t, sqlDB, idx, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{ 4582 Username: security.RootUser, 4583 Description: tc.sql, 4584 DescriptorIDs: sqlbase.IDs{ 4585 tableDesc.ID, 4586 }, 4587 }); err != nil { 4588 t.Fatal(err) 4589 } 4590 } 4591 idx++ 4592 } 4593 4594 // Verify that the index foo over v is consistent, and that column x has 4595 // been backfilled properly. 4596 rows, err := db.Query(`SELECT v, x from t.test@foo`) 4597 if err != nil { 4598 t.Fatal(err) 4599 } 4600 defer rows.Close() 4601 4602 count := 0 4603 for ; rows.Next(); count++ { 4604 var val int 4605 var x float64 4606 if err := rows.Scan(&val, &x); err != nil { 4607 t.Errorf("row %d scan failed: %s", count, err) 4608 continue 4609 } 4610 if count != val { 4611 t.Errorf("e = %d, v = %d", count, val) 4612 } 4613 if x != 1.2 { 4614 t.Errorf("e = %f, v = %f", 1.2, x) 4615 } 4616 } 4617 if err := rows.Err(); err != nil { 4618 t.Fatal(err) 4619 } 4620 eCount := maxValue + 1 4621 if eCount != count { 4622 t.Fatalf("read the wrong number of rows: e = %d, v = %d", eCount, count) 4623 } 4624 4625 // Verify that the data from the canceled CREATE INDEX is cleaned up. 4626 atomic.StoreUint32(&enableAsyncSchemaChanges, 1) 4627 // TODO (lucy): when this test is no longer canceled, have it correctly handle doing GC immediately 4628 if _, err := sqltestutils.AddImmediateGCZoneConfig(db, tableDesc.ID); err != nil { 4629 t.Fatal(err) 4630 } 4631 testutils.SucceedsSoon(t, func() error { 4632 return checkTableKeyCount(ctx, kvDB, 3, maxValue) 4633 }) 4634 4635 // Check that constraints are cleaned up. 4636 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4637 if checks := tableDesc.AllActiveAndInactiveChecks(); len(checks) != 1 { 4638 t.Fatalf("expected 1 check, found %+v", checks) 4639 } 4640 } 4641 4642 // This test checks that when a transaction containing schema changes 4643 // needs to be retried it gets retried internal to cockroach. This test 4644 // currently fails because a schema changeg transaction is not retried. 4645 func TestSchemaChangeRetryError(t *testing.T) { 4646 defer leaktest.AfterTest(t)() 4647 const numNodes = 3 4648 4649 params, _ := tests.CreateTestServerParams() 4650 4651 tc := serverutils.StartTestCluster(t, numNodes, 4652 base.TestClusterArgs{ 4653 ReplicationMode: base.ReplicationManual, 4654 ServerArgs: params, 4655 }) 4656 defer tc.Stopper().Stop(context.Background()) 4657 sqlDB := tc.ServerConn(0) 4658 4659 if _, err := sqlDB.Exec(` 4660 CREATE DATABASE t; 4661 CREATE TABLE t.test (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 4662 `); err != nil { 4663 t.Fatal(err) 4664 } 4665 4666 tx, err := sqlDB.Begin() 4667 if err != nil { 4668 t.Fatal(err) 4669 } 4670 4671 // The timestamp of the transaction is guaranteed to be fixed after 4672 // this statement. 4673 if _, err := tx.Exec(` 4674 CREATE TABLE t.another (k INT PRIMARY KEY, v INT, pi DECIMAL DEFAULT (DECIMAL '3.14')); 4675 `); err != nil { 4676 t.Fatal(err) 4677 } 4678 4679 otherSQLDB := tc.ServerConn(1) 4680 4681 // Read schema on another node that picks a later timestamp. 4682 rows, err := otherSQLDB.Query("SELECT * FROM t.test") 4683 if err != nil { 4684 t.Fatal(err) 4685 } 4686 rows.Close() 4687 4688 if _, err := tx.Exec(` 4689 CREATE UNIQUE INDEX vidx ON t.test (v); 4690 `); err != nil { 4691 t.Fatal(err) 4692 } 4693 4694 // The transaction should get pushed and commit without an error. 4695 if err := tx.Commit(); err != nil { 4696 t.Fatal(err) 4697 } 4698 } 4699 4700 // TestCancelSchemaChangeContext tests that a canceled context on 4701 // the session with a schema change after the schema change transaction 4702 // has committed will not indefinitely retry executing the post schema 4703 // execution transactions using a canceled context. The schema 4704 // change will give up and ultimately be executed to completion through 4705 // the asynchronous schema changer. 4706 func TestCancelSchemaChangeContext(t *testing.T) { 4707 defer leaktest.AfterTest(t)() 4708 4709 const maxValue = 100 4710 notifyBackfill := make(chan struct{}) 4711 cancelSessionDone := make(chan struct{}) 4712 4713 params, _ := tests.CreateTestServerParams() 4714 params.Knobs = base.TestingKnobs{ 4715 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4716 RunBeforeBackfill: func() error { 4717 if notify := notifyBackfill; notify != nil { 4718 notifyBackfill = nil 4719 close(notify) 4720 <-cancelSessionDone 4721 } 4722 return nil 4723 }, 4724 // TODO (lucy): We need an OnError knob so we can verify that we got a 4725 // context cancellation error, but it should be for jobs, not for schema 4726 // changes. For now, don't try to intercept the error. It's sufficient to 4727 // test that the schema change terminates. 4728 }, 4729 } 4730 s, db, kvDB := serverutils.StartServer(t, params) 4731 defer s.Stopper().Stop(context.Background()) 4732 sqlDB := sqlutils.MakeSQLRunner(db) 4733 4734 sqlDB.Exec(t, ` 4735 CREATE DATABASE t; 4736 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4737 `) 4738 4739 // Bulk insert. 4740 if err := bulkInsertIntoTable(db, maxValue); err != nil { 4741 t.Fatal(err) 4742 } 4743 4744 ctx := context.Background() 4745 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 4746 t.Fatal(err) 4747 } 4748 4749 notification := notifyBackfill 4750 4751 var wg sync.WaitGroup 4752 wg.Add(1) 4753 go func() { 4754 defer wg.Done() 4755 ctx := context.Background() 4756 // When using db.Exec(), CANCEL SESSION below will result in the 4757 // database client retrying the request on another connection. 4758 // Use a connection here so when the session gets canceled; a 4759 // connection failure is returned. 4760 // TODO(vivek): It's likely we need to vendor lib/pq#422 and check 4761 // that this is unnecessary. 4762 conn, err := db.Conn(ctx) 4763 if err != nil { 4764 t.Error(err) 4765 } 4766 if _, err := conn.ExecContext( 4767 ctx, `CREATE INDEX foo ON t.public.test (v)`); !errors.Is(err, driver.ErrBadConn) { 4768 t.Errorf("unexpected err = %+v", err) 4769 } 4770 }() 4771 4772 <-notification 4773 4774 if _, err := db.Exec(` 4775 CANCEL SESSIONS (SELECT session_id FROM [SHOW SESSIONS] WHERE last_active_query LIKE 'CREATE INDEX%') 4776 `); err != nil { 4777 t.Error(err) 4778 } 4779 4780 close(cancelSessionDone) 4781 4782 wg.Wait() 4783 } 4784 4785 func TestSchemaChangeGRPCError(t *testing.T) { 4786 defer leaktest.AfterTest(t)() 4787 4788 defer setTestJobsAdoptInterval()() 4789 4790 const maxValue = 100 4791 params, _ := tests.CreateTestServerParams() 4792 seenNodeUnavailable := false 4793 params.Knobs = base.TestingKnobs{ 4794 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4795 RunBeforeBackfill: func() error { 4796 if !seenNodeUnavailable { 4797 seenNodeUnavailable = true 4798 return errors.Errorf("node unavailable") 4799 } 4800 return nil 4801 }, 4802 }, 4803 } 4804 s, db, kvDB := serverutils.StartServer(t, params) 4805 defer s.Stopper().Stop(context.Background()) 4806 sqlDB := sqlutils.MakeSQLRunner(db) 4807 4808 sqlDB.Exec(t, ` 4809 CREATE DATABASE t; 4810 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4811 `) 4812 4813 // Bulk insert. 4814 if err := bulkInsertIntoTable(db, maxValue); err != nil { 4815 t.Fatal(err) 4816 } 4817 4818 ctx := context.Background() 4819 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 4820 t.Fatal(err) 4821 } 4822 4823 if _, err := db.Exec(`CREATE INDEX foo ON t.public.test (v)`); err != nil { 4824 t.Fatal(err) 4825 } 4826 4827 if err := checkTableKeyCount(ctx, kvDB, 2, maxValue); err != nil { 4828 t.Fatal(err) 4829 } 4830 } 4831 4832 // TestBlockedSchemaChange tests whether a schema change that 4833 // has no data backfill processing will be blocked by a schema 4834 // change that is holding the schema change lease while backfill 4835 // processing. 4836 func TestBlockedSchemaChange(t *testing.T) { 4837 defer leaktest.AfterTest(t)() 4838 4839 const maxValue = 100 4840 notifyBackfill := make(chan struct{}) 4841 tableRenameDone := make(chan struct{}) 4842 4843 params, _ := tests.CreateTestServerParams() 4844 params.Knobs = base.TestingKnobs{ 4845 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4846 RunBeforeBackfill: func() error { 4847 if notify := notifyBackfill; notify != nil { 4848 notifyBackfill = nil 4849 close(notify) 4850 <-tableRenameDone 4851 } 4852 return nil 4853 }, 4854 }, 4855 } 4856 s, db, kvDB := serverutils.StartServer(t, params) 4857 defer s.Stopper().Stop(context.Background()) 4858 sqlDB := sqlutils.MakeSQLRunner(db) 4859 4860 sqlDB.Exec(t, ` 4861 CREATE DATABASE t; 4862 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4863 `) 4864 4865 // Bulk insert. 4866 if err := bulkInsertIntoTable(db, maxValue); err != nil { 4867 t.Fatal(err) 4868 } 4869 4870 ctx := context.Background() 4871 if err := checkTableKeyCount(ctx, kvDB, 1, maxValue); err != nil { 4872 t.Fatal(err) 4873 } 4874 4875 notification := notifyBackfill 4876 4877 var wg sync.WaitGroup 4878 wg.Add(1) 4879 go func() { 4880 defer wg.Done() 4881 if _, err := db.Exec(`CREATE INDEX foo ON t.public.test (v)`); err != nil { 4882 t.Error(err) 4883 } 4884 }() 4885 4886 <-notification 4887 4888 if _, err := db.Exec(`ALTER TABLE t.test RENAME TO t.newtest`); err != nil { 4889 t.Fatal(err) 4890 } 4891 4892 close(tableRenameDone) 4893 4894 if _, err := db.Query(`SELECT x from t.test`); !testutils.IsError(err, `relation "t.test" does not exist`) { 4895 t.Fatalf("err = %+v", err) 4896 } 4897 4898 wg.Wait() 4899 } 4900 4901 // Tests index backfill validation step by purposely deleting an index 4902 // value during the index backfill and checking that the validation 4903 // fails. 4904 func TestIndexBackfillValidation(t *testing.T) { 4905 defer leaktest.AfterTest(t)() 4906 params, _ := tests.CreateTestServerParams() 4907 const maxValue = 1000 4908 backfillCount := int64(0) 4909 var db *kv.DB 4910 var tableDesc *sqlbase.TableDescriptor 4911 params.Knobs = base.TestingKnobs{ 4912 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4913 BackfillChunkSize: maxValue / 5, 4914 }, 4915 DistSQL: &execinfra.TestingKnobs{ 4916 RunAfterBackfillChunk: func() { 4917 count := atomic.AddInt64(&backfillCount, 1) 4918 if count == 2 { 4919 // drop an index value before validation. 4920 key := keys.SystemSQLCodec.IndexPrefix(uint32(tableDesc.ID), uint32(tableDesc.NextIndexID)) 4921 kv, err := db.Scan(context.Background(), key, key.PrefixEnd(), 1) 4922 if err != nil { 4923 t.Error(err) 4924 } 4925 if err := db.Del(context.Background(), kv[0].Key); err != nil { 4926 t.Error(err) 4927 } 4928 } 4929 }, 4930 }, 4931 // Disable backfill migrations, we still need the jobs table migration. 4932 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 4933 DisableBackfillMigrations: true, 4934 }, 4935 } 4936 server, sqlDB, kvDB := serverutils.StartServer(t, params) 4937 db = kvDB 4938 defer server.Stopper().Stop(context.Background()) 4939 4940 if _, err := sqlDB.Exec(` 4941 CREATE DATABASE t; 4942 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 4943 `); err != nil { 4944 t.Fatal(err) 4945 } 4946 4947 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4948 4949 // Bulk insert enough rows to exceed the chunk size. 4950 inserts := make([]string, maxValue+1) 4951 for i := 0; i < maxValue+1; i++ { 4952 inserts[i] = fmt.Sprintf(`(%d, %d)`, i, i) 4953 } 4954 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ` + strings.Join(inserts, ",")); err != nil { 4955 t.Fatal(err) 4956 } 4957 4958 // Start schema change that eventually runs a backfill. 4959 if _, err := sqlDB.Exec(`CREATE UNIQUE INDEX foo ON t.test (v)`); !testutils.IsError( 4960 err, fmt.Sprintf("%d entries, expected %d violates unique constraint", maxValue, maxValue+1), 4961 ) { 4962 t.Fatal(err) 4963 } 4964 4965 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 4966 if len(tableDesc.Indexes) > 0 || len(tableDesc.Mutations) > 0 { 4967 t.Fatalf("descriptor broken %d, %d", len(tableDesc.Indexes), len(tableDesc.Mutations)) 4968 } 4969 } 4970 4971 // Tests inverted index backfill validation step by purposely deleting an index 4972 // value during the index backfill and checking that the validation fails. 4973 func TestInvertedIndexBackfillValidation(t *testing.T) { 4974 defer leaktest.AfterTest(t)() 4975 params, _ := tests.CreateTestServerParams() 4976 const maxValue = 1000 4977 backfillCount := int64(0) 4978 var db *kv.DB 4979 var tableDesc *sqlbase.TableDescriptor 4980 params.Knobs = base.TestingKnobs{ 4981 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 4982 BackfillChunkSize: maxValue / 5, 4983 }, 4984 DistSQL: &execinfra.TestingKnobs{ 4985 RunAfterBackfillChunk: func() { 4986 count := atomic.AddInt64(&backfillCount, 1) 4987 if count == 2 { 4988 // drop an index value before validation. 4989 key := keys.SystemSQLCodec.IndexPrefix(uint32(tableDesc.ID), uint32(tableDesc.NextIndexID)) 4990 kv, err := db.Scan(context.Background(), key, key.PrefixEnd(), 1) 4991 if err != nil { 4992 t.Error(err) 4993 } 4994 if err := db.Del(context.Background(), kv[0].Key); err != nil { 4995 t.Error(err) 4996 } 4997 } 4998 }, 4999 }, 5000 // Disable backfill migrations, we still need the jobs table migration. 5001 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5002 DisableBackfillMigrations: true, 5003 }, 5004 } 5005 server, sqlDB, kvDB := serverutils.StartServer(t, params) 5006 db = kvDB 5007 defer server.Stopper().Stop(context.Background()) 5008 5009 if _, err := sqlDB.Exec(` 5010 CREATE DATABASE t; 5011 CREATE TABLE t.test (k INT PRIMARY KEY, v JSON); 5012 `); err != nil { 5013 t.Fatal(err) 5014 } 5015 5016 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5017 5018 r := rand.New(rand.NewSource(timeutil.Now().UnixNano())) 5019 // Insert enough rows to exceed the chunk size. 5020 for i := 0; i < maxValue+1; i++ { 5021 jsonVal, err := json.Random(20, r) 5022 if err != nil { 5023 t.Fatal(err) 5024 } 5025 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ($1, $2)`, i, jsonVal.String()); err != nil { 5026 t.Fatal(err) 5027 } 5028 } 5029 5030 // Start schema change that eventually runs a backfill. 5031 if _, err := sqlDB.Exec(`CREATE INVERTED INDEX foo ON t.test (v)`); !testutils.IsError( 5032 err, "validation of index foo failed", 5033 ) { 5034 t.Fatal(err) 5035 } 5036 5037 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5038 if len(tableDesc.Indexes) > 0 || len(tableDesc.Mutations) > 0 { 5039 t.Fatalf("descriptor broken %d, %d", len(tableDesc.Indexes), len(tableDesc.Mutations)) 5040 } 5041 } 5042 5043 // Test multiple index backfills (for forward and inverted indexes) from the 5044 // same transaction. 5045 func TestMultipleIndexBackfills(t *testing.T) { 5046 defer leaktest.AfterTest(t)() 5047 params, _ := tests.CreateTestServerParams() 5048 const maxValue = 1000 5049 params.Knobs = base.TestingKnobs{ 5050 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5051 BackfillChunkSize: maxValue / 5, 5052 }, 5053 // Disable backfill migrations, we still need the jobs table migration. 5054 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5055 DisableBackfillMigrations: true, 5056 }, 5057 } 5058 server, sqlDB, _ := serverutils.StartServer(t, params) 5059 defer server.Stopper().Stop(context.Background()) 5060 5061 if _, err := sqlDB.Exec(` 5062 CREATE DATABASE t; 5063 CREATE TABLE t.test (a INT, b INT, c JSON, d JSON); 5064 `); err != nil { 5065 t.Fatal(err) 5066 } 5067 5068 r := rand.New(rand.NewSource(timeutil.Now().UnixNano())) 5069 // Insert enough rows to exceed the chunk size. 5070 for i := 0; i < maxValue+1; i++ { 5071 jsonVal1, err := json.Random(20, r) 5072 if err != nil { 5073 t.Fatal(err) 5074 } 5075 jsonVal2, err := json.Random(20, r) 5076 if err != nil { 5077 t.Fatal(err) 5078 } 5079 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES ($1, $2, $3, $4)`, i, i, jsonVal1.String(), jsonVal2.String()); err != nil { 5080 t.Fatal(err) 5081 } 5082 } 5083 5084 // Start schema changes. 5085 tx, err := sqlDB.Begin() 5086 if err != nil { 5087 t.Fatal(err) 5088 } 5089 if _, err := tx.Exec(`CREATE INDEX idx_a ON t.test (a)`); err != nil { 5090 t.Fatal(err) 5091 } 5092 if _, err := tx.Exec(`CREATE INDEX idx_b ON t.test (b)`); err != nil { 5093 t.Fatal(err) 5094 } 5095 if _, err := tx.Exec(`CREATE INVERTED INDEX idx_c ON t.test (c)`); err != nil { 5096 t.Fatal(err) 5097 } 5098 if _, err := tx.Exec(`CREATE INVERTED INDEX idx_d ON t.test (d)`); err != nil { 5099 t.Fatal(err) 5100 } 5101 if err := tx.Commit(); err != nil { 5102 t.Fatal(err) 5103 } 5104 } 5105 5106 func TestCreateStatsAfterSchemaChange(t *testing.T) { 5107 defer leaktest.AfterTest(t)() 5108 5109 defer func(oldRefreshInterval, oldAsOf time.Duration) { 5110 stats.DefaultRefreshInterval = oldRefreshInterval 5111 stats.DefaultAsOfTime = oldAsOf 5112 }(stats.DefaultRefreshInterval, stats.DefaultAsOfTime) 5113 stats.DefaultRefreshInterval = time.Millisecond 5114 stats.DefaultAsOfTime = time.Microsecond 5115 5116 server, sqlDB, _ := serverutils.StartServer(t, base.TestServerArgs{}) 5117 defer server.Stopper().Stop(context.Background()) 5118 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 5119 5120 sqlRun.Exec(t, `SET CLUSTER SETTING sql.stats.automatic_collection.enabled=false`) 5121 5122 sqlRun.Exec(t, ` 5123 CREATE DATABASE t; 5124 CREATE TABLE t.test (k INT PRIMARY KEY, v CHAR, w CHAR);`) 5125 5126 sqlRun.Exec(t, `SET CLUSTER SETTING sql.stats.automatic_collection.enabled=true`) 5127 5128 // Add an index. 5129 sqlRun.Exec(t, `CREATE INDEX foo ON t.test (w)`) 5130 5131 // Verify that statistics have been created for the new index (note that 5132 // column w is ordered before column v, since index columns are added first). 5133 sqlRun.CheckQueryResultsRetry(t, 5134 `SELECT statistics_name, column_names, row_count, distinct_count, null_count 5135 FROM [SHOW STATISTICS FOR TABLE t.test]`, 5136 [][]string{ 5137 {"__auto__", "{k}", "0", "0", "0"}, 5138 {"__auto__", "{w}", "0", "0", "0"}, 5139 {"__auto__", "{v}", "0", "0", "0"}, 5140 }) 5141 5142 // Add a column. 5143 sqlRun.Exec(t, `ALTER TABLE t.test ADD COLUMN x INT`) 5144 5145 // Verify that statistics have been created for the new column. 5146 sqlRun.CheckQueryResultsRetry(t, 5147 `SELECT statistics_name, column_names, row_count, distinct_count, null_count 5148 FROM [SHOW STATISTICS FOR TABLE t.test] ORDER BY column_names::STRING`, 5149 [][]string{ 5150 {"__auto__", "{k}", "0", "0", "0"}, 5151 {"__auto__", "{k}", "0", "0", "0"}, 5152 {"__auto__", "{v}", "0", "0", "0"}, 5153 {"__auto__", "{v}", "0", "0", "0"}, 5154 {"__auto__", "{w}", "0", "0", "0"}, 5155 {"__auto__", "{w}", "0", "0", "0"}, 5156 {"__auto__", "{x}", "0", "0", "0"}, 5157 }) 5158 } 5159 5160 func TestTableValidityWhileAddingFK(t *testing.T) { 5161 defer leaktest.AfterTest(t)() 5162 params, _ := tests.CreateTestServerParams() 5163 5164 publishWriteNotification := make(chan struct{}) 5165 continuePublishWriteNotification := make(chan struct{}) 5166 5167 backfillNotification := make(chan struct{}) 5168 continueBackfillNotification := make(chan struct{}) 5169 5170 params.Knobs = base.TestingKnobs{ 5171 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5172 RunBeforePublishWriteAndDelete: func() { 5173 if publishWriteNotification != nil { 5174 // Notify before the delete and write only state is published. 5175 close(publishWriteNotification) 5176 publishWriteNotification = nil 5177 <-continuePublishWriteNotification 5178 } 5179 }, 5180 RunBeforeBackfill: func() error { 5181 if backfillNotification != nil { 5182 // Notify before the backfill begins. 5183 close(backfillNotification) 5184 backfillNotification = nil 5185 <-continueBackfillNotification 5186 } 5187 return nil 5188 }, 5189 }, 5190 // Disable backfill migrations, we still need the jobs table migration. 5191 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5192 DisableBackfillMigrations: true, 5193 }, 5194 } 5195 5196 server, sqlDB, _ := serverutils.StartServer(t, params) 5197 defer server.Stopper().Stop(context.Background()) 5198 5199 if _, err := sqlDB.Exec(` 5200 CREATE DATABASE t; 5201 CREATE TABLE t.child (a INT PRIMARY KEY, b INT, INDEX (b)); 5202 CREATE TABLE t.parent (a INT PRIMARY KEY); 5203 `); err != nil { 5204 t.Fatal(err) 5205 } 5206 5207 n1 := publishWriteNotification 5208 n2 := backfillNotification 5209 var wg sync.WaitGroup 5210 wg.Add(1) 5211 go func() { 5212 if _, err := sqlDB.Exec(`ALTER TABLE t.child ADD FOREIGN KEY (b) REFERENCES t.child (a), ADD FOREIGN KEY (a) REFERENCES t.parent (a)`); err != nil { 5213 t.Error(err) 5214 } 5215 wg.Done() 5216 }() 5217 5218 <-n1 5219 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.child`); err != nil { 5220 t.Fatal(err) 5221 } 5222 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.parent`); err != nil { 5223 t.Fatal(err) 5224 } 5225 close(continuePublishWriteNotification) 5226 5227 <-n2 5228 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.child`); err != nil { 5229 t.Fatal(err) 5230 } 5231 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.parent`); err != nil { 5232 t.Fatal(err) 5233 } 5234 close(continueBackfillNotification) 5235 5236 wg.Wait() 5237 5238 if err := sqlutils.RunScrub(sqlDB, "t", "child"); err != nil { 5239 t.Fatal(err) 5240 } 5241 if err := sqlutils.RunScrub(sqlDB, "t", "parent"); err != nil { 5242 t.Fatal(err) 5243 } 5244 } 5245 5246 // TestWritesWithChecksBeforeDefaultColumnBackfill tests that when a check on a 5247 // column being added references a different public column, writes to the public 5248 // column ignore the constraint before the backfill for the non-public column 5249 // begins. See #35258. 5250 func TestWritesWithChecksBeforeDefaultColumnBackfill(t *testing.T) { 5251 defer leaktest.AfterTest(t)() 5252 params, _ := tests.CreateTestServerParams() 5253 5254 publishWriteNotification := make(chan struct{}) 5255 continuePublishWriteNotification := make(chan struct{}) 5256 5257 backfillNotification := make(chan struct{}) 5258 continueBackfillNotification := make(chan struct{}) 5259 5260 params.Knobs = base.TestingKnobs{ 5261 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5262 RunBeforePublishWriteAndDelete: func() { 5263 if publishWriteNotification != nil { 5264 // Notify before the delete and write only state is published. 5265 close(publishWriteNotification) 5266 publishWriteNotification = nil 5267 <-continuePublishWriteNotification 5268 } 5269 }, 5270 RunBeforeBackfill: func() error { 5271 if backfillNotification != nil { 5272 // Notify before the backfill begins. 5273 close(backfillNotification) 5274 backfillNotification = nil 5275 <-continueBackfillNotification 5276 } 5277 return nil 5278 }, 5279 }, 5280 // Disable backfill migrations, we still need the jobs table migration. 5281 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5282 DisableBackfillMigrations: true, 5283 }, 5284 } 5285 5286 server, sqlDB, _ := serverutils.StartServer(t, params) 5287 defer server.Stopper().Stop(context.Background()) 5288 5289 if _, err := sqlDB.Exec(` 5290 CREATE DATABASE t; 5291 CREATE TABLE t.test ( 5292 k INT PRIMARY KEY NOT NULL, 5293 v INT NOT NULL 5294 ); 5295 `); err != nil { 5296 t.Fatal(err) 5297 } 5298 5299 if err := bulkInsertIntoTable(sqlDB, 1000); err != nil { 5300 t.Fatal(err) 5301 } 5302 5303 n1 := publishWriteNotification 5304 n2 := backfillNotification 5305 var wg sync.WaitGroup 5306 wg.Add(1) 5307 go func() { 5308 _, err := sqlDB.Exec(`ALTER TABLE t.test ADD COLUMN a INT DEFAULT 0, ADD CHECK (a < v AND a IS NOT NULL)`) 5309 if !testutils.IsError(err, `validation of CHECK "\(a < v\) AND \(a IS NOT NULL\)" failed on row: k=1003, v=-1003, a=0`) { 5310 t.Error(err) 5311 } 5312 wg.Done() 5313 }() 5314 5315 <-n1 5316 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1001, 1001)`); err != nil { 5317 t.Fatal(err) 5318 } 5319 if _, err := sqlDB.Exec(`UPDATE t.test SET v = 100 WHERE v < 100`); err != nil { 5320 t.Fatal(err) 5321 } 5322 close(continuePublishWriteNotification) 5323 5324 <-n2 5325 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1002, 1002)`); err != nil { 5326 t.Fatal(err) 5327 } 5328 if _, err := sqlDB.Exec(`UPDATE t.test SET v = 200 WHERE v < 200`); err != nil { 5329 t.Fatal(err) 5330 } 5331 // Final insert violates the constraint 5332 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1003, -1003)`); err != nil { 5333 t.Fatal(err) 5334 } 5335 close(continueBackfillNotification) 5336 5337 wg.Wait() 5338 5339 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 5340 t.Fatal(err) 5341 } 5342 } 5343 5344 // TestWritesWithChecksBeforeComputedColumnBackfill tests that when a check on a 5345 // column being added references a different public column, writes to the public 5346 // column ignore the constraint before the backfill for the non-public column 5347 // begins. See #35258. 5348 func TestWritesWithChecksBeforeComputedColumnBackfill(t *testing.T) { 5349 defer leaktest.AfterTest(t)() 5350 params, _ := tests.CreateTestServerParams() 5351 5352 publishWriteNotification := make(chan struct{}) 5353 continuePublishWriteNotification := make(chan struct{}) 5354 5355 backfillNotification := make(chan struct{}) 5356 continueBackfillNotification := make(chan struct{}) 5357 5358 params.Knobs = base.TestingKnobs{ 5359 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5360 RunBeforePublishWriteAndDelete: func() { 5361 if publishWriteNotification != nil { 5362 // Notify before the delete and write only state is published. 5363 close(publishWriteNotification) 5364 publishWriteNotification = nil 5365 <-continuePublishWriteNotification 5366 } 5367 }, 5368 RunBeforeBackfill: func() error { 5369 if backfillNotification != nil { 5370 // Notify before the backfill begins. 5371 close(backfillNotification) 5372 backfillNotification = nil 5373 <-continueBackfillNotification 5374 } 5375 return nil 5376 }, 5377 }, 5378 // Disable backfill migrations, we still need the jobs table migration. 5379 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5380 DisableBackfillMigrations: true, 5381 }, 5382 } 5383 5384 server, sqlDB, _ := serverutils.StartServer(t, params) 5385 defer server.Stopper().Stop(context.Background()) 5386 5387 if _, err := sqlDB.Exec(` 5388 CREATE DATABASE t; 5389 CREATE TABLE t.test ( 5390 k INT PRIMARY KEY NOT NULL, 5391 v INT NOT NULL 5392 ); 5393 `); err != nil { 5394 t.Fatal(err) 5395 } 5396 5397 if err := bulkInsertIntoTable(sqlDB, 1000); err != nil { 5398 t.Fatal(err) 5399 } 5400 5401 n1 := publishWriteNotification 5402 n2 := backfillNotification 5403 var wg sync.WaitGroup 5404 wg.Add(1) 5405 go func() { 5406 _, err := sqlDB.Exec(`ALTER TABLE t.test ADD COLUMN a INT AS (v - 1) STORED, ADD CHECK (a < v AND a > -1000 AND a IS NOT NULL)`) 5407 if !testutils.IsError(err, `validation of CHECK "\(\(a < v\) AND \(a > \(-1000\):::INT8\)\) AND \(a IS NOT NULL\)" failed on row: k=1003, v=-1003, a=-1004`) { 5408 t.Error(err) 5409 } 5410 wg.Done() 5411 }() 5412 5413 <-n1 5414 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1001, 1001)`); err != nil { 5415 t.Fatal(err) 5416 } 5417 if _, err := sqlDB.Exec(`UPDATE t.test SET v = 100 WHERE v < 100`); err != nil { 5418 t.Fatal(err) 5419 } 5420 close(continuePublishWriteNotification) 5421 5422 <-n2 5423 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1002, 1002)`); err != nil { 5424 t.Fatal(err) 5425 } 5426 if _, err := sqlDB.Exec(`UPDATE t.test SET v = 200 WHERE v < 200`); err != nil { 5427 t.Fatal(err) 5428 } 5429 // Final insert violates the constraint 5430 if _, err := sqlDB.Exec(`INSERT INTO t.test VALUES (1003, -1003)`); err != nil { 5431 t.Fatal(err) 5432 } 5433 close(continueBackfillNotification) 5434 5435 wg.Wait() 5436 5437 if err := sqlutils.RunScrub(sqlDB, "t", "test"); err != nil { 5438 t.Fatal(err) 5439 } 5440 } 5441 5442 // Test schema change backfills are not affected by various operations 5443 // that run simultaneously. 5444 func TestIntentRaceWithIndexBackfill(t *testing.T) { 5445 defer leaktest.AfterTest(t)() 5446 5447 var readyToBackfill, canStartBackfill, backfillProgressing chan struct{} 5448 5449 const numNodes = 1 5450 var maxValue = 2000 5451 5452 params, _ := tests.CreateTestServerParams() 5453 params.Knobs = base.TestingKnobs{ 5454 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5455 BackfillChunkSize: 100, 5456 RunBeforeBackfill: func() error { 5457 select { 5458 case <-readyToBackfill: 5459 default: 5460 close(readyToBackfill) 5461 <-canStartBackfill 5462 } 5463 return nil 5464 }, 5465 }, 5466 DistSQL: &execinfra.TestingKnobs{ 5467 RunAfterBackfillChunk: func() { 5468 select { 5469 case <-backfillProgressing: 5470 default: 5471 close(backfillProgressing) 5472 } 5473 }, 5474 }, 5475 } 5476 5477 tc := serverutils.StartTestCluster(t, numNodes, 5478 base.TestClusterArgs{ 5479 ReplicationMode: base.ReplicationManual, 5480 ServerArgs: params, 5481 }) 5482 defer tc.Stopper().Stop(context.Background()) 5483 kvDB := tc.Server(0).DB() 5484 sqlDB := tc.ServerConn(0) 5485 5486 ctx, cancel := context.WithCancel(context.Background()) 5487 5488 readyToBackfill = make(chan struct{}) 5489 canStartBackfill = make(chan struct{}) 5490 backfillProgressing = make(chan struct{}) 5491 5492 if _, err := sqlDB.Exec(` 5493 CREATE DATABASE t; 5494 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 5495 `); err != nil { 5496 t.Fatal(err) 5497 } 5498 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5499 5500 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 5501 t.Fatal(err) 5502 } 5503 5504 var sps []sql.SplitPoint 5505 for i := 1; i < numNodes-1; i++ { 5506 sps = append(sps, sql.SplitPoint{TargetNodeIdx: i, Vals: []interface{}{maxValue / 2}}) 5507 } 5508 sql.SplitTable(t, tc, tableDesc, sps) 5509 5510 bg := ctxgroup.WithContext(ctx) 5511 bg.Go(func() error { 5512 if _, err := sqlDB.ExecContext(ctx, "CREATE UNIQUE INDEX ON t.test(v)"); err != nil { 5513 cancel() 5514 return err 5515 } 5516 return nil 5517 }) 5518 5519 // Wait until the schema change backfill starts. 5520 select { 5521 case <-readyToBackfill: 5522 case <-ctx.Done(): 5523 } 5524 5525 tx, err := sqlDB.Begin() 5526 if err != nil { 5527 t.Fatal(err) 5528 } 5529 if _, err := tx.Exec(`UPDATE t.test SET v = $2 WHERE k = $1`, maxValue-1, maxValue-1); err != nil { 5530 t.Error(err) 5531 } 5532 if _, err := tx.Exec(`DELETE FROM t.test WHERE k = $1`, maxValue-1); err != nil { 5533 t.Error(err) 5534 } 5535 5536 close(canStartBackfill) 5537 5538 bg.Go(func() error { 5539 // We need to give the schema change time in which it could progress and end 5540 // up writing between our intent and its write before we rollback and the 5541 // intent is cleaned up. At the same time, we need to rollback so that a 5542 // correct schema change -- which waits for any intents -- will eventually 5543 // proceed and not block the test forever. 5544 time.Sleep(50 * time.Millisecond) 5545 return tx.Rollback() 5546 }) 5547 5548 select { 5549 case <-backfillProgressing: 5550 case <-ctx.Done(): 5551 } 5552 5553 rows, err := sqlDB.Query(` 5554 SELECT t.range_id, t.start_key_pretty, t.status, t.detail 5555 FROM 5556 crdb_internal.check_consistency(false, '', '') as t 5557 WHERE t.status NOT IN ('RANGE_CONSISTENT', 'RANGE_INDETERMINATE', 'RANGE_CONSISTENT_STATS_ESTIMATED')`) 5558 if err != nil { 5559 t.Fatal(err) 5560 } 5561 defer rows.Close() 5562 5563 for rows.Next() { 5564 var rangeID int32 5565 var prettyKey, status, detail string 5566 if err := rows.Scan(&rangeID, &prettyKey, &status, &detail); err != nil { 5567 t.Fatal(err) 5568 } 5569 t.Fatalf("r%d (%s) is inconsistent: %s %s", rangeID, prettyKey, status, detail) 5570 } 5571 if err := rows.Err(); err != nil { 5572 t.Fatal(err) 5573 } 5574 5575 if err := bg.Wait(); err != nil { 5576 t.Fatal(err) 5577 } 5578 } 5579 5580 func TestSchemaChangeJobRunningStatusValidation(t *testing.T) { 5581 defer leaktest.AfterTest(t)() 5582 params, _ := tests.CreateTestServerParams() 5583 var runBeforeConstraintValidation func() error 5584 params.Knobs = base.TestingKnobs{ 5585 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5586 RunBeforeConstraintValidation: func() error { 5587 return runBeforeConstraintValidation() 5588 }, 5589 }, 5590 // Disable backfill migrations, we still need the jobs table migration. 5591 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5592 DisableBackfillMigrations: true, 5593 }, 5594 } 5595 s, sqlDB, kvDB := serverutils.StartServer(t, params) 5596 defer s.Stopper().Stop(context.Background()) 5597 if _, err := sqlDB.Exec(` 5598 CREATE DATABASE t; 5599 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 5600 INSERT INTO t.test (k, v) VALUES (1, 99), (2, 100); 5601 `); err != nil { 5602 t.Fatal(err) 5603 } 5604 5605 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5606 5607 sqlRun := sqlutils.MakeSQLRunner(sqlDB) 5608 runBeforeConstraintValidation = func() error { 5609 // TODO (lucy): Maybe this test API should use an offset starting 5610 // from the most recent job instead. 5611 return jobutils.VerifyRunningSystemJob(t, sqlRun, 0, jobspb.TypeSchemaChange, sql.RunningStatusValidation, jobs.Record{ 5612 Username: security.RootUser, 5613 Description: "ALTER TABLE t.public.test ADD COLUMN a INT8 AS (v - 1) STORED, ADD CHECK ((a < v) AND (a IS NOT NULL))", 5614 DescriptorIDs: sqlbase.IDs{ 5615 tableDesc.ID, 5616 }, 5617 }) 5618 } 5619 5620 if _, err := sqlDB.Exec( 5621 `ALTER TABLE t.test ADD COLUMN a INT AS (v - 1) STORED, ADD CHECK (a < v AND a IS NOT NULL)`, 5622 ); err != nil { 5623 t.Fatal(err) 5624 } 5625 } 5626 5627 // TestFKReferencesAddedOnlyOnceOnRetry verifies that if ALTER TABLE ADD FOREIGN 5628 // KEY is retried, both the FK reference and backreference (on another table) 5629 // are only added once. This is addressed by #38377. 5630 func TestFKReferencesAddedOnlyOnceOnRetry(t *testing.T) { 5631 defer leaktest.AfterTest(t)() 5632 5633 defer setTestJobsAdoptInterval()() 5634 params, _ := tests.CreateTestServerParams() 5635 var runBeforeConstraintValidation func() error 5636 errorReturned := false 5637 params.Knobs = base.TestingKnobs{ 5638 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5639 RunBeforeConstraintValidation: func() error { 5640 return runBeforeConstraintValidation() 5641 }, 5642 }, 5643 // Disable backfill migrations, we still need the jobs table migration. 5644 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 5645 DisableBackfillMigrations: true, 5646 }, 5647 } 5648 s, sqlDB, _ := serverutils.StartServer(t, params) 5649 defer s.Stopper().Stop(context.Background()) 5650 if _, err := sqlDB.Exec(` 5651 CREATE DATABASE t; 5652 CREATE TABLE t.test (k INT PRIMARY KEY, v INT); 5653 CREATE TABLE t.test2 (k INT, INDEX (k)); 5654 `); err != nil { 5655 t.Fatal(err) 5656 } 5657 5658 // After FK forward references and backreferences are installed, and before 5659 // the validation query is run, return an error so that the schema change 5660 // has to be retried. The error is only returned on the first try. 5661 runBeforeConstraintValidation = func() error { 5662 if !errorReturned { 5663 errorReturned = true 5664 return context.DeadlineExceeded 5665 5666 } 5667 return nil 5668 } 5669 if _, err := sqlDB.Exec(` 5670 ALTER TABLE t.test2 ADD FOREIGN KEY (k) REFERENCES t.test; 5671 `); err != nil { 5672 t.Fatal(err) 5673 } 5674 5675 // Table descriptor validation failures, resulting from, e.g., broken or 5676 // duplicated backreferences, are returned by SHOW CONSTRAINTS. 5677 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.test`); err != nil { 5678 t.Fatal(err) 5679 } 5680 if _, err := sqlDB.Query(`SHOW CONSTRAINTS FROM t.test2`); err != nil { 5681 t.Fatal(err) 5682 } 5683 } 5684 5685 // TestOrphanedGCMutationsRemoved tests that if a table descriptor has a 5686 // GCMutations which references a job that does not exist anymore, that it will 5687 // eventually be cleaned up anyway. One way this can arise is when a table 5688 // was backed up right after an index deletion. 5689 func TestOrphanedGCMutationsRemoved(t *testing.T) { 5690 defer leaktest.AfterTest(t)() 5691 // TODO (lucy): get rid of this test once GCMutations goes away 5692 t.Skip("") 5693 params, _ := tests.CreateTestServerParams() 5694 const chunkSize = 200 5695 // Disable synchronous schema change processing so that the mutations get 5696 // processed asynchronously. 5697 var enableAsyncSchemaChanges uint32 5698 params.Knobs = base.TestingKnobs{ 5699 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5700 BackfillChunkSize: chunkSize, 5701 }, 5702 } 5703 s, sqlDB, kvDB := serverutils.StartServer(t, params) 5704 defer s.Stopper().Stop(context.Background()) 5705 5706 // Disable strict GC TTL enforcement because we're going to shove a zero-value 5707 // TTL into the system with AddImmediateGCZoneConfig. 5708 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 5709 5710 retryOpts := retry.Options{ 5711 InitialBackoff: 20 * time.Millisecond, 5712 MaxBackoff: 200 * time.Millisecond, 5713 Multiplier: 2, 5714 } 5715 5716 // Create a k-v table. 5717 if _, err := sqlDB.Exec(` 5718 CREATE DATABASE t; 5719 CREATE TABLE t.test (k INT PRIMARY KEY, v INT8); 5720 `); err != nil { 5721 t.Fatal(err) 5722 } 5723 if _, err := sqlDB.Exec(`CREATE INDEX t_v ON t.test(v)`); err != nil { 5724 t.Fatal(err) 5725 } 5726 5727 // Add some data. 5728 const maxValue = chunkSize + 1 5729 if err := bulkInsertIntoTable(sqlDB, maxValue); err != nil { 5730 t.Fatal(err) 5731 } 5732 5733 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5734 // Wait until indexes are created. 5735 for r := retry.Start(retryOpts); r.Next(); { 5736 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5737 if len(tableDesc.Indexes) == 1 { 5738 break 5739 } 5740 } 5741 5742 if _, err := sqlDB.Exec(`DROP INDEX t.t_v`); err != nil { 5743 t.Fatal(err) 5744 } 5745 5746 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5747 if e := 1; e != len(tableDesc.GCMutations) { 5748 t.Fatalf("e = %d, v = %d", e, len(tableDesc.GCMutations)) 5749 } 5750 5751 // Delete the associated job. 5752 jobID := tableDesc.GCMutations[0].JobID 5753 if _, err := sqlDB.Exec(fmt.Sprintf("DELETE FROM system.jobs WHERE id=%d", jobID)); err != nil { 5754 t.Fatal(err) 5755 } 5756 5757 // Ensure the GCMutations has not yet been completed. 5758 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5759 if e := 1; e != len(tableDesc.GCMutations) { 5760 t.Fatalf("e = %d, v = %d", e, len(tableDesc.GCMutations)) 5761 } 5762 5763 // Enable async schema change processing for purged schema changes. 5764 atomic.StoreUint32(&enableAsyncSchemaChanges, 1) 5765 5766 // Add immediate GC TTL to allow index creation purge to complete. 5767 if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil { 5768 t.Fatal(err) 5769 } 5770 5771 // Ensure that GC mutations that cannot find their job will eventually be 5772 // cleared. 5773 testutils.SucceedsSoon(t, func() error { 5774 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5775 if len(tableDesc.GCMutations) > 0 { 5776 return errors.Errorf("%d gc mutations remaining", len(tableDesc.GCMutations)) 5777 } 5778 return nil 5779 }) 5780 } 5781 5782 // TestMultipleRevert starts a schema change then cancels it. After the canceled 5783 // job, after reversing the mutations the job is set up to throw an error so 5784 // that mutations are attempted to be reverted again. The mutation shouldn't be 5785 // attempted to be reversed twice. 5786 func TestMultipleRevert(t *testing.T) { 5787 defer leaktest.AfterTest(t)() 5788 5789 defer func(oldInterval time.Duration) { 5790 jobs.DefaultAdoptInterval = oldInterval 5791 }(jobs.DefaultAdoptInterval) 5792 jobs.DefaultAdoptInterval = 100 * time.Millisecond 5793 5794 shouldBlockBackfill := true 5795 ranCancelCommand := false 5796 shouldRetryAfterReversingMutations := true 5797 5798 params, _ := tests.CreateTestServerParams() 5799 var db *gosql.DB 5800 params.Knobs = base.TestingKnobs{ 5801 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5802 RunBeforeBackfill: func() error { 5803 if !shouldBlockBackfill { 5804 return nil 5805 } 5806 if !ranCancelCommand { 5807 // Cancel the job the first time it tried to backfill. 5808 if _, err := db.Exec(`CANCEL JOB ( 5809 SELECT job_id FROM [SHOW JOBS] 5810 WHERE 5811 job_type = 'SCHEMA CHANGE' AND 5812 status = $1 AND 5813 description NOT LIKE 'ROLL BACK%' 5814 )`, jobs.StatusRunning); err != nil { 5815 t.Error(err) 5816 } 5817 ranCancelCommand = true 5818 } 5819 // Keep returning a retryable error until the job was actually canceled. 5820 return jobs.NewRetryJobError("retry until cancel") 5821 }, 5822 RunBeforeOnFailOrCancel: func(_ int64) error { 5823 // Allow the backfill to proceed normally once the job was actually 5824 // canceled. 5825 shouldBlockBackfill = false 5826 return nil 5827 }, 5828 RunAfterMutationReversal: func(_ int64) error { 5829 // Throw one retryable error right after mutations were reversed so that 5830 // the mutation gets attempted to be reversed again. 5831 if !shouldRetryAfterReversingMutations { 5832 return nil 5833 } 5834 shouldRetryAfterReversingMutations = false 5835 // After cancelation, the job should get one more retryable error. 5836 return jobs.NewRetryJobError("retry once after cancel") 5837 }, 5838 }, 5839 } 5840 5841 s, sqlDB, _ := serverutils.StartServer(t, params) 5842 db = sqlDB 5843 defer s.Stopper().Stop(context.Background()) 5844 5845 // Disable strict GC TTL enforcement because we're going to shove a zero-value 5846 // TTL into the system with AddImmediateGCZoneConfig. 5847 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 5848 5849 // Create a k-v table and kick off a schema change that should get rolled 5850 // back. 5851 if _, err := sqlDB.Exec(` 5852 CREATE DATABASE t; 5853 CREATE TABLE t.test (k INT PRIMARY KEY, v INT8); 5854 INSERT INTO t.test VALUES (1, 2); 5855 ALTER TABLE t.public.test DROP COLUMN v; 5856 `); err == nil { 5857 t.Fatal("expected job to be canceled") 5858 } else if !strings.Contains(err.Error(), "job canceled by user") { 5859 t.Fatal(err) 5860 } 5861 5862 // Ensure that the schema change was rolled back. 5863 runner := sqlutils.MakeSQLRunner(sqlDB) 5864 rows := runner.QueryStr(t, "SELECT * FROM t.test") 5865 require.Equal(t, [][]string{ 5866 {"1", "2"}, 5867 }, rows) 5868 } 5869 5870 // TestRetriableErrorDuringRollback tests that a retriable error while rolling 5871 // back a schema change causes the rollback to retry and succeed. 5872 func TestRetriableErrorDuringRollback(t *testing.T) { 5873 defer leaktest.AfterTest(t)() 5874 defer setTestJobsAdoptInterval()() 5875 ctx := context.Background() 5876 5877 runTest := func(params base.TestServerArgs) { 5878 s, sqlDB, kvDB := serverutils.StartServer(t, params) 5879 defer s.Stopper().Stop(ctx) 5880 5881 // Disable strict GC TTL enforcement because we're going to shove a zero-value 5882 // TTL into the system with AddImmediateGCZoneConfig. 5883 defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)() 5884 5885 _, err := sqlDB.Exec(` 5886 CREATE DATABASE t; 5887 CREATE TABLE t.test (k INT PRIMARY KEY, v INT8); 5888 INSERT INTO t.test VALUES (1, 2), (2, 2); 5889 `) 5890 require.NoError(t, err) 5891 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "test") 5892 // Add a zone config for the table. 5893 _, err = sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID) 5894 require.NoError(t, err) 5895 5896 // Try to create a unique index which won't be valid and will need a rollback. 5897 _, err = sqlDB.Exec(` 5898 CREATE UNIQUE INDEX i ON t.test(v); 5899 `) 5900 require.Regexp(t, "violates unique constraint", err.Error()) 5901 // Verify that the index was cleaned up. 5902 testutils.SucceedsSoon(t, func() error { 5903 return checkTableKeyCountExact(ctx, kvDB, 2) 5904 }) 5905 } 5906 5907 t.Run("error-before-backfill", func(t *testing.T) { 5908 onFailOrCancelStarted := false 5909 injectedError := false 5910 params, _ := tests.CreateTestServerParams() 5911 params.Knobs = base.TestingKnobs{ 5912 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5913 RunBeforeOnFailOrCancel: func(_ int64) error { 5914 onFailOrCancelStarted = true 5915 return nil 5916 }, 5917 RunBeforeBackfill: func() error { 5918 // The first time through the backfiller in OnFailOrCancel, return a 5919 // retriable error. 5920 if !onFailOrCancelStarted || injectedError { 5921 return nil 5922 } 5923 injectedError = true 5924 // Return an artificial context canceled error. 5925 return context.Canceled 5926 }, 5927 }, 5928 } 5929 runTest(params) 5930 }) 5931 5932 t.Run("error-before-reversing-mutations", func(t *testing.T) { 5933 onFailOrCancelStarted := false 5934 injectedError := false 5935 params, _ := tests.CreateTestServerParams() 5936 params.Knobs = base.TestingKnobs{ 5937 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5938 RunBeforeOnFailOrCancel: func(_ int64) error { 5939 onFailOrCancelStarted = true 5940 return nil 5941 }, 5942 RunBeforeMutationReversal: func(_ int64) error { 5943 // The first time through reversing mutations, return a retriable 5944 // error. 5945 if !onFailOrCancelStarted || injectedError { 5946 return nil 5947 } 5948 injectedError = true 5949 // Return an artificial context canceled error. 5950 return context.Canceled 5951 }, 5952 }, 5953 } 5954 runTest(params) 5955 }) 5956 } 5957 5958 // TestPermanentErrorDuringRollback tests that a permanent error while rolling 5959 // back a schema change causes the job to fail, and that the appropriate error 5960 // is displayed in the jobs table. 5961 func TestPermanentErrorDuringRollback(t *testing.T) { 5962 defer leaktest.AfterTest(t)() 5963 defer setTestJobsAdoptInterval()() 5964 ctx := context.Background() 5965 5966 runTest := func(params base.TestServerArgs) { 5967 s, sqlDB, _ := serverutils.StartServer(t, params) 5968 defer s.Stopper().Stop(ctx) 5969 5970 _, err := sqlDB.Exec(` 5971 CREATE DATABASE t; 5972 CREATE TABLE t.test (k INT PRIMARY KEY, v INT8); 5973 INSERT INTO t.test VALUES (1, 2), (2, 2); 5974 `) 5975 require.NoError(t, err) 5976 5977 // Try to create a unique index which won't be valid and will need a rollback. 5978 _, err = sqlDB.Exec(` 5979 CREATE UNIQUE INDEX i ON t.test(v); 5980 `) 5981 require.Regexp(t, "violates unique constraint", err.Error()) 5982 5983 var jobErr string 5984 row := sqlDB.QueryRow("SELECT error FROM [SHOW JOBS] WHERE job_type = 'SCHEMA CHANGE'") 5985 require.NoError(t, row.Scan(&jobErr)) 5986 require.Regexp(t, "cannot be reverted, manual cleanup may be required: permanent error", jobErr) 5987 } 5988 5989 t.Run("error-before-backfill", func(t *testing.T) { 5990 onFailOrCancelStarted := false 5991 injectedError := false 5992 params, _ := tests.CreateTestServerParams() 5993 params.Knobs = base.TestingKnobs{ 5994 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 5995 RunBeforeOnFailOrCancel: func(_ int64) error { 5996 onFailOrCancelStarted = true 5997 return nil 5998 }, 5999 RunBeforeBackfill: func() error { 6000 // The first time through the backfiller in OnFailOrCancel, return a 6001 // permanent error. 6002 if !onFailOrCancelStarted || injectedError { 6003 return nil 6004 } 6005 injectedError = true 6006 // Any error not on the whitelist of retriable errors is considered permanent. 6007 return errors.New("permanent error") 6008 }, 6009 }, 6010 } 6011 runTest(params) 6012 }) 6013 6014 t.Run("error-before-reversing-mutations", func(t *testing.T) { 6015 onFailOrCancelStarted := false 6016 injectedError := false 6017 params, _ := tests.CreateTestServerParams() 6018 params.Knobs = base.TestingKnobs{ 6019 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 6020 RunBeforeOnFailOrCancel: func(_ int64) error { 6021 onFailOrCancelStarted = true 6022 return nil 6023 }, 6024 RunBeforeBackfill: func() error { 6025 // The first time through reversing mutations, return a permanent 6026 // error. 6027 if !onFailOrCancelStarted || injectedError { 6028 return nil 6029 } 6030 injectedError = true 6031 // Any error not on the whitelist of retriable errors is considered permanent. 6032 return errors.New("permanent error") 6033 }, 6034 }, 6035 } 6036 runTest(params) 6037 }) 6038 }