github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/tests/hash_sharded_test.go (about) 1 // Copyright 2020 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 tests_test 12 13 import ( 14 "context" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/base" 18 "github.com/cockroachdb/cockroach/pkg/keys" 19 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 20 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 21 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 22 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 23 ) 24 25 // getShardColumnID fetches the id of the shard column associated with the given sharded 26 // index. 27 func getShardColumnID( 28 t *testing.T, tableDesc *sqlbase.TableDescriptor, shardedIndexName string, 29 ) sqlbase.ColumnID { 30 idx, _, err := tableDesc.FindIndexByName(shardedIndexName) 31 if err != nil { 32 t.Fatal(err) 33 } 34 shardCol, _, err := tableDesc.FindColumnByName(tree.Name(idx.Sharded.Name)) 35 if err != nil { 36 t.Fatal(err) 37 } 38 return shardCol.ID 39 } 40 41 // verifyTableDescriptorStates ensures that the given table descriptor fulfills the 42 // following conditions after the creation of a sharded index: 43 // 1. A hidden shard column was created. 44 // 2. A hidden check constraint was created on the aforementioned shard column. 45 // 3. The first column in the index set is the aforementioned shard column. 46 func verifyTableDescriptorState( 47 t *testing.T, tableDesc *sqlbase.TableDescriptor, shardedIndexName string, 48 ) { 49 idx, _, err := tableDesc.FindIndexByName(shardedIndexName) 50 if err != nil { 51 t.Fatal(err) 52 } 53 54 if !idx.IsSharded() { 55 t.Fatalf(`Expected index %s to be sharded`, shardedIndexName) 56 } 57 // Note that this method call will fail if the shard column doesn't exist 58 shardColID := getShardColumnID(t, tableDesc, shardedIndexName) 59 foundCheckConstraint := false 60 for _, check := range tableDesc.AllActiveAndInactiveChecks() { 61 usesShard, err := check.UsesColumn(tableDesc, shardColID) 62 if err != nil { 63 t.Fatal(err) 64 } 65 if usesShard && check.Hidden { 66 foundCheckConstraint = true 67 break 68 } 69 } 70 if !foundCheckConstraint { 71 t.Fatalf(`Could not find hidden check constraint for shard column`) 72 } 73 if idx.ColumnIDs[0] != shardColID { 74 t.Fatalf(`Expected shard column to be the first column in the set of index columns`) 75 } 76 } 77 78 func TestBasicHashShardedIndexes(t *testing.T) { 79 defer leaktest.AfterTest(t)() 80 ctx := context.Background() 81 s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) 82 defer s.Stopper().Stop(ctx) 83 if _, err := db.Exec(`CREATE DATABASE d`); err != nil { 84 t.Fatal(err) 85 } 86 if _, err := db.Exec(`USE d`); err != nil { 87 t.Fatal(err) 88 } 89 if _, err := db.Exec(`SET experimental_enable_hash_sharded_indexes = true`); err != nil { 90 t.Fatal(err) 91 } 92 93 t.Run("primary", func(t *testing.T) { 94 if _, err := db.Exec(` 95 CREATE TABLE kv_primary ( 96 k INT PRIMARY KEY USING HASH WITH BUCKET_COUNT=5, 97 v BYTES 98 ) 99 `); err != nil { 100 t.Fatal(err) 101 } 102 103 if _, err := db.Exec(`CREATE INDEX foo ON kv_primary (v)`); err != nil { 104 t.Fatal(err) 105 } 106 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, `d`, `kv_primary`) 107 verifyTableDescriptorState(t, tableDesc, "primary" /* shardedIndexName */) 108 shardColID := getShardColumnID(t, tableDesc, "primary" /* shardedIndexName */) 109 110 // Ensure that secondary indexes on table `kv` have the shard column in their 111 // `ExtraColumnIDs` field so they can reconstruct the sharded primary key. 112 fooDesc, _, err := tableDesc.FindIndexByName("foo") 113 if err != nil { 114 t.Fatal(err) 115 } 116 foundShardColumn := false 117 for _, colID := range fooDesc.ExtraColumnIDs { 118 if colID == shardColID { 119 foundShardColumn = true 120 break 121 } 122 } 123 if !foundShardColumn { 124 t.Fatalf(`Secondary index cannot reconstruct sharded primary key`) 125 } 126 }) 127 128 t.Run("secondary_in_create_table", func(t *testing.T) { 129 if _, err := db.Exec(` 130 CREATE TABLE kv_secondary ( 131 k INT, 132 v BYTES, 133 INDEX sharded_secondary (k) USING HASH WITH BUCKET_COUNT = 12 134 ) 135 `); err != nil { 136 t.Fatal(err) 137 } 138 139 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, `d`, `kv_secondary`) 140 verifyTableDescriptorState(t, tableDesc, "sharded_secondary" /* shardedIndexName */) 141 }) 142 143 t.Run("secondary_in_separate_ddl", func(t *testing.T) { 144 if _, err := db.Exec(` 145 CREATE TABLE kv_secondary2 ( 146 k INT, 147 v BYTES 148 ) 149 `); err != nil { 150 t.Fatal(err) 151 } 152 153 if _, err := db.Exec(`CREATE INDEX sharded_secondary2 ON kv_secondary2 (k) USING HASH WITH BUCKET_COUNT = 12`); err != nil { 154 t.Fatal(err) 155 } 156 tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, `d`, `kv_secondary2`) 157 verifyTableDescriptorState(t, tableDesc, "sharded_secondary2" /* shardedIndexName */) 158 }) 159 }