github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/namespace_test.go (about)

     1  // Copyright 2015 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  	"testing"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/keys"
    18  	"github.com/cockroachdb/cockroach/pkg/sql"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    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/util/hlc"
    26  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    27  )
    28  
    29  // This test creates table/database descriptors that have entries in the
    30  // deprecated namespace table. This simulates objects created in the window
    31  // where the migration from the old -> new system.namespace has run, but the
    32  // cluster version has not been finalized yet.
    33  func TestNamespaceTableSemantics(t *testing.T) {
    34  	defer leaktest.AfterTest(t)()
    35  	params, _ := tests.CreateTestServerParams()
    36  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
    37  	defer s.Stopper().Stop(context.Background())
    38  	ctx := context.Background()
    39  	codec := keys.SystemSQLCodec
    40  
    41  	// IDs to map (parentID, name) to. Actual ID value is irrelevant to the test.
    42  	idCounter := keys.MinNonPredefinedUserDescID
    43  
    44  	// Database name.
    45  	dKey := sqlbase.NewDeprecatedDatabaseKey("test").Key(codec)
    46  	if gr, err := kvDB.Get(ctx, dKey); err != nil {
    47  		t.Fatal(err)
    48  	} else if gr.Exists() {
    49  		t.Fatal("expected non-existing key")
    50  	}
    51  
    52  	// Add an entry for the database in the deprecated namespace table directly.
    53  	if err := kvDB.CPut(ctx, dKey, idCounter, nil); err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	idCounter++
    57  
    58  	// Creating the database should fail, because an entry was explicitly added to
    59  	// the system.namespace_deprecated table.
    60  	_, err := sqlDB.Exec(`CREATE DATABASE test`)
    61  	if !testutils.IsError(err, sqlbase.NewDatabaseAlreadyExistsError("test").Error()) {
    62  		t.Fatalf("unexpected error %v", err)
    63  	}
    64  
    65  	// Renaming the database should fail as well.
    66  	if _, err = sqlDB.Exec(`CREATE DATABASE test2`); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	_, err = sqlDB.Exec(`ALTER DATABASE test2 RENAME TO test`)
    70  	if !testutils.IsError(err, pgerror.Newf(pgcode.DuplicateDatabase,
    71  		"the new database name \"test\" already exists").Error()) {
    72  		t.Fatalf("unexpected error %v", err)
    73  	}
    74  
    75  	// Remove the entry.
    76  	if err := kvDB.Del(ctx, dKey); err != nil {
    77  		t.Fatal(err)
    78  	}
    79  
    80  	// Creating the database should work now, because we removed the mapping in
    81  	// the old system.namespace table.
    82  	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	idCounter++
    86  
    87  	// Ensure the new entry is added to the new namespace table.
    88  	if gr, err := kvDB.Get(ctx, dKey); err != nil {
    89  		t.Fatal(err)
    90  	} else if gr.Exists() {
    91  		t.Fatal("database key unexpectedly found in the deprecated system.namespace")
    92  	}
    93  	newDKey := sqlbase.NewDatabaseKey("test").Key(codec)
    94  	if gr, err := kvDB.Get(ctx, newDKey); err != nil {
    95  		t.Fatal(err)
    96  	} else if !gr.Exists() {
    97  		t.Fatal("database key not found in the new system.namespace")
    98  	}
    99  
   100  	txn := kvDB.NewTxn(ctx, "lookup-test-db-id")
   101  	found, dbID, err := sqlbase.LookupDatabaseID(ctx, txn, codec, "test")
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	if !found {
   106  		t.Fatal("Error looking up the dbID")
   107  	}
   108  
   109  	// Simulate the same test for a table and sequence.
   110  	tKey := sqlbase.NewDeprecatedTableKey(dbID, "rel").Key(codec)
   111  	if err := kvDB.CPut(ctx, tKey, idCounter, nil); err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	// TODO (rohany): This is pretty hacky, but needs to be done in order
   116  	//  for the exact errors to show up below.
   117  	// The tests below ensure that namespace collisions are detected against
   118  	// the deprecated namespace key entry for (dbID, "rel"). Just writing
   119  	// the key in the namespace table worked until the create table functions
   120  	// perform a lookup into system.descriptor to see what kind of object they
   121  	// collided with, now that user defined types are present. To make sure
   122  	// everything is working as expected, we need to bump the ID generator
   123  	// counter to be in line with idCounter, and write a dummy table descriptor
   124  	// into system.descriptor so that conflicts against this fake entry are
   125  	// correctly detected.
   126  	if _, err := kvDB.Inc(ctx, codec.DescIDSequenceKey(), 1); err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	mKey := sqlbase.MakeDescMetadataKey(codec, sqlbase.ID(idCounter))
   130  	// Fill the dummy descriptor with garbage.
   131  	desc := sql.InitTableDescriptor(
   132  		sqlbase.ID(idCounter),
   133  		dbID,
   134  		keys.PublicSchemaID,
   135  		"rel",
   136  		hlc.Timestamp{},
   137  		&sqlbase.PrivilegeDescriptor{},
   138  		false,
   139  	)
   140  	if err := desc.AllocateIDs(); err != nil {
   141  		t.Fatal(err)
   142  	}
   143  	if err := kvDB.Put(ctx, mKey, sqlbase.WrapDescriptor(&desc)); err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	// Creating a table should fail now, because an entry was explicitly added to
   148  	// the old system.namespace_deprecated table.
   149  	_, err = sqlDB.Exec(`CREATE TABLE test.public.rel(a int)`)
   150  	if !testutils.IsError(err, sqlbase.NewRelationAlreadyExistsError("rel").Error()) {
   151  		t.Fatalf("unexpected error %v", err)
   152  	}
   153  	// Same applies to a table which doesn't explicitly specify the public schema,
   154  	// as that is the default.
   155  	_, err = sqlDB.Exec(`CREATE TABLE test.rel(a int)`)
   156  	if !testutils.IsError(err, sqlbase.NewRelationAlreadyExistsError("rel").Error()) {
   157  		t.Fatalf("unexpected error %v", err)
   158  	}
   159  	// Can not create a sequence with the same name either.
   160  	_, err = sqlDB.Exec(`CREATE SEQUENCE test.rel`)
   161  	if !testutils.IsError(err, sqlbase.NewRelationAlreadyExistsError("rel").Error()) {
   162  		t.Fatalf("unexpected error %v", err)
   163  	}
   164  
   165  	// Can not rename a table to the same name either.
   166  	if _, err = sqlDB.Exec(`CREATE TABLE rel2(a int)`); err != nil {
   167  		t.Fatal(err)
   168  	}
   169  	_, err = sqlDB.Exec(`ALTER TABLE rel2 RENAME TO rel`)
   170  	if testutils.IsError(err, sqlbase.NewRelationAlreadyExistsError("rel").Error()) {
   171  		t.Fatalf("unexpected error %v", err)
   172  	}
   173  
   174  	// Can not rename sequences to the same name either.
   175  	if _, err = sqlDB.Exec(`CREATE SEQUENCE rel2`); err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	_, err = sqlDB.Exec(`ALTER SEQUENCE rel2 RENAME TO rel`)
   179  	if !testutils.IsError(err, sqlbase.NewRelationAlreadyExistsError("rel").Error()) {
   180  		t.Fatalf("unexpected error %v", err)
   181  	}
   182  
   183  	// Remove the entry.
   184  	if err := kvDB.Del(ctx, tKey); err != nil {
   185  		t.Fatal(err)
   186  	}
   187  
   188  	// Creating a new table should succeed now.
   189  	if _, err = sqlDB.Exec(`CREATE TABLE test.public.rel(a int)`); err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	// Ensure the new entry is added to the new namespace table.
   194  	if gr, err := kvDB.Get(ctx, tKey); err != nil {
   195  		t.Fatal(err)
   196  	} else if gr.Exists() {
   197  		t.Fatal("table key unexpectedly found in the deprecated system.namespace")
   198  	}
   199  	newTKey := sqlbase.NewPublicTableKey(dbID, "rel").Key(codec)
   200  	if gr, err := kvDB.Get(ctx, newTKey); err != nil {
   201  		t.Fatal(err)
   202  	} else if !gr.Exists() {
   203  		t.Fatal("table key not found in the new system.namespace")
   204  	}
   205  }