From 2d00efaab74b14bad7dcfda43dbf74ccf4e714c8 Mon Sep 17 00:00:00 2001 From: hopebo Date: Wed, 21 Oct 2020 15:35:42 +0800 Subject: [PATCH] Bugfix Regexp_engine::Replace doesn't reset error code after processing a record Description ----------- When REGEXP_REPLACE is used in a SQL, the function Regexp_engine::Replace() is responsible for dealing with records one by one. But after processing on a record, the function doesn't reset the value of error code(Regexp_engine::m_error_code). And the error code will affect the execution of processing on the next record, which may cause a problem. Reset error code to U_ZERO_ERROR after checking the icu status. Function check_icu_status() will be called every time after a whole regexp operation has happened. --- sql/regexp/errors.cc | 11 +++++++---- sql/regexp/errors.h | 2 +- sql/regexp/regexp_engine.cc | 4 ++-- sql/regexp/regexp_engine.h | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sql/regexp/errors.cc b/sql/regexp/errors.cc index 6d4ea332b18..244238b429a 100644 --- a/sql/regexp/errors.cc +++ b/sql/regexp/errors.cc @@ -74,10 +74,13 @@ std::unordered_map error_map = { {U_REGEX_INVALID_CAPTURE_GROUP_NAME, ER_REGEXP_INVALID_CAPTURE_GROUP_NAME}, {U_REGEX_INVALID_FLAG, ER_REGEXP_INVALID_FLAG}}; -bool check_icu_status(UErrorCode status, const UParseError *parse_error) { - if (status == U_ZERO_ERROR || U_SUCCESS(status)) return false; +bool check_icu_status(UErrorCode *status, const UParseError *parse_error) { + if (U_SUCCESS(*status)) { + *status = U_ZERO_ERROR; + return false; + } - int error_code = error_map[status]; + int error_code = error_map[*status]; if (error_code == 0) { /* If this fires, there is no translation from this ICU status code to a @@ -86,7 +89,7 @@ bool check_icu_status(UErrorCode status, const UParseError *parse_error) { regexp". */ DBUG_ASSERT(false); - my_error(ER_REGEXP_ERROR, MYF(0), u_errorName(status)); + my_error(ER_REGEXP_ERROR, MYF(0), u_errorName(*status)); return true; } diff --git a/sql/regexp/errors.h b/sql/regexp/errors.h index 0217bdab4eb..b4841e10b4f 100644 --- a/sql/regexp/errors.h +++ b/sql/regexp/errors.h @@ -28,7 +28,7 @@ namespace regexp { -bool check_icu_status(UErrorCode status, +bool check_icu_status(UErrorCode *status, const UParseError *parse_error = nullptr); } // namespace regexp diff --git a/sql/regexp/regexp_engine.cc b/sql/regexp/regexp_engine.cc index 2e03e572b6a..1a8feea0556 100644 --- a/sql/regexp/regexp_engine.cc +++ b/sql/regexp/regexp_engine.cc @@ -59,7 +59,7 @@ bool Regexp_engine::Matches(int start, int occurrence) { for (int i = 1; i < occurrence && found; ++i) found = uregex_findNext(m_re, &m_error_code); - check_icu_status(m_error_code); + check_icu_status(&m_error_code); return found; } @@ -100,7 +100,7 @@ const std::u16string &Regexp_engine::Replace(const std::u16string &replacement, // ... put the part after the matches back. AppendTail(); - check_icu_status(m_error_code); + check_icu_status(&m_error_code); m_replace_buffer.resize(m_replace_buffer_pos); return m_replace_buffer; } diff --git a/sql/regexp/regexp_engine.h b/sql/regexp/regexp_engine.h index c4d7325ab15..a62f9976a44 100644 --- a/sql/regexp/regexp_engine.h +++ b/sql/regexp/regexp_engine.h @@ -106,12 +106,12 @@ class Regexp_engine { uregex_setStackLimit(m_re, stack_limit, &m_error_code); uregex_setTimeLimit(m_re, time_limit, &m_error_code); uregex_setMatchCallback(m_re, QueryNotKilled, current_thd, &m_error_code); - check_icu_status(m_error_code, &error); + check_icu_status(&m_error_code, &error); } uint flags() { uint flags = uregex_flags(m_re, &m_error_code); - check_icu_status(m_error_code); + check_icu_status(&m_error_code); return flags; } @@ -181,7 +181,7 @@ class Regexp_engine { String *MatchedSubstring(String *result); bool IsError() const { return U_FAILURE(m_error_code); } - bool CheckError() const { return check_icu_status(m_error_code); } + bool CheckError() { return check_icu_status(&m_error_code); } virtual ~Regexp_engine() { uregex_close(m_re); } -- 2.19.1.6.gb485710b