diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index d4a41c0de..b5cb590be 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -2091,7 +2091,6 @@ bool PgSQL_Connection::is_valid_formatted_pq_error_header(const std::string& s, // Check valid size format size_t size_end = size_start; - if (s[size_end] == '-') size_end++; if (size_end >= s.size() || !std::isdigit(s[size_end])) return false; while (size_end < s.size() && std::isdigit(s[size_end])) size_end++; return (size_end < s.size() && s[size_end] == ':'); @@ -2102,40 +2101,24 @@ std::map> PgSQL_Connection::parse_pq_error size_t pos = 0; while (pos < error_str.size()) { - if (!is_valid_formatted_pq_error_header(error_str, pos)) { - pos++; - continue; - } - - std::string prefix; - int size = 0; - std::string value; - - // Extract prefix - size_t prefix_end = pos; - while (prefix_end < error_str.size() && std::isupper(error_str[prefix_end])) - prefix_end++; - prefix = error_str.substr(pos, prefix_end - pos); - pos = prefix_end + 1; // Move past the colon after prefix - - // Parse size - bool negative = false; - if (pos < error_str.size() && error_str[pos] == '-') { - negative = true; - pos++; - } - size_t size_start = pos; - while (pos < error_str.size() && std::isdigit(error_str[pos])) pos++; - std::string size_str = error_str.substr(size_start, pos - size_start); - bool valid_size = true; + if (is_valid_formatted_pq_error_header(error_str, pos)) { + std::string prefix; + int size = 0; + std::string value; + + // Extract prefix + size_t prefix_end = pos; + while (prefix_end < error_str.size() && std::isupper(error_str[prefix_end])) + prefix_end++; + prefix = error_str.substr(pos, prefix_end - pos); + pos = prefix_end + 1; + + // Parse size + size_t size_start = pos; + while (pos < error_str.size() && std::isdigit(error_str[pos])) pos++; + std::string size_str = error_str.substr(size_start, pos - size_start); + bool valid_size = true; - if (negative) { - if (size_str != "1") { - valid_size = false; - } else { - size = -1; - } - } else { if (size_str.empty()) { valid_size = false; } else { @@ -2153,35 +2136,38 @@ std::map> PgSQL_Connection::parse_pq_error size = size * 10 + digit; } } - } - - // Validate size: must be -1 or non-negative - if (!valid_size || (size < 0 && size != -1)) { - pos = size_start; // Rewind to before the size part - continue; - } + - pos++; // Move past the colon after size + if (!valid_size || size < 0) { + pos = size_start; + continue; + } - // Extract and clean value - size_t value_start = pos; - size_t value_end; + pos++; - if (size != -1) { + // Extract value + size_t value_start = pos; + size_t value_end; value_end = value_start + size; if (value_end > error_str.size()) { - pos = value_start; // Skip invalid component + pos = value_start; continue; } - } else { - value_end = value_start; - while (value_end < error_str.size() && !is_valid_formatted_pq_error_header(error_str, value_end)) - value_end++; - } - value = trim(error_str.substr(value_start, value_end - value_start)); - components[prefix].push_back(value); - pos = value_end; + value = trim(error_str.substr(value_start, value_end - value_start)); + components[prefix].push_back(value); + pos = value_end; + } + else { + size_t le_start = pos; + while (pos < error_str.size() && !is_valid_formatted_pq_error_header(error_str, pos)) + pos++; + std::string le_value = error_str.substr(le_start, pos - le_start); + le_value = trim(le_value); + if (!le_value.empty()) { + components["LE"].push_back(le_value); + } + } } return components; @@ -2203,7 +2189,7 @@ void PgSQL_Connection::set_error_from_PQerrorMessage() { const auto error_field_map = parse_pq_error_message(org_msg); - auto lookup = [&error_field_map](const char* key, const char* fallback) -> std::string_view { + auto lookup = [&error_field_map](const char* key, std::string_view fallback) -> std::string_view { auto it = error_field_map.find(key); if (it != error_field_map.end() && !it->second.empty()) return it->second.back(); @@ -2213,16 +2199,10 @@ void PgSQL_Connection::set_error_from_PQerrorMessage() { std::string_view severity = lookup("S", PgSQL_Error_Helper::get_severity(PGSQL_ERROR_SEVERITY::ERRSEVERITY_FATAL)); std::string_view sqlstate = lookup("C", PgSQL_Error_Helper::get_error_code(PGSQL_ERROR_CODES::ERRCODE_RAISE_EXCEPTION)); std::string_view primary_msg = lookup("M", ""); - // if primary_msg is empty, means this is a library generated error, use original error message from PQerrorMessage - std::string_view lib_errmsg = lookup("LE", (primary_msg.empty() ? org_msg.c_str() : "")); - - std::string full_msg; - if (!lib_errmsg.empty()) { - full_msg.reserve(primary_msg.size() + 1 + lib_errmsg.size()); - full_msg.append(primary_msg).append(" ").append(lib_errmsg); - } else { - full_msg = primary_msg; - } + std::string_view lib_errmsg = lookup("LE", ""); - PgSQL_Error_Helper::fill_error_info(error_info, sqlstate.data(), full_msg.c_str(), severity.data()); + // we are currently distinguishing between server errors and library-generated errors. + // A library-generated error is only set when a server error is not available. + const std::string_view& full_msg = !primary_msg.empty() ? primary_msg : lib_errmsg; + PgSQL_Error_Helper::fill_error_info(error_info, sqlstate.data(), full_msg.data(), severity.data()); }