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 }