github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/indexbackfiller_test.go (about) 1 // Copyright 2017 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 "sync" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/base" 20 "github.com/cockroachdb/cockroach/pkg/sql" 21 "github.com/cockroachdb/cockroach/pkg/sql/tests" 22 "github.com/cockroachdb/cockroach/pkg/sqlmigrations" 23 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 24 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 25 ) 26 27 // TestIndexBackfiller tests the scenarios described in docs/tech-notes/index-backfill.md 28 func TestIndexBackfiller(t *testing.T) { 29 defer leaktest.AfterTest(t)() 30 31 params, _ := tests.CreateTestServerParams() 32 33 moveToTDelete := make(chan bool) 34 moveToTWrite := make(chan bool) 35 moveToTScan := make(chan bool) 36 moveToBackfill := make(chan bool) 37 38 params.Knobs = base.TestingKnobs{ 39 SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{ 40 RunBeforePublishWriteAndDelete: func() { 41 // Signal that we've moved into DELETE_ONLY. 42 moveToTDelete <- true 43 // Wait until we get a signal to move to DELETE_AND_WRITE_ONLY. 44 <-moveToTWrite 45 }, 46 RunBeforeBackfill: func() error { 47 // Wait until we get a signal to pick our scan timestamp. 48 <-moveToTScan 49 return nil 50 }, 51 RunBeforeIndexBackfill: func() { 52 // Wait until we get a signal to begin backfill. 53 <-moveToBackfill 54 }, 55 }, 56 // Disable backfill migrations, we still need the jobs table migration. 57 SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{ 58 DisableBackfillMigrations: true, 59 }, 60 } 61 62 tc := serverutils.StartTestCluster(t, 3, 63 base.TestClusterArgs{ 64 ServerArgs: params, 65 }) 66 defer tc.Stopper().Stop(context.Background()) 67 sqlDB := tc.ServerConn(0) 68 69 execOrFail := func(query string) gosql.Result { 70 if res, err := sqlDB.Exec(query); err != nil { 71 t.Fatal(err) 72 } else { 73 return res 74 } 75 return nil 76 } 77 78 // The sequence of events here exactly matches the test cases in 79 // docs/tech-notes/index-backfill.md. If you update this, please remember to 80 // update the tech note as well. 81 82 execOrFail("CREATE DATABASE t") 83 execOrFail("CREATE TABLE t.kv (k int PRIMARY KEY, v char)") 84 execOrFail("INSERT INTO t.kv VALUES (1, 'a'), (3, 'c'), (4, 'e'), (6, 'f'), (7, 'g'), (9, 'h')") 85 86 // Start the schema change. 87 var finishedSchemaChange sync.WaitGroup 88 finishedSchemaChange.Add(1) 89 go func() { 90 execOrFail("CREATE UNIQUE INDEX vidx on t.kv(v)") 91 finishedSchemaChange.Done() 92 }() 93 94 // Wait until the schema change has moved the cluster into DELETE_ONLY mode. 95 <-moveToTDelete 96 execOrFail("DELETE FROM t.kv WHERE k=9") 97 execOrFail("INSERT INTO t.kv VALUES (9, 'h')") 98 99 // Move to WRITE_ONLY mode. 100 moveToTWrite <- true 101 execOrFail("INSERT INTO t.kv VALUES (2, 'b')") 102 103 // Pick our scan timestamp. 104 moveToTScan <- true 105 execOrFail("UPDATE t.kv SET v = 'd' WHERE k = 3") 106 execOrFail("UPDATE t.kv SET k = 5 WHERE v = 'e'") 107 execOrFail("DELETE FROM t.kv WHERE k = 6") 108 109 // Begin the backfill. 110 moveToBackfill <- true 111 112 finishedSchemaChange.Wait() 113 114 pairsPrimary := queryPairs(t, sqlDB, "SELECT k, v FROM t.kv ORDER BY k ASC") 115 pairsIndex := queryPairs(t, sqlDB, "SELECT k, v FROM t.kv@vidx ORDER BY k ASC") 116 117 if len(pairsPrimary) != len(pairsIndex) { 118 t.Fatalf("Mismatched entries in table and index: %+v %+v", pairsPrimary, pairsIndex) 119 } 120 121 for i, pPrimary := range pairsPrimary { 122 if pPrimary != pairsIndex[i] { 123 t.Fatalf("Mismatched entry in table and index: %+v %+v", pPrimary, pairsIndex[i]) 124 } 125 } 126 } 127 128 type pair struct { 129 k int 130 v string 131 } 132 133 func queryPairs(t *testing.T, sqlDB *gosql.DB, query string) []pair { 134 rows, err := sqlDB.Query(query) 135 if err != nil { 136 t.Fatal(err) 137 } 138 defer rows.Close() 139 140 ret := make([]pair, 0) 141 for rows.Next() { 142 p := pair{} 143 if err := rows.Scan(&p.k, &p.v); err != nil { 144 t.Fatal(err) 145 } 146 ret = append(ret, p) 147 } 148 return ret 149 }