github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ccl/partitionccl/drop_test.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Licensed as a CockroachDB Enterprise file under the Cockroach Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt 8 9 package partitionccl 10 11 import ( 12 "context" 13 "fmt" 14 "testing" 15 16 "github.com/cockroachdb/cockroach/pkg/base" 17 "github.com/cockroachdb/cockroach/pkg/config/zonepb" 18 "github.com/cockroachdb/cockroach/pkg/keys" 19 "github.com/cockroachdb/cockroach/pkg/sql" 20 "github.com/cockroachdb/cockroach/pkg/sql/gcjob" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 22 "github.com/cockroachdb/cockroach/pkg/sql/tests" 23 "github.com/cockroachdb/cockroach/pkg/testutils" 24 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 25 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 26 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 27 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 28 "github.com/cockroachdb/errors" 29 ) 30 31 func subzoneExists(cfg *zonepb.ZoneConfig, index uint32, partition string) bool { 32 for _, s := range cfg.Subzones { 33 if s.IndexID == index && s.PartitionName == partition { 34 return true 35 } 36 } 37 return false 38 } 39 40 func TestDropIndexWithZoneConfigCCL(t *testing.T) { 41 defer leaktest.AfterTest(t)() 42 43 const numRows = 100 44 45 defer gcjob.SetSmallMaxGCIntervalForTest()() 46 47 asyncNotification := make(chan struct{}) 48 49 params, _ := tests.CreateTestServerParams() 50 params.Knobs = base.TestingKnobs{ 51 GCJob: &sql.GCJobTestingKnobs{ 52 RunBeforeResume: func(_ int64) error { 53 <-asyncNotification 54 return nil 55 }, 56 }, 57 } 58 s, sqlDBRaw, kvDB := serverutils.StartServer(t, params) 59 sqlDB := sqlutils.MakeSQLRunner(sqlDBRaw) 60 defer s.Stopper().Stop(context.Background()) 61 62 // Create a test table with a partitioned secondary index. 63 if err := tests.CreateKVTable(sqlDBRaw, "kv", numRows); err != nil { 64 t.Fatal(err) 65 } 66 sqlDB.Exec(t, `CREATE INDEX i ON t.kv (v) PARTITION BY LIST (v) ( 67 PARTITION p1 VALUES IN (1), 68 PARTITION p2 VALUES IN (2) 69 )`) 70 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv") 71 indexDesc, _, err := tableDesc.FindIndexByName("i") 72 if err != nil { 73 t.Fatal(err) 74 } 75 indexSpan := tableDesc.IndexSpan(keys.SystemSQLCodec, indexDesc.ID) 76 tests.CheckKeyCount(t, kvDB, indexSpan, numRows) 77 78 // Set zone configs on the primary index, secondary index, and one partition 79 // of the secondary index. 80 ttlYaml := "gc: {ttlseconds: 1}" 81 sqlutils.SetZoneConfig(t, sqlDB, "INDEX t.kv@primary", "") 82 sqlutils.SetZoneConfig(t, sqlDB, "INDEX t.kv@i", ttlYaml) 83 sqlutils.SetZoneConfig(t, sqlDB, "PARTITION p2 OF INDEX t.kv@i", ttlYaml) 84 85 // Drop the index and verify that the zone config for the secondary index and 86 // its partition are removed but the zone config for the primary index 87 // remains. 88 sqlDB.Exec(t, `DROP INDEX t.kv@i`) 89 // All zone configs should still exist. 90 var buf []byte 91 cfg := &zonepb.ZoneConfig{} 92 sqlDB.QueryRow(t, "SELECT config FROM system.zones WHERE id = $1", tableDesc.ID).Scan(&buf) 93 if err := protoutil.Unmarshal(buf, cfg); err != nil { 94 t.Fatal(err) 95 } 96 97 subzones := []struct { 98 index uint32 99 partition string 100 }{ 101 {1, ""}, 102 {3, ""}, 103 {3, "p2"}, 104 } 105 for _, target := range subzones { 106 if exists := subzoneExists(cfg, target.index, target.partition); !exists { 107 t.Fatalf(`zone config for %v does not exist`, target) 108 } 109 } 110 // Dropped indexes waiting for GC shouldn't have their zone configs be visible 111 // using SHOW ZONE CONFIGURATIONS ..., but still need to exist in system.zones. 112 for _, target := range []string{"t.kv@i", "t.kv.p2"} { 113 if exists := sqlutils.ZoneConfigExists(t, sqlDB, target); exists { 114 t.Fatalf(`zone config for %s still exists`, target) 115 } 116 } 117 tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv") 118 if _, _, err := tableDesc.FindIndexByName("i"); err == nil { 119 t.Fatalf("table descriptor still contains index after index is dropped") 120 } 121 close(asyncNotification) 122 123 // Wait for index drop to complete so zone configs are updated. 124 testutils.SucceedsSoon(t, func() error { 125 if kvs, err := kvDB.Scan(context.Background(), indexSpan.Key, indexSpan.EndKey, 0); err != nil { 126 return err 127 } else if l := 0; len(kvs) != l { 128 return errors.Errorf("expected %d key value pairs, but got %d", l, len(kvs)) 129 } 130 sqlDB.QueryRow(t, "SELECT config FROM system.zones WHERE id = $1", tableDesc.ID).Scan(&buf) 131 if err := protoutil.Unmarshal(buf, cfg); err != nil { 132 return err 133 } 134 if exists := subzoneExists(cfg, 1, ""); !exists { 135 return errors.New("zone config for primary index removed after dropping secondary index") 136 } 137 for _, target := range subzones[1:] { 138 if exists := subzoneExists(cfg, target.index, target.partition); exists { 139 return fmt.Errorf(`zone config for %v still exists`, target) 140 } 141 } 142 return nil 143 }) 144 }