@@ -6356,9 +6356,11 @@ func TestRollbackForeignKeyAddition(t *testing.T) {
6356
6356
tdb .Exec (t , `CREATE TABLE db.t2 (a INT)` )
6357
6357
tdb .Exec (t , `SET use_declarative_schema_changer = off` )
6358
6358
6359
+ const alterTableSQL = `ALTER TABLE db.public.t2 ADD FOREIGN KEY (a) REFERENCES db.public.t`
6360
+
6359
6361
g := ctxgroup .WithContext (ctx )
6360
6362
g .GoCtx (func (ctx context.Context ) error {
6361
- _ , err := sqlDB .ExecContext (ctx , `ALTER TABLE db.t2 ADD FOREIGN KEY (a) REFERENCES db.t` )
6363
+ _ , err := sqlDB .ExecContext (ctx , alterTableSQL )
6362
6364
require .Regexp (t , "job canceled by user" , err )
6363
6365
return nil
6364
6366
})
@@ -6367,9 +6369,54 @@ func TestRollbackForeignKeyAddition(t *testing.T) {
6367
6369
6368
6370
var jobID jobspb.JobID
6369
6371
6370
- // We filter by running because there's a bug where we create an extra
6371
- // no-op job for the referenced table (#57624).
6372
- require .NoError (t , sqlDB .QueryRow (`SELECT job_id FROM crdb_internal.jobs WHERE description LIKE '%ALTER TABLE%' AND status = 'running'` ).Scan (& jobID ))
6372
+ // The ALTER creates two jobs, but we only end up pausing one with the
6373
+ // RunBeforeBackfill callback. Capture the job ID of the one that is paused
6374
+ // and allow the other one to complete.
6375
+ testutils .SucceedsSoon (t , func () error {
6376
+ rows , err := sqlDB .Query (`SELECT job_id, status FROM crdb_internal.jobs WHERE description = $1 ORDER BY job_id` , alterTableSQL )
6377
+ if err != nil {
6378
+ return err
6379
+ }
6380
+ defer rows .Close ()
6381
+
6382
+ var jobs []struct {
6383
+ id jobspb.JobID
6384
+ status string
6385
+ }
6386
+
6387
+ for rows .Next () {
6388
+ var id jobspb.JobID
6389
+ var status string
6390
+ if err := rows .Scan (& id , & status ); err != nil {
6391
+ return err
6392
+ }
6393
+ jobs = append (jobs , struct {
6394
+ id jobspb.JobID
6395
+ status string
6396
+ }{id , status })
6397
+ }
6398
+
6399
+ if len (jobs ) != 2 {
6400
+ return errors .Errorf ("expected 2 jobs, found %d" , len (jobs ))
6401
+ }
6402
+
6403
+ var runningCount , succeededCount int
6404
+ for _ , job := range jobs {
6405
+ switch job .status {
6406
+ case "running" :
6407
+ runningCount ++
6408
+ jobID = job .id
6409
+ case "succeeded" :
6410
+ succeededCount ++
6411
+ }
6412
+ }
6413
+
6414
+ if runningCount != 1 || succeededCount != 1 {
6415
+ return errors .Errorf ("expected 1 running and 1 succeeded job, found %d running, %d succeeded" , runningCount , succeededCount )
6416
+ }
6417
+
6418
+ return nil
6419
+ })
6373
6420
tdb .Exec (t , "CANCEL JOB $1" , jobID )
6374
6421
6375
6422
close (continueNotification )
@@ -6381,6 +6428,15 @@ func TestRollbackForeignKeyAddition(t *testing.T) {
6381
6428
Scan (& status , & error )
6382
6429
require .Equal (t , status , jobs .StateCanceled )
6383
6430
require .Equal (t , error , "job canceled by user" )
6431
+
6432
+ // Verify that descriptors are valid after job cancellation
6433
+ rows , err := sqlDB .Query (`SELECT * FROM "".crdb_internal.invalid_objects` )
6434
+ require .NoError (t , err )
6435
+ defer rows .Close ()
6436
+ if rows .Next () {
6437
+ t .Fatal ("found catalog corruptions after job cancellation" )
6438
+ }
6439
+ require .NoError (t , rows .Err ())
6384
6440
}
6385
6441
6386
6442
// TestRevertingJobsOnDatabasesAndSchemas tests that schema change jobs on
0 commit comments