diff --git a/src/Functions/countDigits.cpp b/src/Functions/countDigits.cpp index e0376d9a568..9f60bdf9689 100644 --- a/src/Functions/countDigits.cpp +++ b/src/Functions/countDigits.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace DB @@ -17,8 +16,10 @@ namespace ErrorCodes extern const int ILLEGAL_COLUMN; } -/// Returns 1 if and Decimal value has more digits then it's Precision allow, 0 otherwise. -/// Precision could be set as second argument or omitted. If ommited function uses Decimal presicion of the first argument. +/// Returns number of decimal digits you need to represent the value. +/// For Decimal values takes in account their scales: calculates result over underlying int type which is (value * scale). +/// countDigits(42) = 2, countDigits(42.000) = 5, countDigits(0.04200) = 4. +/// I.e. you may check decimal overflow for Decimal64 with 'countDecimal(x) > 18'. It's a slow variant of isDecimalOverflow(). class FunctionCountDigits : public IFunction { public: @@ -30,7 +31,7 @@ public: } String getName() const override { return name; } - bool useDefaultImplementationForNulls() const override { return false; } + bool useDefaultImplementationForConstants() const override { return true; } size_t getNumberOfArguments() const override { return 1; } DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override @@ -58,18 +59,7 @@ public: using Type = typename Types::RightType; using ColVecType = std::conditional_t, ColumnDecimal, ColumnVector>; - if (const ColumnConst * const_column = checkAndGetColumnConst(src_column.column.get())) - { - Type const_value = checkAndGetColumn(const_column->getDataColumnPtr().get())->getData()[0]; - UInt32 num_digits = 0; - if constexpr (IsDecimalNumber) - num_digits = digits(const_value.value); - else - num_digits = digits(const_value); - result_column->getData().resize_fill(input_rows_count, num_digits); - return true; - } - else if (const ColVecType * col_vec = checkAndGetColumn(src_column.column.get())) + if (const ColVecType * col_vec = checkAndGetColumn(src_column.column.get())) { execute(*col_vec, *result_column, input_rows_count); return true; diff --git a/src/Functions/isDecimalOverflow.cpp b/src/Functions/isDecimalOverflow.cpp index f1b63fd0844..dbd57101a64 100644 --- a/src/Functions/isDecimalOverflow.cpp +++ b/src/Functions/isDecimalOverflow.cpp @@ -32,7 +32,6 @@ public: } String getName() const override { return name; } - bool useDefaultImplementationForNulls() const override { return false; } bool isVariadic() const override { return true; } size_t getNumberOfArguments() const override { return 0; } diff --git a/tests/queries/0_stateless/01458_count_digits.reference b/tests/queries/0_stateless/01458_count_digits.reference index 46b87cd22b7..80c210bc0af 100644 --- a/tests/queries/0_stateless/01458_count_digits.reference +++ b/tests/queries/0_stateless/01458_count_digits.reference @@ -4,3 +4,4 @@ 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 5 5 5 10 10 10 19 19 20 +2 3 4 5 6 7 diff --git a/tests/queries/0_stateless/01458_count_digits.sql b/tests/queries/0_stateless/01458_count_digits.sql index 91ca07469e5..4a95af38de7 100644 --- a/tests/queries/0_stateless/01458_count_digits.sql +++ b/tests/queries/0_stateless/01458_count_digits.sql @@ -24,3 +24,7 @@ SELECT countDigits(toInt8(127)), countDigits(toInt8(-128)), countDigits(toUInt8 countDigits(toInt16(32767)), countDigits(toInt16(-32768)), countDigits(toUInt16(65535)), countDigits(toInt32(2147483647)), countDigits(toInt32(-2147483648)), countDigits(toUInt32(4294967295)), countDigits(toInt64(9223372036854775807)), countDigits(toInt64(-9223372036854775808)), countDigits(toUInt64(18446744073709551615)); + +SELECT countDigits(toNullable(toDecimal32(4.2, 1))), countDigits(materialize(toNullable(toDecimal32(4.2, 2)))), + countDigits(toNullable(toDecimal64(4.2, 3))), countDigits(materialize(toNullable(toDecimal64(4.2, 4)))), + countDigits(toNullable(toDecimal128(4.2, 5))), countDigits(materialize(toNullable(toDecimal128(4.2, 6)))); diff --git a/tests/queries/0_stateless/01458_is_decimal_overflow.reference b/tests/queries/0_stateless/01458_is_decimal_overflow.reference index f74a62f2faf..80f8f2e8c18 100644 --- a/tests/queries/0_stateless/01458_is_decimal_overflow.reference +++ b/tests/queries/0_stateless/01458_is_decimal_overflow.reference @@ -17,3 +17,4 @@ 1 1 1 1 0 0 0 0 1 1 1 1 1 1 +1 0 1 0 1 0 diff --git a/tests/queries/0_stateless/01458_is_decimal_overflow.sql b/tests/queries/0_stateless/01458_is_decimal_overflow.sql index 51db639b651..abf96e71445 100644 --- a/tests/queries/0_stateless/01458_is_decimal_overflow.sql +++ b/tests/queries/0_stateless/01458_is_decimal_overflow.sql @@ -91,3 +91,10 @@ SELECT isDecimalOverflow(materialize(toDecimal128('99999999999999999999999999999 isDecimalOverflow(materialize(toDecimal128('-99999999999999999999999999999999999999', 0)), 37), isDecimalOverflow(materialize(toDecimal128('-10', 0)), 1), isDecimalOverflow(materialize(toDecimal128('-1', 0)), 0); + +SELECT isDecimalOverflow(toNullable(toDecimal32(42, 0)), 1), + isDecimalOverflow(materialize(toNullable(toDecimal32(42, 0))), 2), + isDecimalOverflow(toNullable(toDecimal64(42, 0)), 1), + isDecimalOverflow(materialize(toNullable(toDecimal64(42, 0))), 2), + isDecimalOverflow(toNullable(toDecimal128(42, 0)), 1), + isDecimalOverflow(materialize(toNullable(toDecimal128(42, 0))), 2);