func (c *conn) CreateTable(p *parser.CreateTable, args []driver.Value) (*rows, error) { if err := c.normalizeTableName(p.Table); err != nil { return nil, err } dbID, err := c.lookupDatabase(p.Table.Qualifier) if err != nil { return nil, err } schema, err := makeSchema(p) if err != nil { return nil, err } desc := structured.TableDescFromSchema(schema) if err := structured.ValidateTableDesc(desc); err != nil { return nil, err } nameKey := keys.MakeNameMetadataKey(dbID, p.Table.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 := c.db.Get(nameKey); err != nil { return nil, err } else if gr.Exists() { if p.IfNotExists { return &rows{}, nil } return nil, fmt.Errorf("table \"%s\" already exists", p.Table) } ir, err := c.db.Inc(keys.DescIDGenerator, 1) if err != nil { return nil, 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. err = c.db.Txn(func(txn *client.Txn) error { descKey := keys.MakeDescMetadataKey(desc.ID) b := &client.Batch{} b.CPut(nameKey, descKey, nil) b.Put(descKey, &desc) return txn.Commit(b) }) if err != nil { // TODO(pmattis): Need to handle if-not-exists here as well. return nil, err } return &rows{}, nil }
// 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(schema structured.TableSchema) error { schema.Name = strings.ToLower(schema.Name) desc := structured.TableDescFromSchema(schema) if err := structured.ValidateTableDesc(desc); 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) }) }