Esempio n. 1
0
// CreateTable creates a table from the specified schema. Table creation will
// fail if the table name is already in use. The table name is required to have
// the form "<namespace>.<table>".
func (db *DB) CreateTable(desc *structured.TableDescriptor) error {
	desc.Name = strings.ToLower(desc.Name)
	if err := desc.AllocateIDs(); err != nil {
		return err
	}

	nsID, name, err := db.lookupTable(desc.Name)
	if err != nil {
		return err
	}
	if name == "" {
		return fmt.Errorf("empty table name: %s", desc.Name)
	}
	nameKey := keys.MakeNameMetadataKey(nsID, name)

	// This isn't strictly necessary as the conditional put below will fail if
	// the key already exists, but it seems good to avoid the table ID allocation
	// in most cases when the table already exists.
	if gr, err := db.Get(nameKey); err != nil {
		return err
	} else if gr.Exists() {
		return fmt.Errorf("table \"%s\" already exists", desc.Name)
	}

	ir, err := db.Inc(keys.DescIDGenerator, 1)
	if err != nil {
		return err
	}
	desc.ID = uint32(ir.ValueInt() - 1)

	// TODO(pmattis): Be cognizant of error messages when this is ported to the
	// server. The error currently returned below is likely going to be difficult
	// to interpret.
	return db.Txn(func(txn *Txn) error {
		descKey := keys.MakeDescMetadataKey(desc.ID)
		b := &Batch{}
		b.CPut(nameKey, descKey, nil)
		b.Put(descKey, desc)
		return txn.Commit(b)
	})
}