TIDB源码分析-每一次PR(13)

*: fix duplicated table name when join #180

修复类似下列SQL没有报错:

create table if not exists t (c1 int, c2 int);
create table if not exists t1 (c1 int, c2 int);
select * from t join t1 as t;

在:

if err := r.checkTableDuplicate(t, tr); err != nil {
    return nil, nil, errors.Trace(err)
}

使用了新添加的checkTableDuplicate来检查重复即可。

Shenli/fix beego #181

对更新操作支持别名,如:UPDATE items T0 join month T1 on T0.id=T1.mid SET T0.price=T1.mprice;

并且对like支持二进制,如:LIKE BINARY xxx

TiDB MySQL protocol server #170

支持mysql-server协议,不再是一个嵌入式驱动,可像mysql那样通过mysql客户端连接。

doc: update README.md. #184

修改 README.md。

*: add autocommit judgment and test #183

对session的ServerStatusInTrans和ServerStatusInTrans 都合并到Status作为标志位,并且统一了修改状态的函数SetStatusFlag()。

table: Fix run xorm error #185

修复一个二进制解码错误。

例如:

drop table t if exists;
CREATE TABLE test.t (c1 tinyint unsigned, c2 smallint unsigned, c3 int unsigned, c4 bigint unsigned, c5 double, c6 bit);
insert test.t values (1, 2, 3, 4, 5, 6);
select * from test.t where c1 = 1;

这里的最后一个6会返回null。

原因是这里没有TypeBit类型:

func (t *Table) unflatten(rec interface{}, col *column.Col) (interface{}, error) {
    if rec == nil {
        return nil, nil
    }
    switch col.Tp {
    case mysql.TypeFloat:
        return float32(rec.(float64)), nil
    case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong,
        mysql.TypeDouble, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob,
        mysql.TypeVarchar, mysql.TypeString:
        return rec, nil
    case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp:
        var t mysql.Time
        t.Type = col.Tp
        t.Fsp = col.Decimal
        err := t.Unmarshal(rec.([]byte))
        if err != nil {
            return nil, errors.Trace(err)
        }
        return t, nil
    case mysql.TypeDuration:
        return mysql.Duration{Duration: time.Duration(rec.(int64)), Fsp: col.Decimal}, nil
    case mysql.TypeNewDecimal, mysql.TypeDecimal:
        return mysql.ParseDecimal(rec.(string))
    }
    log.Error(col.Tp, rec, reflect.TypeOf(rec))
    return nil, nil
}

https://github.com/pingcap/tidb/blob/4ceedcfc27db925052215d228217afea4d6d0af7/table/tables/tables.go#L131-L158

加上即可。

tidb-server: Remove tidb-server binary file from repo #189

删除生成的可执行二进制文件。

table: Add the bit unit test #190

添加对PR185 的二进制的测试数据。

Makefile: able to specify binary location #186

Makefile中修改编译后可执行文件的位置。

support null safe <=> compare #187

支持<=>安全的比较null值。否则用=比较的话有null会返回null。

expressions: Extract builtin information functions to builtin_info.go #192

把builtinDatabase和builtinFoundRows独立出一个文件。

tidb-server: Add bootstrap methord to create. user table.#191

修改mysql内置表初始化函数CreateTiDBTestDatabase为Bootstrap,并增加了mysql.user表。

refactor subquery to support correlated subquery #182

支持了select * from t1 where c1 = (select c2 from t2 where t1.c2 = t2.c1);这样的语法。

rset: remove redundant rset layer. #202

清理了一些无用代码。

roadmap: Change status of MySQL protocol to checked.

修改了ROADMAP.md的开发进度描述。

Shenli/set password #195

支持set password 语法。

Add golint package get in makefile and update ci. #198

更新了makefile文件。

stmt/stmts: fix show stmt use current db bug. #206

修复获取当前数据库信息时的错误,运行下面查询为空。

use test;
create table if not exists t (c int);
show columns from t;

parser: make WhereClauseOptional return Expression.#201

修改了parser,更换了部分表达式绑定。

support show variables where syntax #200

支持如下SQL语句:

show variables where variable_name = 'autocommit';

Support basic create user statement #207

新增支持创建用户的SQL。

support bit type #196

支持bit类型

*: Remove leading comment when check IsQuery #210

对原来的自带tidb输入行忽略注释。已经存在的新版tidb-server不存在这个问题。

support boundary check for bit type #213

对插入bit类型数据检查最大长度限制。

       if err = column.CastValues(ctx, r, cols); err != nil {
            return nil, errors.Trace(err)
        }
        if err = column.CheckNotNull(tableCols, r); err != nil {
            return nil, errors.Trace(err)
        }

        // Notes: incompatible with mysql
        // MySQL will set last insert id to the first row, as follows:
        // `t(id int AUTO_INCREMENT, c1 int, PRIMARY KEY (id))`
        // `insert t (c1) values(1),(2),(3);`
        // Last insert id will be 1, not 3.
        h, err := t.AddRecord(ctx, r)
        if err == nil {
            continue
        }
        if len(s.OnDuplicate) == 0 || !errors2.ErrorEqual(err, kv.ErrKeyExists) {
            return nil, errors.Trace(err)
        }
        // On duplicate key Update the duplicate row.
        // Evaluate the updated value.
        // TODO: report rows affected and last insert id.
        toUpdateColumns, err := getUpdateColumns(t, s.OnDuplicate, false, nil)
        if err != nil {
            return nil, errors.Trace(err)
        }
        data, err := t.Row(ctx, h)
        if err != nil {
            return nil, errors.Trace(err)
        }
        err = updateRecord(ctx, h, data, t, toUpdateColumns, s.OnDuplicate, r, nil)
        if err != nil {
            return nil, errors.Trace(err)
        }
    }

    return nil, nil
}

在CastValues检查了长度限制。

expression: remove return error in Clone interface #211

删除某些不会返回错误的检查。

first MVCC support #209

支持MVCC,用Key -> META 以及Key_version->val来表示版本号,其中版本号越大数据越新,所以快照查询k的函数变成了:

func (s *dbSnapshot) Get(k kv.Key) ([]byte, error) {
    // engine Snapshot return nil, nil for value not found,
    // so here we will check nil and return kv.ErrNotExist.

    // get newest version, (0, MaxUint64)
    // Key arrangement:
    // Key -> META
    // ...
    // Key_ver
    // Key_ver-1
    // Key_ver-2
    // ...
    // Key_ver-n
    // Key_0
    // NextKey -> META
    // NextKey_xxx
    startKey := MvccEncodeVersionKey(k, kv.Version{math.MaxUint64})
    endKey := MvccEncodeVersionKey(k, kv.Version{0})

    // get raw iterator
    it := s.Snapshot.NewIterator(startKey)
    defer it.Release()

    var rawKey []byte
    var v []byte
    if it.Next() {
        // If scan exceed this key's all versions
        // it.Key() > endKey.
        if kv.EncodedKey(it.Key()).Cmp(endKey) < 0 {
            // Check newest version of this key.
            // If it's tombstone, just skip it.
            if !isTombstone(it.Value()) {
                rawKey = it.Key()
                v = it.Value()
            }
        }
    }

    // No such key (or it's tombstone).
    if rawKey == nil {
        return nil, kv.ErrNotExist
    }

    return v, nil
}

https://github.com/pingcap/tidb/blob/20180eb4630ba62e5cdba094b071f4b45139ba27/store/localstore/snapshot.go#L37-L81

搜索版本变成从大到小。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

请输入正确的验证码