Files
tidb/expression/helper_test.go
Shen Li 06e7e891af Merge pull request #414 from pingcap/goroutine/rename
*: Rename mysqldef to mysql
2015-10-19 16:35:29 +08:00

265 lines
6.7 KiB
Go

package expression
import (
"errors"
"time"
. "github.com/pingcap/check"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/sessionctx/variable"
)
var _ = Suite(&testHelperSuite{})
type testHelperSuite struct {
}
func (s *testHelperSuite) TestContainAggFunc(c *C) {
v := Value{}
tbl := []struct {
Expr Expression
Expect bool
}{
{Value{1}, false},
{&BinaryOperation{L: v, R: v}, false},
{&Call{F: "count", Args: []Expression{v}}, true},
{&Call{F: "abs", Args: []Expression{v}}, false},
{&IsNull{Expr: v}, false},
{&PExpr{Expr: v}, false},
{&PatternIn{Expr: v, List: []Expression{v}}, false},
{&PatternLike{Expr: v, Pattern: v}, false},
{&UnaryOperation{V: v}, false},
{&ParamMarker{Expr: v}, false},
{&FunctionCast{Expr: v}, false},
{&FunctionConvert{Expr: v}, false},
{&FunctionSubstring{StrExpr: v, Pos: v, Len: v}, false},
{&FunctionCase{Value: v, WhenClauses: []*WhenClause{{Expr: v, Result: v}}, ElseClause: v}, false},
{&WhenClause{Expr: v, Result: v}, false},
{&IsTruth{Expr: v}, false},
{&Between{Expr: v, Left: v, Right: v}, false},
{&Row{Values: []Expression{v, v}}, false},
}
for _, t := range tbl {
b := ContainAggregateFunc(t.Expr)
c.Assert(b, Equals, t.Expect)
}
expr := &Call{
F: "count",
Args: []Expression{
&Call{F: "count", Args: []Expression{v}},
},
}
_, err := MentionedAggregateFuncs(expr)
c.Assert(err, NotNil)
}
func (s *testHelperSuite) TestMentionedColumns(c *C) {
v := Value{}
tbl := []struct {
Expr Expression
Expect int
}{
{Value{1}, 0},
{&BinaryOperation{L: v, R: v}, 0},
{&Ident{CIStr: model.NewCIStr("id")}, 1},
{&Call{F: "count", Args: []Expression{v}}, 0},
{&IsNull{Expr: v}, 0},
{&PExpr{Expr: v}, 0},
{&PatternIn{Expr: v, List: []Expression{v}}, 0},
{&PatternLike{Expr: v, Pattern: v}, 0},
{&UnaryOperation{V: v}, 0},
{&ParamMarker{Expr: v}, 0},
{&FunctionCast{Expr: v}, 0},
{&FunctionConvert{Expr: v}, 0},
{&FunctionSubstring{StrExpr: v, Pos: v, Len: v}, 0},
{&FunctionCase{Value: v, WhenClauses: []*WhenClause{{Expr: v, Result: v}}, ElseClause: v}, 0},
{&WhenClause{Expr: v, Result: v}, 0},
{&IsTruth{Expr: v}, 0},
{&Between{Expr: v, Left: v, Right: v}, 0},
{&Row{Values: []Expression{v, v}}, 0},
}
for _, t := range tbl {
ret := MentionedColumns(t.Expr)
c.Assert(ret, HasLen, t.Expect)
}
}
func NewTestRow(v1 interface{}, v2 interface{}, args ...interface{}) *Row {
r := &Row{}
a := make([]Expression, len(args))
for i := range a {
a[i] = Value{args[i]}
}
r.Values = append([]Expression{Value{v1}, Value{v2}}, a...)
return r
}
func (s *testHelperSuite) TestBase(c *C) {
e1 := Value{1}
e2 := &PExpr{Expr: e1}
e3 := Expr(e2)
c.Assert(e1, DeepEquals, e3)
tbl := []struct {
Expr interface{}
Ret interface{}
}{
{Value{1}, 1},
{int64(1), int64(1)},
{&UnaryOperation{Op: opcode.Plus, V: Value{1}}, 1},
{&UnaryOperation{Op: opcode.Not, V: Value{1}}, nil},
{&UnaryOperation{Op: opcode.Plus, V: &Ident{CIStr: model.NewCIStr("id")}}, nil},
{nil, nil},
}
for _, t := range tbl {
v := FastEval(t.Expr)
c.Assert(v, DeepEquals, t.Ret)
}
v, err := EvalBoolExpr(nil, Value{1}, nil)
c.Assert(v, IsTrue)
v, err = EvalBoolExpr(nil, Value{nil}, nil)
c.Assert(v, IsFalse)
v, err = EvalBoolExpr(nil, Value{errors.New("must error")}, nil)
c.Assert(err, NotNil)
v, err = EvalBoolExpr(nil, mockExpr{err: errors.New("must error")}, nil)
c.Assert(err, NotNil)
err = CheckOneColumn(nil, &Row{})
c.Assert(err, NotNil)
err = CheckOneColumn(nil, Value{nil})
c.Assert(err, IsNil)
// err = CheckOneColumn(nil, newMockSubQuery([][]interface{}{}, []string{"id", "name"}))
// c.Assert(err, NotNil)
columns := []struct {
lhs Expression
rhs Expression
checker Checker
}{
{Value{nil}, Value{nil}, IsNil},
{Value{nil}, &Row{}, NotNil},
{NewTestRow(1, 2), NewTestRow(1, 2), IsNil},
{NewTestRow(1, 2, 3), NewTestRow(1, 2), NotNil},
}
for _, t := range columns {
err = hasSameColumnCount(nil, t.lhs, t.rhs)
c.Assert(err, t.checker)
err = hasSameColumnCount(nil, t.rhs, t.lhs)
c.Assert(err, t.checker)
}
}
func (s *testHelperSuite) TestGetTimeValue(c *C) {
v, err := GetTimeValue(nil, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, IsNil)
timeValue, ok := v.(mysql.Time)
c.Assert(ok, IsTrue)
c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
ctx := newMockCtx()
variable.BindSessionVars(ctx)
sessionVars := variable.GetSessionVars(ctx)
sessionVars.Systems["timestamp"] = ""
v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, IsNil)
timeValue, ok = v.(mysql.Time)
c.Assert(ok, IsTrue)
c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
sessionVars.Systems["timestamp"] = "0"
v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, IsNil)
timeValue, ok = v.(mysql.Time)
c.Assert(ok, IsTrue)
c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
delete(sessionVars.Systems, "timestamp")
v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, IsNil)
timeValue, ok = v.(mysql.Time)
c.Assert(ok, IsTrue)
c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
sessionVars.Systems["timestamp"] = "1234"
tbl := []struct {
Expr interface{}
Ret interface{}
}{
{"2012-12-12 00:00:00", "2012-12-12 00:00:00"},
{CurrentTimestamp, time.Unix(1234, 0).Format(mysql.TimeFormat)},
{ZeroTimestamp, "0000-00-00 00:00:00"},
{Value{"2012-12-12 00:00:00"}, "2012-12-12 00:00:00"},
{Value{int64(0)}, "0000-00-00 00:00:00"},
{Value{}, nil},
{CurrentTimeExpr, CurrentTimestamp},
{NewUnaryOperation(opcode.Minus, Value{int64(0)}), "0000-00-00 00:00:00"},
{mockExpr{}, nil},
}
for _, t := range tbl {
v, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, IsNil)
switch x := v.(type) {
case mysql.Time:
c.Assert(x.String(), DeepEquals, t.Ret)
default:
c.Assert(x, DeepEquals, t.Ret)
}
}
errTbl := []struct {
Expr interface{}
}{
{"2012-13-12 00:00:00"},
{Value{"2012-13-12 00:00:00"}},
{Value{0}},
{Value{int64(1)}},
{&Ident{CIStr: model.NewCIStr("xxx")}},
{NewUnaryOperation(opcode.Minus, Value{int64(1)})},
}
for _, t := range errTbl {
_, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, mysql.MinFsp)
c.Assert(err, NotNil)
}
}
func (s *testHelperSuite) TestIsCurrentTimeExpr(c *C) {
v := IsCurrentTimeExpr(mockExpr{})
c.Assert(v, IsFalse)
v = IsCurrentTimeExpr(CurrentTimeExpr)
c.Assert(v, IsTrue)
}
func convert(v interface{}) interface{} {
switch x := v.(type) {
case int:
return int64(x)
}
return v
}