// createDescriptor implements the DescriptorAccessor interface. func (p *planner) createDescriptor(plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ifNotExists bool) (bool, error) { idKey := plainKey.Key() // Check whether idKey exists. gr, err := p.txn.Get(idKey) if err != nil { return false, err } if gr.Exists() { if ifNotExists { // Noop. return false, nil } // Key exists, but we don't want it to: error out. return false, fmt.Errorf("%s %q already exists", descriptor.TypeName(), plainKey.Name()) } // Increment unique descriptor counter. if ir, err := p.txn.Inc(keys.DescIDGenerator, 1); err == nil { descriptor.SetID(sqlbase.ID(ir.ValueInt() - 1)) } else { return false, err } // TODO(pmattis): The error currently returned below is likely going to be // difficult to interpret. // // TODO(pmattis): Need to handle if-not-exists here as well. // // TODO(pmattis): This is writing the namespace and descriptor table entries, // but not going through the normal INSERT logic and not performing a precise // mimicry. In particular, we're only writing a single key per table, while // perfect mimicry would involve writing a sentinel key for each row as well. descKey := sqlbase.MakeDescMetadataKey(descriptor.GetID()) b := client.Batch{} descID := descriptor.GetID() descDesc := sqlbase.WrapDescriptor(descriptor) if log.V(2) { log.Infof("CPut %s -> %d", idKey, descID) log.Infof("CPut %s -> %s", descKey, descDesc) } b.CPut(idKey, descID, nil) b.CPut(descKey, descDesc, nil) p.setTestingVerifyMetadata(func(systemConfig config.SystemConfig) error { if err := expectDescriptorID(systemConfig, idKey, descID); err != nil { return err } return expectDescriptor(systemConfig, descKey, descDesc) }) return true, p.txn.Run(&b) }
// createDescriptor implements the DescriptorAccessor interface. func (p *planner) createDescriptor( plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ifNotExists bool, ) (bool, error) { idKey := plainKey.Key() if exists, err := p.descExists(idKey); err == nil && exists { if ifNotExists { // Noop. return false, nil } // Key exists, but we don't want it to: error out. return false, descriptorAlreadyExistsErr{descriptor, plainKey.Name()} } else if err != nil { return false, err } id, err := p.generateUniqueDescID() if err != nil { return false, err } return p.createDescriptorWithID(idKey, id, descriptor) }
// getDescriptor implements the DescriptorAccessor interface. func (p *planner) getDescriptor(plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ) (bool, error) { gr, err := p.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 := p.txn.GetProto(descKey, desc); err != nil { return false, err } switch t := descriptor.(type) { case *sqlbase.TableDescriptor: table := desc.GetTable() 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 table == nil { return false, errors.Errorf("%q is not a table", plainKey.Name()) } if err := table.Validate(p.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 }
// getDescriptor implements the DescriptorAccessor interface. func (p *planner) getDescriptor(plainKey sqlbase.DescriptorKey, descriptor sqlbase.DescriptorProto, ) (bool, error) { gr, err := p.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 := p.txn.GetProto(descKey, desc); err != nil { return false, err } switch t := descriptor.(type) { case *sqlbase.TableDescriptor: table := desc.GetTable() if table == nil { return false, util.Errorf("%q is not a table", plainKey.Name()) } *t = *table case *sqlbase.DatabaseDescriptor: database := desc.GetDatabase() if database == nil { return false, util.Errorf("%q is not a database", plainKey.Name()) } *t = *database } if err := descriptor.Validate(); err != nil { return false, err } return true, nil }