Skip to content

Commit

Permalink
*: Convert CaseExpr to ScalarFunction and clean up (pingcap#1377)
Browse files Browse the repository at this point in the history
* *: support CaseExpr to ScalarFunction and tiny clean up
  • Loading branch information
zimulala authored Jul 4, 2016
1 parent c72917d commit 5520e26
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 90 deletions.
1 change: 1 addition & 0 deletions evaluator/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ var Funcs = map[string]Func{
ast.IsTruth: {isTrueOpFactory(opcode.IsTruth), 1, 1},
ast.IsFalsity: {isTrueOpFactory(opcode.IsFalsity), 1, 1},
ast.Like: {builtinLike, 1, 3},
ast.Case: {builtinCaseWhen, 1, -1},
ast.RowFunc: {builtinRow, 2, -1},
}

Expand Down
24 changes: 24 additions & 0 deletions evaluator/builtin_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,30 @@ func builtinOrOr(args []types.Datum, _ context.Context) (d types.Datum, err erro
return
}

func builtinCaseWhen(args []types.Datum, _ context.Context) (d types.Datum, err error) {
l := len(args)
for i := 0; i < l-1; i += 2 {
if args[i].IsNull() {
continue
}
b, err1 := args[i].ToBool()
if err1 != nil {
return d, errors.Trace(err1)
}
if b == 1 {
d = args[i+1]
return
}
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
d = args[l-1]
}
return
}

func builtinLike(args []types.Datum, _ context.Context) (d types.Datum, err error) {
if args[0].IsNull() {
return
Expand Down
53 changes: 45 additions & 8 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,8 @@ func (s *testSuite) TestBuiltin(c *C) {
defer testleak.AfterTest(c)()
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")

// for is true
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int, b int, index idx_b (b))")
tk.MustExec("insert t values (1, 1)")
Expand All @@ -1356,19 +1358,12 @@ func (s *testSuite) TestBuiltin(c *C) {
result.Check(nil)
result = tk.MustQuery("select * from t where a is not true")
result.Check(nil)
// for in
result = tk.MustQuery("select * from t where b in (a)")
result.Check(testkit.Rows("1 1", "2 2"))
result = tk.MustQuery("select * from t where b not in (a)")
result.Check(testkit.Rows("3 2"))

tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(255), b int)")
tk.MustExec("insert t values ('abc123', 1)")
tk.MustExec("insert t values ('ab123', 2)")
result = tk.MustQuery("select * from t where a like 'ab_123'")
rowStr := fmt.Sprintf("%v %v", []byte("abc123"), "1")
result.Check(testkit.Rows(rowStr))

// test cast
result = tk.MustQuery("select cast(1 as decimal(1,2))")
result.Check(testkit.Rows("1.00"))
Expand All @@ -1378,6 +1373,48 @@ func (s *testSuite) TestBuiltin(c *C) {
result.Check(testkit.Rows("1991-09-05 11:11:11"))
result = tk.MustQuery("select cast('11:11:11' as time)")
result.Check(testkit.Rows("11:11:11"))

// for like
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(255), b int)")
tk.MustExec("insert t values ('abc123', 1)")
tk.MustExec("insert t values ('ab123', 2)")
result = tk.MustQuery("select * from t where a like 'ab_123'")
rowStr := fmt.Sprintf("%v %v", []byte("abc123"), "1")
result.Check(testkit.Rows(rowStr))

// case
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(255), b int)")
tk.MustExec("insert t values ('str1', 1)")
result = tk.MustQuery("select * from t where a = case b when 1 then 'str1' when 2 then 'str2' end")
rowStr1 := fmt.Sprintf("%v %v", []byte("str1"), "1")
result.Check(testkit.Rows(rowStr1))
result = tk.MustQuery("select * from t where a = case b when 1 then 'str2' when 2 then 'str3' end")
result.Check(nil)
tk.MustExec("insert t values ('str2', 2)")
result = tk.MustQuery("select * from t where a = case b when 2 then 'str2' when 3 then 'str3' end")
rowStr2 := fmt.Sprintf("%v %v", []byte("str2"), "2")
result.Check(testkit.Rows(rowStr2))
tk.MustExec("insert t values ('str3', 3)")
result = tk.MustQuery("select * from t where a = case b when 4 then 'str4' when 5 then 'str5' else 'str3' end")
rowStr3 := fmt.Sprintf("%v %v", []byte("str3"), "3")
result.Check(testkit.Rows(rowStr3))
result = tk.MustQuery("select * from t where a = case b when 4 then 'str4' when 5 then 'str5' else 'str6' end")
result.Check(nil)
result = tk.MustQuery("select * from t where a = case when b then 'str3' when 1 then 'str1' else 'str2' end")
result.Check(testkit.Rows(rowStr3))
tk.MustExec("delete from t")
tk.MustExec("insert t values ('str2', 0)")
result = tk.MustQuery("select * from t where a = case when b then 'str3' when 0 then 'str1' else 'str2' end")
rowStr2 = fmt.Sprintf("%v %v", []byte("str2"), "0")
result.Check(testkit.Rows(rowStr2))
tk.MustExec("insert t values ('str1', null)")
result = tk.MustQuery("select * from t where a = case b when null then 'str3' when 10 then 'str1' else 'str2' end")
result.Check(testkit.Rows(rowStr2))
result = tk.MustQuery("select * from t where a = case null when b then 'str3' when 10 then 'str1' else 'str2' end")
result.Check(testkit.Rows(rowStr2))

plan.UseNewPlanner = false
}

Expand Down
Loading

0 comments on commit 5520e26

Please sign in to comment.