Skip to content

Commit ece299d

Browse files
lovewin99zz-jason
authored andcommitted
expression, session: handle CASE WHEN specially when folding… (#11441)
1 parent e743395 commit ece299d

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

expression/constant_fold.go

+54
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func init() {
2929
specialFoldHandler = map[string]func(*ScalarFunction) (Expression, bool){
3030
ast.If: ifFoldHandler,
3131
ast.Ifnull: ifNullFoldHandler,
32+
ast.Case: caseWhenHandler,
3233
}
3334
}
3435

@@ -80,6 +81,59 @@ func ifNullFoldHandler(expr *ScalarFunction) (Expression, bool) {
8081
return expr, isDeferredConst
8182
}
8283

84+
func caseWhenHandler(expr *ScalarFunction) (Expression, bool) {
85+
args, l := expr.GetArgs(), len(expr.GetArgs())
86+
var isDeferred, isDeferredConst, hasNonConstCondition bool
87+
for i := 0; i < l-1; i += 2 {
88+
expr.GetArgs()[i], isDeferred = foldConstant(args[i])
89+
isDeferredConst = isDeferredConst || isDeferred
90+
if _, isConst := expr.GetArgs()[i].(*Constant); isConst && !hasNonConstCondition {
91+
// If the condition is const and true, and the previous conditions
92+
// has no expr, then the folded execution body is returned, otherwise
93+
// the arguments of the casewhen are folded and replaced.
94+
val, isNull, err := args[i].EvalInt(expr.GetCtx(), chunk.Row{})
95+
if err != nil {
96+
return expr, false
97+
}
98+
if val != 0 && !isNull {
99+
foldedExpr, isDeferred := foldConstant(args[i+1])
100+
isDeferredConst = isDeferredConst || isDeferred
101+
if _, isConst := foldedExpr.(*Constant); isConst {
102+
foldedExpr.GetType().Decimal = expr.GetType().Decimal
103+
return foldedExpr, isDeferredConst
104+
}
105+
return BuildCastFunction(expr.GetCtx(), foldedExpr, foldedExpr.GetType()), isDeferredConst
106+
}
107+
} else {
108+
hasNonConstCondition = true
109+
}
110+
expr.GetArgs()[i+1], isDeferred = foldConstant(args[i+1])
111+
isDeferredConst = isDeferredConst || isDeferred
112+
}
113+
114+
if l%2 == 0 {
115+
return expr, isDeferredConst
116+
}
117+
118+
// If the number of arguments in casewhen is odd, and the previous conditions
119+
// is const and false, then the folded else execution body is returned. otherwise
120+
// the execution body of the else are folded and replaced.
121+
if !hasNonConstCondition {
122+
foldedExpr, isDeferred := foldConstant(args[l-1])
123+
isDeferredConst = isDeferredConst || isDeferred
124+
if _, isConst := foldedExpr.(*Constant); isConst {
125+
foldedExpr.GetType().Decimal = expr.GetType().Decimal
126+
return foldedExpr, isDeferredConst
127+
}
128+
return BuildCastFunction(expr.GetCtx(), foldedExpr, foldedExpr.GetType()), isDeferredConst
129+
}
130+
131+
expr.GetArgs()[l-1], isDeferred = foldConstant(args[l-1])
132+
isDeferredConst = isDeferredConst || isDeferred
133+
134+
return expr, isDeferredConst
135+
}
136+
83137
func foldConstant(expr Expression) (Expression, bool) {
84138
switch x := expr.(type) {
85139
case *ScalarFunction:

expression/integration_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -4584,5 +4584,17 @@ func (s *testIntegrationSuite) TestDatetimeMicrosecond(c *C) {
45844584
testkit.Rows("2007-03-28 22:06:28"))
45854585
tk.MustQuery(`select DATE_ADD('2007-03-28 22:08:28',INTERVAL "-2.-2" MICROSECOND);`).Check(
45864586
testkit.Rows("2007-03-28 22:08:27.999998"))
4587+
}
4588+
4589+
func (s *testIntegrationSuite) TestFuncCaseWithLeftJoin(c *C) {
4590+
tk := testkit.NewTestKitWithInit(c, s.store)
4591+
4592+
tk.MustExec("create table kankan1(id int, name text)")
4593+
tk.MustExec("insert into kankan1 values(1, 'a')")
4594+
tk.MustExec("insert into kankan1 values(2, 'a')")
4595+
4596+
tk.MustExec("create table kankan2(id int, h1 text)")
4597+
tk.MustExec("insert into kankan2 values(2, 'z')")
45874598

4599+
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"))
45884600
}

0 commit comments

Comments
 (0)