Skip to content

Commit

Permalink
fix issue:pingcap#11102
Browse files Browse the repository at this point in the history
                                                            Unexcepted result in `SELECT ... CASE WHEN ... ELSE NULL...`
  • Loading branch information
lovewin99 committed Jul 9, 2019
1 parent 0aaf491 commit 760d28a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
58 changes: 48 additions & 10 deletions expression/constant_fold.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package expression

import (
"github.com/pingcap/parser/ast"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/logutil"
"go.uber.org/zap"
Expand All @@ -23,18 +24,11 @@ import (
// specialFoldHandler stores functions for special UDF to constant fold
var specialFoldHandler = map[string]func(*ScalarFunction) (Expression, bool){}

// specialNullRejectCheck stores function names for special UDF to skip constant fold.
var specialNullRejectCheck = map[string]struct{}{}

func init() {
specialFoldHandler = map[string]func(*ScalarFunction) (Expression, bool){
ast.If: ifFoldHandler,
ast.Ifnull: ifNullFoldHandler,
}

specialNullRejectCheck = map[string]struct{}{
ast.NullEQ: {},
ast.Case: {},
ast.Case: caseWhenHandler,
}
}

Expand Down Expand Up @@ -86,6 +80,51 @@ func ifNullFoldHandler(expr *ScalarFunction) (Expression, bool) {
return expr, isDeferredConst
}

func caseWhenHandler(expr *ScalarFunction) (Expression, bool) {
args, l := expr.GetArgs(), len(expr.GetArgs())
firstCondition := true
isDeferredConst := false
for i := 0; i < l-1; i += 2 {
foldedArg, isDeferred := foldConstant(args[i])
expr.GetArgs()[i] = foldedArg
isDeferredConst = isDeferredConst || isDeferred
if _, isConst := foldedArg.(*Constant); isConst {
condition, isNull, err := args[i].EvalInt(expr.GetCtx(), chunk.Row{})
if err != nil {
return expr, false
}
if firstCondition && condition != 0 && !isNull {
return retProcess(args[i+1], expr.GetType())
}
} else {
firstCondition = false
}
foldedArg1, isDeferred1 := foldConstant(args[i+1])
expr.GetArgs()[i+1] = foldedArg1
isDeferredConst = isDeferredConst || isDeferred1
}

if l%2 == 1 && firstCondition {
return retProcess(args[l-1], expr.GetType())
} else if l%2 == 1 {
foldedArg, isDeferred := foldConstant(args[l-1])
expr.GetArgs()[l-1] = foldedArg
isDeferredConst = isDeferredConst || isDeferred
}

return expr, isDeferredConst
}

func retProcess(expr Expression, retType *types.FieldType) (Expression, bool) {
foldedExpr, b := foldConstant(expr)
if fc, isConst := foldedExpr.(*Constant); isConst {
fc.RetType = retType
return fc, b
}

return foldedExpr, b
}

func foldConstant(expr Expression) (Expression, bool) {
switch x := expr.(type) {
case *ScalarFunction:
Expand All @@ -112,8 +151,7 @@ func foldConstant(expr Expression) (Expression, bool) {
isDeferredConst = isDeferredConst || isDeferred
}
if !allConstArg {
_, ok := specialNullRejectCheck[x.FuncName.L]
if !hasNullArg || !sc.InNullRejectCheck || ok {
if !hasNullArg || !sc.InNullRejectCheck || x.FuncName.L == ast.NullEQ {
return expr, isDeferredConst
}
constArgs := make([]Expression, len(args))
Expand Down
4 changes: 1 addition & 3 deletions session/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2733,7 +2733,5 @@ func (s *testSessionSuite) TestFuncCaseWithLeftJoin(c *C) {
tk.MustExec("create table kankan2(id int, h1 text)")
tk.MustExec("insert into kankan2 values(2, 'z')")

tk.MustQuery("select * from (select t1.id, t2.h1, case when t1.name='b' then 'case2' when t1.name='a' then " +
"'case1' else null end as flag from kankan1 t1 left join kankan2 t2 on t1.id = t2.id) t3 where t3.flag='case1' " +
"order by t3.id").Check(testkit.Rows("1 <nil> case1", "2 z case1"))
tk.MustQuery("select t1.id from kankan1 t1 left join kankan2 t2 on t1.id = t2.id where (case when t1.name='b' then 'case2' when t1.name='a' then 'case1' else NULL end) = 'case1' order by t1.id").Check(testkit.Rows("1", "2"))
}

0 comments on commit 760d28a

Please sign in to comment.