From 69fee6812b756a8ca4866038d4ff866eccc2f303 Mon Sep 17 00:00:00 2001 From: chertus Date: Tue, 21 Jan 2020 21:04:22 +0300 Subject: [PATCH] variant without catch --- dbms/src/IO/readDecimalText.h | 46 ++++++++++++------- .../01070_to_decimal_or_null_exception.sql | 6 +-- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/dbms/src/IO/readDecimalText.h b/dbms/src/IO/readDecimalText.h index 045cc38736..5b2a3f7648 100644 --- a/dbms/src/IO/readDecimalText.h +++ b/dbms/src/IO/readDecimalText.h @@ -11,8 +11,8 @@ namespace ErrorCodes } -template -inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exponent, bool digits_only = false) +template +inline bool readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exponent, bool digits_only = false) { x = 0; exponent = 0; @@ -24,7 +24,11 @@ inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp bool after_point = false; if (buf.eof()) - throwReadAfterEOF(); + { + if constexpr (_throw_on_error) + throwReadAfterEOF(); + return false; + } if (!buf.eof()) { @@ -75,8 +79,12 @@ inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp ++places; // num zeroes before + current digit if (digits + places > max_digits) - throw Exception("Too many digits (" + std::to_string(digits + places) + " > " + std::to_string(max_digits) + { + if constexpr (_throw_on_error) + throw Exception("Too many digits (" + std::to_string(digits + places) + " > " + std::to_string(max_digits) + ") in decimal value", ErrorCodes::ARGUMENT_OUT_OF_BOUND); + return false; + } digits += places; if (after_point) @@ -93,7 +101,13 @@ inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp { ++buf.position(); Int32 addition_exp = 0; - readIntText(addition_exp, buf); + if (!tryReadIntText(addition_exp, buf)) + { + if constexpr (_throw_on_error) + throw Exception("Cannot parse exponent while reading decimal", ErrorCodes::CANNOT_PARSE_NUMBER); + else + return false; + } exponent += addition_exp; stop = true; continue; @@ -101,7 +115,11 @@ inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp default: if (digits_only) - throw Exception("Unexpected symbol while reading decimal", ErrorCodes::CANNOT_PARSE_NUMBER); + { + if constexpr (_throw_on_error) + throw Exception("Unexpected symbol while reading decimal", ErrorCodes::CANNOT_PARSE_NUMBER); + return false; + } stop = true; continue; } @@ -109,6 +127,7 @@ inline void readDigits(ReadBuffer & buf, T & x, unsigned int & digits, int & exp } x *= sign; + return true; } template @@ -116,7 +135,7 @@ inline void readDecimalText(ReadBuffer & buf, T & x, unsigned int precision, uns { unsigned int digits = precision; int exponent; - readDigits(buf, x, digits, exponent, digits_only); + readDigits(buf, x, digits, exponent, digits_only); if (static_cast(digits) + exponent > static_cast(precision - scale)) throw Exception("Decimal value is too big", ErrorCodes::ARGUMENT_OUT_OF_BOUND); @@ -132,17 +151,10 @@ inline bool tryReadDecimalText(ReadBuffer & buf, T & x, unsigned int precision, unsigned int digits = precision; int exponent; - try - { - readDigits(buf, x, digits, exponent, true); - if (static_cast(digits) + exponent > static_cast(precision - scale) || - static_cast(scale) + exponent < 0) - return false; - } - catch (const Exception &) - { + if (!readDigits(buf, x, digits, exponent, true) || + static_cast(digits) + exponent > static_cast(precision - scale) || + static_cast(scale) + exponent < 0) return false; - } scale += exponent; return true; diff --git a/dbms/tests/queries/0_stateless/01070_to_decimal_or_null_exception.sql b/dbms/tests/queries/0_stateless/01070_to_decimal_or_null_exception.sql index 691d117ac5..9283cc76cd 100644 --- a/dbms/tests/queries/0_stateless/01070_to_decimal_or_null_exception.sql +++ b/dbms/tests/queries/0_stateless/01070_to_decimal_or_null_exception.sql @@ -1,6 +1,6 @@ -SELECT toDecimal32('e', 1); -- { serverError 32 } -SELECT toDecimal64('e', 2); -- { serverError 32 } -SELECT toDecimal128('e', 3); -- { serverError 32 } +SELECT toDecimal32('e', 1); -- { serverError 72 } +SELECT toDecimal64('e', 2); -- { serverError 72 } +SELECT toDecimal128('e', 3); -- { serverError 72 } SELECT toDecimal32OrNull('e', 1) x, isNull(x); SELECT toDecimal64OrNull('e', 2) x, isNull(x); -- GitLab