From 7b8fd3729f7cbb8a6f652b33e714b102ba88ae8c Mon Sep 17 00:00:00 2001 From: YangKeao Date: Wed, 27 Mar 2024 10:24:47 +0800 Subject: [PATCH] expression: set a collation according to the arguments for `ifnull` in constant folding (#52119) close pingcap/tidb#51765 --- pkg/expression/constant_fold.go | 10 ++++++- .../r/expression/constant_fold.result | 26 +++++++++++++++++++ .../t/expression/constant_fold.test | 13 ++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/integrationtest/r/expression/constant_fold.result create mode 100644 tests/integrationtest/t/expression/constant_fold.test diff --git a/pkg/expression/constant_fold.go b/pkg/expression/constant_fold.go index 28ce83be59ff8..96198ebdb9133 100644 --- a/pkg/expression/constant_fold.go +++ b/pkg/expression/constant_fold.go @@ -100,7 +100,15 @@ func ifNullFoldHandler(ctx BuildContext, expr *ScalarFunction) (Expression, bool // evaluated to constArg.Value after foldConstant(args[0]), it's not // needed to be checked. if constArg.Value.IsNull() { - return foldConstant(ctx, args[1]) + foldedExpr, isConstant := foldConstant(ctx, args[1]) + + // See https://github.com/pingcap/tidb/issues/51765. If the first argument can + // be folded into NULL, the collation of IFNULL should be the same as the second + // arguments. + expr.GetType().SetCharset(args[1].GetType().GetCharset()) + expr.GetType().SetCollate(args[1].GetType().GetCollate()) + + return foldedExpr, isConstant } return constArg, isDeferred } diff --git a/tests/integrationtest/r/expression/constant_fold.result b/tests/integrationtest/r/expression/constant_fold.result new file mode 100644 index 0000000000000..05becb4d7a29e --- /dev/null +++ b/tests/integrationtest/r/expression/constant_fold.result @@ -0,0 +1,26 @@ +drop table if exists t, t1; +create table t (id varbinary(16)); +create table t1(id char(16) charset utf8mb4 collate utf8mb4_general_ci); +insert into t values (); +insert into t1 values ("Hello World"); +select collation(ifnull(concat(NULL),'~')); +collation(ifnull(concat(NULL),'~')) +utf8mb4_general_ci +select collation(ifnull(concat(NULL),ifnull(concat(NULL),'~'))); +collation(ifnull(concat(NULL),ifnull(concat(NULL),'~'))) +utf8mb4_general_ci +select collation(ifnull(concat(id),'~')) from t; +collation(ifnull(concat(id),'~')) +binary +select collation(ifnull(concat(NULL),ifnull(concat(id),'~'))) from t; +collation(ifnull(concat(NULL),ifnull(concat(id),'~'))) +binary +select collation(ifnull(concat(id),ifnull(concat(id),'~'))) from t; +collation(ifnull(concat(id),ifnull(concat(id),'~'))) +binary +select collation(ifnull(concat(NULL),id)) from t1; +collation(ifnull(concat(NULL),id)) +utf8mb4_general_ci +select collation(ifnull(concat(NULL),ifnull(concat(NULL),id))) from t1; +collation(ifnull(concat(NULL),ifnull(concat(NULL),id))) +utf8mb4_general_ci diff --git a/tests/integrationtest/t/expression/constant_fold.test b/tests/integrationtest/t/expression/constant_fold.test new file mode 100644 index 0000000000000..43a09302ca740 --- /dev/null +++ b/tests/integrationtest/t/expression/constant_fold.test @@ -0,0 +1,13 @@ +# TestFoldIfNull +drop table if exists t, t1; +create table t (id varbinary(16)); +create table t1(id char(16) charset utf8mb4 collate utf8mb4_general_ci); +insert into t values (); +insert into t1 values ("Hello World"); +select collation(ifnull(concat(NULL),'~')); +select collation(ifnull(concat(NULL),ifnull(concat(NULL),'~'))); +select collation(ifnull(concat(id),'~')) from t; +select collation(ifnull(concat(NULL),ifnull(concat(id),'~'))) from t; +select collation(ifnull(concat(id),ifnull(concat(id),'~'))) from t; +select collation(ifnull(concat(NULL),id)) from t1; +select collation(ifnull(concat(NULL),ifnull(concat(NULL),id))) from t1;