github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/tests/system_table_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 tests_test 12 13 import ( 14 "context" 15 "fmt" 16 "strconv" 17 "strings" 18 "testing" 19 20 "github.com/cockroachdb/cockroach/pkg/config/zonepb" 21 "github.com/cockroachdb/cockroach/pkg/keys" 22 "github.com/cockroachdb/cockroach/pkg/roachpb" 23 "github.com/cockroachdb/cockroach/pkg/sql" 24 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 25 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 26 "github.com/cockroachdb/cockroach/pkg/testutils" 27 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 28 "github.com/cockroachdb/datadriven" 29 "github.com/gogo/protobuf/proto" 30 "github.com/kr/pretty" 31 "github.com/stretchr/testify/require" 32 ) 33 34 func TestInitialKeys(t *testing.T) { 35 defer leaktest.AfterTest(t)() 36 const keysPerDesc = 2 37 38 testutils.RunTrueAndFalse(t, "system tenant", func(t *testing.T, systemTenant bool) { 39 var codec keys.SQLCodec 40 var nonDescKeys int 41 if systemTenant { 42 codec = keys.SystemSQLCodec 43 nonDescKeys = 9 44 } else { 45 codec = keys.MakeSQLCodec(roachpb.MakeTenantID(5)) 46 nonDescKeys = 2 47 } 48 49 ms := sqlbase.MakeMetadataSchema(codec, zonepb.DefaultZoneConfigRef(), zonepb.DefaultSystemZoneConfigRef()) 50 kv, _ /* splits */ := ms.GetInitialValues() 51 expected := nonDescKeys + keysPerDesc*ms.SystemDescriptorCount() 52 if actual := len(kv); actual != expected { 53 t.Fatalf("Wrong number of initial sql kv pairs: %d, wanted %d", actual, expected) 54 } 55 56 // Add an additional table. 57 sqlbase.SystemAllowedPrivileges[keys.MaxReservedDescID] = privilege.List{privilege.ALL} 58 desc, err := sql.CreateTestTableDescriptor( 59 context.Background(), 60 keys.SystemDatabaseID, 61 keys.MaxReservedDescID, 62 "CREATE TABLE system.x (val INTEGER PRIMARY KEY)", 63 sqlbase.NewDefaultPrivilegeDescriptor(), 64 ) 65 if err != nil { 66 t.Fatal(err) 67 } 68 ms.AddDescriptor(keys.SystemDatabaseID, &desc) 69 kv, _ /* splits */ = ms.GetInitialValues() 70 expected = nonDescKeys + keysPerDesc*ms.SystemDescriptorCount() 71 if actual := len(kv); actual != expected { 72 t.Fatalf("Wrong number of initial sql kv pairs: %d, wanted %d", actual, expected) 73 } 74 75 // Verify that IDGenerator value is correct. 76 found := false 77 idgen := codec.DescIDSequenceKey() 78 var idgenkv roachpb.KeyValue 79 for _, v := range kv { 80 if v.Key.Equal(idgen) { 81 idgenkv = v 82 found = true 83 break 84 } 85 } 86 87 if !found { 88 t.Fatal("Could not find descriptor ID generator in initial key set") 89 } 90 // Expect 2 non-reserved IDs to have been allocated. 91 i, err := idgenkv.Value.GetInt() 92 if err != nil { 93 t.Fatal(err) 94 } 95 if a, e := i, int64(keys.MinUserDescID); a != e { 96 t.Fatalf("Expected next descriptor ID to be %d, was %d", e, a) 97 } 98 }) 99 } 100 101 func TestInitialKeysAndSplits(t *testing.T) { 102 defer leaktest.AfterTest(t)() 103 datadriven.RunTest(t, "testdata/initial_keys", func(t *testing.T, d *datadriven.TestData) string { 104 switch d.Cmd { 105 case "initial-keys": 106 var tenant string 107 d.ScanArgs(t, "tenant", &tenant) 108 109 var codec keys.SQLCodec 110 if tenant == "system" { 111 codec = keys.SystemSQLCodec 112 } else { 113 id, err := strconv.ParseUint(tenant, 10, 64) 114 if err != nil { 115 t.Fatal(err) 116 } 117 codec = keys.MakeSQLCodec(roachpb.MakeTenantID(id)) 118 } 119 120 ms := sqlbase.MakeMetadataSchema( 121 codec, zonepb.DefaultZoneConfigRef(), zonepb.DefaultSystemZoneConfigRef(), 122 ) 123 kvs, splits := ms.GetInitialValues() 124 125 var buf strings.Builder 126 fmt.Fprintf(&buf, "%d keys:\n", len(kvs)) 127 for _, kv := range kvs { 128 fmt.Fprintf(&buf, " %s\n", kv.Key) 129 } 130 fmt.Fprintf(&buf, "%d splits:\n", len(splits)) 131 for _, k := range splits { 132 fmt.Fprintf(&buf, " %s\n", k.AsRawKey()) 133 } 134 return buf.String() 135 default: 136 return fmt.Sprintf("unknown command: %s", d.Cmd) 137 } 138 }) 139 } 140 141 // TestSystemTableLiterals compares the result of evaluating the `CREATE TABLE` 142 // statement strings that describe each system table with the TableDescriptor 143 // literals that are actually used at runtime. This ensures we can use the hand- 144 // written literals instead of having to evaluate the `CREATE TABLE` statements 145 // before initialization and with limited SQL machinery bootstraped, while still 146 // confident that the result is the same as if `CREATE TABLE` had been run. 147 // 148 // This test may also be useful when writing a new system table: 149 // adding the new schema along with a trivial, empty TableDescriptor literal 150 // will print the expected proto which can then be used to replace the empty 151 // one (though pruning the explicit zero values may make it more readable). 152 func TestSystemTableLiterals(t *testing.T) { 153 defer leaktest.AfterTest(t)() 154 type testcase struct { 155 id sqlbase.ID 156 schema string 157 pkg sqlbase.TableDescriptor 158 } 159 160 for _, test := range []testcase{ 161 {keys.NamespaceTableID, sqlbase.NamespaceTableSchema, sqlbase.NamespaceTable}, 162 {keys.DescriptorTableID, sqlbase.DescriptorTableSchema, sqlbase.DescriptorTable}, 163 {keys.UsersTableID, sqlbase.UsersTableSchema, sqlbase.UsersTable}, 164 {keys.ZonesTableID, sqlbase.ZonesTableSchema, sqlbase.ZonesTable}, 165 {keys.LeaseTableID, sqlbase.LeaseTableSchema, sqlbase.LeaseTable}, 166 {keys.EventLogTableID, sqlbase.EventLogTableSchema, sqlbase.EventLogTable}, 167 {keys.RangeEventTableID, sqlbase.RangeEventTableSchema, sqlbase.RangeEventTable}, 168 {keys.UITableID, sqlbase.UITableSchema, sqlbase.UITable}, 169 {keys.JobsTableID, sqlbase.JobsTableSchema, sqlbase.JobsTable}, 170 {keys.SettingsTableID, sqlbase.SettingsTableSchema, sqlbase.SettingsTable}, 171 {keys.DescIDSequenceID, sqlbase.DescIDSequenceSchema, sqlbase.DescIDSequence}, 172 {keys.TenantsTableID, sqlbase.TenantsTableSchema, sqlbase.TenantsTable}, 173 {keys.WebSessionsTableID, sqlbase.WebSessionsTableSchema, sqlbase.WebSessionsTable}, 174 {keys.TableStatisticsTableID, sqlbase.TableStatisticsTableSchema, sqlbase.TableStatisticsTable}, 175 {keys.LocationsTableID, sqlbase.LocationsTableSchema, sqlbase.LocationsTable}, 176 {keys.RoleMembersTableID, sqlbase.RoleMembersTableSchema, sqlbase.RoleMembersTable}, 177 {keys.CommentsTableID, sqlbase.CommentsTableSchema, sqlbase.CommentsTable}, 178 {keys.ProtectedTimestampsMetaTableID, sqlbase.ProtectedTimestampsMetaTableSchema, sqlbase.ProtectedTimestampsMetaTable}, 179 {keys.ProtectedTimestampsRecordsTableID, sqlbase.ProtectedTimestampsRecordsTableSchema, sqlbase.ProtectedTimestampsRecordsTable}, 180 {keys.RoleOptionsTableID, sqlbase.RoleOptionsTableSchema, sqlbase.RoleOptionsTable}, 181 {keys.StatementBundleChunksTableID, sqlbase.StatementBundleChunksTableSchema, sqlbase.StatementBundleChunksTable}, 182 {keys.StatementDiagnosticsRequestsTableID, sqlbase.StatementDiagnosticsRequestsTableSchema, sqlbase.StatementDiagnosticsRequestsTable}, 183 {keys.StatementDiagnosticsTableID, sqlbase.StatementDiagnosticsTableSchema, sqlbase.StatementDiagnosticsTable}, 184 } { 185 privs := *test.pkg.Privileges 186 gen, err := sql.CreateTestTableDescriptor( 187 context.Background(), 188 keys.SystemDatabaseID, 189 test.id, 190 test.schema, 191 &privs, 192 ) 193 if err != nil { 194 t.Fatalf("test: %+v, err: %v", test, err) 195 } 196 require.NoError(t, gen.ValidateTable()) 197 198 if !proto.Equal(&test.pkg, &gen) { 199 diff := strings.Join(pretty.Diff(&test.pkg, &gen), "\n") 200 t.Errorf("%s table descriptor generated from CREATE TABLE statement does not match "+ 201 "hardcoded table descriptor:\n%s", test.pkg.Name, diff) 202 } 203 } 204 }