diff --git a/expression/constant_fold.go b/expression/constant_fold.go index 738def5d041b..6ebcce1871a2 100644 --- a/expression/constant_fold.go +++ b/expression/constant_fold.go @@ -41,7 +41,10 @@ func ifFoldHandler(expr *ScalarFunction) (Expression, bool) { if constArg, isConst := foldedArg0.(*Constant); isConst { arg0, isNull0, err := constArg.EvalInt(expr.Function.getCtx(), chunk.Row{}) if err != nil { - log.Warnf("fold constant %s: %s", expr.ExplainInfo(), err.Error()) + // Failed to fold this expr to a constant, print the DEBUG log and + // return the original expression to let the error to be evaluated + // again, in that time, the error is returned to the client. + log.Debugf("fold constant %s: %s", expr.ExplainInfo(), err.Error()) return expr, false } if !isNull0 && arg0 != 0 { @@ -59,16 +62,15 @@ func ifFoldHandler(expr *ScalarFunction) (Expression, bool) { func ifNullFoldHandler(expr *ScalarFunction) (Expression, bool) { args := expr.GetArgs() - foldedArg0, _ := foldConstant(args[0]) + foldedArg0, isDeferred := foldConstant(args[0]) if constArg, isConst := foldedArg0.(*Constant); isConst { - _, isNull0, err := constArg.EvalInt(expr.Function.getCtx(), chunk.Row{}) - if err != nil { - log.Warnf("fold constant %s: %s", expr.ExplainInfo(), err.Error()) - return expr, false - } - if isNull0 == true { + // Only check constArg.Value here. Because deferred expression is + // evaluated to constArg.Value after foldConstant(args[0]), it's not + // needed to be checked. + if constArg.Value.IsNull() { return foldConstant(args[1]) } + return constArg, isDeferred } isDeferredConst := false expr.GetArgs()[1], isDeferredConst = foldConstant(args[1]) diff --git a/expression/constant_fold_test.go b/expression/constant_fold_test.go new file mode 100644 index 000000000000..3ea8e972cfe0 --- /dev/null +++ b/expression/constant_fold_test.go @@ -0,0 +1,35 @@ +// Copyright 2019 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/util/testkit" +) + +func (s *testIntegrationSuite) TestFoldIfNull(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec(`use test;`) + tk.MustExec(`drop table if exists t;`) + tk.MustExec(`create table t(a bigint, b bigint);`) + tk.MustExec(`insert into t values(1, 1);`) + tk.MustQuery(`desc select ifnull("aaaa", a) from t;`).Check(testkit.Rows( + `Projection_3 10000.00 root "aaaa"`, + `└─TableReader_5 10000.00 root data:TableScan_4`, + ` └─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo`, + )) + tk.MustQuery(`show warnings;`).Check(testkit.Rows()) + tk.MustQuery(`select ifnull("aaaa", a) from t;`).Check(testkit.Rows("aaaa")) + tk.MustQuery(`show warnings;`).Check(testkit.Rows()) +}