// GetZoneConfig returns the zone config for the object with 'id'. func GetZoneConfig(cfg config.SystemConfig, id uint32) (config.ZoneConfig, bool, error) { // Look in the zones table. if zoneVal := cfg.GetValue(sqlbase.MakeZoneKey(sqlbase.ID(id))); zoneVal != nil { // We're done. zone, err := config.MigrateZoneConfig(zoneVal) return zone, true, err } // No zone config for this ID. We need to figure out if it's a database // or table. Lookup its descriptor. if descVal := cfg.GetValue(sqlbase.MakeDescMetadataKey(sqlbase.ID(id))); descVal != nil { // Determine whether this is a database or table. var desc sqlbase.Descriptor if err := descVal.GetProto(&desc); err != nil { return config.ZoneConfig{}, false, err } if tableDesc := desc.GetTable(); tableDesc != nil { // This is a table descriptor. Lookup its parent database zone config. return GetZoneConfig(cfg, uint32(tableDesc.ParentID)) } } // Retrieve the default zone config, but only as long as that wasn't the ID // we were trying to retrieve (avoid infinite recursion). if id != keys.RootNamespaceID { return GetZoneConfig(cfg, keys.RootNamespaceID) } // No descriptor or not a table. return config.ZoneConfig{}, false, nil }
// TestRenameTable tests the table descriptor changes during // a rename operation. func TestRenameTable(t *testing.T) { defer leaktest.AfterTest(t)() s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() counter := int64(keys.MaxReservedDescID) counter++ oldDBID := sqlbase.ID(counter) if _, err := db.Exec(`CREATE DATABASE test`); err != nil { t.Fatal(err) } // Create table in 'test'. counter++ oldName := "foo" if _, err := db.Exec(`CREATE TABLE test.foo (k INT PRIMARY KEY, v int)`); err != nil { t.Fatal(err) } // Check the table descriptor. desc := &sqlbase.Descriptor{} tableDescKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(counter)) if err := kvDB.GetProto(context.TODO(), tableDescKey, desc); err != nil { t.Fatal(err) } tableDesc := desc.GetTable() if tableDesc.Name != oldName { t.Fatalf("Wrong table name, expected %s, got: %+v", oldName, tableDesc) } if tableDesc.ParentID != oldDBID { t.Fatalf("Wrong parent ID on table, expected %d, got: %+v", oldDBID, tableDesc) } // Create database test2. counter++ newDBID := sqlbase.ID(counter) if _, err := db.Exec(`CREATE DATABASE test2`); err != nil { t.Fatal(err) } // Move table to test2 and change its name as well. newName := "bar" if _, err := db.Exec(`ALTER TABLE test.foo RENAME TO test2.bar`); err != nil { t.Fatal(err) } // Check the table descriptor again. if err := kvDB.GetProto(context.TODO(), tableDescKey, desc); err != nil { t.Fatal(err) } tableDesc = desc.GetTable() if tableDesc.Name != newName { t.Fatalf("Wrong table name, expected %s, got: %+v", newName, tableDesc) } if tableDesc.ParentID != newDBID { t.Fatalf("Wrong parent ID on table, expected %d, got: %+v", newDBID, tableDesc) } }
// queryNamespaceID queries for the ID of the namespace with the given name and // parent ID. func (s *adminServer) queryNamespaceID( session *sql.Session, parentID sqlbase.ID, name string, ) (sqlbase.ID, error) { const query = `SELECT id FROM system.namespace WHERE parentID = $1 AND name = $2` params := parser.NewPlaceholderInfo() params.SetValue(`1`, parser.NewDInt(parser.DInt(parentID))) params.SetValue(`2`, parser.NewDString(name)) r := s.server.sqlExecutor.ExecuteStatements(session, query, params) defer r.Close() if err := s.checkQueryResults(r.ResultList, 1); err != nil { return 0, err } result := r.ResultList[0] if result.Rows.Len() == 0 { return 0, errors.Errorf("namespace %s with ParentID %d not found", name, parentID) } var id int64 scanner := resultScanner{} err := scanner.ScanIndex(result.Rows.At(0), 0, &id) if err != nil { return 0, err } return sqlbase.ID(id), nil }
// getTableID retrieves the table ID for the specified table. func getTableID(p *planner, tn *parser.TableName) (sqlbase.ID, error) { if err := tn.QualifyWithDatabase(p.session.Database); err != nil { return 0, err } virtual, err := p.session.virtualSchemas.getVirtualTableDesc(tn) if err != nil { return 0, err } if virtual != nil { return virtual.GetID(), nil } dbID, err := p.getDatabaseID(tn.Database()) if err != nil { return 0, err } nameKey := tableKey{dbID, tn.Table()} key := nameKey.Key() gr, err := p.txn.Get(key) if err != nil { return 0, err } if !gr.Exists() { return 0, sqlbase.NewUndefinedTableError(parser.AsString(tn)) } return sqlbase.ID(gr.ValueInt()), nil }
func queryZones(conn *sqlConn) (map[sqlbase.ID]config.ZoneConfig, error) { rows, err := makeQuery(`SELECT * FROM system.zones`)(conn) if err != nil { return nil, err } defer func() { _ = rows.Close() }() vals := make([]driver.Value, len(rows.Columns())) zones := make(map[sqlbase.ID]config.ZoneConfig) for { if err := rows.Next(vals); err != nil { if err == io.EOF { break } return nil, err } id, ok := vals[0].(int64) if !ok { return nil, fmt.Errorf("unexpected value: %T", vals[0]) } zone := config.ZoneConfig{} if err := unmarshalProto(vals[1], &zone); err != nil { return nil, err } zones[sqlbase.ID(id)] = zone } return zones, nil }
func queryNamespace(conn *sqlConn, parentID sqlbase.ID, name string) (sqlbase.ID, error) { rows, err := makeQuery( `SELECT id FROM system.namespace WHERE parentID = $1 AND name = $2`, parentID, parser.Name(name).Normalize())(conn) if err != nil { return 0, err } defer func() { _ = rows.Close() }() if err != nil { return 0, fmt.Errorf("%s not found: %v", name, err) } if len(rows.Columns()) != 1 { return 0, fmt.Errorf("unexpected result columns: %d", len(rows.Columns())) } vals := make([]driver.Value, 1) if err := rows.Next(vals); err != nil { return 0, err } switch t := vals[0].(type) { case int64: return sqlbase.ID(t), nil default: return 0, fmt.Errorf("unexpected result type: %T", vals[0]) } }
// getCachedDatabaseDesc implements the DatabaseAccessor interface. func (p *planner) getCachedDatabaseDesc(name string) (*sqlbase.DatabaseDescriptor, error) { if name == sqlbase.SystemDB.Name { return &sqlbase.SystemDB, nil } nameKey := databaseKey{name} nameVal := p.systemConfig.GetValue(nameKey.Key()) if nameVal == nil { return nil, fmt.Errorf("database %q does not exist in system cache", name) } id, err := nameVal.GetInt() if err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(id)) descVal := p.systemConfig.GetValue(descKey) if descVal == nil { return nil, fmt.Errorf("database %q has name entry, but no descriptor in system cache", name) } desc := &sqlbase.Descriptor{} if err := descVal.GetProto(desc); err != nil { return nil, err } database := desc.GetDatabase() if database == nil { return nil, errors.Errorf("%q is not a database", name) } return database, database.Validate() }
// GenerateUniqueDescID returns the next available Descriptor ID and increments // the counter. func GenerateUniqueDescID(txn *client.Txn) (sqlbase.ID, error) { // Increment unique descriptor counter. ir, err := txn.Inc(keys.DescIDGenerator, 1) if err != nil { return 0, err } return sqlbase.ID(ir.ValueInt() - 1), nil }
func restoreTableDesc( ctx context.Context, txn *client.Txn, database sqlbase.DatabaseDescriptor, table sqlbase.TableDescriptor, ) error { // Run getDescriptorID again to make sure the database hasn't been dropped // while we were importing. var err error if table.ParentID, err = getDescriptorID(txn, tableKey{name: database.Name}); err != nil { return err } tableIDKey := tableKey{parentID: table.ParentID, name: table.Name}.Key() tableDescKey := sqlbase.MakeDescMetadataKey(table.ID) // Check for an existing table. var existingDesc sqlbase.Descriptor existingIDKV, err := txn.Get(tableIDKey) if err != nil { return err } if existingIDKV.Value != nil { existingID, err := existingIDKV.Value.GetInt() if err != nil { return err } existingDescKV, err := txn.Get(sqlbase.MakeDescMetadataKey(sqlbase.ID(existingID))) if err != nil { return err } if err := existingDescKV.Value.GetProto(&existingDesc); err != nil { return err } } // Write the new descriptors. First the ID -> TableDescriptor for the new // table, then flip (or initialize) the name -> ID entry so any new queries // will use the new one. If there was an existing table, it can now be // cleaned up. b := txn.NewBatch() b.CPut(tableDescKey, sqlbase.WrapDescriptor(&table), nil) if existingTable := existingDesc.GetTable(); existingTable == nil { b.CPut(tableIDKey, table.ID, nil) } else { existingIDKV.Value.ClearChecksum() b.CPut(tableIDKey, table.ID, existingIDKV.Value) // TODO(dan): This doesn't work for interleaved tables. Fix it when we // fix the empty range interleaved table TODO below. existingDataPrefix := roachpb.Key(keys.MakeTablePrefix(uint32(existingTable.ID))) b.DelRange(existingDataPrefix, existingDataPrefix.PrefixEnd(), false) zoneKey, _, descKey := GetKeysForTableDescriptor(existingTable) // Delete the desc and zone entries. Leave the name because the new // table is using it. b.Del(descKey) b.Del(zoneKey) } return txn.Run(b) }
func getDescriptorID(txn *client.Txn, key sqlbase.DescriptorKey) (sqlbase.ID, error) { // TODO(dan): Share this with (*planner).getDescriptor. idValue, err := txn.Get(key.Key()) if err != nil { return 0, err } if !idValue.Exists() { return 0, errors.Errorf("no descriptor for key: %s", key) } return sqlbase.ID(idValue.ValueInt()), nil }
// resolveName resolves a table name to a descriptor ID by looking in the // database. If the mapping is not found, sqlbase.ErrDescriptorNotFound is returned. func (m *LeaseManager) resolveName( txn *client.Txn, dbID sqlbase.ID, tableName string, ) (sqlbase.ID, error) { nameKey := tableKey{dbID, tableName} key := nameKey.Key() gr, err := txn.Get(key) if err != nil { return 0, err } if !gr.Exists() { return 0, sqlbase.ErrDescriptorNotFound } return sqlbase.ID(gr.ValueInt()), nil }
func expectDescriptorID(systemConfig config.SystemConfig, idKey roachpb.Key, id sqlbase.ID) error { idValue := systemConfig.GetValue(idKey) if idValue == nil { return errStaleMetadata } cachedID, err := idValue.GetInt() if err != nil { return err } if sqlbase.ID(cachedID) != id { return errStaleMetadata } return nil }
func getDescriptor( txn *client.Txn, plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ) (bool, error) { gr, err := txn.Get(plainKey.Key()) if err != nil { return false, err } if !gr.Exists() { return false, nil } descKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(gr.ValueInt())) desc := &sqlbase.Descriptor{} if err := txn.GetProto(descKey, desc); err != nil { return false, err } switch t := descriptor.(type) { case *sqlbase.TableDescriptor: table := desc.GetTable() if table == nil { return false, errors.Errorf("%q is not a table", plainKey.Name()) } table.MaybeUpgradeFormatVersion() // TODO(dan): Write the upgraded TableDescriptor back to kv. This will break // the ability to use a previous version of cockroach with the on-disk data, // but it's worth it to avoid having to do the upgrade every time the // descriptor is fetched. Our current test for this enforces compatibility // backward and forward, so that'll have to be extended before this is done. if err := table.Validate(txn); err != nil { return false, err } *t = *table case *sqlbase.DatabaseDescriptor: database := desc.GetDatabase() if database == nil { return false, errors.Errorf("%q is not a database", plainKey.Name()) } if err := database.Validate(); err != nil { return false, err } *t = *database } return true, nil }
func TestSchemaChangeLease(t *testing.T) { defer leaktest.AfterTest(t)() params, _ := createTestServerParams() s, sqlDB, kvDB := serverutils.StartServer(t, params) defer s.Stopper().Stop() // Set MinSchemaChangeLeaseDuration to always expire the lease. minLeaseDuration := csql.MinSchemaChangeLeaseDuration csql.MinSchemaChangeLeaseDuration = 2 * csql.SchemaChangeLeaseDuration defer func() { csql.MinSchemaChangeLeaseDuration = minLeaseDuration }() if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR); `); err != nil { t.Fatal(err) } var lease sqlbase.TableDescriptor_SchemaChangeLease var id = sqlbase.ID(keys.MaxReservedDescID + 2) var node = roachpb.NodeID(2) changer := csql.NewSchemaChangerForTesting(id, 0, node, *kvDB, nil) // Acquire a lease. lease, err := changer.AcquireLease() if err != nil { t.Fatal(err) } if !validExpirationTime(lease.ExpirationTime) { t.Fatalf("invalid expiration time: %s", time.Unix(0, lease.ExpirationTime)) } // Acquiring another lease will fail. if _, err := changer.AcquireLease(); !testutils.IsError( err, "an outstanding schema change lease exists", ) { t.Fatal(err) } // Extend the lease. newLease, err := changer.ExtendLease(lease) if err != nil { t.Fatal(err) } if !validExpirationTime(newLease.ExpirationTime) { t.Fatalf("invalid expiration time: %s", time.Unix(0, newLease.ExpirationTime)) } // The new lease is a brand new lease. if newLease == lease { t.Fatalf("lease was not extended: %v", lease) } // Extending an old lease fails. if _, err := changer.ExtendLease(lease); !testutils.IsError(err, "table: .* has lease") { t.Fatal(err) } // Releasing an old lease fails. err = changer.ReleaseLease(lease) if err == nil { t.Fatal("releasing a old lease succeeded") } // Release lease. err = changer.ReleaseLease(newLease) if err != nil { t.Fatal(err) } // Extending the lease fails. _, err = changer.ExtendLease(newLease) if err == nil { t.Fatalf("was able to extend an already released lease: %d, %v", id, lease) } // acquiring the lease succeeds lease, err = changer.AcquireLease() if err != nil { t.Fatal(err) } // Set MinSchemaChangeLeaseDuration to not expire the lease. csql.MinSchemaChangeLeaseDuration = minLeaseDuration newLease, err = changer.ExtendLease(lease) if err != nil { t.Fatal(err) } // The old lease is renewed. if newLease != lease { t.Fatalf("acquired new lease: %v, old lease: %v", newLease, lease) } }
func TestSchemaChangeProcess(t *testing.T) { defer leaktest.AfterTest(t)() // The descriptor changes made must have an immediate effect // so disable leases on tables. defer csql.TestDisableTableLeases()() params, _ := createTestServerParams() // Disable external processing of mutations. params.Knobs.SQLSchemaChanger = &csql.SchemaChangerTestingKnobs{ AsyncExecNotification: asyncSchemaChangerDisabled, } s, sqlDB, kvDB := serverutils.StartServer(t, params) defer s.Stopper().Stop() var id = sqlbase.ID(keys.MaxReservedDescID + 2) var node = roachpb.NodeID(2) stopper := stop.NewStopper() leaseMgr := csql.NewLeaseManager( &base.NodeIDContainer{}, *kvDB, hlc.NewClock(hlc.UnixNano, time.Nanosecond), csql.LeaseManagerTestingKnobs{}, stopper, &csql.MemoryMetrics{}, ) defer stopper.Stop() changer := csql.NewSchemaChangerForTesting(id, 0, node, *kvDB, leaseMgr) if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.test (k CHAR PRIMARY KEY, v CHAR, INDEX foo(v)); INSERT INTO t.test VALUES ('a', 'b'), ('c', 'd'); `); err != nil { t.Fatal(err) } // Read table descriptor for version. tableDesc := sqlbase.GetTableDescriptor(kvDB, "t", "test") expectedVersion := tableDesc.Version desc, err := changer.MaybeIncrementVersion() if err != nil { t.Fatal(err) } tableDesc = desc.GetTable() newVersion := tableDesc.Version if newVersion != expectedVersion { t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) } isDone, err := changer.IsDone() if err != nil { t.Fatal(err) } if !isDone { t.Fatalf("table expected to not have an outstanding schema change: %v", tableDesc) } // Check that MaybeIncrementVersion increments the version // correctly. expectedVersion++ tableDesc.UpVersion = true if err := kvDB.Put( context.TODO(), sqlbase.MakeDescMetadataKey(tableDesc.ID), sqlbase.WrapDescriptor(tableDesc), ); err != nil { t.Fatal(err) } isDone, err = changer.IsDone() if err != nil { t.Fatal(err) } if isDone { t.Fatalf("table expected to have an outstanding schema change: %v", desc.GetTable()) } desc, err = changer.MaybeIncrementVersion() if err != nil { t.Fatal(err) } tableDesc = desc.GetTable() savedTableDesc := sqlbase.GetTableDescriptor(kvDB, "t", "test") newVersion = tableDesc.Version if newVersion != expectedVersion { t.Fatalf("bad version in returned desc; e = %d, v = %d", expectedVersion, newVersion) } newVersion = savedTableDesc.Version if newVersion != expectedVersion { t.Fatalf("bad version in saved desc; e = %d, v = %d", expectedVersion, newVersion) } isDone, err = changer.IsDone() if err != nil { t.Fatal(err) } if !isDone { t.Fatalf("table expected to not have an outstanding schema change: %v", tableDesc) } // Check that RunStateMachineBeforeBackfill doesn't do anything // if there are no mutations queued. if err := changer.RunStateMachineBeforeBackfill(); err != nil { t.Fatal(err) } tableDesc = sqlbase.GetTableDescriptor(kvDB, "t", "test") newVersion = tableDesc.Version if newVersion != expectedVersion { t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) } // Check that RunStateMachineBeforeBackfill functions properly. expectedVersion = tableDesc.Version // Make a copy of the index for use in a mutation. index := protoutil.Clone(&tableDesc.Indexes[0]).(*sqlbase.IndexDescriptor) index.Name = "bar" index.ID = tableDesc.NextIndexID tableDesc.NextIndexID++ changer = csql.NewSchemaChangerForTesting(id, tableDesc.NextMutationID, node, *kvDB, leaseMgr) tableDesc.Mutations = append(tableDesc.Mutations, sqlbase.DescriptorMutation{ Descriptor_: &sqlbase.DescriptorMutation_Index{Index: index}, Direction: sqlbase.DescriptorMutation_ADD, State: sqlbase.DescriptorMutation_DELETE_ONLY, MutationID: tableDesc.NextMutationID, }) tableDesc.NextMutationID++ // Run state machine in both directions. for _, direction := range []sqlbase.DescriptorMutation_Direction{sqlbase.DescriptorMutation_ADD, sqlbase.DescriptorMutation_DROP} { tableDesc.Mutations[0].Direction = direction expectedVersion++ if err := kvDB.Put( context.TODO(), sqlbase.MakeDescMetadataKey(tableDesc.ID), sqlbase.WrapDescriptor(tableDesc), ); err != nil { t.Fatal(err) } // The expected end state. expectedState := sqlbase.DescriptorMutation_WRITE_ONLY if direction == sqlbase.DescriptorMutation_DROP { expectedState = sqlbase.DescriptorMutation_DELETE_ONLY } // Run two times to ensure idempotency of operations. for i := 0; i < 2; i++ { if err := changer.RunStateMachineBeforeBackfill(); err != nil { t.Fatal(err) } tableDesc = sqlbase.GetTableDescriptor(kvDB, "t", "test") newVersion = tableDesc.Version if newVersion != expectedVersion { t.Fatalf("bad version; e = %d, v = %d", expectedVersion, newVersion) } state := tableDesc.Mutations[0].State if state != expectedState { t.Fatalf("bad state; e = %d, v = %d", expectedState, state) } } } // RunStateMachineBeforeBackfill() doesn't complete the schema change. isDone, err = changer.IsDone() if err != nil { t.Fatal(err) } if isDone { t.Fatalf("table expected to have an outstanding schema change: %v", tableDesc) } }
func TestSystemConfigGossip(t *testing.T) { defer leaktest.AfterTest(t)() t.Skip("#12351") s, _, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() ts := s.(*TestServer) ctx := context.TODO() key := sqlbase.MakeDescMetadataKey(keys.MaxReservedDescID) valAt := func(i int) *sqlbase.DatabaseDescriptor { return &sqlbase.DatabaseDescriptor{Name: "foo", ID: sqlbase.ID(i)} } // Register a callback for gossip updates. resultChan := ts.Gossip().RegisterSystemConfigChannel() // The span gets gossiped when it first shows up. select { case <-resultChan: case <-time.After(500 * time.Millisecond): t.Fatal("did not receive gossip message") } // Try a plain KV write first. if err := kvDB.Put(ctx, key, valAt(0)); err != nil { t.Fatal(err) } // Now do it as part of a transaction, but without the trigger set. if err := kvDB.Txn(ctx, func(txn *client.Txn) error { return txn.Put(key, valAt(1)) }); err != nil { t.Fatal(err) } // Gossip channel should be dormant. // TODO(tschottdorf): This test is likely flaky. Why can't some other // process trigger gossip? It seems that a new range lease being // acquired will gossip a new system config since the hash changed and fail // the test (seen in practice during some buggy WIP). var systemConfig config.SystemConfig select { case <-resultChan: systemConfig, _ = ts.gossip.GetSystemConfig() t.Fatalf("unexpected message received on gossip channel: %v", systemConfig) case <-time.After(50 * time.Millisecond): } // This time mark the transaction as having a Gossip trigger. if err := kvDB.Txn(ctx, func(txn *client.Txn) error { txn.SetSystemConfigTrigger() return txn.Put(key, valAt(2)) }); err != nil { t.Fatal(err) } // New system config received. select { case <-resultChan: systemConfig, _ = ts.gossip.GetSystemConfig() case <-time.After(500 * time.Millisecond): t.Fatal("did not receive gossip message") } // Now check the new config. var val *roachpb.Value for _, kv := range systemConfig.Values { if bytes.Equal(key, kv.Key) { val = &kv.Value break } } if val == nil { t.Fatal("key not found in gossiped info") } // Make sure the returned value is valAt(2). got := new(sqlbase.DatabaseDescriptor) if err := val.GetProto(got); err != nil { t.Fatal(err) } if expected := valAt(2); !reflect.DeepEqual(got, expected) { t.Fatalf("mismatch: expected %+v, got %+v", *expected, *got) } }
func TestGolangQueryArgs(t *testing.T) { defer leaktest.AfterTest(t)() // Each test case pairs an arbitrary value and parser.Datum which has the same // type testCases := []struct { value interface{} expectedType reflect.Type }{ // Null type. {nil, reflect.TypeOf(parser.TypeNull)}, // Bool type. {true, reflect.TypeOf(parser.TypeBool)}, // Primitive Integer types. {int(1), reflect.TypeOf(parser.TypeInt)}, {int8(1), reflect.TypeOf(parser.TypeInt)}, {int16(1), reflect.TypeOf(parser.TypeInt)}, {int32(1), reflect.TypeOf(parser.TypeInt)}, {int64(1), reflect.TypeOf(parser.TypeInt)}, {uint(1), reflect.TypeOf(parser.TypeInt)}, {uint8(1), reflect.TypeOf(parser.TypeInt)}, {uint16(1), reflect.TypeOf(parser.TypeInt)}, {uint32(1), reflect.TypeOf(parser.TypeInt)}, {uint64(1), reflect.TypeOf(parser.TypeInt)}, // Primitive Float types. {float32(1.0), reflect.TypeOf(parser.TypeFloat)}, {float64(1.0), reflect.TypeOf(parser.TypeFloat)}, // Decimal type. {inf.NewDec(55, 1), reflect.TypeOf(parser.TypeDecimal)}, // String type. {"test", reflect.TypeOf(parser.TypeString)}, // Bytes type. {[]byte("abc"), reflect.TypeOf(parser.TypeBytes)}, // Interval and timestamp. {time.Duration(1), reflect.TypeOf(parser.TypeInterval)}, {timeutil.Now(), reflect.TypeOf(parser.TypeTimestamp)}, // Primitive type aliases. {roachpb.NodeID(1), reflect.TypeOf(parser.TypeInt)}, {sqlbase.ID(1), reflect.TypeOf(parser.TypeInt)}, {floatAlias(1), reflect.TypeOf(parser.TypeFloat)}, {boolAlias(true), reflect.TypeOf(parser.TypeBool)}, {stringAlias("string"), reflect.TypeOf(parser.TypeString)}, // Byte slice aliases. {roachpb.Key("key"), reflect.TypeOf(parser.TypeBytes)}, {roachpb.RKey("key"), reflect.TypeOf(parser.TypeBytes)}, } pinfo := &parser.PlaceholderInfo{} for i, tcase := range testCases { golangFillQueryArguments(pinfo, []interface{}{tcase.value}) output, valid := pinfo.Type("1") if !valid { t.Errorf("case %d failed: argument was invalid", i) continue } if a, e := reflect.TypeOf(output), tcase.expectedType; a != e { t.Errorf("case %d failed: expected type %s, got %s", i, e.String(), a.String()) } } }
func TestDropTable(t *testing.T) { defer leaktest.AfterTest(t)() params, _ := createTestServerParams() s, sqlDB, kvDB := serverutils.StartServer(t, params) defer s.Stopper().Stop() ctx := context.TODO() numRows := 2*sql.TableTruncateChunkSize + 1 createKVTable(t, sqlDB, numRows) tableDesc := sqlbase.GetTableDescriptor(kvDB, "t", "kv") nameKey := sqlbase.MakeNameMetadataKey(keys.MaxReservedDescID+1, "kv") gr, err := kvDB.Get(ctx, nameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf("Name entry %q does not exist", nameKey) } descKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(gr.ValueInt())) // Add a zone config for the table. cfg := config.DefaultZoneConfig() buf, err := protoutil.Marshal(&cfg) if err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, tableDesc.ID, buf); err != nil { t.Fatal(err) } zoneKey := sqlbase.MakeZoneKey(tableDesc.ID) if gr, err := kvDB.Get(ctx, zoneKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatalf("zone config entry not found") } tablePrefix := roachpb.Key(keys.MakeTablePrefix(uint32(tableDesc.ID))) checkKeyCount(t, kvDB, tablePrefix, 3*numRows) if _, err := sqlDB.Exec(`DROP TABLE t.kv`); err != nil { t.Fatal(err) } checkKeyCount(t, kvDB, tablePrefix, 0) // Test that deleted table cannot be used. This prevents regressions where // name -> descriptor ID caches might make this statement erronously work. if _, err := sqlDB.Exec(`SELECT * FROM t.kv`); !testutils.IsError(err, `table "t.kv" does not exist`) { t.Fatalf("different error than expected: %v", err) } if gr, err := kvDB.Get(ctx, descKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor still exists after the table is dropped") } if gr, err := kvDB.Get(ctx, nameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table namekey still exists after the table is dropped") } if gr, err := kvDB.Get(ctx, zoneKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("zone config entry still exists after the table is dropped") } }
func TestDropDatabase(t *testing.T) { defer leaktest.AfterTest(t)() params, _ := createTestServerParams() s, sqlDB, kvDB := serverutils.StartServer(t, params) defer s.Stopper().Stop() ctx := context.TODO() // Fix the column families so the key counts below don't change if the // family heuristics are updated. if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR, FAMILY (k), FAMILY (v)); INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd'); `); err != nil { t.Fatal(err) } dbNameKey := sqlbase.MakeNameMetadataKey(keys.RootNamespaceID, "t") r, err := kvDB.Get(ctx, dbNameKey) if err != nil { t.Fatal(err) } if !r.Exists() { t.Fatalf(`database "t" does not exist`) } dbDescKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(r.ValueInt())) desc := &sqlbase.Descriptor{} if err := kvDB.GetProto(ctx, dbDescKey, desc); err != nil { t.Fatal(err) } dbDesc := desc.GetDatabase() tbNameKey := sqlbase.MakeNameMetadataKey(dbDesc.ID, "kv") gr, err := kvDB.Get(ctx, tbNameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf(`table "kv" does not exist`) } tbDescKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(gr.ValueInt())) if err := kvDB.GetProto(ctx, tbDescKey, desc); err != nil { t.Fatal(err) } tbDesc := desc.GetTable() // Add a zone config for both the table and database. cfg := config.DefaultZoneConfig() buf, err := protoutil.Marshal(&cfg) if err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, tbDesc.ID, buf); err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, dbDesc.ID, buf); err != nil { t.Fatal(err) } tbZoneKey := sqlbase.MakeZoneKey(tbDesc.ID) dbZoneKey := sqlbase.MakeZoneKey(dbDesc.ID) if gr, err := kvDB.Get(ctx, tbZoneKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatalf("table zone config entry not found") } if gr, err := kvDB.Get(ctx, dbZoneKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatalf("database zone config entry not found") } tablePrefix := keys.MakeTablePrefix(uint32(tbDesc.ID)) tableStartKey := roachpb.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if kvs, err := kvDB.Scan(ctx, tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 6; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if _, err := sqlDB.Exec(`DROP DATABASE t`); err != nil { t.Fatal(err) } if kvs, err := kvDB.Scan(ctx, tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 0; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if gr, err := kvDB.Get(ctx, tbDescKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor still exists after database is dropped: %q", tbDescKey) } if gr, err := kvDB.Get(ctx, tbNameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor key still exists after database is dropped") } if gr, err := kvDB.Get(ctx, dbDescKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("database descriptor still exists after database is dropped") } if gr, err := kvDB.Get(ctx, dbNameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("database descriptor key still exists after database is dropped") } if gr, err := kvDB.Get(ctx, tbZoneKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table zone config entry still exists after the database is dropped") } if gr, err := kvDB.Get(ctx, dbZoneKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("database zone config entry still exists after the database is dropped") } }
"github.com/pkg/errors" "golang.org/x/net/context" "github.com/cockroachdb/cockroach/pkg/config" "github.com/cockroachdb/cockroach/pkg/internal/client" "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/server" "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" "github.com/cockroachdb/cockroach/pkg/util/leaktest" "github.com/cockroachdb/cockroach/pkg/util/protoutil" ) var configID = sqlbase.ID(1) var configDescKey = sqlbase.MakeDescMetadataKey(keys.MaxReservedDescID) // forceNewConfig forces a system config update by writing a bogus descriptor with an // incremented value inside. It then repeatedly fetches the gossip config until the // just-written descriptor is found. func forceNewConfig(t *testing.T, s *server.TestServer) config.SystemConfig { configID++ configDesc := &sqlbase.Descriptor{ Union: &sqlbase.Descriptor_Database{ Database: &sqlbase.DatabaseDescriptor{ Name: "sentinel", ID: configID, Privileges: &sqlbase.PrivilegeDescriptor{}, }, },
func TestDatabaseDescriptor(t *testing.T) { defer leaktest.AfterTest(t)() params, _ := createTestServerParams() s, sqlDB, kvDB := serverutils.StartServer(t, params) defer s.Stopper().Stop() ctx := context.TODO() expectedCounter := int64(keys.MaxReservedDescID + 1) // Test values before creating the database. // descriptor ID counter. if ir, err := kvDB.Get(ctx, keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. nameKey := sqlbase.MakeNameMetadataKey(keys.RootNamespaceID, "test") if gr, err := kvDB.Get(ctx, nameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatal("expected non-existing key") } // Write a descriptor key that will interfere with database creation. dbDescKey := sqlbase.MakeDescMetadataKey(sqlbase.ID(expectedCounter)) dbDesc := &sqlbase.Descriptor{ Union: &sqlbase.Descriptor_Database{ Database: &sqlbase.DatabaseDescriptor{ Name: "sentinel", ID: sqlbase.ID(expectedCounter), Privileges: &sqlbase.PrivilegeDescriptor{}, }, }, } if err := kvDB.CPut(ctx, dbDescKey, dbDesc, nil); err != nil { t.Fatal(err) } // Database creation should fail, and nothing should have been written. if _, err := sqlDB.Exec(`CREATE DATABASE test`); !testutils.IsError(err, "unexpected value") { t.Fatalf("unexpected error %v", err) } if ir, err := kvDB.Get(ctx, keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } start := roachpb.Key(keys.MakeTablePrefix(uint32(keys.NamespaceTableID))) if kvs, err := kvDB.Scan(ctx, start, start.PrefixEnd(), 0); err != nil { t.Fatal(err) } else { if a, e := len(kvs), server.GetBootstrapSchema().SystemDescriptorCount(); a != e { t.Fatalf("expected %d keys to have been written, found %d keys", e, a) } } // Remove the junk; allow database creation to proceed. if err := kvDB.Del(ctx, dbDescKey); err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil { t.Fatal(err) } expectedCounter++ // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(ctx, keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. if gr, err := kvDB.Get(ctx, nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. if gr, err := kvDB.Get(ctx, dbDescKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // Now try to create it again. We should fail, but not increment the counter. if _, err := sqlDB.Exec(`CREATE DATABASE test`); err == nil { t.Fatal("failure expected") } // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(ctx, keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. if gr, err := kvDB.Get(ctx, nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. if gr, err := kvDB.Get(ctx, dbDescKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } }
func TestSystemConfigGossip(t *testing.T) { defer leaktest.AfterTest(t)() t.Skip("#12351") s, _, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() ts := s.(*TestServer) ctx := context.TODO() key := sqlbase.MakeDescMetadataKey(keys.MaxReservedDescID) valAt := func(i int) *sqlbase.DatabaseDescriptor { return &sqlbase.DatabaseDescriptor{Name: "foo", ID: sqlbase.ID(i)} } // Register a callback for gossip updates. resultChan := ts.Gossip().RegisterSystemConfigChannel() // The span gets gossiped when it first shows up. select { case <-resultChan: case <-time.After(500 * time.Millisecond): t.Fatal("did not receive gossip message") } // Write a system key with the transaction marked as having a Gossip trigger. if err := kvDB.Txn(ctx, func(txn *client.Txn) error { txn.SetSystemConfigTrigger() return txn.Put(key, valAt(2)) }); err != nil { t.Fatal(err) } // This has to be wrapped in a SucceedSoon because system migrations on the // testserver's startup can trigger system config updates without the key we // wrote. testutils.SucceedsSoon(t, func() error { // New system config received. var systemConfig config.SystemConfig select { case <-resultChan: systemConfig, _ = ts.gossip.GetSystemConfig() case <-time.After(500 * time.Millisecond): return errors.Errorf("did not receive gossip message") } // Now check the new config. var val *roachpb.Value for _, kv := range systemConfig.Values { if bytes.Equal(key, kv.Key) { val = &kv.Value break } } if val == nil { return errors.Errorf("key not found in gossiped info") } // Make sure the returned value is valAt(2). got := new(sqlbase.DatabaseDescriptor) if err := val.GetProto(got); err != nil { return err } if expected := valAt(2); !reflect.DeepEqual(got, expected) { return errors.Errorf("mismatch: expected %+v, got %+v", *expected, *got) } return nil }) }