Пример #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(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)
	})
}
Пример #2
0
func makeSchema(p *parser.CreateTable) (structured.TableSchema, error) {
	s := structured.TableSchema{}
	s.Name = p.Table.String()

	for _, def := range p.Defs {
		switch d := def.(type) {
		case *parser.ColumnTableDef:
			col := structured.Column{
				Name:     d.Name,
				Nullable: (d.Nullable != parser.NotNull),
			}
			switch t := d.Type.(type) {
			case *parser.BitType:
				col.Type.Kind = structured.ColumnType_BIT
				col.Type.Width = int32(t.N)
			case *parser.IntType:
				col.Type.Kind = structured.ColumnType_INT
				col.Type.Width = int32(t.N)
			case *parser.FloatType:
				col.Type.Kind = structured.ColumnType_FLOAT
				col.Type.Width = int32(t.N)
				col.Type.Precision = int32(t.Prec)
			case *parser.DecimalType:
				col.Type.Kind = structured.ColumnType_DECIMAL
				col.Type.Width = int32(t.N)
				col.Type.Precision = int32(t.Prec)
			case *parser.DateType:
				col.Type.Kind = structured.ColumnType_DATE
			case *parser.TimeType:
				col.Type.Kind = structured.ColumnType_TIME
			case *parser.DateTimeType:
				col.Type.Kind = structured.ColumnType_DATETIME
			case *parser.TimestampType:
				col.Type.Kind = structured.ColumnType_TIMESTAMP
			case *parser.CharType:
				col.Type.Kind = structured.ColumnType_CHAR
				col.Type.Width = int32(t.N)
			case *parser.BinaryType:
				col.Type.Kind = structured.ColumnType_BINARY
				col.Type.Width = int32(t.N)
			case *parser.TextType:
				col.Type.Kind = structured.ColumnType_TEXT
			case *parser.BlobType:
				col.Type.Kind = structured.ColumnType_BLOB
			case *parser.EnumType:
				col.Type.Kind = structured.ColumnType_ENUM
				col.Type.Vals = t.Vals
			case *parser.SetType:
				col.Type.Kind = structured.ColumnType_SET
				col.Type.Vals = t.Vals
			}
			s.Columns = append(s.Columns, col)

			// Create any associated index.
			if d.PrimaryKey || d.Unique {
				index := structured.TableSchema_IndexByName{
					Index: structured.Index{
						Unique: true,
					},
					ColumnNames: []string{d.Name},
				}
				if d.PrimaryKey {
					index.Name = "primary"
				}
				s.Indexes = append(s.Indexes, index)
			}
		case *parser.IndexTableDef:
			index := structured.TableSchema_IndexByName{
				Index: structured.Index{
					Name:   d.Name,
					Unique: d.Unique,
				},
				ColumnNames: d.Columns,
			}
			s.Indexes = append(s.Indexes, index)
		default:
			return s, fmt.Errorf("unsupported table def: %T", def)
		}
	}
	return s, nil
}