From 4ffbd35d3e19cdd276c5d1afb8cb3ad09393792f Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Tue, 11 Feb 2025 17:19:41 +0800 Subject: [PATCH] support tidb truncate function (#9842) close pingcap/tiflash#9846 Signed-off-by: guo-shaoge Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- dbms/src/Flash/Coprocessor/DAGUtils.cpp | 8 +- dbms/src/Functions/FunctionsRound.cpp | 1 + dbms/src/Functions/FunctionsRound.h | 183 +++++-- dbms/src/Functions/FunctionsString.cpp | 4 +- .../tests/gtest_functions_round_with_frac.cpp | 108 ++-- .../gtest_functions_truncate_with_frac.cpp | 345 +++++++++++++ tests/fullstack-test/expr/tidb_truncate.test | 479 ++++++++++++++++++ 7 files changed, 1031 insertions(+), 97 deletions(-) create mode 100644 dbms/src/Functions/tests/gtest_functions_truncate_with_frac.cpp create mode 100644 tests/fullstack-test/expr/tidb_truncate.test diff --git a/dbms/src/Flash/Coprocessor/DAGUtils.cpp b/dbms/src/Flash/Coprocessor/DAGUtils.cpp index 77acc88fa3b..dad4a3da415 100644 --- a/dbms/src/Flash/Coprocessor/DAGUtils.cpp +++ b/dbms/src/Flash/Coprocessor/DAGUtils.cpp @@ -309,10 +309,10 @@ const std::unordered_map scalar_func_map({ {tipb::ScalarFuncSig::Radians, "radians"}, {tipb::ScalarFuncSig::Sin, "sin"}, {tipb::ScalarFuncSig::Tan, "tan"}, - {tipb::ScalarFuncSig::TruncateInt, "trunc"}, - {tipb::ScalarFuncSig::TruncateReal, "trunc"}, - //{tipb::ScalarFuncSig::TruncateDecimal, "cast"}, - {tipb::ScalarFuncSig::TruncateUint, "trunc"}, + {tipb::ScalarFuncSig::TruncateInt, "tidbTruncateWithFrac"}, + {tipb::ScalarFuncSig::TruncateReal, "tidbTruncateWithFrac"}, + {tipb::ScalarFuncSig::TruncateDecimal, "tidbTruncateWithFrac"}, + {tipb::ScalarFuncSig::TruncateUint, "tidbTruncateWithFrac"}, {tipb::ScalarFuncSig::LogicalAnd, "and"}, {tipb::ScalarFuncSig::LogicalOr, "or"}, diff --git a/dbms/src/Functions/FunctionsRound.cpp b/dbms/src/Functions/FunctionsRound.cpp index 4be2051e95c..aa8ec68a7f3 100644 --- a/dbms/src/Functions/FunctionsRound.cpp +++ b/dbms/src/Functions/FunctionsRound.cpp @@ -38,6 +38,7 @@ void registerFunctionsRound(FunctionFactory & factory) factory.registerFunction("truncate", FunctionFactory::CaseInsensitive); factory.registerFunction(); + factory.registerFunction(); } } // namespace DB diff --git a/dbms/src/Functions/FunctionsRound.h b/dbms/src/Functions/FunctionsRound.h index 04e374aaf25..f0f5db66adf 100644 --- a/dbms/src/Functions/FunctionsRound.h +++ b/dbms/src/Functions/FunctionsRound.h @@ -965,7 +965,7 @@ struct ConstPowOf10 static_assert(!overflow, "Computation overflows"); }; -template +template struct TiDBFloatingRound { static_assert(std::is_floating_point_v); @@ -974,8 +974,8 @@ struct TiDBFloatingRound static OutputType eval(InputType input, FracType frac) { - // modified from . - + // ported from https://github.com/pingcap/tidb/blob/26237b35f857c2388eab46f9ee3b351687143681/types/helper.go#L33-L48 and + // https://github.com/pingcap/tidb/blob/26237b35f857c2388eab46f9ee3b351687143681/types/helper.go#L50-L61. auto value = static_cast(input); auto base = 1.0; @@ -997,9 +997,16 @@ struct TiDBFloatingRound value = scaled_value; } - // floating-point environment is thread-local, so `fesetround` is thread-safe. - std::fesetround(FE_TONEAREST); - value = std::nearbyint(value); + if constexpr (is_tidb_truncate) + { + value = std::trunc(value); + } + else + { + // floating-point environment is thread-local, so `fesetround` is thread-safe. + std::fesetround(FE_TONEAREST); + value = std::nearbyint(value); + } if (frac != 0) { @@ -1018,7 +1025,7 @@ struct TiDBFloatingRound } }; -template +template struct TiDBIntegerRound { static_assert(is_integer_v); @@ -1061,7 +1068,7 @@ struct TiDBIntegerRound } } - static OutputType eval(InputType input, FracType frac) + static OutputType evalRound(InputType input, FracType frac) { auto value = static_cast(input); @@ -1107,6 +1114,33 @@ struct TiDBIntegerRound return castBack((input < 0), absolute_value); } } + + static OutputType evalTruncate(InputType input, FracType frac) + { + // ported from https://github.com/pingcap/tidb/blob/807b8923c0181d89d4ea8e4195f9d27d299298a7/pkg/expression/builtin_math.go#L2196-L2219 + const auto value = static_cast(input); + if (frac >= 0) + return value; + else if (frac <= -max_digits) + return 0; + else + { + // To make sure static_cast(Pow::result[-frac]) will not overflow. + assert(Pow::result[-frac] < std::numeric_limits::max()); + const auto base = static_cast(Pow::result[-frac]); + + const auto remainder = value % base; + return value - remainder; + } + } + + static OutputType eval(InputType input, FracType frac) + { + if constexpr (is_tidb_truncate) + return evalTruncate(input, frac); + else + return evalRound(input, frac); + } }; struct TiDBDecimalRoundInfo @@ -1127,7 +1161,7 @@ struct TiDBDecimalRoundInfo {} }; -template +template struct TiDBDecimalRound { static_assert(IsDecimal); @@ -1158,10 +1192,13 @@ struct TiDBDecimalRound auto remainder = absolute_value % base; absolute_value -= remainder; - if (remainder >= base / 2) + if constexpr (!is_tidb_truncate) { - // round up. - absolute_value += base; + if (remainder >= base / 2) + { + // round up. + absolute_value += base; + } } } @@ -1198,7 +1235,12 @@ struct TiDBDecimalRound struct TiDBRoundPrecisionInferer { - static std::tuple infer(PrecType prec, ScaleType scale, FracType frac, bool is_const_frac) + static std::tuple infer( + PrecType prec, + ScaleType scale, + FracType frac, + bool is_const_frac, + bool is_tidb_truncate) { assert(prec >= scale); PrecType int_prec = prec - scale; @@ -1206,6 +1248,8 @@ struct TiDBRoundPrecisionInferer // +1 for possible overflow, e.g. round(99999.9) => 100000 ScaleType int_prec_increment = 1; + if (is_tidb_truncate) + int_prec_increment = 0; if (is_const_frac) { @@ -1219,6 +1263,14 @@ struct TiDBRoundPrecisionInferer } PrecType new_prec = std::min(decimal_max_prec, int_prec + int_prec_increment + new_scale); + if (new_prec == 0) + { + // new_prec can be zero when the prec is eq to scale and frac is le to zero for truncate: + // select truncate(0.22, 0) from t_col_decimal_2_2; + // Not possible for round, because int_prec_increment is 1 for round. + RUNTIME_CHECK(is_tidb_truncate && is_const_frac && frac <= 0 && prec == scale); + new_prec = 1; + } return std::make_tuple(new_prec, new_scale); } }; @@ -1239,7 +1291,8 @@ template < typename OutputType, typename InputColumn, typename FracColumn, - typename OutputColumn> + typename OutputColumn, + bool is_tidb_truncate> struct TiDBRound { static void apply(const TiDBRoundArguments & args) @@ -1273,11 +1326,14 @@ struct TiDBRound auto frac_data = frac_column->template getValue(); if constexpr (std::is_floating_point_v) - output_data[0] = TiDBFloatingRound::eval(input_data, frac_data); + output_data[0] + = TiDBFloatingRound::eval(input_data, frac_data); else if constexpr (IsDecimal) - output_data[0] = TiDBDecimalRound::eval(input_data, frac_data, info); + output_data[0] + = TiDBDecimalRound::eval(input_data, frac_data, info); else - output_data[0] = TiDBIntegerRound::eval(input_data, frac_data); + output_data[0] + = TiDBIntegerRound::eval(input_data, frac_data); } else { @@ -1287,11 +1343,17 @@ struct TiDBRound for (size_t i = 0; i < size; ++i) { if constexpr (std::is_floating_point_v) - output_data[i] = TiDBFloatingRound::eval(input_data, frac_data[i]); + output_data[i] = TiDBFloatingRound::eval( + input_data, + frac_data[i]); else if constexpr (IsDecimal) - output_data[i] = TiDBDecimalRound::eval(input_data, frac_data[i], info); + output_data[i] = TiDBDecimalRound::eval( + input_data, + frac_data[i], + info); else - output_data[i] = TiDBIntegerRound::eval(input_data, frac_data[i]); + output_data[i] + = TiDBIntegerRound::eval(input_data, frac_data[i]); } } } @@ -1305,11 +1367,17 @@ struct TiDBRound for (size_t i = 0; i < size; ++i) { if constexpr (std::is_floating_point_v) - output_data[i] = TiDBFloatingRound::eval(input_data[i], frac_data); + output_data[i] = TiDBFloatingRound::eval( + input_data[i], + frac_data); else if constexpr (IsDecimal) - output_data[i] = TiDBDecimalRound::eval(input_data[i], frac_data, info); + output_data[i] = TiDBDecimalRound::eval( + input_data[i], + frac_data, + info); else - output_data[i] = TiDBIntegerRound::eval(input_data[i], frac_data); + output_data[i] + = TiDBIntegerRound::eval(input_data[i], frac_data); } } else @@ -1320,12 +1388,18 @@ struct TiDBRound for (size_t i = 0; i < size; ++i) { if constexpr (std::is_floating_point_v) - output_data[i] = TiDBFloatingRound::eval(input_data[i], frac_data[i]); + output_data[i] = TiDBFloatingRound::eval( + input_data[i], + frac_data[i]); else if constexpr (IsDecimal) - output_data[i] - = TiDBDecimalRound::eval(input_data[i], frac_data[i], info); + output_data[i] = TiDBDecimalRound::eval( + input_data[i], + frac_data[i], + info); else - output_data[i] = TiDBIntegerRound::eval(input_data[i], frac_data[i]); + output_data[i] = TiDBIntegerRound::eval( + input_data[i], + frac_data[i]); } } } @@ -1333,14 +1407,15 @@ struct TiDBRound }; /** - * round(x, d) for TiDB. + * round(x, d) and truncate(x, d) for TiDB. */ -class FunctionTiDBRoundWithFrac : public IFunction +template +class FunctionTiDBRoundImpl : public IFunction { public: - static constexpr auto name = "tidbRoundWithFrac"; + static constexpr auto name = Name::name; - static FunctionPtr create(const Context &) { return std::make_shared(); } + static FunctionPtr create(const Context &) { return std::make_shared(); } String getName() const override { return name; } size_t getNumberOfArguments() const override { return 2; } @@ -1355,7 +1430,6 @@ class FunctionTiDBRoundWithFrac : public IFunction // non-const frac column can generate different return types. Plese see TiDBRoundPrecisionInferer for details. bool useDefaultImplementationForConstants() const override { return false; } -private: static FracType getFracFromConstColumn(const ColumnConst * column) { using UnsignedFrac = make_unsigned_t; @@ -1383,6 +1457,7 @@ class FunctionTiDBRoundWithFrac : public IFunction } } +private: DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override { checkArguments(arguments); @@ -1430,7 +1505,8 @@ class FunctionTiDBRoundWithFrac : public IFunction else is_const_frac = false; - auto [new_prec, new_scale] = TiDBRoundPrecisionInferer::infer(prec, scale, frac, is_const_frac); + auto [new_prec, new_scale] + = TiDBRoundPrecisionInferer::infer(prec, scale, frac, is_const_frac, is_tidb_truncate); return createDecimal(new_prec, new_scale); } } @@ -1566,16 +1642,44 @@ class FunctionTiDBRoundWithFrac : public IFunction if (args.input_column->isColumnConst()) { if (args.frac_column->isColumnConst()) - TiDBRound::apply(args); + TiDBRound< + InputType, + FracType, + OutputType, + ColumnConst, + ColumnConst, + OutputColumn, + is_tidb_truncate>::apply(args); else - TiDBRound::apply(args); + TiDBRound< + InputType, + FracType, + OutputType, + ColumnConst, + FracColumn, + OutputColumn, + is_tidb_truncate>::apply(args); } else { if (args.frac_column->isColumnConst()) - TiDBRound::apply(args); + TiDBRound< + InputType, + FracType, + OutputType, + InputColumn, + ColumnConst, + OutputColumn, + is_tidb_truncate>::apply(args); else - TiDBRound::apply(args); + TiDBRound< + InputType, + FracType, + OutputType, + InputColumn, + FracColumn, + OutputColumn, + is_tidb_truncate>::apply(args); } return true; @@ -1622,6 +1726,9 @@ struct NameRoundDecimalToInt { static constexpr auto name = "roundDecimalToInt"; struct NameCeilDecimalToInt { static constexpr auto name = "ceilDecimalToInt"; }; struct NameFloorDecimalToInt { static constexpr auto name = "floorDecimalToInt"; }; struct NameTruncDecimalToInt { static constexpr auto name = "truncDecimalToInt"; }; + +struct NameTiDBRoundWithFrac { static constexpr auto name = "tidbRoundWithFrac"; }; +struct NameTiDBTruncateWithFrac { static constexpr auto name = "tidbTruncateWithFrac"; }; // clang-format on using FunctionRoundToExp2 = FunctionUnaryArithmetic; @@ -1638,6 +1745,8 @@ using FunctionCeilDecimalToInt = FunctionRoundingDecimalToInt; using FunctionTruncDecimalToInt = FunctionRoundingDecimalToInt; +using FunctionTiDBRoundWithFrac = FunctionTiDBRoundImpl; +using FunctionTiDBTruncateWithFrac = FunctionTiDBRoundImpl; struct PositiveMonotonicity { diff --git a/dbms/src/Functions/FunctionsString.cpp b/dbms/src/Functions/FunctionsString.cpp index bda73bc5f09..a4503fc1f5c 100644 --- a/dbms/src/Functions/FunctionsString.cpp +++ b/dbms/src/Functions/FunctionsString.cpp @@ -5893,9 +5893,9 @@ class FormatImpl : public IFunction const TiDBDecimalRoundInfo & info [[maybe_unused]]) { if constexpr (IsDecimal) - return TiDBDecimalRound::eval(number, max_num_decimals, info); + return TiDBDecimalRound::eval(number, max_num_decimals, info); else if constexpr (std::is_floating_point_v) - return TiDBFloatingRound::eval(number, max_num_decimals); + return TiDBFloatingRound::eval(number, max_num_decimals); else { static_assert(std::is_integral_v); diff --git a/dbms/src/Functions/tests/gtest_functions_round_with_frac.cpp b/dbms/src/Functions/tests/gtest_functions_round_with_frac.cpp index 4eaa30f2bc3..885f2c92021 100644 --- a/dbms/src/Functions/tests/gtest_functions_round_with_frac.cpp +++ b/dbms/src/Functions/tests/gtest_functions_round_with_frac.cpp @@ -46,60 +46,60 @@ TEST_F(TestFunctionsRoundWithFrac, PrecisionInfer) constexpr auto infer = TiDBRoundPrecisionInferer::infer; using Result = std::tuple; - EXPECT_EQ(infer(9, 3, 2, true), Result(9, 2)); - EXPECT_EQ(infer(9, 3, 1, true), Result(8, 1)); - EXPECT_EQ(infer(9, 3, 0, true), Result(7, 0)); - EXPECT_EQ(infer(9, 3, -1, true), Result(7, 0)); - EXPECT_EQ(infer(9, 3, -2, true), Result(7, 0)); - EXPECT_EQ(infer(9, 3, 40, true), Result(36, 30)); - EXPECT_EQ(infer(9, 3, -100, true), Result(7, 0)); - EXPECT_EQ(infer(9, 3, 0, false), Result(10, 3)); - EXPECT_EQ(infer(9, 3, 233, false), Result(10, 3)); - - EXPECT_EQ(infer(18, 6, 2, true), Result(15, 2)); - EXPECT_EQ(infer(18, 6, 1, true), Result(14, 1)); - EXPECT_EQ(infer(18, 6, 0, true), Result(13, 0)); - EXPECT_EQ(infer(18, 6, -1, true), Result(13, 0)); - EXPECT_EQ(infer(18, 6, -2, true), Result(13, 0)); - EXPECT_EQ(infer(18, 6, 40, true), Result(42, 30)); - EXPECT_EQ(infer(18, 6, -100, true), Result(13, 0)); - EXPECT_EQ(infer(18, 6, 0, false), Result(19, 6)); - EXPECT_EQ(infer(18, 6, -233, false), Result(19, 6)); - - EXPECT_EQ(infer(30, 30, 2, true), Result(3, 2)); - EXPECT_EQ(infer(30, 30, 1, true), Result(2, 1)); - EXPECT_EQ(infer(30, 30, 0, true), Result(1, 0)); - EXPECT_EQ(infer(30, 30, -1, true), Result(1, 0)); - EXPECT_EQ(infer(30, 30, -2, true), Result(1, 0)); - EXPECT_EQ(infer(30, 30, 40, true), Result(30, 30)); - EXPECT_EQ(infer(30, 30, -100, true), Result(1, 0)); - EXPECT_EQ(infer(30, 30, 0, false), Result(31, 30)); - EXPECT_EQ(infer(30, 30, 233, false), Result(31, 30)); - - EXPECT_EQ(infer(64, 0, 40, true), Result(65, 30)); - EXPECT_EQ(infer(64, 0, -100, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, -62, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, -63, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, -64, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, -65, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, -66, true), Result(65, 0)); - EXPECT_EQ(infer(64, 0, 0, false), Result(65, 0)); - EXPECT_EQ(infer(64, 0, 233, false), Result(65, 0)); - - EXPECT_EQ(infer(65, 30, 40, true), Result(65, 30)); - EXPECT_EQ(infer(65, 30, -100, true), Result(36, 0)); - EXPECT_EQ(infer(65, 30, 0, false), Result(65, 30)); - EXPECT_EQ(infer(65, 30, 233, false), Result(65, 30)); - - EXPECT_EQ(infer(65, 0, 233, false), Result(65, 0)); - EXPECT_EQ(infer(65, 1, 233, false), Result(65, 1)); - EXPECT_EQ(infer(64, 0, 233, false), Result(65, 0)); - - EXPECT_EQ(infer(18, 6, 4, true), Result(17, 4)); - EXPECT_EQ(infer(18, 6, 5, true), Result(18, 5)); - EXPECT_EQ(infer(18, 6, 6, true), Result(18, 6)); - EXPECT_EQ(infer(18, 6, 7, true), Result(19, 7)); - EXPECT_EQ(infer(18, 6, 8, true), Result(20, 8)); + EXPECT_EQ(infer(9, 3, 2, true, false), Result(9, 2)); + EXPECT_EQ(infer(9, 3, 1, true, false), Result(8, 1)); + EXPECT_EQ(infer(9, 3, 0, true, false), Result(7, 0)); + EXPECT_EQ(infer(9, 3, -1, true, false), Result(7, 0)); + EXPECT_EQ(infer(9, 3, -2, true, false), Result(7, 0)); + EXPECT_EQ(infer(9, 3, 40, true, false), Result(36, 30)); + EXPECT_EQ(infer(9, 3, -100, true, false), Result(7, 0)); + EXPECT_EQ(infer(9, 3, 0, false, false), Result(10, 3)); + EXPECT_EQ(infer(9, 3, 233, false, false), Result(10, 3)); + + EXPECT_EQ(infer(18, 6, 2, true, false), Result(15, 2)); + EXPECT_EQ(infer(18, 6, 1, true, false), Result(14, 1)); + EXPECT_EQ(infer(18, 6, 0, true, false), Result(13, 0)); + EXPECT_EQ(infer(18, 6, -1, true, false), Result(13, 0)); + EXPECT_EQ(infer(18, 6, -2, true, false), Result(13, 0)); + EXPECT_EQ(infer(18, 6, 40, true, false), Result(42, 30)); + EXPECT_EQ(infer(18, 6, -100, true, false), Result(13, 0)); + EXPECT_EQ(infer(18, 6, 0, false, false), Result(19, 6)); + EXPECT_EQ(infer(18, 6, -233, false, false), Result(19, 6)); + + EXPECT_EQ(infer(30, 30, 2, true, false), Result(3, 2)); + EXPECT_EQ(infer(30, 30, 1, true, false), Result(2, 1)); + EXPECT_EQ(infer(30, 30, 0, true, false), Result(1, 0)); + EXPECT_EQ(infer(30, 30, -1, true, false), Result(1, 0)); + EXPECT_EQ(infer(30, 30, -2, true, false), Result(1, 0)); + EXPECT_EQ(infer(30, 30, 40, true, false), Result(30, 30)); + EXPECT_EQ(infer(30, 30, -100, true, false), Result(1, 0)); + EXPECT_EQ(infer(30, 30, 0, false, false), Result(31, 30)); + EXPECT_EQ(infer(30, 30, 233, false, false), Result(31, 30)); + + EXPECT_EQ(infer(64, 0, 40, true, false), Result(65, 30)); + EXPECT_EQ(infer(64, 0, -100, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, -62, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, -63, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, -64, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, -65, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, -66, true, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, 0, false, false), Result(65, 0)); + EXPECT_EQ(infer(64, 0, 233, false, false), Result(65, 0)); + + EXPECT_EQ(infer(65, 30, 40, true, false), Result(65, 30)); + EXPECT_EQ(infer(65, 30, -100, true, false), Result(36, 0)); + EXPECT_EQ(infer(65, 30, 0, false, false), Result(65, 30)); + EXPECT_EQ(infer(65, 30, 233, false, false), Result(65, 30)); + + EXPECT_EQ(infer(65, 0, 233, false, false), Result(65, 0)); + EXPECT_EQ(infer(65, 1, 233, false, false), Result(65, 1)); + EXPECT_EQ(infer(64, 0, 233, false, false), Result(65, 0)); + + EXPECT_EQ(infer(18, 6, 4, true, false), Result(17, 4)); + EXPECT_EQ(infer(18, 6, 5, true, false), Result(18, 5)); + EXPECT_EQ(infer(18, 6, 6, true, false), Result(18, 6)); + EXPECT_EQ(infer(18, 6, 7, true, false), Result(19, 7)); + EXPECT_EQ(infer(18, 6, 8, true, false), Result(20, 8)); } template diff --git a/dbms/src/Functions/tests/gtest_functions_truncate_with_frac.cpp b/dbms/src/Functions/tests/gtest_functions_truncate_with_frac.cpp new file mode 100644 index 00000000000..733aabc2784 --- /dev/null +++ b/dbms/src/Functions/tests/gtest_functions_truncate_with_frac.cpp @@ -0,0 +1,345 @@ +// Copyright 2025 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, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +namespace DB +{ +namespace tests +{ +class TestFunctionsTruncateWithFrac : public DB::tests::FunctionTest +{ +public: + String func_name = "tidbTruncateWithFrac"; + + auto getFrac(size_t size, const std::optional & frac) + { + return createConstColumn>(size, {frac}); + } + + auto execute(const ColumnWithTypeAndName & input, const ColumnWithTypeAndName & frac) + { + return executeFunction(func_name, input, frac); + } + + auto execute(const ColumnWithTypeAndName & input, std::optional frac) + { + return execute(input, getFrac(input.column->size(), frac)); + } +}; + +template +class TestFunctionsTruncateWithFracSigned : public TestFunctionsTruncateWithFrac +{ +}; + +using TestFunctionsTruncateWithFracSignedTypes = ::testing::Types; +TYPED_TEST_CASE(TestFunctionsTruncateWithFracSigned, TestFunctionsTruncateWithFracSignedTypes); + +TYPED_TEST(TestFunctionsTruncateWithFracSigned, ConstFrac) +try +{ + using Int = TypeParam; + + int digits = std::numeric_limits::digits10; + Int large = 5; + for (int i = 0; i < digits - 1; ++i) + large *= 10; + +#define DATA \ + { \ + 0, 1, -1, 4, 5, -4, -5, 49, 50, -49, -50, large - 1, large, -(large - 1), -large, {} \ + } + + auto input = createColumn>(DATA); + auto output = createColumn>(DATA); +#undef DATA + + ASSERT_COLUMN_EQ(output, this->execute(input, std::numeric_limits::max())); + for (int i = 0; i <= 100; ++i) + ASSERT_COLUMN_EQ(output, this->execute(input, i)) << "i = " << i; + + const auto res = (large / 10) * 10; + const auto res1 = ((large - 1) / 10) * 10; + ASSERT_COLUMN_EQ( + createColumn>({0, 0, 0, 0, 0, 0, 0, 40, 50, -40, -50, res1, res, -res1, -res, {}}), + this->execute(input, -1)); +} +CATCH + +TEST_F(TestFunctionsTruncateWithFrac, Float32) +{ + using Float = Float32; + + auto input = createColumn>( + {0.0, 2.5, -2.5, 0.25, -0.25, 0.125, -0.125, 25, -25, 250, -250, 2.6, 2.4, -2.6, -2.4, {}}); + + // const frac + ASSERT_COLUMN_EQ( + createColumn>({0, 2, -2, 0.0, -0.0, 0.0, -0.0, 25, -25, 250, -250, 2, 2, -2, -2, {}}), + this->execute(input, 0)); + // truncate(2.6, 1) -> 2.6 is 2.599... in Float32, so the result is 2.5 for Float32. + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.2, -0.2, 0.1, -0.1, 25, -25, 250, -250, 2.5, 2.4, -2.5, -2.4, {}}), + this->execute(input, 1)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.25, -0.25, 0.12, -0.12, 25, -25, 250, -250, 2.59, 2.4, -2.59, -2.4, {}}), + this->execute(input, 2)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.25, -0.25, 0.125, -0.125, 25, -25, 250, -250, 2.599, 2.4, -2.599, -2.4, {}}), + this->execute(input, 3)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 20, -20, 250, -250, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -1)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 200, -200, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -2)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -3)); + + // const input + ASSERT_COLUMN_EQ( + createColumn>({0, 0.1, 0.12, 0.125, {}}), + this->execute(createConstColumn(5, 0.125), createColumn>({0, 1, 2, 3, {}}))); + ASSERT_COLUMN_EQ( + createConstColumn>(5, {}), + this->execute(createConstColumn>(5, {}), createColumn>({0, 1, 2, 3, {}}))); + + // const input & frac + ASSERT_COLUMN_EQ( + createConstColumn(1, 0.12), + this->execute(createConstColumn(1, 0.125), createConstColumn(1, 2))); + ASSERT_COLUMN_EQ( + createConstColumn>(1, {}), + this->execute(createConstColumn(1, 0.125), createConstColumn>(1, {}))); + ASSERT_COLUMN_EQ( + createConstColumn>(1, {}), + this->execute(createConstColumn>(1, {}), createConstColumn(1, 2))); +} + +TEST_F(TestFunctionsTruncateWithFrac, Float64) +{ + using Float = Float64; + + auto input = createColumn>( + {0.0, 2.5, -2.5, 0.25, -0.25, 0.125, -0.125, 25, -25, 250, -250, 2.6, 2.4, -2.6, -2.4, {}}); + + // const frac + ASSERT_COLUMN_EQ( + createColumn>({0, 2, -2, 0.0, -0.0, 0.0, -0.0, 25, -25, 250, -250, 2, 2, -2, -2, {}}), + this->execute(input, 0)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.2, -0.2, 0.1, -0.1, 25, -25, 250, -250, 2.6, 2.4, -2.6, -2.4, {}}), + this->execute(input, 1)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.25, -0.25, 0.12, -0.12, 25, -25, 250, -250, 2.6, 2.4, -2.6, -2.4, {}}), + this->execute(input, 2)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 2.5, -2.5, 0.25, -0.25, 0.125, -0.125, 25, -25, 250, -250, 2.6, 2.4, -2.6, -2.4, {}}), + this->execute(input, 3)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 20, -20, 250, -250, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -1)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 200, -200, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -2)); + ASSERT_COLUMN_EQ( + createColumn>( + {0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, -0.0, 0.0, 0.0, -0.0, -0.0, {}}), + this->execute(input, -3)); + + // const input + ASSERT_COLUMN_EQ( + createColumn>({0, 0.1, 0.12, 0.125, {}}), + this->execute(createConstColumn(5, 0.125), createColumn>({0, 1, 2, 3, {}}))); + ASSERT_COLUMN_EQ( + createConstColumn>(5, {}), + this->execute(createConstColumn>(5, {}), createColumn>({0, 1, 2, 3, {}}))); + + // const input & frac + ASSERT_COLUMN_EQ( + createConstColumn(1, 0.12), + this->execute(createConstColumn(1, 0.125), createConstColumn(1, 2))); + ASSERT_COLUMN_EQ( + createConstColumn>(1, {}), + this->execute(createConstColumn(1, 0.125), createConstColumn>(1, {}))); + ASSERT_COLUMN_EQ( + createConstColumn>(1, {}), + this->execute(createConstColumn>(1, {}), createConstColumn(1, 2))); +} + +TEST_F(TestFunctionsTruncateWithFrac, DecimalUpgrade) +{ + // decimal upgrade + // Decimal(2, 1) -> Decimal(11, 10) + ASSERT_COLUMN_EQ( + createConstColumn(std::make_tuple(11, 10), 100, "9.9" + String(9, '0')), + execute(createConstColumn(std::make_tuple(2, 1), 100, "9.9"), createConstColumn(100, 10))); + + // Decimal(5, 0) -> Decimal(35, 30) + ASSERT_COLUMN_EQ( + createConstColumn(std::make_tuple(35, 30), 100, "99999." + String(30, '0')), + execute( + createConstColumn(std::make_tuple(5, 0), 100, "99999"), + createConstColumn(100, 1000))); + + // Decimal(9, 0) -> Decimal(39, 30) + ASSERT_COLUMN_EQ( + createConstColumn(std::make_tuple(39, 30), 100, "999999999." + String(30, '0')), + execute( + createConstColumn(std::make_tuple(9, 0), 100, "999999999"), + createConstColumn(100, 30))); +} + +template +class TestFunctionsTruncateWithFracDecimal : public TestFunctionsTruncateWithFrac +{ +}; + +using TestFunctionsTruncateWithFracDecimalTypes = ::testing::Types; +TYPED_TEST_CASE(TestFunctionsTruncateWithFracDecimal, TestFunctionsTruncateWithFracDecimalTypes); + +TYPED_TEST(TestFunctionsTruncateWithFracDecimal, Basic) +try +{ + using Decimal = TypeParam; + constexpr int max_prec = maxDecimalPrecision(); + + auto column = [](std::tuple args, const std::vector> & data) { + return createColumn>(args, data); + }; + + auto constColumn = [](std::tuple args, size_t size, const std::optional & data) { + return createConstColumn>(args, size, data); + }; + + // const frac + { + // Decimal(max_prec - 1, 3) + constexpr int prec = max_prec - 1; + auto large = String(prec - 3, '9') + ".999"; + auto truncated = String(prec - 3, '9'); + auto input = column( + {prec, 3}, + {"0.000", + "2.490", + "-2.490", + "2.500", + "-2.500", + "0.250", + "-0.250", + "25.000", + "-25.000", + large, + "-" + large, + {}}); + ASSERT_COLUMN_EQ(input, this->execute(input, 3)); + ASSERT_COLUMN_EQ( + column( + {prec - 1, 2}, + {"0.00", + "2.49", + "-2.49", + "2.50", + "-2.50", + "0.25", + "-0.25", + "25.00", + "-25.00", + truncated + ".99", + "-" + truncated + ".99", + {}}), + this->execute(input, 2)); + ASSERT_COLUMN_EQ( + column( + {prec - 2, 1}, + {"0.0", + "2.4", + "-2.4", + "2.5", + "-2.5", + "0.2", + "-0.2", + "25.0", + "-25.0", + truncated + ".9", + "-" + truncated + ".9", + {}}), + this->execute(input, 1)); + } + + // const input + { + auto frac = createColumn>({3, 2, 1, 0, -1, -2, -3, -4, -5, -6, {}}); + + ASSERT_COLUMN_EQ( + createColumn>( + std::make_tuple(8, 3), + {"98765.432", + "98765.430", + "98765.400", + "98765.000", + "98760.000", + "98700.000", + "98000.000", + "90000.000", + "0.000", + "0.000", + {}}), + this->execute(constColumn({max_prec - 1, 3}, 11, "98765.432"), frac)); + ASSERT_COLUMN_EQ( + constColumn({max_prec - 1, 3}, 11, {}), + this->execute(constColumn({max_prec - 1, 3}, 11, {}), frac)); + } + + // const input & frac + ASSERT_COLUMN_EQ( + createConstColumn(std::make_tuple(2, 2), 1, "0.02"), + this->execute(constColumn({max_prec - 1, 3}, 1, "0.025"), createConstColumn(1, 2))); + ASSERT_COLUMN_EQ( + constColumn({max_prec - 2, 2}, 1, {}), + this->execute(constColumn({max_prec - 1, 3}, 1, {}), createConstColumn(1, 2))); + ASSERT_COLUMN_EQ( + createConstColumn>(std::make_tuple(1, 0), 1, {}, "", 0), + this->execute(constColumn({max_prec - 1, 3}, 1, "0.025"), createConstColumn>(1, {}))); + ASSERT_COLUMN_EQ( + createConstColumn(std::make_tuple(6, 5), 100, "1." + String(5, '0')), + this->execute( + createConstColumn(std::make_tuple(max_prec - 5, 0), 100, "1"), + createConstColumn(100, 5))); + + ASSERT_COLUMN_EQ( + createColumn>(std::make_tuple(1, 0), {"0"}), + this->execute(column({3, 3}, {"0.025"}), createConstColumn(1, 0))); + ASSERT_COLUMN_EQ( + createColumn>(std::make_tuple(1, 0), {"0"}), + this->execute(column({3, 3}, {"0.025"}), createConstColumn(1, -1))); +} +CATCH +} // namespace tests +} // namespace DB diff --git a/tests/fullstack-test/expr/tidb_truncate.test b/tests/fullstack-test/expr/tidb_truncate.test new file mode 100644 index 00000000000..585a1fedcd7 --- /dev/null +++ b/tests/fullstack-test/expr/tidb_truncate.test @@ -0,0 +1,479 @@ +# Copyright 2025 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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# truncate(col_double, col_int) +mysql> drop table if exists test.t1; +mysql> create table test.t1(c1 double, c2 bigint); +mysql> alter table test.t1 set tiflash replica 1; +mysql> insert into test.t1 values(-1.23, 0), (1.58, 0), (1.298, 1), (123.2, -1), (123.2, 100), (123.2, -100), (123.2, -100), (1.797693134862315708145274237317043567981e+308, 2), (Null, 2), (1.1, 400), (1.1, -400), (0, 400), (0, -400), (1.1, 3), (0, 3), (99.99, 1), (99.99, -1), (-99.99, 1), (-99.99, -1), (0.0001, 3), (0.0001, -3); +func> wait_table test t1 +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, c2, truncate(c1, c2) from test.t1 order by 1, 2, 3; ++------------------------+------+------------------------+ +| c1 | c2 | truncate(c1, c2) | ++------------------------+------+------------------------+ +| NULL | 2 | NULL | +| -99.99 | -1 | -90 | +| -99.99 | 1 | -99.9 | +| -1.23 | 0 | -1 | +| 0 | -400 | 0 | +| 0 | 3 | 0 | +| 0 | 400 | 0 | +| 0.0001 | -3 | 0 | +| 0.0001 | 3 | 0 | +| 1.1 | -400 | 0 | +| 1.1 | 3 | 1.1 | +| 1.1 | 400 | 1.1 | +| 1.298 | 1 | 1.2 | +| 1.58 | 0 | 1 | +| 99.99 | -1 | 90 | +| 99.99 | 1 | 99.9 | +| 123.2 | -100 | 0 | +| 123.2 | -100 | 0 | +| 123.2 | -1 | 120 | +| 123.2 | 100 | 123.2 | +| 1.7976931348623157e308 | 2 | 1.7976931348623157e308 | ++------------------------+------+------------------------+ + +# truncate(col_str, col_int) +mysql> drop table if exists test.t2; +mysql> create table test.t2(c1 varchar(100), c2 bigint); +mysql> insert into test.t2 values("-1.23", 0), ("-1.23", 1), ("-11.23", -1), ("1.58", 0), ("1.58", 1), ("11.58", -1), ("23.298", -1), ("23.298", -100), ("23.298", 100); +mysql> alter table test.t2 set tiflash replica 1; +func> wait_table test t2 +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, c2, truncate(c1, c2) from test.t2 order by 1, 2, 3; ++--------+------+------------------+ +| c1 | c2 | truncate(c1, c2) | ++--------+------+------------------+ +| -1.23 | 0 | -1 | +| -1.23 | 1 | -1.2 | +| -11.23 | -1 | -10 | +| 1.58 | 0 | 1 | +| 1.58 | 1 | 1.5 | +| 11.58 | -1 | 10 | +| 23.298 | -100 | 0 | +| 23.298 | -1 | 20 | +| 23.298 | 100 | 23.298 | ++--------+------+------------------+ + +# truncate(col_bigint_unsigned, col_int) +mysql> drop table if exists test.t3; +mysql> create table test.t3(c1 bigint unsigned); +mysql> alter table test.t3 set tiflash replica 1; +mysql> insert into test.t3 values(9223372036854775808), (18446744073709551615); +func> wait_table test t3 +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, truncate(c1, -10) from test.t3 order by 1, 2; ++----------------------+----------------------+ +| c1 | truncate(c1, -10) | ++----------------------+----------------------+ +| 9223372036854775808 | 9223372030000000000 | +| 18446744073709551615 | 18446744070000000000 | ++----------------------+----------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, truncate(c1, -7) from test.t3 order by 1, 2; ++----------------------+----------------------+ +| c1 | truncate(c1, -7) | ++----------------------+----------------------+ +| 9223372036854775808 | 9223372036850000000 | +| 18446744073709551615 | 18446744073700000000 | ++----------------------+----------------------+ + +# truncate(col_bigint_signed, col_int) +mysql> drop table if exists test.t3_1; +mysql> create table test.t3_1(c1 bigint); +mysql> alter table test.t3_1 set tiflash replica 1; +mysql> insert into test.t3_1 values(-9223372036854775808), (9223372036854775807); +func> wait_table test t3_1 +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, truncate(c1, -10) from test.t3_1 order by 1, 2; ++----------------------+----------------------+ +| c1 | truncate(c1, -10) | ++----------------------+----------------------+ +| -9223372036854775808 | -9223372030000000000 | +| 9223372036854775807 | 9223372030000000000 | ++----------------------+----------------------+ + +# # truncate(col_decimal, col_int) +# mysql> drop table if exists test.t4; +# mysql> create table test.t4(c1 decimal(10, 5), c2 bigint); +# mysql> insert into test.t4 values(-1.23, 0), (1.58, 0), (1.298, 1), (123.2, -1), (123.2, 100), (123.2, -100), (123.2, -100), (Null, 2), (1.1, 400), (1.1, -400), (0, 400), (0, -400), (1.1, 3), (0, 3), (99.99, 1), (99.99, -1), (-99.99, 1), (-99.99, -1), (0.0001, 3), (0.0001, -3); +# mysql> alter table test.t4 set tiflash replica 1; +# func> wait_table test t4 +# # todo tidb result +# # +-----------+------+------------------+ +# # | c1 | c2 | truncate(c1, c2) | +# # +-----------+------+------------------+ +# # | NULL | 2 | NULL | +# # | -99.99000 | -1 | -90 | +# # | -99.99000 | 1 | -99.9 | +# # | -1.23000 | 0 | -1 | +# # | 0.00000 | -400 | 0 | +# # | 0.00000 | 3 | 0.000 | +# # | 0.00000 | 400 | 0.00000 | +# # | 0.00010 | -3 | 0 | +# # | 0.00010 | 3 | 0.000 | +# # | 1.10000 | -400 | 0 | +# # | 1.10000 | 3 | 1.100 | +# # | 1.10000 | 400 | 1.10000 | +# # | 1.29800 | 1 | 1.2 | +# # | 1.58000 | 0 | 1 | +# # | 99.99000 | -1 | 90 | +# # | 99.99000 | 1 | 99.9 | +# # | 123.20000 | -100 | 0 | +# # | 123.20000 | -100 | 0 | +# # | 123.20000 | -1 | 120 | +# # | 123.20000 | 100 | 123.20000 | +# # +-----------+------+------------------+ +# mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select c1, c2, truncate(c1, c2) from test.t4 order by 1, 2, 3; +# +-----------+------+------------------+ +# | c1 | c2 | truncate(c1, c2) | +# +-----------+------+------------------+ +# | NULL | 2 | NULL | +# | -99.99000 | -1 | -90.00000 | +# | -99.99000 | 1 | -99.90000 | +# | -1.23000 | 0 | -1.00000 | +# | 0.00000 | -400 | 0.00000 | +# | 0.00000 | 3 | 0.00000 | +# | 0.00000 | 400 | 0.00000 | +# | 0.00010 | -3 | 0.00000 | +# | 0.00010 | 3 | 0.00000 | +# | 1.10000 | -400 | 0.00000 | +# | 1.10000 | 3 | 1.10000 | +# | 1.10000 | 400 | 1.10000 | +# | 1.29800 | 1 | 1.20000 | +# | 1.58000 | 0 | 1.00000 | +# | 99.99000 | -1 | 90.00000 | +# | 99.99000 | 1 | 99.90000 | +# | 123.20000 | -100 | 0.00000 | +# | 123.20000 | -100 | 0.00000 | +# | 123.20000 | -1 | 120.00000 | +# | 123.20000 | 100 | 123.20000 | +# +-----------+------+------------------+ + +# case copied from round_with_frac.test +mysql> drop table if exists test.f32 +mysql> create table test.f32 (id bigint, a float) +mysql> alter table test.f32 set tiflash replica 1 +mysql> insert into test.f32 values (1, 0), (2, 2.5), (3, -2.5), (4, 0.25), (5, -0.25), (6, 0.25e-10), (7, -0.25e-10), (8, 49e10), (9, 50e10), (10, -49e10), (11, -50e10), (12, 0.3), (13, null) + +mysql> drop table if exists test.f64 +mysql> create table test.f64 (id bigint, a double) +mysql> alter table test.f64 set tiflash replica 1 +mysql> insert into test.f64 values (1, 0), (2, 2.5), (3, -2.5), (4, 0.25), (5, -0.25), (6, 0.25e-10), (7, -0.25e-10), (8, 49e10), (9, 50e10), (10, -49e10), (11, -50e10), (12, 0.3), (13, null) + +mysql> drop table if exists test.d9 +mysql> create table test.d9 (id bigint, a decimal(9, 4)) +mysql> alter table test.d9 set tiflash replica 1 +mysql> insert into test.d9 values (1, 0), (2, 0.25), (3, -0.25), (4, 0.0499), (5, 0.05), (6, -0.0499), (7, -0.05), (8, 49999.9999), (9, 50000), (10, -49999.9999), (11, -50000), (12, 99999.9999), (13, -99999.9999), (14, 25), (15, -25), (16, null) + +mysql> drop table if exists test.d64 +mysql> create table test.d64 (id bigint, a decimal(64, 2)) +mysql> alter table test.d64 set tiflash replica 1 +mysql> insert into test.d64 values (1, 0), (2, 0.25), (3, -0.25), (4, 25), (5, -25), (6, 49999999999999999999999999999999999999999999999999999999999999.99), (7, 50000000000000000000000000000000000000000000000000000000000000), (8, -49999999999999999999999999999999999999999999999999999999999999.99), (9, -50000000000000000000000000000000000000000000000000000000000000), (10, 0.49), (11, 0.5), (12, -0.49), (13, -0.5), (14, 99999999999999999999999999999999999999999999999999999999999999.99), (15, -99999999999999999999999999999999999999999999999999999999999999.99), (16, null) + +mysql> drop table if exists test.t +mysql> create table test.t (i bigint) +mysql> alter table test.t set tiflash replica 1 +mysql> insert into test.t values (-66), (-65), (-64), (-63), (-62), (-61), (-60), (-59), (-58), (-57), (-56), (-55), (-54), (-53), (-52), (-51), (-50), (-49), (-48), (-47), (-46), (-45), (-44), (-43), (-42), (-41), (-40), (-39), (-38), (-37), (-36), (-35), (-34), (-33), (-32), (-31), (-30), (-29), (-28), (-27), (-26), (-25), (-24), (-23), (-22), (-21), (-20), (-19), (-18), (-17), (-16), (-15), (-14), (-13), (-12), (-11), (-10), (-9), (-8), (-7), (-6), (-5), (-4), (-3), (-2), (-1), (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15), (16), (17), (18), (19), (20), (21), (22), (23), (24), (25), (26), (27), (28), (29), (30), (31), (9223372036854775807), (-9223372036854775808) + +# func> wait_table test i8 u8 i32 u32 i64 u64 +func> wait_table test f32 f64 d9 d64 t + +# const frac +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 2)), sum(truncate(a, 1)), sum(truncate(a, 0)), sum(truncate(a, -1)), sum(truncate(a, -2)) from test.f32 group by id order by id ++------------------------------+---------------------+---------------------+---------------------+----------------------+----------------------+ +| sum(a) | sum(truncate(a, 2)) | sum(truncate(a, 1)) | sum(truncate(a, 0)) | sum(truncate(a, -1)) | sum(truncate(a, -2)) | ++------------------------------+---------------------+---------------------+---------------------+----------------------+----------------------+ +| 0 | 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 2.5 | 2 | 0 | 0 | +| -2.5 | -2.5 | -2.5 | -2 | 0 | 0 | +| 0.25 | 0.25 | 0.2 | 0 | 0 | 0 | +| -0.25 | -0.25 | -0.2 | 0 | 0 | 0 | +| 0.0000000000250000003337858 | 0 | 0 | 0 | 0 | 0 | +| -0.0000000000250000003337858 | 0 | 0 | 0 | 0 | 0 | +| 489999990784 | 489999990784 | 489999990784 | 489999990784 | 489999990780 | 489999990700 | +| 499999997952 | 499999997952 | 499999997952 | 499999997952 | 499999997950 | 499999997900 | +| -489999990784 | -489999990784 | -489999990784 | -489999990784 | -489999990780 | -489999990700 | +| -499999997952 | -499999997952 | -499999997952 | -499999997952 | -499999997950 | -499999997900 | +| 0.30000001192092896 | 0.3 | 0.3 | 0 | 0 | 0 | +| NULL | NULL | NULL | NULL | NULL | NULL | ++------------------------------+---------------------+---------------------+---------------------+----------------------+----------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 8)), sum(truncate(a, 9)), sum(truncate(a, -9)), sum(truncate(a, -10)) from test.f32 group by id order by id ++------------------------------+---------------------+---------------------+----------------------+-----------------------+ +| sum(a) | sum(truncate(a, 8)) | sum(truncate(a, 9)) | sum(truncate(a, -9)) | sum(truncate(a, -10)) | ++------------------------------+---------------------+---------------------+----------------------+-----------------------+ +| 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 2.5 | 0 | 0 | +| -2.5 | -2.5 | -2.5 | 0 | 0 | +| 0.25 | 0.25 | 0.25 | 0 | 0 | +| -0.25 | -0.25 | -0.25 | 0 | 0 | +| 0.0000000000250000003337858 | 0 | 0 | 0 | 0 | +| -0.0000000000250000003337858 | 0 | 0 | 0 | 0 | +| 489999990784 | 489999990784 | 489999990784 | 489000000000 | 480000000000 | +| 499999997952 | 499999997952 | 499999997952 | 498999999999.99994 | 490000000000 | +| -489999990784 | -489999990784 | -489999990784 | -489000000000 | -480000000000 | +| -499999997952 | -499999997952 | -499999997952 | -498999999999.99994 | -490000000000 | +| 0.30000001192092896 | 0.30000001 | 0.300000011 | 0 | 0 | +| NULL | NULL | NULL | NULL | NULL | ++------------------------------+---------------------+---------------------+----------------------+-----------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 30)), sum(truncate(a, -30)), sum(truncate(a, 1000000)), sum(truncate(a, -1000000)) from test.f32 group by id order by id ++------------------------------+------------------------------+-----------------------+------------------------------+----------------------------+ +| sum(a) | sum(truncate(a, 30)) | sum(truncate(a, -30)) | sum(truncate(a, 1000000)) | sum(truncate(a, -1000000)) | ++------------------------------+------------------------------+-----------------------+------------------------------+----------------------------+ +| 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 0 | 2.5 | 0 | +| -2.5 | -2.5 | 0 | -2.5 | 0 | +| 0.25 | 0.25 | 0 | 0.25 | 0 | +| -0.25 | -0.25 | 0 | -0.25 | 0 | +| 0.0000000000250000003337858 | 0.0000000000250000003337858 | 0 | 0.0000000000250000003337858 | 0 | +| -0.0000000000250000003337858 | -0.0000000000250000003337858 | 0 | -0.0000000000250000003337858 | 0 | +| 489999990784 | 489999990784 | 0 | 489999990784 | 0 | +| 499999997952 | 499999997952 | 0 | 499999997952 | 0 | +| -489999990784 | -489999990784 | 0 | -489999990784 | 0 | +| -499999997952 | -499999997952 | 0 | -499999997952 | 0 | +| 0.30000001192092896 | 0.30000001192092896 | 0 | 0.30000001192092896 | 0 | +| NULL | NULL | NULL | NULL | NULL | ++------------------------------+------------------------------+-----------------------+------------------------------+----------------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 2)), sum(truncate(a, 1)), sum(truncate(a, 0)), sum(truncate(a, -1)), sum(truncate(a, -2)) from test.f64 group by id order by id ++-----------------+---------------------+---------------------+---------------------+----------------------+----------------------+ +| sum(a) | sum(truncate(a, 2)) | sum(truncate(a, 1)) | sum(truncate(a, 0)) | sum(truncate(a, -1)) | sum(truncate(a, -2)) | ++-----------------+---------------------+---------------------+---------------------+----------------------+----------------------+ +| 0 | 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 2.5 | 2 | 0 | 0 | +| -2.5 | -2.5 | -2.5 | -2 | 0 | 0 | +| 0.25 | 0.25 | 0.2 | 0 | 0 | 0 | +| -0.25 | -0.25 | -0.2 | 0 | 0 | 0 | +| 0.000000000025 | 0 | 0 | 0 | 0 | 0 | +| -0.000000000025 | 0 | 0 | 0 | 0 | 0 | +| 490000000000 | 490000000000 | 490000000000 | 490000000000 | 490000000000 | 490000000000 | +| 500000000000 | 500000000000 | 500000000000 | 500000000000 | 500000000000 | 500000000000 | +| -490000000000 | -490000000000 | -490000000000 | -490000000000 | -490000000000 | -490000000000 | +| -500000000000 | -500000000000 | -500000000000 | -500000000000 | -500000000000 | -500000000000 | +| 0.3 | 0.3 | 0.3 | 0 | 0 | 0 | +| NULL | NULL | NULL | NULL | NULL | NULL | ++-----------------+---------------------+---------------------+---------------------+----------------------+----------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 8)), sum(truncate(a, 9)), sum(truncate(a, -9)), sum(truncate(a, -10)) from test.f64 group by id order by id ++-----------------+---------------------+---------------------+----------------------+-----------------------+ +| sum(a) | sum(truncate(a, 8)) | sum(truncate(a, 9)) | sum(truncate(a, -9)) | sum(truncate(a, -10)) | ++-----------------+---------------------+---------------------+----------------------+-----------------------+ +| 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 2.5 | 0 | 0 | +| -2.5 | -2.5 | -2.5 | 0 | 0 | +| 0.25 | 0.25 | 0.25 | 0 | 0 | +| -0.25 | -0.25 | -0.25 | 0 | 0 | +| 0.000000000025 | 0 | 0 | 0 | 0 | +| -0.000000000025 | 0 | 0 | 0 | 0 | +| 490000000000 | 490000000000 | 490000000000 | 489999999999.99994 | 490000000000 | +| 500000000000 | 500000000000 | 500000000000 | 499999999999.99994 | 500000000000 | +| -490000000000 | -490000000000 | -490000000000 | -489999999999.99994 | -490000000000 | +| -500000000000 | -500000000000 | -500000000000 | -499999999999.99994 | -500000000000 | +| 0.3 | 0.3 | 0.3 | 0 | 0 | +| NULL | NULL | NULL | NULL | NULL | ++-----------------+---------------------+---------------------+----------------------+-----------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 30)), sum(truncate(a, -30)), sum(truncate(a, 1000000)), sum(truncate(a, -1000000)) from test.f64 group by id order by id ++-----------------+----------------------+-----------------------+---------------------------+----------------------------+ +| sum(a) | sum(truncate(a, 30)) | sum(truncate(a, -30)) | sum(truncate(a, 1000000)) | sum(truncate(a, -1000000)) | ++-----------------+----------------------+-----------------------+---------------------------+----------------------------+ +| 0 | 0 | 0 | 0 | 0 | +| 2.5 | 2.5 | 0 | 2.5 | 0 | +| -2.5 | -2.5 | 0 | -2.5 | 0 | +| 0.25 | 0.25 | 0 | 0.25 | 0 | +| -0.25 | -0.25 | 0 | -0.25 | 0 | +| 0.000000000025 | 0.000000000025 | 0 | 0.000000000025 | 0 | +| -0.000000000025 | -0.000000000025 | 0 | -0.000000000025 | 0 | +| 490000000000 | 490000000000 | 0 | 490000000000 | 0 | +| 500000000000 | 500000000000 | 0 | 500000000000 | 0 | +| -490000000000 | -490000000000 | 0 | -490000000000 | 0 | +| -500000000000 | -500000000000 | 0 | -500000000000 | 0 | +| 0.3 | 0.3 | 0 | 0.3 | 0 | +| NULL | NULL | NULL | NULL | NULL | ++-----------------+----------------------+-----------------------+---------------------------+----------------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, -1)), sum(truncate(a, 0)), sum(truncate(a, 1)) from test.d9 group by id order by id ++-------------+----------------------+---------------------+---------------------+ +| sum(a) | sum(truncate(a, -1)) | sum(truncate(a, 0)) | sum(truncate(a, 1)) | ++-------------+----------------------+---------------------+---------------------+ +| 0.0000 | 0 | 0 | 0.0 | +| 0.2500 | 0 | 0 | 0.2 | +| -0.2500 | 0 | 0 | -0.2 | +| 0.0499 | 0 | 0 | 0.0 | +| 0.0500 | 0 | 0 | 0.0 | +| -0.0499 | 0 | 0 | 0.0 | +| -0.0500 | 0 | 0 | 0.0 | +| 49999.9999 | 49990 | 49999 | 49999.9 | +| 50000.0000 | 50000 | 50000 | 50000.0 | +| -49999.9999 | -49990 | -49999 | -49999.9 | +| -50000.0000 | -50000 | -50000 | -50000.0 | +| 99999.9999 | 99990 | 99999 | 99999.9 | +| -99999.9999 | -99990 | -99999 | -99999.9 | +| 25.0000 | 20 | 25 | 25.0 | +| -25.0000 | -20 | -25 | -25.0 | +| NULL | NULL | NULL | NULL | ++-------------+----------------------+---------------------+---------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 3)), sum(truncate(a, 4)), sum(truncate(a, 5)), sum(truncate(a, 40)) from test.d9 group by id order by id ++-------------+---------------------+---------------------+---------------------+---------------------------------------+ +| sum(a) | sum(truncate(a, 3)) | sum(truncate(a, 4)) | sum(truncate(a, 5)) | sum(truncate(a, 40)) | ++-------------+---------------------+---------------------+---------------------+---------------------------------------+ +| 0.0000 | 0.000 | 0.0000 | 0.00000 | 0.000000000000000000000000000000 | +| 0.2500 | 0.250 | 0.2500 | 0.25000 | 0.250000000000000000000000000000 | +| -0.2500 | -0.250 | -0.2500 | -0.25000 | -0.250000000000000000000000000000 | +| 0.0499 | 0.049 | 0.0499 | 0.04990 | 0.049900000000000000000000000000 | +| 0.0500 | 0.050 | 0.0500 | 0.05000 | 0.050000000000000000000000000000 | +| -0.0499 | -0.049 | -0.0499 | -0.04990 | -0.049900000000000000000000000000 | +| -0.0500 | -0.050 | -0.0500 | -0.05000 | -0.050000000000000000000000000000 | +| 49999.9999 | 49999.999 | 49999.9999 | 49999.99990 | 49999.999900000000000000000000000000 | +| 50000.0000 | 50000.000 | 50000.0000 | 50000.00000 | 50000.000000000000000000000000000000 | +| -49999.9999 | -49999.999 | -49999.9999 | -49999.99990 | -49999.999900000000000000000000000000 | +| -50000.0000 | -50000.000 | -50000.0000 | -50000.00000 | -50000.000000000000000000000000000000 | +| 99999.9999 | 99999.999 | 99999.9999 | 99999.99990 | 99999.999900000000000000000000000000 | +| -99999.9999 | -99999.999 | -99999.9999 | -99999.99990 | -99999.999900000000000000000000000000 | +| 25.0000 | 25.000 | 25.0000 | 25.00000 | 25.000000000000000000000000000000 | +| -25.0000 | -25.000 | -25.0000 | -25.00000 | -25.000000000000000000000000000000 | +| NULL | NULL | NULL | NULL | NULL | ++-------------+---------------------+---------------------+---------------------+---------------------------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, -4)), sum(truncate(a, -5)), sum(truncate(a, -6)), sum(truncate(a, -100)) from test.d9 group by id order by id ++-------------+----------------------+----------------------+----------------------+------------------------+ +| sum(a) | sum(truncate(a, -4)) | sum(truncate(a, -5)) | sum(truncate(a, -6)) | sum(truncate(a, -100)) | ++-------------+----------------------+----------------------+----------------------+------------------------+ +| 0.0000 | 0 | 0 | 0 | 0 | +| 0.2500 | 0 | 0 | 0 | 0 | +| -0.2500 | 0 | 0 | 0 | 0 | +| 0.0499 | 0 | 0 | 0 | 0 | +| 0.0500 | 0 | 0 | 0 | 0 | +| -0.0499 | 0 | 0 | 0 | 0 | +| -0.0500 | 0 | 0 | 0 | 0 | +| 49999.9999 | 40000 | 0 | 0 | 0 | +| 50000.0000 | 50000 | 0 | 0 | 0 | +| -49999.9999 | -40000 | 0 | 0 | 0 | +| -50000.0000 | -50000 | 0 | 0 | 0 | +| 99999.9999 | 90000 | 0 | 0 | 0 | +| -99999.9999 | -90000 | 0 | 0 | 0 | +| 25.0000 | 0 | 0 | 0 | 0 | +| -25.0000 | 0 | 0 | 0 | 0 | +| NULL | NULL | NULL | NULL | NULL | ++-------------+----------------------+----------------------+----------------------+------------------------+ + +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, -1)), sum(truncate(a, 0)), sum(truncate(a, 1)) from test.d64 group by id order by id ++--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-------------------------------------------------------------------+ +| sum(a) | sum(truncate(a, -1)) | sum(truncate(a, 0)) | sum(truncate(a, 1)) | ++--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-------------------------------------------------------------------+ +| 0.00 | 0 | 0 | 0.0 | +| 0.25 | 0 | 0 | 0.2 | +| -0.25 | 0 | 0 | -0.2 | +| 25.00 | 20 | 25 | 25.0 | +| -25.00 | -20 | -25 | -25.0 | +| 49999999999999999999999999999999999999999999999999999999999999.99 | 49999999999999999999999999999999999999999999999999999999999990 | 49999999999999999999999999999999999999999999999999999999999999 | 49999999999999999999999999999999999999999999999999999999999999.9 | +| 50000000000000000000000000000000000000000000000000000000000000.00 | 50000000000000000000000000000000000000000000000000000000000000 | 50000000000000000000000000000000000000000000000000000000000000 | 50000000000000000000000000000000000000000000000000000000000000.0 | +| -49999999999999999999999999999999999999999999999999999999999999.99 | -49999999999999999999999999999999999999999999999999999999999990 | -49999999999999999999999999999999999999999999999999999999999999 | -49999999999999999999999999999999999999999999999999999999999999.9 | +| -50000000000000000000000000000000000000000000000000000000000000.00 | -50000000000000000000000000000000000000000000000000000000000000 | -50000000000000000000000000000000000000000000000000000000000000 | -50000000000000000000000000000000000000000000000000000000000000.0 | +| 0.49 | 0 | 0 | 0.4 | +| 0.50 | 0 | 0 | 0.5 | +| -0.49 | 0 | 0 | -0.4 | +| -0.50 | 0 | 0 | -0.5 | +| 99999999999999999999999999999999999999999999999999999999999999.99 | 99999999999999999999999999999999999999999999999999999999999990 | 99999999999999999999999999999999999999999999999999999999999999 | 99999999999999999999999999999999999999999999999999999999999999.9 | +| -99999999999999999999999999999999999999999999999999999999999999.99 | -99999999999999999999999999999999999999999999999999999999999990 | -99999999999999999999999999999999999999999999999999999999999999 | -99999999999999999999999999999999999999999999999999999999999999.9 | +| NULL | NULL | NULL | NULL | ++--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-------------------------------------------------------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, 2)), sum(truncate(a, -61)), sum(truncate(a, -62)) from test.d64 group by id order by id ++--------------------------------------------------------------------+--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------+ +| sum(a) | sum(truncate(a, 2)) | sum(truncate(a, -61)) | sum(truncate(a, -62)) | ++--------------------------------------------------------------------+--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------+ +| 0.00 | 0.00 | 0 | 0 | +| 0.25 | 0.25 | 0 | 0 | +| -0.25 | -0.25 | 0 | 0 | +| 25.00 | 25.00 | 0 | 0 | +| -25.00 | -25.00 | 0 | 0 | +| 49999999999999999999999999999999999999999999999999999999999999.99 | 49999999999999999999999999999999999999999999999999999999999999.99 | 40000000000000000000000000000000000000000000000000000000000000 | 0 | +| 50000000000000000000000000000000000000000000000000000000000000.00 | 50000000000000000000000000000000000000000000000000000000000000.00 | 50000000000000000000000000000000000000000000000000000000000000 | 0 | +| -49999999999999999999999999999999999999999999999999999999999999.99 | -49999999999999999999999999999999999999999999999999999999999999.99 | -40000000000000000000000000000000000000000000000000000000000000 | 0 | +| -50000000000000000000000000000000000000000000000000000000000000.00 | -50000000000000000000000000000000000000000000000000000000000000.00 | -50000000000000000000000000000000000000000000000000000000000000 | 0 | +| 0.49 | 0.49 | 0 | 0 | +| 0.50 | 0.50 | 0 | 0 | +| -0.49 | -0.49 | 0 | 0 | +| -0.50 | -0.50 | 0 | 0 | +| 99999999999999999999999999999999999999999999999999999999999999.99 | 99999999999999999999999999999999999999999999999999999999999999.99 | 90000000000000000000000000000000000000000000000000000000000000 | 0 | +| -99999999999999999999999999999999999999999999999999999999999999.99 | -99999999999999999999999999999999999999999999999999999999999999.99 | -90000000000000000000000000000000000000000000000000000000000000 | 0 | +| NULL | NULL | NULL | NULL | ++--------------------------------------------------------------------+--------------------------------------------------------------------+-----------------------------------------------------------------+-----------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(a), sum(truncate(a, -63)), sum(truncate(a, -100)) from test.d64 group by id order by id ++--------------------------------------------------------------------+-----------------------+------------------------+ +| sum(a) | sum(truncate(a, -63)) | sum(truncate(a, -100)) | ++--------------------------------------------------------------------+-----------------------+------------------------+ +| 0.00 | 0 | 0 | +| 0.25 | 0 | 0 | +| -0.25 | 0 | 0 | +| 25.00 | 0 | 0 | +| -25.00 | 0 | 0 | +| 49999999999999999999999999999999999999999999999999999999999999.99 | 0 | 0 | +| 50000000000000000000000000000000000000000000000000000000000000.00 | 0 | 0 | +| -49999999999999999999999999999999999999999999999999999999999999.99 | 0 | 0 | +| -50000000000000000000000000000000000000000000000000000000000000.00 | 0 | 0 | +| 0.49 | 0 | 0 | +| 0.50 | 0 | 0 | +| -0.49 | 0 | 0 | +| -0.50 | 0 | 0 | +| 99999999999999999999999999999999999999999999999999999999999999.99 | 0 | 0 | +| -99999999999999999999999999999999999999999999999999999999999999.99 | 0 | 0 | +| NULL | NULL | NULL | ++--------------------------------------------------------------------+-----------------------+------------------------+ + +# const input, variable frac +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(null, i)) from test.t ++------------------------+ +| sum(truncate(null, i)) | ++------------------------+ +| NULL | ++------------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(-123456789123456789, i)) from test.t ++---------------------------------------+ +| sum(truncate(-123456789123456789, i)) | ++---------------------------------------+ +| -6145404623034293517 | ++---------------------------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(123456789123456789.123456789123456789, i)) from test.t ++---------------------------------------------------------+ +| sum(truncate(123456789123456789.123456789123456789, i)) | ++---------------------------------------------------------+ +| 6145404623034293520.923182418812071315 | ++---------------------------------------------------------+ + +# variable input & frac +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(a, i)) from test.d9 cross join test.t where a >= 0 ++---------------------+ +| sum(truncate(a, i)) | ++---------------------+ +| 7378633.8083 | ++---------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(a, i)) from test.d9 cross join test.t where a < 0 ++---------------------+ +| sum(truncate(a, i)) | ++---------------------+ +| -7378633.8083 | ++---------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(a, i)) from test.d64 cross join test.t where a >= 0 ++----------------------------------------------------------------------+ +| sum(truncate(a, i)) | ++----------------------------------------------------------------------+ +| 18777777777777777777777777777777777777777777777777777777777778661.72 | ++----------------------------------------------------------------------+ +mysql> set tidb_isolation_read_engines='tiflash'; set tidb_allow_mpp = 1; set tidb_enforce_mpp = 1; select sum(truncate(a, i)) from test.d64 cross join test.t where a < 0 ++-----------------------------------------------------------------------+ +| sum(truncate(a, i)) | ++-----------------------------------------------------------------------+ +| -18777777777777777777777777777777777777777777777777777777777778661.72 | ++-----------------------------------------------------------------------+