diff --git a/executor/aggfuncs/func_count_distinct.go b/executor/aggfuncs/func_count_distinct.go index 8e73fd2b32ca4..21c9e54115f7d 100644 --- a/executor/aggfuncs/func_count_distinct.go +++ b/executor/aggfuncs/func_count_distinct.go @@ -319,6 +319,10 @@ func (e *countOriginalWithDistinct) UpdatePartialResult(sctx sessionctx.Context, p := (*partialResult4CountWithDistinct)(pr) encodedBytes := make([]byte, 0) + collators := make([]collate.Collator, 0, len(e.args)) + for _, arg := range e.args { + collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + } // Decimal struct is the biggest type we will use. buf := make([]byte, types.MyDecimalStructSize) @@ -328,7 +332,7 @@ func (e *countOriginalWithDistinct) UpdatePartialResult(sctx sessionctx.Context, encodedBytes = encodedBytes[:0] for i := 0; i < len(e.args) && !hasNull; i++ { - encodedBytes, isNull, err = evalAndEncode(sctx, e.args[i], row, buf, encodedBytes) + encodedBytes, isNull, err = evalAndEncode(sctx, e.args[i], collators[i], row, buf, encodedBytes) if err != nil { return memDelta, err } @@ -349,7 +353,7 @@ func (e *countOriginalWithDistinct) UpdatePartialResult(sctx sessionctx.Context, // evalAndEncode eval one row with an expression and encode value to bytes. func evalAndEncode( - sctx sessionctx.Context, arg expression.Expression, + sctx sessionctx.Context, arg expression.Expression, collator collate.Collator, row chunk.Row, buf, encodedBytes []byte, ) (_ []byte, isNull bool, err error) { switch tp := arg.GetType().EvalType(); tp { @@ -401,7 +405,7 @@ func evalAndEncode( if err != nil || isNull { break } - encodedBytes = codec.EncodeCompactBytes(encodedBytes, hack.Slice(val)) + encodedBytes = codec.EncodeCompactBytes(encodedBytes, collator.Key(val)) default: return nil, false, errors.Errorf("unsupported column type for encode %d", tp) } @@ -784,6 +788,10 @@ func (e *approxCountDistinctOriginal) UpdatePartialResult(sctx sessionctx.Contex encodedBytes := make([]byte, 0) // Decimal struct is the biggest type we will use. buf := make([]byte, types.MyDecimalStructSize) + collators := make([]collate.Collator, 0, len(e.args)) + for _, arg := range e.args { + collators = append(collators, collate.GetCollator(arg.GetType().Collate)) + } for _, row := range rowsInGroup { var err error @@ -791,7 +799,7 @@ func (e *approxCountDistinctOriginal) UpdatePartialResult(sctx sessionctx.Contex encodedBytes = encodedBytes[:0] for i := 0; i < len(e.args) && !hasNull; i++ { - encodedBytes, isNull, err = evalAndEncode(sctx, e.args[i], row, buf, encodedBytes) + encodedBytes, isNull, err = evalAndEncode(sctx, e.args[i], collators[i], row, buf, encodedBytes) if err != nil { return memDelta, err } diff --git a/expression/integration_test.go b/expression/integration_test.go index 25c5972c0c789..4bef62b16d047 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -7026,6 +7026,22 @@ func (s *testIntegrationSerialSuite) TestIssue16668(c *C) { tk.MustQuery("select count(distinct(b)) from tx").Check(testkit.Rows("4")) } +func (s *testIntegrationSerialSuite) TestIssue27091(c *C) { + collate.SetNewCollationEnabledForTest(true) + defer collate.SetNewCollationEnabledForTest(false) + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists tx") + tk.MustExec("CREATE TABLE `tx` ( `a` int(11) NOT NULL,`b` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `c` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL)") + tk.MustExec("insert into tx values (1, 'a', 'a'), (2, 'A ', 'a '), (3, 'A', 'A'), (4, 'a ', 'A ')") + tk.MustQuery("select count(distinct b) from tx").Check(testkit.Rows("1")) + tk.MustQuery("select count(distinct c) from tx").Check(testkit.Rows("2")) + tk.MustQuery("select count(distinct b, c) from tx where a < 3").Check(testkit.Rows("1")) + tk.MustQuery("select approx_count_distinct(b) from tx").Check(testkit.Rows("1")) + tk.MustQuery("select approx_count_distinct(c) from tx").Check(testkit.Rows("2")) + tk.MustQuery("select approx_count_distinct(b, c) from tx where a < 3").Check(testkit.Rows("1")) +} + func (s *testIntegrationSerialSuite) TestCollateStringFunction(c *C) { collate.SetNewCollationEnabledForTest(true) defer collate.SetNewCollationEnabledForTest(false)