func (s *Server) getTableDesc(database string, qname parser.QualifiedName) ( *structured.TableDescriptor, error) { var err error qname, err = s.normalizeTableName(database, qname) if err != nil { return nil, err } dbID, err := s.lookupDatabase(qname.Database()) if err != nil { return nil, err } gr, err := s.db.Get(keys.MakeNameMetadataKey(dbID, qname.Table())) if err != nil { return nil, err } if !gr.Exists() { return nil, fmt.Errorf("table \"%s\" does not exist", qname) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := s.db.GetProto(descKey, &desc); err != nil { return nil, err } if err := desc.Validate(); err != nil { return nil, err } return &desc, nil }
func (db *DB) getTableDesc(path string) (*structured.TableDescriptor, error) { nsID, name, err := db.lookupTable(path) if err != nil { return nil, err } if name == "" { return nil, fmt.Errorf("empty table name: %s", path) } gr, err := db.Get(keys.MakeNameMetadataKey(nsID, name)) if err != nil { return nil, err } if !gr.Exists() { return nil, fmt.Errorf("unable to find table \"%s\"", path) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := db.GetProto(descKey, &desc); err != nil { return nil, err } if err := desc.Validate(); err != nil { return nil, err } return &desc, nil }
func (c *conn) getTableDesc(table *parser.TableName) (*structured.TableDescriptor, error) { if err := c.normalizeTableName(table); err != nil { return nil, err } dbID, err := c.lookupDatabase(table.Qualifier) if err != nil { return nil, err } gr, err := c.db.Get(keys.MakeNameMetadataKey(dbID, table.Name)) if err != nil { return nil, err } if !gr.Exists() { return nil, fmt.Errorf("table \"%s\" does not exist", table) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := c.db.GetProto(descKey, &desc); err != nil { return nil, err } if err := desc.Validate(); err != nil { return nil, err } return &desc, nil }
// DropTable drops a table. // Privileges: WRITE on table. // Notes: postgres allows only the table owner to DROP a table. // mysql requires the DROP privilege on the table. func (p *planner) DropTable(n *parser.DropTable) (planNode, error) { // TODO(XisiHuang): should do truncate and delete descriptor in // the same txn for i, tableQualifiedName := range n.Names { if err := tableQualifiedName.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(tableQualifiedName.Database()) if err != nil { return nil, err } tbKey := tableKey{dbDesc.ID, tableQualifiedName.Table()} nameKey := tbKey.Key() gr, err := p.txn.Get(nameKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. continue } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", tbKey.Name()) } tableDesc := structured.TableDescriptor{} if err := p.txn.GetProto(gr.ValueBytes(), &tableDesc); err != nil { return nil, err } if err := tableDesc.Validate(); err != nil { return nil, err } if !tableDesc.HasPrivilege(p.user, parser.PrivilegeWrite) { return nil, fmt.Errorf("user %s does not have %s privilege on table %s", p.user, parser.PrivilegeWrite, tableDesc.Name) } if _, err = p.Truncate(&parser.Truncate{Tables: n.Names[i : i+1]}); err != nil { return nil, err } // Delete table descriptor descKey := gr.ValueBytes() b := &client.Batch{} b.Del(descKey) b.Del(nameKey) err = p.txn.Run(b) if err != nil { return nil, err } } return &valuesNode{}, nil }
// RenameTable renames a table. Old path and new path have the form // "<namespace>.<table>". func (db *DB) RenameTable(oldPath, newPath string) error { // TODO(pmattis): Should we allow both the old and new name to exist // simultaneously for a period of time? The thought is to allow an // application to access the table via either name while the application is // being upgraded. Alternatively, instead of a rename table operation perhaps // there should be a link table operation which adds a "hard link" to the // table. Similar to a file, a table would not be removed until all of the // hard links are removed. oldNSID, oldName, err := db.lookupTable(oldPath) if err != nil { return err } newNSID, newName, err := db.lookupTable(newPath) if err != nil { return err } if newName == "" { return fmt.Errorf("empty table name: %s", newPath) } return db.Txn(func(txn *Txn) error { oldNameKey := keys.MakeNameMetadataKey(oldNSID, oldName) gr, err := txn.Get(oldNameKey) if err != nil { return err } if !gr.Exists() { return fmt.Errorf("unable to find table \"%s\"", oldPath) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := txn.GetProto(descKey, &desc); err != nil { return err } desc.Name = strings.ToLower(newPath) if err := desc.Validate(); err != nil { return err } newNameKey := keys.MakeNameMetadataKey(newNSID, newName) b := &Batch{} b.Put(descKey, &desc) // If the new name already exists the conditional put will fail causing the // transaction to fail. b.CPut(newNameKey, descKey, nil) b.Del(oldNameKey) return txn.Commit(b) }) }