Bugfix: PgBatchConnection did not report error message. (#1588)

This commit is contained in:
Nitromelon 2023-05-09 19:20:23 +08:00 committed by GitHub
parent 29984f26e0
commit 5baca75359
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 16 deletions

View File

@ -441,7 +441,7 @@ void PgConnection::handleRead()
if (type == PGRES_BAD_RESPONSE || type == PGRES_FATAL_ERROR || if (type == PGRES_BAD_RESPONSE || type == PGRES_FATAL_ERROR ||
type == PGRES_PIPELINE_ABORTED) type == PGRES_PIPELINE_ABORTED)
{ {
handleFatalError(false); handleFatalError(false, type == PGRES_PIPELINE_ABORTED);
continue; continue;
} }
if (type == PGRES_PIPELINE_SYNC) if (type == PGRES_PIPELINE_SYNC)
@ -493,11 +493,14 @@ void PgConnection::doAfterPreparing()
{ {
} }
void PgConnection::handleFatalError(bool clearAll) void PgConnection::handleFatalError(bool clearAll, bool isAbortPipeline)
{ {
LOG_ERROR << PQerrorMessage(connectionPtr_.get()); std::string errmsg =
auto exceptPtr = isAbortPipeline
std::make_exception_ptr(Failure(PQerrorMessage(connectionPtr_.get()))); ? "Command didn't run because of an abort earlier in a pipeline"
: PQerrorMessage(connectionPtr_.get());
LOG_ERROR << errmsg;
auto exceptPtr = std::make_exception_ptr(Failure(errmsg));
if (clearAll) if (clearAll)
{ {
for (auto &cmd : batchCommandsForWaitingResults_) for (auto &cmd : batchCommandsForWaitingResults_)
@ -522,19 +525,13 @@ void PgConnection::handleFatalError(bool clearAll)
else if (!batchCommandsForWaitingResults_.empty()) else if (!batchCommandsForWaitingResults_.empty())
{ {
auto &cmd = batchCommandsForWaitingResults_.front(); auto &cmd = batchCommandsForWaitingResults_.front();
if (!cmd->preparingStatement_.empty()) cmd->exceptionCallback_(exceptPtr);
{ batchCommandsForWaitingResults_.pop_front();
cmd->preparingStatement_.clear();
}
else
{
cmd->exceptionCallback_(exceptPtr);
batchCommandsForWaitingResults_.pop_front();
}
} }
else else
{ {
assert(false); // PQsendPrepare failed, error message has already been reported
// Ignore PQsendQueryPrepared failure
} }
} }
} }

View File

@ -132,7 +132,7 @@ class PgConnection : public DbConnection,
std::set<std::string> preparedStatements_; std::set<std::string> preparedStatements_;
string_view sql_; string_view sql_;
#if LIBPQ_SUPPORTS_BATCH_MODE #if LIBPQ_SUPPORTS_BATCH_MODE
void handleFatalError(bool clearAll); void handleFatalError(bool clearAll, bool isAbortPipeline = false);
std::list<std::shared_ptr<SqlCmd>> batchCommandsForWaitingResults_; std::list<std::shared_ptr<SqlCmd>> batchCommandsForWaitingResults_;
std::deque<std::shared_ptr<SqlCmd>> batchSqlCommands_; std::deque<std::shared_ptr<SqlCmd>> batchSqlCommands_;
void sendBatchedSql(); void sendBatchedSql();

View File

@ -44,6 +44,18 @@ DbClientPtr postgreClient;
DROGON_TEST(PostgreTest) DROGON_TEST(PostgreTest)
{ {
auto &clientPtr = postgreClient; auto &clientPtr = postgreClient;
// Test bugfix #1588
// PgBatchConnection.cc did not report error message to application
try
{
clientPtr->execSqlSync("select * from t_not_exists");
}
catch (const DrogonDbException &e)
{
MANDATE(!std::string{e.base().what()}.empty());
}
// Prepare the test environment // Prepare the test environment
*clientPtr << "DROP TABLE IF EXISTS USERS" >> [TEST_CTX, *clientPtr << "DROP TABLE IF EXISTS USERS" >> [TEST_CTX,
clientPtr](const Result &r) { clientPtr](const Result &r) {