Files
tidb/plan/plans/from_test.go
2015-11-03 17:06:56 +08:00

209 lines
5.0 KiB
Go

// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package plans_test
import (
"fmt"
"reflect"
. "github.com/pingcap/check"
"github.com/pingcap/tidb"
"github.com/pingcap/tidb/column"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/field"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/plan/plans"
"github.com/pingcap/tidb/rset/rsets"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/table/tables"
"github.com/pingcap/tidb/util/types"
)
type testFromSuit struct {
txn kv.Transaction
cols []*column.Col
tbl table.Table
vars map[string]interface{}
}
type simpleAllocator struct {
id int64
}
func (s *simpleAllocator) Alloc(tableID int64) (int64, error) {
s.id++
return s.id, nil
}
// implement Context interface
func (p *testFromSuit) GetTxn(forceNew bool) (kv.Transaction, error) { return p.txn, nil }
func (p *testFromSuit) FinishTxn(rollback bool) error { return nil }
// SetValue saves a value associated with this context for key
func (p *testFromSuit) SetValue(key fmt.Stringer, value interface{}) {
p.vars[key.String()] = value
}
// Value returns the value associated with this context for key
func (p *testFromSuit) Value(key fmt.Stringer) interface{} {
return p.vars[key.String()]
}
// ClearValue clears the value associated with this context for key
func (p *testFromSuit) ClearValue(key fmt.Stringer) {}
var _ = Suite(&testFromSuit{})
func (p *testFromSuit) SetUpSuite(c *C) {
store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory)
c.Assert(err, IsNil)
p.vars = map[string]interface{}{}
p.txn, _ = store.Begin()
p.cols = []*column.Col{
{
ColumnInfo: model.ColumnInfo{
ID: 0,
Name: model.NewCIStr("id"),
Offset: 0,
DefaultValue: 0,
FieldType: *types.NewFieldType(mysql.TypeLonglong),
State: model.StatePublic,
},
},
{
ColumnInfo: model.ColumnInfo{
ID: 1,
Name: model.NewCIStr("name"),
Offset: 1,
DefaultValue: nil,
FieldType: *types.NewFieldType(mysql.TypeVarchar),
State: model.StatePublic,
},
},
}
p.tbl = tables.NewTable(1, "t", p.cols, &simpleAllocator{})
variable.BindSessionVars(p)
var i int64
for i = 0; i < 10; i++ {
_, err = p.tbl.AddRecord(p, []interface{}{i * 10, "hello"})
c.Assert(err, IsNil)
}
}
func (p *testFromSuit) TestTableNilPlan(c *C) {
nilPlan := &plans.TableNilPlan{
T: p.tbl,
}
var ids []int64
rset := rsets.Recordset{
Plan: nilPlan,
Ctx: p,
}
var id int64
rset.Do(func(data []interface{}) (bool, error) {
id++
ids = append(ids, id)
return true, nil
})
c.Assert(reflect.DeepEqual(ids, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}), Equals, true)
}
func (p *testFromSuit) TestTableDefaultPlan(c *C) {
pln := &plans.TableDefaultPlan{
T: p.tbl,
Fields: []*field.ResultField{
field.ColToResultField(p.cols[0], "t"),
field.ColToResultField(p.cols[1], "t"),
},
}
ret := map[int64]string{}
rset := rsets.Recordset{Ctx: p, Plan: pln}
rset.Do(func(data []interface{}) (bool, error) {
ret[data[0].(int64)] = data[1].(string)
return true, nil
})
excepted := map[int64]string{}
for i := 0; i < 10; i++ {
excepted[int64(i*10)] = "hello"
}
c.Assert(reflect.DeepEqual(ret, excepted), Equals, true)
// expr: id > 0
expr := &expression.BinaryOperation{
Op: opcode.GE,
L: &expression.Ident{
CIStr: model.NewCIStr("id"),
},
R: &expression.Value{
Val: 5,
},
}
_, filtered, err := pln.FilterForUpdateAndDelete(p, expr)
c.Assert(err, IsNil)
c.Assert(filtered, IsFalse)
// with no index
idxCol := &column.IndexedCol{
IndexInfo: model.IndexInfo{
Name: model.NewCIStr("id"),
Table: model.NewCIStr("t"),
Columns: []*model.IndexColumn{
{
Name: model.NewCIStr("id"),
Offset: 0,
Length: 0,
},
},
Unique: false,
Primary: false,
State: model.StatePublic,
},
X: kv.NewKVIndex("i", "id", false),
}
p.tbl.AddIndex(idxCol)
expr4 := &expression.Ident{
CIStr: model.NewCIStr("id"),
}
_, filtered, err = pln.FilterForUpdateAndDelete(p, expr4)
c.Assert(err, IsNil)
// with no index
c.Assert(filtered, IsTrue)
expr5 := &expression.IsNull{
Expr: &expression.Ident{
CIStr: model.NewCIStr("id"),
},
Not: true,
}
_, filtered, err = pln.FilterForUpdateAndDelete(p, expr5)
c.Assert(err, IsNil)
// with no index
c.Assert(filtered, IsTrue)
}
func (p *testFromSuit) TestTableIndexPlan(c *C) {
}
func (p *testFromSuit) TearDownSuite(c *C) {
p.txn.Commit()
}