Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: Fix #254 #334

Merged
merged 12 commits into from
Oct 10, 2015
51 changes: 47 additions & 4 deletions ddl/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ func (d *ddl) AlterTable(ctx context.Context, ident table.Ident, specs []*AlterS
for _, spec := range specs {
switch spec.Action {
case AlterAddColumn:
if err := d.addColumn(ident.Schema, tbl, spec, is.SchemaMetaVersion()); err != nil {
if err := d.addColumn(ctx, ident.Schema, tbl, spec, is.SchemaMetaVersion()); err != nil {
return errors.Trace(err)
}
default:
Expand All @@ -438,7 +438,7 @@ func (d *ddl) AlterTable(ctx context.Context, ident table.Ident, specs []*AlterS
}

// Add a column into table
func (d *ddl) addColumn(schema model.CIStr, tbl table.Table, spec *AlterSpecification, schemaMetaVersion int64) error {
func (d *ddl) addColumn(ctx context.Context, schema model.CIStr, tbl table.Table, spec *AlterSpecification, schemaMetaVersion int64) error {
// Find position
cols := tbl.Cols()
position := len(cols)
Expand Down Expand Up @@ -489,9 +489,11 @@ func (d *ddl) addColumn(schema model.CIStr, tbl table.Table, spec *AlterSpecific
tb := tbl.(*tables.Table)
tb.Columns = newCols
// TODO: update index
// TODO: update default value
// update infomation schema
if err = updateDefaultValue(ctx, tb, col); err != nil {
return errors.Trace(err)
}

// update infomation schema
err = kv.RunInNewTxn(d.store, false, func(txn kv.Transaction) error {
err := d.verifySchemaMetaVersion(txn, schemaMetaVersion)
if err != nil {
Expand All @@ -506,6 +508,47 @@ func (d *ddl) addColumn(schema model.CIStr, tbl table.Table, spec *AlterSpecific
return errors.Trace(err)
}

func updateDefaultValue(ctx context.Context, t *tables.Table, col *column.Col) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any comment for this function? Or pick up a better name. "updateDefaultValue" is a little confused. "updateOldRows" may be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it.

txn, err := ctx.GetTxn(false)
if err != nil {
return errors.Trace(err)
}
it, err := txn.Seek([]byte(t.FirstKey()), nil)
if err != nil {
return errors.Trace(err)
}
defer it.Close()

prefix := t.KeyPrefix()
for it.Valid() && strings.HasPrefix(it.Key(), prefix) {
handle, err0 := util.DecodeHandleFromRowKey(it.Key())
if err0 != nil {
return errors.Trace(err0)
}
k := t.RecordKey(handle, col)
colID, err0 := tables.ColumnID(k)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that in addColumn there will be no new column, so here colID == col.ID will always be true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep.
here colID == col.ID is always true. Because the key is produced by RecordKey(handle, col)

if err0 != nil {
return errors.Trace(err0)
}
if colID != col.ID {
continue
}

// TODO: check and get timestamp/datetime default value.
// refer to getDefaultValue in stmt/stmts/stmt_helper.go.
if err0 = t.SetColValue(txn, k, col.DefaultValue); err0 != nil {
return errors.Trace(err0)
}

rk := t.RecordKey(handle, nil)
if it, err0 = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)); err0 != nil {
return errors.Trace(err0)
}
}

return nil
}

// drop table will proceed even if some table in the list does not exists
func (d *ddl) DropTable(ctx context.Context, ti table.Ident) (err error) {
is := d.GetInformationSchema()
Expand Down
41 changes: 39 additions & 2 deletions ddl/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/pingcap/tidb/ddl"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/model"
mysql "github.com/pingcap/tidb/mysqldef"
"github.com/pingcap/tidb/parser"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/stmt"
Expand Down Expand Up @@ -78,13 +79,49 @@ func (ts *testSuite) TestT(c *C) {
tbStmt = statement("create table t2 (a int unique not null)").(*stmts.CreateTableStmt)
err = sessionctx.GetDomain(ctx).DDL().CreateTable(ctx, tbIdent2, tbStmt.Cols, tbStmt.Constraints)
c.Assert(err, IsNil)
tb, err := sessionctx.GetDomain(ctx).InfoSchema().TableByName(tbIdent2.Schema, tbIdent2.Name)
c.Assert(err, IsNil)
c.Assert(tb, NotNil)
rid0, err := tb.AddRecord(ctx, []interface{}{1})
c.Assert(err, IsNil)
rid1, err := tb.AddRecord(ctx, []interface{}{2})
c.Assert(err, IsNil)
alterStmt := statement(`alter table t2 add b enum("bb") first`).(*stmts.AlterTableStmt)
sessionctx.GetDomain(ctx).DDL().AlterTable(ctx, tbIdent2, alterStmt.Specs)
c.Assert(alterStmt.Specs[0].String(), Not(Equals), "")
cols, err := tb.Row(ctx, rid0)
c.Assert(err, IsNil)
c.Assert(len(cols), Equals, 2)
c.Assert(cols[0], Equals, nil)
c.Assert(cols[1], Equals, int64(1))
alterStmt = statement("alter table t2 add c varchar(255) after b").(*stmts.AlterTableStmt)
sessionctx.GetDomain(ctx).DDL().AlterTable(ctx, tbIdent2, alterStmt.Specs)
c.Assert(alterStmt.Specs[0].String(), Not(Equals), "")
tb, err = sessionctx.GetDomain(ctx).InfoSchema().TableByName(tbIdent2.Schema, tbIdent2.Name)
c.Assert(err, IsNil)
c.Assert(tb, NotNil)
cols, err = tb.Row(ctx, rid1)
c.Assert(err, IsNil)
c.Assert(len(cols), Equals, 3)
c.Assert(cols[0], Equals, nil)
c.Assert(cols[1], Equals, nil)
c.Assert(cols[2], Equals, int64(2))
rid3, err := tb.AddRecord(ctx, []interface{}{mysql.Enum{Name: "bb", Value: 1}, "c", 3})
c.Assert(err, IsNil)
cols, err = tb.Row(ctx, rid3)
c.Assert(err, IsNil)
c.Assert(len(cols), Equals, 3)
c.Assert(cols[0], Equals, mysql.Enum{Name: "bb", Value: 1})
c.Assert(cols[1], Equals, "c")
c.Assert(cols[2], Equals, int64(3))

tb, err := sessionctx.GetDomain(ctx).InfoSchema().TableByName(tbIdent.Schema, tbIdent.Name)
tb, err = sessionctx.GetDomain(ctx).InfoSchema().TableByName(tbIdent.Schema, tbIdent.Name)
c.Assert(err, IsNil)
c.Assert(tb, NotNil)
_, err = tb.AddRecord(ctx, []interface{}{1, "b", 2, 4})
c.Assert(err, IsNil)

alterStmt := statement("alter table t add column aa int first").(*stmts.AlterTableStmt)
alterStmt = statement("alter table t add column aa int first").(*stmts.AlterTableStmt)
sessionctx.GetDomain(ctx).DDL().AlterTable(ctx, tbIdent, alterStmt.Specs)
c.Assert(alterStmt.Specs[0].String(), Not(Equals), "")
// Check indices info
Expand Down
2 changes: 1 addition & 1 deletion domain/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (do *Domain) loadInfoSchema(txn kv.Transaction) (err error) {
if err != nil {
return
}
log.Info("loadInfoSchema %d", schemaMetaVersion)
log.Infof("loadInfoSchema %d", schemaMetaVersion)
do.infoHandle.Set(schemas, schemaMetaVersion)
return
}
Expand Down
50 changes: 35 additions & 15 deletions table/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ import (
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/util"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/errors2"
)

// The record key has tableID_r, rowID, columnID three parts.
// recordKeyItemsCount is the items count in the record key.
const recordKeyItemsCount = 3

// Table implements table.Table interface.
type Table struct {
ID int64
Expand Down Expand Up @@ -128,6 +133,19 @@ func (t *Table) Cols() []*column.Col {
return t.Columns
}

// ColumnID returns the column ID from the key.
func ColumnID(key []byte) (interface{}, error) {
k, err := codec.DecodeKey(key)
if err != nil {
return 0, errors.Trace(err)
}
if len(k) != recordKeyItemsCount {
return 0, errors.New("column not exist")
}

return k[recordKeyItemsCount-1], nil
}

func (t *Table) unflatten(rec interface{}, col *column.Col) (interface{}, error) {
if rec == nil {
return nil, nil
Expand Down Expand Up @@ -263,21 +281,28 @@ func (t *Table) setOnUpdateData(ctx context.Context, touched []bool, data []inte
return nil
}

// SetColValue sets the column value.
// If the column untouched, we don't need to do this.
func (t *Table) SetColValue(txn kv.Transaction, key []byte, data interface{}) error {
v, err := t.EncodeValue(data)
if err != nil {
return errors.Trace(err)
}
if err := txn.Set(key, v); err != nil {
return errors.Trace(err)
}
return nil
}

func (t *Table) setNewData(ctx context.Context, h int64, data []interface{}) error {
txn, err := ctx.GetTxn(false)
if err != nil {
return err
}
for _, col := range t.Cols() {
// set new value
// If column untouched, we do not need to do this
k := t.RecordKey(h, col)
v, err := t.EncodeValue(data[col.Offset])
if err != nil {
return err
}
if err := txn.Set([]byte(k), v); err != nil {
return err
if err := t.SetColValue(txn, k, data[col.Offset]); err != nil {
return errors.Trace(err)
}
}
return nil
Expand Down Expand Up @@ -365,13 +390,8 @@ func (t *Table) AddRecord(ctx context.Context, r []interface{}) (recordID int64,
}
// column key -> column value
for _, c := range t.Cols() {
colKey := t.RecordKey(recordID, c)
data, err := t.EncodeValue(r[c.Offset])
if err != nil {
return 0, err
}
err = txn.Set([]byte(colKey), data)
if err != nil {
k := t.RecordKey(recordID, c)
if err := t.SetColValue(txn, k, r[c.Offset]); err != nil {
return 0, err
}
}
Expand Down