Skip to content

Commit

Permalink
Dedicated result/error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
d-frey committed Dec 17, 2024
1 parent 3225097 commit e902534
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 22 deletions.
4 changes: 3 additions & 1 deletion include/tao/pq/connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ namespace tao::pq
void cancel();

[[nodiscard]] auto get_result( const std::chrono::steady_clock::time_point end ) -> std::unique_ptr< PGresult, decltype( &PQclear ) >;
[[nodiscard]] auto get_fatal_error( const std::chrono::steady_clock::time_point end ) -> std::unique_ptr< PGresult, decltype( &PQclear ) >;
void consume_empty_result( const std::chrono::steady_clock::time_point end );

[[nodiscard]] auto get_copy_data( char*& buffer, const std::chrono::steady_clock::time_point end ) -> std::size_t;
[[nodiscard]] auto get_copy_data( char*& buffer ) -> std::size_t;

void put_copy_data( const char* buffer, const std::size_t size );
void put_copy_end( const char* error_message = nullptr );

void clear_results( const std::chrono::steady_clock::time_point end );
void clear_copy_data( const std::chrono::steady_clock::time_point end );

// pass-key idiom
Expand Down
33 changes: 25 additions & 8 deletions src/lib/pq/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,29 @@ namespace tao::pq
return result;
}

auto connection::get_fatal_error( const std::chrono::steady_clock::time_point end ) -> std::unique_ptr< PGresult, decltype( &PQclear ) >
{
auto result = connection::get_result( end );
if( !result ) {
throw std::runtime_error( "unable to obtain result" );
}

const auto status = PQresultStatus( result.get() );
if( status != PGRES_FATAL_ERROR ) {
throw std::runtime_error( std::format( "unexpected result status: {}", PQresStatus( status ) ) );
}

return result;
}

void connection::consume_empty_result( const std::chrono::steady_clock::time_point end )
{
if( const auto result = connection::get_result( end ) ) {
const auto status = PQresultStatus( result.get() );
throw std::runtime_error( std::format( "unexpected result status: {}", PQresStatus( status ) ) );
}
}

auto connection::get_copy_data( char*& buffer, const std::chrono::steady_clock::time_point end ) -> std::size_t
{
while( true ) {
Expand Down Expand Up @@ -378,12 +401,6 @@ namespace tao::pq
}
}

void connection::clear_results( const std::chrono::steady_clock::time_point end )
{
while( connection::get_result( end ) ) {
}
}

void connection::clear_copy_data( const std::chrono::steady_clock::time_point end )
{
char* ptr;
Expand Down Expand Up @@ -540,7 +557,7 @@ namespace tao::pq
const auto result = connection::get_result( end );
switch( PQresultStatus( result.get() ) ) {
case PGRES_COMMAND_OK:
connection::clear_results( end );
connection::consume_empty_result( end );
break;

case PGRES_TUPLES_OK:
Expand All @@ -550,7 +567,7 @@ namespace tao::pq
TAO_PQ_INTERNAL_UNREACHABLE; // LCOV_EXCL_LINE

default:
connection::clear_results( end );
connection::consume_empty_result( end );
internal::throw_sqlstate( result.get() );
}

Expand Down
6 changes: 3 additions & 3 deletions src/lib/pq/table_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ namespace tao::pq

case PGRES_COMMAND_OK:
case PGRES_TUPLES_OK:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
throw std::runtime_error( "expected COPY TO statement" );

case PGRES_EMPTY_QUERY:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
throw std::runtime_error( "unexpected empty query" );

default:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
internal::throw_sqlstate( result.get() );
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/lib/pq/table_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,29 @@ namespace tao::pq
void table_writer::check_result()
{
const auto end = m_transaction->connection()->timeout_end();
auto result = m_transaction->connection()->get_result( end );
const auto result = m_transaction->connection()->get_result( end );
switch( PQresultStatus( result.get() ) ) {
case PGRES_COPY_IN:
break;

case PGRES_COPY_OUT:
m_transaction->connection()->cancel();
m_transaction->connection()->clear_copy_data( end );
m_transaction->connection()->clear_results( end );
std::ignore = m_transaction->connection()->get_fatal_error( end );
m_transaction->connection()->consume_empty_result( end );
throw std::runtime_error( "unexpected COPY TO statement" );

case PGRES_COMMAND_OK:
case PGRES_TUPLES_OK:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
throw std::runtime_error( "expected COPY FROM statement" );

case PGRES_EMPTY_QUERY:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
throw std::runtime_error( "unexpected empty query" );

default:
m_transaction->connection()->clear_results( end );
m_transaction->connection()->consume_empty_result( end );
internal::throw_sqlstate( result.get() );
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/lib/pq/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ namespace tao::pq
switch( PQresultStatus( result.get() ) ) {
case PGRES_COPY_IN:
m_connection->put_copy_end( "unexpected COPY FROM statement" );
result = m_connection->get_fatal_error( end );
break;

case PGRES_COPY_OUT:
m_connection->cancel();
m_connection->clear_copy_data( end );
m_connection->clear_results( end );
std::ignore = m_connection->get_fatal_error( end );
m_connection->consume_empty_result( end );
throw std::runtime_error( "unexpected COPY TO statement" );

case PGRES_SINGLE_TUPLE:
Expand All @@ -190,10 +192,7 @@ namespace tao::pq
default:;
}

while( auto next = m_connection->get_result( end ) ) {
result = std::move( next );
}

m_connection->consume_empty_result( end );
return pq::result( result.release() );
}

Expand Down

0 comments on commit e902534

Please sign in to comment.