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  }