Improved parser

pull/4947/head
Rahim Kanji 11 months ago
parent 1326edfbf2
commit 7c46f6c48c

@ -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<std::string, std::vector<std::string>> 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<std::string, std::vector<std::string>> 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());
}

Loading…
Cancel
Save