Files
tidb/expression/cmp_subquery_test.go
2015-09-21 20:26:10 +08:00

172 lines
6.1 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 expression_test
import (
. "github.com/pingcap/check"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/types"
)
var _ = Suite(&testCompSubQuerySuite{})
type testCompSubQuerySuite struct {
}
func (s *testCompSubQuerySuite) TestCompSubQuery(c *C) {
tbl := []struct {
lhs interface{}
op opcode.Op
rhs []interface{}
all bool
result interface{} // 0 for false, 1 for true, nil for nil.
}{
// Test any subquery.
{nil, opcode.EQ, []interface{}{1, 2}, false, nil},
{0, opcode.EQ, []interface{}{1, 2}, false, 0},
{0, opcode.EQ, []interface{}{1, 2, nil}, false, nil},
{1, opcode.EQ, []interface{}{1, 1}, false, 1},
{1, opcode.EQ, []interface{}{1, 1, nil}, false, 1},
{nil, opcode.NE, []interface{}{1, 2}, false, nil},
{1, opcode.NE, []interface{}{1, 2}, false, 1},
{1, opcode.NE, []interface{}{1, 2, nil}, false, 1},
{1, opcode.NE, []interface{}{1, 1}, false, 0},
{1, opcode.NE, []interface{}{1, 1, nil}, false, nil},
{nil, opcode.GT, []interface{}{1, 2}, false, nil},
{1, opcode.GT, []interface{}{1, 2}, false, 0},
{1, opcode.GT, []interface{}{1, 2, nil}, false, nil},
{2, opcode.GT, []interface{}{1, 2}, false, 1},
{2, opcode.GT, []interface{}{1, 2, nil}, false, 1},
{3, opcode.GT, []interface{}{1, 2}, false, 1},
{3, opcode.GT, []interface{}{1, 2, nil}, false, 1},
{nil, opcode.GE, []interface{}{1, 2}, false, nil},
{0, opcode.GE, []interface{}{1, 2}, false, 0},
{0, opcode.GE, []interface{}{1, 2, nil}, false, nil},
{1, opcode.GE, []interface{}{1, 2}, false, 1},
{1, opcode.GE, []interface{}{1, 2, nil}, false, 1},
{2, opcode.GE, []interface{}{1, 2}, false, 1},
{3, opcode.GE, []interface{}{1, 2}, false, 1},
{nil, opcode.LT, []interface{}{1, 2}, false, nil},
{0, opcode.LT, []interface{}{1, 2}, false, 1},
{0, opcode.LT, []interface{}{1, 2, nil}, false, 1},
{1, opcode.LT, []interface{}{1, 2}, false, 1},
{2, opcode.LT, []interface{}{1, 2}, false, 0},
{2, opcode.LT, []interface{}{1, 2, nil}, false, nil},
{3, opcode.LT, []interface{}{1, 2}, false, 0},
{nil, opcode.LE, []interface{}{1, 2}, false, nil},
{0, opcode.LE, []interface{}{1, 2}, false, 1},
{0, opcode.LE, []interface{}{1, 2, nil}, false, 1},
{1, opcode.LE, []interface{}{1, 2}, false, 1},
{2, opcode.LE, []interface{}{1, 2}, false, 1},
{3, opcode.LE, []interface{}{1, 2}, false, 0},
{3, opcode.LE, []interface{}{1, 2, nil}, false, nil},
// Test all subquery.
{nil, opcode.EQ, []interface{}{1, 2}, true, nil},
{0, opcode.EQ, []interface{}{1, 2}, true, 0},
{0, opcode.EQ, []interface{}{1, 2, nil}, true, 0},
{1, opcode.EQ, []interface{}{1, 2}, true, 0},
{1, opcode.EQ, []interface{}{1, 2, nil}, true, 0},
{1, opcode.EQ, []interface{}{1, 1}, true, 1},
{1, opcode.EQ, []interface{}{1, 1, nil}, true, nil},
{nil, opcode.NE, []interface{}{1, 2}, true, nil},
{0, opcode.NE, []interface{}{1, 2}, true, 1},
{1, opcode.NE, []interface{}{1, 2, nil}, true, 0},
{1, opcode.NE, []interface{}{1, 1}, true, 0},
{1, opcode.NE, []interface{}{1, 1, nil}, true, 0},
{nil, opcode.GT, []interface{}{1, 2}, true, nil},
{1, opcode.GT, []interface{}{1, 2}, true, 0},
{1, opcode.GT, []interface{}{1, 2, nil}, true, 0},
{2, opcode.GT, []interface{}{1, 2}, true, 0},
{2, opcode.GT, []interface{}{1, 2, nil}, true, 0},
{3, opcode.GT, []interface{}{1, 2}, true, 1},
{3, opcode.GT, []interface{}{1, 2, nil}, true, nil},
{nil, opcode.GE, []interface{}{1, 2}, true, nil},
{0, opcode.GE, []interface{}{1, 2}, true, 0},
{0, opcode.GE, []interface{}{1, 2, nil}, true, 0},
{1, opcode.GE, []interface{}{1, 2}, true, 0},
{1, opcode.GE, []interface{}{1, 2, nil}, true, 0},
{2, opcode.GE, []interface{}{1, 2}, true, 1},
{3, opcode.GE, []interface{}{1, 2}, true, 1},
{3, opcode.GE, []interface{}{1, 2, nil}, true, nil},
{nil, opcode.LT, []interface{}{1, 2}, true, nil},
{0, opcode.LT, []interface{}{1, 2}, true, 1},
{0, opcode.LT, []interface{}{1, 2, nil}, true, nil},
{1, opcode.LT, []interface{}{1, 2}, true, 0},
{2, opcode.LT, []interface{}{1, 2}, true, 0},
{2, opcode.LT, []interface{}{1, 2, nil}, true, 0},
{3, opcode.LT, []interface{}{1, 2}, true, 0},
{nil, opcode.LE, []interface{}{1, 2}, true, nil},
{0, opcode.LE, []interface{}{1, 2}, true, 1},
{0, opcode.LE, []interface{}{1, 2, nil}, true, nil},
{1, opcode.LE, []interface{}{1, 2}, true, 1},
{2, opcode.LE, []interface{}{1, 2}, true, 0},
{3, opcode.LE, []interface{}{1, 2}, true, 0},
{3, opcode.LE, []interface{}{1, 2, nil}, true, 0},
}
ctx := mock.NewContext()
for _, t := range tbl {
lhs := convert(t.lhs)
rhs := make([][]interface{}, 0, len(t.rhs))
for _, v := range t.rhs {
rhs = append(rhs, []interface{}{convert(v)})
}
sq := newMockSubQuery(rhs, []string{"c"})
expr := expression.NewCompareSubQuery(t.op, expression.Value{Val: lhs}, sq, t.all)
c.Assert(expr.IsStatic(), IsFalse)
str := expr.String()
c.Assert(len(str), Greater, 0)
v, err := expr.Eval(ctx, nil)
c.Assert(err, IsNil)
switch x := t.result.(type) {
case nil:
c.Assert(v, IsNil)
case int:
val, err := types.ToBool(v)
c.Assert(err, IsNil)
c.Assert(val, Equals, int64(x))
}
}
// Test error.
sq := newMockSubQuery([][]interface{}{{1, 2}}, []string{"c1", "c2"})
expr := expression.NewCompareSubQuery(opcode.EQ, expression.Value{Val: 1}, sq, true)
_, err := expr.Eval(ctx, nil)
c.Assert(err, NotNil)
expr = expression.NewCompareSubQuery(opcode.EQ, expression.Value{Val: 1}, sq, false)
_, err = expr.Eval(ctx, nil)
c.Assert(err, NotNil)
}
func convert(v interface{}) interface{} {
switch x := v.(type) {
case int:
return int64(x)
}
return v
}