@@ -29,6 +29,7 @@ func init() {
29
29
specialFoldHandler = map [string ]func (* ScalarFunction ) (Expression , bool ){
30
30
ast .If : ifFoldHandler ,
31
31
ast .Ifnull : ifNullFoldHandler ,
32
+ ast .Case : caseWhenHandler ,
32
33
}
33
34
}
34
35
@@ -80,6 +81,59 @@ func ifNullFoldHandler(expr *ScalarFunction) (Expression, bool) {
80
81
return expr , isDeferredConst
81
82
}
82
83
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
+
83
137
func foldConstant (expr Expression ) (Expression , bool ) {
84
138
switch x := expr .(type ) {
85
139
case * ScalarFunction :
0 commit comments