diff --git a/.clang-format b/.clang-format
index 5eece0c..71aac94 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,7 +1,7 @@
# The Art of C++
# https://github.com/taocpp
-# Copyright (c) 2016-2024 Dr. Colin Hirsch and Daniel Frey
+# Copyright (c) 2016-2025 Dr. Colin Hirsch and Daniel Frey
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/.clang-tidy b/.clang-tidy
index b3148be..fc1c51e 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,7 +1,7 @@
# The Art of C++
# https://github.com/taocpp
-# Copyright (c) 2016-2024 Dr. Colin Hirsch and Daniel Frey
+# Copyright (c) 2016-2025 Dr. Colin Hirsch and Daniel Frey
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08e3ef9..af0a34b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,7 @@ set(taopq_INCLUDE_FILES
${taopq_INCLUDE_DIRS}/tao/pq/internal/aggregate.hpp
${taopq_INCLUDE_DIRS}/tao/pq/internal/demangle.hpp
${taopq_INCLUDE_DIRS}/tao/pq/internal/exclusive_scan.hpp
+ ${taopq_INCLUDE_DIRS}/tao/pq/internal/format_as.hpp
${taopq_INCLUDE_DIRS}/tao/pq/internal/from_chars.hpp
${taopq_INCLUDE_DIRS}/tao/pq/internal/gen.hpp
${taopq_INCLUDE_DIRS}/tao/pq/internal/parameter_traits_helper.hpp
@@ -43,6 +44,7 @@ set(taopq_INCLUDE_FILES
${taopq_INCLUDE_DIRS}/tao/pq/is_array.hpp
${taopq_INCLUDE_DIRS}/tao/pq/isolation_level.hpp
${taopq_INCLUDE_DIRS}/tao/pq/large_object.hpp
+ ${taopq_INCLUDE_DIRS}/tao/pq/log.hpp
${taopq_INCLUDE_DIRS}/tao/pq/notification.hpp
${taopq_INCLUDE_DIRS}/tao/pq/null.hpp
${taopq_INCLUDE_DIRS}/tao/pq/oid.hpp
diff --git a/Makefile b/Makefile
index ae63709..83f09ab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# The Art of C++
# https://github.com/taocpp
-# Copyright (c) 2016-2024 Daniel Frey
+# Copyright (c) 2016-2025 Daniel Frey
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/README.md b/README.md
index 5af33ca..43fd8af 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,7 @@ taoPQ is part of [The Art of C++](https://taocpp.github.io/).
-Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
taoPQ is certified [Open Source➚](http://www.opensource.org/docs/definition.html) software.
It is [licensed➚](https://pdimov.github.io/blog/2020/09/06/why-use-the-boost-license/) under the terms of the [Boost Software License, Version 1.0➚](https://www.boost.org/LICENSE_1_0.txt) reproduced here.
diff --git a/doc/Aggregate-Support.md b/doc/Aggregate-Support.md
index 405d279..e86663e 100644
--- a/doc/Aggregate-Support.md
+++ b/doc/Aggregate-Support.md
@@ -94,6 +94,6 @@ int main()
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Binary-Data.md b/doc/Binary-Data.md
index b192305..198c455 100644
--- a/doc/Binary-Data.md
+++ b/doc/Binary-Data.md
@@ -53,6 +53,6 @@ In some cases other alternatives are offered, i.e. you may provide a buffer that
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Bulk-Transfer.md b/doc/Bulk-Transfer.md
index e78fa7c..9bef5f6 100644
--- a/doc/Bulk-Transfer.md
+++ b/doc/Bulk-Transfer.md
@@ -248,6 +248,6 @@ namespace tao::pq
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Connection-Pool.md b/doc/Connection-Pool.md
index e54cc23..40d8689 100644
--- a/doc/Connection-Pool.md
+++ b/doc/Connection-Pool.md
@@ -178,6 +178,6 @@ We minimized the work in the [critical sections➚](https://en.wikipedia.org/wik
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Connection.md b/doc/Connection.md
index 611b2b0..1779678 100644
--- a/doc/Connection.md
+++ b/doc/Connection.md
@@ -411,6 +411,6 @@ When taoPQ throws an exception this is usually done internally and the message i
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Error-Handling.md b/doc/Error-Handling.md
index e683294..cbaebf6 100644
--- a/doc/Error-Handling.md
+++ b/doc/Error-Handling.md
@@ -78,6 +78,6 @@ The same exception can also be thrown when calling the connection's `get_notific
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Getting-Started.md b/doc/Getting-Started.md
index 60f7717..b79b4e0 100644
--- a/doc/Getting-Started.md
+++ b/doc/Getting-Started.md
@@ -67,6 +67,6 @@ The following chapters are good next steps to get to know taoPQ:
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Installation.md b/doc/Installation.md
index 3b662fa..90b22e9 100644
--- a/doc/Installation.md
+++ b/doc/Installation.md
@@ -40,6 +40,6 @@ When executing the build step, taoPQ will be built first, as its target is requi
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Large-Object.md b/doc/Large-Object.md
index 14c42db..b43460c 100644
--- a/doc/Large-Object.md
+++ b/doc/Large-Object.md
@@ -222,6 +222,6 @@ If an error occurs an exception will be thrown.
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Parameter-Type-Conversion.md b/doc/Parameter-Type-Conversion.md
index 848c95a..a2db51f 100644
--- a/doc/Parameter-Type-Conversion.md
+++ b/doc/Parameter-Type-Conversion.md
@@ -186,6 +186,6 @@ TODO: Write proper documentation.
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Performance.md b/doc/Performance.md
index 06d5d8e..5552488 100644
--- a/doc/Performance.md
+++ b/doc/Performance.md
@@ -6,6 +6,6 @@
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Requirements.md b/doc/Requirements.md
index 2237356..369ba59 100644
--- a/doc/Requirements.md
+++ b/doc/Requirements.md
@@ -42,6 +42,6 @@ You can decide which options you want to use in your project, we just try to not
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Result-Type-Conversion.md b/doc/Result-Type-Conversion.md
index 6b8eca0..c7abb28 100644
--- a/doc/Result-Type-Conversion.md
+++ b/doc/Result-Type-Conversion.md
@@ -146,6 +146,6 @@ TODO: Write proper documentation.
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Result.md b/doc/Result.md
index 2cff59e..6bbba70 100644
--- a/doc/Result.md
+++ b/doc/Result.md
@@ -482,6 +482,6 @@ auto tao::pq::field::optional() const
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Statement.md b/doc/Statement.md
index 611d222..0632fb5 100644
--- a/doc/Statement.md
+++ b/doc/Statement.md
@@ -125,6 +125,6 @@ The [Parameter Type Conversion](Parameter-Type-Conversion.md) chapter explains w
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/doc/Transaction.md b/doc/Transaction.md
index 9af4fa3..78d83cd 100644
--- a/doc/Transaction.md
+++ b/doc/Transaction.md
@@ -160,6 +160,6 @@ auto tao::pq::transaction::connection() const noexcept
This document is part of [taoPQ](https://github.com/taocpp/taopq).
-Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
Distributed under the Boost Software License, Version 1.0
See accompanying file [LICENSE_1_0.txt](../LICENSE_1_0.txt) or copy at https://www.boost.org/LICENSE_1_0.txt
diff --git a/include/tao/pq.hpp b/include/tao/pq.hpp
index 4172345..fbcde9f 100644
--- a/include/tao/pq.hpp
+++ b/include/tao/pq.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -27,6 +27,7 @@
#include
#include
+#include
#include
#include
diff --git a/include/tao/pq/access_mode.hpp b/include/tao/pq/access_mode.hpp
index 6280816..5237aa4 100644
--- a/include/tao/pq/access_mode.hpp
+++ b/include/tao/pq/access_mode.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,6 +6,9 @@
#define TAO_PQ_ACCESS_MODE_HPP
#include
+#include
+
+#include
namespace tao::pq
{
@@ -16,6 +19,23 @@ namespace tao::pq
read_only
};
+ [[nodiscard]] constexpr auto taopq_format_as( const access_mode am ) noexcept -> std::string_view
+ {
+ switch( am ) {
+ case access_mode::default_access_mode:
+ return "default_access_mode";
+
+ case access_mode::read_write:
+ return "read_write";
+
+ case access_mode::read_only:
+ return "read_only";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/binary.hpp b/include/tao/pq/binary.hpp
index 25229aa..0a38180 100644
--- a/include/tao/pq/binary.hpp
+++ b/include/tao/pq/binary.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/bind.hpp b/include/tao/pq/bind.hpp
index 0345193..122d595 100644
--- a/include/tao/pq/bind.hpp
+++ b/include/tao/pq/bind.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/connection.hpp b/include/tao/pq/connection.hpp
index 658e5b4..a6c334d 100644
--- a/include/tao/pq/connection.hpp
+++ b/include/tao/pq/connection.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -53,6 +54,7 @@ namespace tao::pq
friend class connection_pool;
friend class table_reader;
friend class table_writer;
+ friend class transaction;
friend class transaction_base;
friend class internal::top_level_transaction;
@@ -66,6 +68,7 @@ namespace tao::pq
std::function< poll::callback > m_poll;
std::function< void( const notification& ) > m_notification_handler;
std::map< std::string, std::function< void( const char* ) >, std::less<> > m_notification_handlers;
+ std::shared_ptr< log > m_log;
[[nodiscard]] auto escape_identifier( const std::string_view identifier ) const -> std::unique_ptr< char, decltype( &PQfreemem ) >;
@@ -109,7 +112,7 @@ namespace tao::pq
};
public:
- connection( const private_key /*unused*/, const std::string& connection_info, std::function< poll::callback > poll_cb );
+ connection( const private_key /*unused*/, const std::string& connection_info );
connection( const connection& ) = delete;
connection( connection&& ) = delete;
@@ -118,23 +121,61 @@ namespace tao::pq
~connection() = default;
- [[nodiscard]] static auto create( const std::string& connection_info, std::function< poll::callback > poll_cb = internal::poll ) -> std::shared_ptr< connection >;
+ [[nodiscard]] static auto create( const std::string& connection_info ) -> std::shared_ptr< connection >;
[[nodiscard]] auto error_message() const -> const char*;
- [[nodiscard]] auto poll_callback() const noexcept -> const std::function< poll::callback >&;
- void set_poll_callback( std::function< poll::callback > poll_cb ) noexcept;
- void reset_poll_callback();
+ [[nodiscard]] auto poll_callback() const noexcept -> decltype( auto )
+ {
+ return m_poll;
+ }
+
+ void set_poll_callback( std::function< poll::callback > poll_cb ) noexcept
+ {
+ m_poll = std::move( poll_cb );
+ }
+
+ void reset_poll_callback()
+ {
+ m_poll = internal::poll;
+ }
+
+ [[nodiscard]] auto notification_handler() const noexcept -> decltype( auto )
+ {
+ return m_notification_handler;
+ }
+
+ void set_notification_handler( std::function< void( const notification& ) > handler ) noexcept
+ {
+ m_notification_handler = std::move( handler );
+ }
+
+ void reset_notification_handler() noexcept
+ {
+ m_notification_handler = nullptr;
+ }
- [[nodiscard]] auto notification_handler() const -> std::function< void( const notification& ) >;
[[nodiscard]] auto notification_handler( const std::string_view channel ) const -> std::function< void( const char* payload ) >;
- void set_notification_handler( const std::function< void( const notification& ) >& handler );
void set_notification_handler( const std::string_view channel, const std::function< void( const char* payload ) >& handler );
- void reset_notification_handler() noexcept;
void reset_notification_handler( const std::string_view channel ) noexcept;
+ [[nodiscard]] auto log_handler() const noexcept -> decltype( auto )
+ {
+ return m_log;
+ }
+
+ void set_log_handler( const std::shared_ptr< pq::log >& log ) noexcept
+ {
+ m_log = log;
+ }
+
+ void reset_log_handler() noexcept
+ {
+ m_log = nullptr;
+ }
+
[[nodiscard]] auto status() const noexcept -> connection_status;
[[nodiscard]] auto transaction_status() const noexcept -> pq::transaction_status;
@@ -156,6 +197,10 @@ namespace tao::pq
[[nodiscard]] auto is_busy() const noexcept -> bool;
+ [[nodiscard]] auto flush() -> bool;
+
+ void consume_input();
+
[[nodiscard]] auto direct() -> std::shared_ptr< pq::transaction >;
[[nodiscard]] auto transaction() -> std::shared_ptr< pq::transaction >;
@@ -190,8 +235,15 @@ namespace tao::pq
return m_timeout;
}
- void set_timeout( const std::chrono::milliseconds timeout );
- void reset_timeout() noexcept;
+ void set_timeout( const std::chrono::milliseconds timeout ) noexcept
+ {
+ m_timeout = timeout;
+ }
+
+ void reset_timeout() noexcept
+ {
+ m_timeout = std::nullopt;
+ }
[[nodiscard]] auto password( const internal::zsv passwd, const internal::zsv user, const internal::zsv algorithm = "scram-sha-256" ) -> std::string;
diff --git a/include/tao/pq/connection_pool.hpp b/include/tao/pq/connection_pool.hpp
index 657519a..4418e9d 100644
--- a/include/tao/pq/connection_pool.hpp
+++ b/include/tao/pq/connection_pool.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -24,7 +24,7 @@
namespace tao::pq
{
class connection_pool
- : public internal::pool< connection >
+ : public internal::pool< pq::connection >
{
private:
const std::string m_connection_info;
@@ -34,7 +34,7 @@ namespace tao::pq
protected:
[[nodiscard]] auto v_create() const -> std::unique_ptr< pq::connection > override;
- [[nodiscard]] auto v_is_valid( connection& c ) const noexcept -> bool override
+ [[nodiscard]] auto v_is_valid( pq::connection& c ) const noexcept -> bool override
{
return c.is_idle();
}
@@ -48,12 +48,14 @@ namespace tao::pq
};
public:
- connection_pool( const private_key /*unused*/, const std::string_view connection_info, std::function< poll::callback > poll_cb );
+ connection_pool( const private_key /*unused*/, const std::string_view connection_info );
+
+ void get() const = delete;
template< typename T = connection_pool >
- [[nodiscard]] static auto create( const std::string_view connection_info, std::function< poll::callback > poll_cb = internal::poll ) -> std::shared_ptr< T >
+ [[nodiscard]] static auto create( const std::string_view connection_info ) -> std::shared_ptr< T >
{
- return std::make_shared< T >( private_key(), connection_info, std::move( poll_cb ) );
+ return std::make_shared< T >( private_key(), connection_info );
}
[[nodiscard]] auto timeout() const noexcept -> decltype( auto )
@@ -61,14 +63,32 @@ namespace tao::pq
return m_timeout;
}
- void set_timeout( const std::chrono::milliseconds timeout ) noexcept;
- void reset_timeout() noexcept;
+ void set_timeout( const std::chrono::milliseconds timeout ) noexcept
+ {
+ m_timeout = timeout;
+ }
+
+ void reset_timeout() noexcept
+ {
+ m_timeout = std::nullopt;
+ }
+
+ [[nodiscard]] auto poll_callback() const noexcept -> decltype( auto )
+ {
+ return m_poll;
+ }
- [[nodiscard]] auto poll_callback() const noexcept -> const std::function< poll::callback >&;
- void set_poll_callback( std::function< poll::callback > poll_cb ) noexcept;
- void reset_poll_callback();
+ void set_poll_callback( std::function< poll::callback > poll_cb ) noexcept
+ {
+ m_poll = std::move( poll_cb );
+ }
+
+ void reset_poll_callback()
+ {
+ m_poll = internal::poll;
+ }
- [[nodiscard]] auto connection() -> std::shared_ptr< connection >;
+ [[nodiscard]] auto connection() -> std::shared_ptr< pq::connection >;
template< parameter_type... As >
auto execute( const internal::zsv statement, As&&... as )
diff --git a/include/tao/pq/connection_status.hpp b/include/tao/pq/connection_status.hpp
index 933358f..4011161 100644
--- a/include/tao/pq/connection_status.hpp
+++ b/include/tao/pq/connection_status.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2022-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2022-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,9 +6,12 @@
#define TAO_PQ_CONNECTION_STATUS_HPP
#include
+#include
#include
+#include
+
namespace tao::pq
{
enum class connection_status : std::uint8_t
@@ -17,6 +20,20 @@ namespace tao::pq
bad = CONNECTION_BAD
};
+ [[nodiscard]] constexpr auto taopq_format_as( const connection_status cs ) noexcept -> std::string_view
+ {
+ switch( cs ) {
+ case connection_status::ok:
+ return "ok";
+
+ case connection_status::bad:
+ return "bad";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/exception.hpp b/include/tao/pq/exception.hpp
index 4a3a64c..8645f47 100644
--- a/include/tao/pq/exception.hpp
+++ b/include/tao/pq/exception.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/field.hpp b/include/tao/pq/field.hpp
index 438e337..64b72a6 100644
--- a/include/tao/pq/field.hpp
+++ b/include/tao/pq/field.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/aggregate.hpp b/include/tao/pq/internal/aggregate.hpp
index d7e627c..a4bf63d 100644
--- a/include/tao/pq/internal/aggregate.hpp
+++ b/include/tao/pq/internal/aggregate.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/demangle.hpp b/include/tao/pq/internal/demangle.hpp
index 027739b..93d13ab 100644
--- a/include/tao/pq/internal/demangle.hpp
+++ b/include/tao/pq/internal/demangle.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/exclusive_scan.hpp b/include/tao/pq/internal/exclusive_scan.hpp
index d464115..d0b4d4d 100644
--- a/include/tao/pq/internal/exclusive_scan.hpp
+++ b/include/tao/pq/internal/exclusive_scan.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2019-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/format_as.hpp b/include/tao/pq/internal/format_as.hpp
new file mode 100644
index 0000000..dbabd6d
--- /dev/null
+++ b/include/tao/pq/internal/format_as.hpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef TAO_PQ_INTERNAL_FORMAT_AS_HPP
+#define TAO_PQ_INTERNAL_FORMAT_AS_HPP
+
+#include
+#include
+#include
+
+template< typename T >
+ requires requires { taopq_format_as( std::declval< T >() ); }
+struct std::formatter< T > : std::formatter< decltype( taopq_format_as( std::declval< T >() ) ) >
+{
+ auto format( const T& v, auto& ctx ) const
+ {
+ return std::formatter< decltype( taopq_format_as( v ) ) >::format( taopq_format_as( v ), ctx );
+ }
+};
+
+template< typename T >
+ requires requires { taopq_format_as( std::declval< T >() ); }
+auto operator<<( std::ostream& os, const T& v ) -> std::ostream&
+{
+ return os << taopq_format_as( v );
+}
+
+#endif
diff --git a/include/tao/pq/internal/from_chars.hpp b/include/tao/pq/internal/from_chars.hpp
index abe525b..adda411 100644
--- a/include/tao/pq/internal/from_chars.hpp
+++ b/include/tao/pq/internal/from_chars.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/gen.hpp b/include/tao/pq/internal/gen.hpp
index b9585e6..ff6aca1 100644
--- a/include/tao/pq/internal/gen.hpp
+++ b/include/tao/pq/internal/gen.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2019-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2019-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/parameter_traits_helper.hpp b/include/tao/pq/internal/parameter_traits_helper.hpp
index fc0eefc..3fcb8b7 100644
--- a/include/tao/pq/internal/parameter_traits_helper.hpp
+++ b/include/tao/pq/internal/parameter_traits_helper.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/poll.hpp b/include/tao/pq/internal/poll.hpp
index 8463366..fc9fda4 100644
--- a/include/tao/pq/internal/poll.hpp
+++ b/include/tao/pq/internal/poll.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/pool.hpp b/include/tao/pq/internal/pool.hpp
index 80f91d3..418d643 100644
--- a/include/tao/pq/internal/pool.hpp
+++ b/include/tao/pq/internal/pool.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/resize_uninitialized.hpp b/include/tao/pq/internal/resize_uninitialized.hpp
index ced6ea9..61a3f93 100644
--- a/include/tao/pq/internal/resize_uninitialized.hpp
+++ b/include/tao/pq/internal/resize_uninitialized.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/strtox.hpp b/include/tao/pq/internal/strtox.hpp
index b4284ad..aafe579 100644
--- a/include/tao/pq/internal/strtox.hpp
+++ b/include/tao/pq/internal/strtox.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/unreachable.hpp b/include/tao/pq/internal/unreachable.hpp
index a17ea28..95f25f2 100644
--- a/include/tao/pq/internal/unreachable.hpp
+++ b/include/tao/pq/internal/unreachable.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/internal/zsv.hpp b/include/tao/pq/internal/zsv.hpp
index 2c8d561..4c43f34 100644
--- a/include/tao/pq/internal/zsv.hpp
+++ b/include/tao/pq/internal/zsv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/is_aggregate.hpp b/include/tao/pq/is_aggregate.hpp
index 3b4aefe..ec53b4a 100644
--- a/include/tao/pq/is_aggregate.hpp
+++ b/include/tao/pq/is_aggregate.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/is_array.hpp b/include/tao/pq/is_array.hpp
index ebefb16..26c0601 100644
--- a/include/tao/pq/is_array.hpp
+++ b/include/tao/pq/is_array.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/isolation_level.hpp b/include/tao/pq/isolation_level.hpp
index e1228f5..bdf7ed2 100644
--- a/include/tao/pq/isolation_level.hpp
+++ b/include/tao/pq/isolation_level.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,6 +6,9 @@
#define TAO_PQ_ISOLATION_LEVEL_HPP
#include
+#include
+
+#include
namespace tao::pq
{
@@ -18,6 +21,29 @@ namespace tao::pq
read_uncommitted
};
+ [[nodiscard]] constexpr auto taopq_format_as( const isolation_level il ) noexcept -> std::string_view
+ {
+ switch( il ) {
+ case isolation_level::default_isolation_level:
+ return "default_isolation_level";
+
+ case isolation_level::serializable:
+ return "serializable";
+
+ case isolation_level::repeatable_read:
+ return "repeatable_read";
+
+ case isolation_level::read_committed:
+ return "read_committed";
+
+ case isolation_level::read_uncommitted:
+ return "read_uncommitted";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/large_object.hpp b/include/tao/pq/large_object.hpp
index 1f27676..624cfec 100644
--- a/include/tao/pq/large_object.hpp
+++ b/include/tao/pq/large_object.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/log.hpp b/include/tao/pq/log.hpp
new file mode 100644
index 0000000..e938c60
--- /dev/null
+++ b/include/tao/pq/log.hpp
@@ -0,0 +1,134 @@
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef TAO_PQ_LOG_HPP
+#define TAO_PQ_LOG_HPP
+
+#include
+#include
+
+#include
+
+#include
+
+namespace tao::pq
+{
+ class connection;
+ class transaction;
+
+ struct log
+ {
+ struct connection_pool_t
+ {
+ // TODO...
+
+ } connection_pool;
+
+ struct connection_t
+ {
+ using send_query_t = std::function< void( connection&, const char* statement, int n_params, const Oid types[], const char* const values[], const int lengths[], const int formats[] ) >;
+ using send_query_result_t = std::function< void( connection&, int result ) >;
+
+ using send_query_prepared_t = std::function< void( connection&, const char* statement, int n_params, const char* const values[], const int lengths[], const int formats[] ) >;
+ using send_query_prepared_result_t = std::function< void( connection&, int result ) >;
+
+ using wait_t = std::function< void( connection&, bool wait_for_write, std::chrono::steady_clock::time_point end ) >;
+
+ using poll_t = std::function< void( connection&, int socket, bool wait_for_write, int timeout_ms ) >;
+ using poll_result_t = std::function< void( connection&, int socket, poll::status status ) >;
+
+ using is_busy_result_t = std::function< void( const connection&, int result ) >; // noexcept
+
+ using consume_input_t = std::function< void( connection& ) >;
+ using consume_input_result_t = std::function< void( connection&, int result ) >;
+
+ using flush_t = std::function< void( connection& ) >;
+ using flush_result_t = std::function< void( connection&, int result ) >;
+
+ using get_result_t = std::function< void( connection&, std::chrono::steady_clock::time_point end ) >;
+ using get_result_result_t = std::function< void( connection&, PGresult* ) >;
+
+ using enter_pipeline_mode_result_t = std::function< void( connection&, int result ) >;
+
+ using exit_pipeline_mode_t = std::function< void( connection& ) >;
+ using exit_pipeline_mode_result_t = std::function< void( connection&, int result ) >;
+
+ using pipeline_sync_t = std::function< void( connection& ) >;
+ using pipeline_sync_result_t = std::function< void( connection&, int result ) >;
+
+ struct : send_query_t
+ {
+ send_query_result_t result;
+ using send_query_t::operator=;
+ } send_query;
+
+ struct : send_query_prepared_t
+ {
+ send_query_prepared_result_t result;
+ using send_query_prepared_t::operator=;
+ } send_query_prepared;
+
+ wait_t wait;
+
+ struct : poll_t
+ {
+ poll_result_t result;
+ using poll_t::operator=;
+ } poll;
+
+ struct
+ {
+ is_busy_result_t result;
+ } is_busy;
+
+ struct : consume_input_t
+ {
+ consume_input_result_t result;
+ using consume_input_t::operator=;
+ } consume_input;
+
+ struct : flush_t
+ {
+ flush_result_t result;
+ using flush_t::operator=;
+ } flush;
+
+ struct : get_result_t
+ {
+ get_result_result_t result;
+ using get_result_t::operator=;
+ } get_result;
+
+ struct
+ {
+ enter_pipeline_mode_result_t result;
+ } enter_pipeline_mode;
+
+ struct : exit_pipeline_mode_t
+ {
+ exit_pipeline_mode_result_t result;
+ using exit_pipeline_mode_t::operator=;
+ } exit_pipeline_mode;
+
+ struct : pipeline_sync_t
+ {
+ pipeline_sync_result_t result;
+ using pipeline_sync_t::operator=;
+ } pipeline_sync;
+
+ } connection;
+
+ struct transaction_t
+ {
+ // check std::current_exception() for more information
+ using destructor_rollback_failed_t = std::function< void( transaction& ) >; // noexcept
+
+ destructor_rollback_failed_t destructor_rollback_failed;
+
+ } transaction;
+ };
+
+} // namespace tao::pq
+
+#endif
diff --git a/include/tao/pq/notification.hpp b/include/tao/pq/notification.hpp
index 7169f03..8bbeb0b 100644
--- a/include/tao/pq/notification.hpp
+++ b/include/tao/pq/notification.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/null.hpp b/include/tao/pq/null.hpp
index f149e30..02d664f 100644
--- a/include/tao/pq/null.hpp
+++ b/include/tao/pq/null.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/oid.hpp b/include/tao/pq/oid.hpp
index 33ba150..eb607bb 100644
--- a/include/tao/pq/oid.hpp
+++ b/include/tao/pq/oid.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter.hpp b/include/tao/pq/parameter.hpp
index 78b8012..aa3a4da 100644
--- a/include/tao/pq/parameter.hpp
+++ b/include/tao/pq/parameter.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits.hpp b/include/tao/pq/parameter_traits.hpp
index 13819ab..e92965c 100644
--- a/include/tao/pq/parameter_traits.hpp
+++ b/include/tao/pq/parameter_traits.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits_aggregate.hpp b/include/tao/pq/parameter_traits_aggregate.hpp
index 034a584..f49b8e5 100644
--- a/include/tao/pq/parameter_traits_aggregate.hpp
+++ b/include/tao/pq/parameter_traits_aggregate.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits_array.hpp b/include/tao/pq/parameter_traits_array.hpp
index 628b374..e819dc3 100644
--- a/include/tao/pq/parameter_traits_array.hpp
+++ b/include/tao/pq/parameter_traits_array.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits_optional.hpp b/include/tao/pq/parameter_traits_optional.hpp
index b2b68a1..4c79ad8 100644
--- a/include/tao/pq/parameter_traits_optional.hpp
+++ b/include/tao/pq/parameter_traits_optional.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits_pair.hpp b/include/tao/pq/parameter_traits_pair.hpp
index 964ac07..9d185bd 100644
--- a/include/tao/pq/parameter_traits_pair.hpp
+++ b/include/tao/pq/parameter_traits_pair.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/parameter_traits_tuple.hpp b/include/tao/pq/parameter_traits_tuple.hpp
index cc2cfd1..514136d 100644
--- a/include/tao/pq/parameter_traits_tuple.hpp
+++ b/include/tao/pq/parameter_traits_tuple.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/pipeline.hpp b/include/tao/pq/pipeline.hpp
index f4eae9e..e938b70 100644
--- a/include/tao/pq/pipeline.hpp
+++ b/include/tao/pq/pipeline.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -13,6 +13,7 @@
namespace tao::pq
{
class connection;
+ class transaction;
class pipeline
: public transaction_base
@@ -20,8 +21,17 @@ namespace tao::pq
private:
std::shared_ptr< transaction_base > m_previous;
+ friend class transaction;
+
+ // pass-key idiom
+ class private_key final
+ {
+ private_key() = default;
+ friend class transaction;
+ };
+
public:
- explicit pipeline( const std::shared_ptr< pq::connection >& connection );
+ pipeline( const private_key /*unused*/, const std::shared_ptr< pq::connection >& connection );
~pipeline() override
{
diff --git a/include/tao/pq/pipeline_status.hpp b/include/tao/pq/pipeline_status.hpp
index 0c5e796..e9ccec9 100644
--- a/include/tao/pq/pipeline_status.hpp
+++ b/include/tao/pq/pipeline_status.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,9 +6,12 @@
#define TAO_PQ_PIPELINE_STATUS_HPP
#include
+#include
#include
+#include
+
namespace tao::pq
{
enum class pipeline_status : std::uint8_t
@@ -18,6 +21,23 @@ namespace tao::pq
aborted = PQ_PIPELINE_ABORTED
};
+ [[nodiscard]] constexpr auto taopq_format_as( const pipeline_status ps ) noexcept -> std::string_view
+ {
+ switch( ps ) {
+ case pipeline_status::on:
+ return "on";
+
+ case pipeline_status::off:
+ return "off";
+
+ case pipeline_status::aborted:
+ return "aborted";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/poll.hpp b/include/tao/pq/poll.hpp
index 31b6dc5..231e38c 100644
--- a/include/tao/pq/poll.hpp
+++ b/include/tao/pq/poll.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,6 +6,9 @@
#define TAO_PQ_POLL_HPP
#include
+#include
+
+#include
namespace tao::pq::poll
{
@@ -17,6 +20,26 @@ namespace tao::pq::poll
again
};
+ [[nodiscard]] constexpr auto taopq_format_as( const status st ) noexcept -> std::string_view
+ {
+ switch( st ) {
+ case status::timeout:
+ return "timeout";
+
+ case status::readable:
+ return "readable";
+
+ case status::writable:
+ return "writable";
+
+ case status::again:
+ return "again";
+
+ default:
+ return "";
+ }
+ }
+
using callback = status( const int socket, const bool wait_for_write, const int timeout_ms );
} // namespace tao::pq::poll
diff --git a/include/tao/pq/result.hpp b/include/tao/pq/result.hpp
index d1fb43b..c285dc4 100644
--- a/include/tao/pq/result.hpp
+++ b/include/tao/pq/result.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_status.hpp b/include/tao/pq/result_status.hpp
index 5d43cf8..0930bf2 100644
--- a/include/tao/pq/result_status.hpp
+++ b/include/tao/pq/result_status.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,9 +6,12 @@
#define TAO_PQ_RESULT_STATUS_HPP
#include
+#include
#include
+#include
+
namespace tao::pq
{
enum class result_status : std::uint8_t
@@ -29,6 +32,52 @@ namespace tao::pq
pipeline_aborted = PGRES_PIPELINE_ABORTED
};
+ [[nodiscard]] constexpr auto taopq_format_as( const result_status rs ) noexcept -> std::string_view
+ {
+ switch( rs ) {
+ case result_status::empty_query:
+ return "empty_query";
+
+ case result_status::command_ok:
+ return "command_ok";
+
+ case result_status::tuples_ok:
+ return "tuples_ok";
+
+ case result_status::copy_out:
+ return "copy_out";
+
+ case result_status::copy_in:
+ return "copy_in";
+
+ case result_status::bad_response:
+ return "bad_response";
+
+ case result_status::nonfatal_error:
+ return "nonfatal_error";
+
+ case result_status::fatal_error:
+ return "fatal_error";
+
+ case result_status::single_tuple:
+ return "single_tuple";
+
+#if defined( LIBPQ_HAS_CHUNK_MODE )
+ case result_status::tuples_chunk:
+ return "tuples_chunk";
+#endif
+
+ case result_status::pipeline_sync:
+ return "pipeline_sync";
+
+ case result_status::pipeline_aborted:
+ return "pipeline_aborted";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/result_traits.hpp b/include/tao/pq/result_traits.hpp
index b06a6b1..2e0ea7a 100644
--- a/include/tao/pq/result_traits.hpp
+++ b/include/tao/pq/result_traits.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_traits_aggregate.hpp b/include/tao/pq/result_traits_aggregate.hpp
index 9e12dd6..0ce3192 100644
--- a/include/tao/pq/result_traits_aggregate.hpp
+++ b/include/tao/pq/result_traits_aggregate.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_traits_array.hpp b/include/tao/pq/result_traits_array.hpp
index 120e8cb..f4f0801 100644
--- a/include/tao/pq/result_traits_array.hpp
+++ b/include/tao/pq/result_traits_array.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_traits_optional.hpp b/include/tao/pq/result_traits_optional.hpp
index 7409e8a..cf74430 100644
--- a/include/tao/pq/result_traits_optional.hpp
+++ b/include/tao/pq/result_traits_optional.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_traits_pair.hpp b/include/tao/pq/result_traits_pair.hpp
index f5e24c3..8170b1a 100644
--- a/include/tao/pq/result_traits_pair.hpp
+++ b/include/tao/pq/result_traits_pair.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/result_traits_tuple.hpp b/include/tao/pq/result_traits_tuple.hpp
index eb86c66..87cde99 100644
--- a/include/tao/pq/result_traits_tuple.hpp
+++ b/include/tao/pq/result_traits_tuple.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/row.hpp b/include/tao/pq/row.hpp
index 7abd494..55b204b 100644
--- a/include/tao/pq/row.hpp
+++ b/include/tao/pq/row.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/table_field.hpp b/include/tao/pq/table_field.hpp
index 88efd5e..60dc10d 100644
--- a/include/tao/pq/table_field.hpp
+++ b/include/tao/pq/table_field.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/table_reader.hpp b/include/tao/pq/table_reader.hpp
index 5dbfc98..0f1a12b 100644
--- a/include/tao/pq/table_reader.hpp
+++ b/include/tao/pq/table_reader.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/table_row.hpp b/include/tao/pq/table_row.hpp
index f39b611..f623829 100644
--- a/include/tao/pq/table_row.hpp
+++ b/include/tao/pq/table_row.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/table_writer.hpp b/include/tao/pq/table_writer.hpp
index 360ea20..a74fba4 100644
--- a/include/tao/pq/table_writer.hpp
+++ b/include/tao/pq/table_writer.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/transaction.hpp b/include/tao/pq/transaction.hpp
index a8d2a91..6e6500b 100644
--- a/include/tao/pq/transaction.hpp
+++ b/include/tao/pq/transaction.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -32,6 +32,8 @@ namespace tao::pq
virtual void v_reset() noexcept = 0;
+ void rollback_in_dtor() noexcept;
+
public:
[[nodiscard]] auto subtransaction() -> std::shared_ptr< transaction >;
[[nodiscard]] auto pipeline() -> std::shared_ptr< pq::pipeline >;
diff --git a/include/tao/pq/transaction_base.hpp b/include/tao/pq/transaction_base.hpp
index 1015bfc..03eff20 100644
--- a/include/tao/pq/transaction_base.hpp
+++ b/include/tao/pq/transaction_base.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/include/tao/pq/transaction_status.hpp b/include/tao/pq/transaction_status.hpp
index dc5d765..0cd4b12 100644
--- a/include/tao/pq/transaction_status.hpp
+++ b/include/tao/pq/transaction_status.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2022-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2022-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,9 +6,12 @@
#define TAO_PQ_TRANSACTION_STATUS_HPP
#include
+#include
#include
+#include
+
namespace tao::pq
{
enum class transaction_status : std::uint8_t
@@ -20,6 +23,29 @@ namespace tao::pq
unknown = PQTRANS_UNKNOWN
};
+ [[nodiscard]] constexpr auto taopq_format_as( const transaction_status ts ) noexcept -> std::string_view
+ {
+ switch( ts ) {
+ case transaction_status::idle:
+ return "idle";
+
+ case transaction_status::in_transaction:
+ return "in_transaction";
+
+ case transaction_status::active:
+ return "active";
+
+ case transaction_status::error:
+ return "error";
+
+ case transaction_status::unknown:
+ return "unknown";
+
+ default:
+ return "";
+ }
+ }
+
} // namespace tao::pq
#endif
diff --git a/include/tao/pq/version.hpp b/include/tao/pq/version.hpp
index a4a20e5..eadb81d 100644
--- a/include/tao/pq/version.hpp
+++ b/include/tao/pq/version.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/connection.cpp b/src/lib/pq/connection.cpp
index 98946a0..55a7c52 100644
--- a/src/lib/pq/connection.cpp
+++ b/src/lib/pq/connection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -8,7 +8,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -137,17 +136,7 @@ namespace tao::pq
~top_level_transaction() override
{
if( m_connection && m_connection->attempt_rollback() ) {
- try {
- rollback();
- }
- // LCOV_EXCL_START
- catch( const std::exception& ) { // NOLINT(bugprone-empty-catch)
- // TAO_LOG( WARNING, "unable to rollback transaction, swallowing exception: " + std::string( e.what() ) );
- }
- catch( ... ) { // NOLINT(bugprone-empty-catch)
- // TAO_LOG( WARNING, "unable to rollback transaction, swallowing unknown exception" );
- }
- // LCOV_EXCL_STOP
+ rollback_in_dtor();
}
}
@@ -224,9 +213,34 @@ namespace tao::pq
const int lengths[],
const int formats[] )
{
- const auto result = m_prepared_statements.contains( statement ) ?
+ const auto is_prepared = m_prepared_statements.contains( statement );
+ if( m_log ) {
+ if( is_prepared ) {
+ if( m_log->connection.send_query_prepared ) {
+ m_log->connection.send_query_prepared( *this, statement, n_params, values, lengths, formats );
+ }
+ }
+ else {
+ if( m_log->connection.send_query ) {
+ m_log->connection.send_query( *this, statement, n_params, types, values, lengths, formats );
+ }
+ }
+ }
+ const auto result = is_prepared ?
PQsendQueryPrepared( m_pgconn.get(), statement, n_params, values, lengths, formats, 0 ) :
PQsendQueryParams( m_pgconn.get(), statement, n_params, types, values, lengths, formats, 0 );
+ if( m_log ) {
+ if( is_prepared ) {
+ if( m_log->connection.send_query_prepared.result ) {
+ m_log->connection.send_query_prepared.result( *this, result );
+ }
+ }
+ else {
+ if( m_log->connection.send_query.result ) {
+ m_log->connection.send_query.result( *this, result );
+ }
+ }
+ }
if( result == 0 ) {
throw pq::connection_error( error_message() ); // LCOV_EXCL_LINE
}
@@ -234,13 +248,24 @@ namespace tao::pq
void connection::wait( const bool wait_for_write, const std::chrono::steady_clock::time_point end )
{
+ if( m_log && m_log->connection.wait ) {
+ m_log->connection.wait( *this, wait_for_write, end );
+ }
while( true ) {
int timeout_ms = -1;
if( m_timeout ) {
timeout_ms = std::max( static_cast< int >( std::chrono::duration_cast< std::chrono::milliseconds >( end - std::chrono::steady_clock::now() ).count() ), 0 );
}
- switch( m_poll( socket(), wait_for_write, timeout_ms ) ) {
+ const auto so = socket();
+ if( m_log && m_log->connection.poll ) {
+ m_log->connection.poll( *this, so, wait_for_write, timeout_ms );
+ }
+ const auto status = m_poll( so, wait_for_write, timeout_ms );
+ if( m_log && m_log->connection.poll.result ) {
+ m_log->connection.poll.result( *this, so, status );
+ }
+ switch( status ) {
case poll::status::timeout:
m_pgconn.reset();
throw timeout_reached( "timeout reached" );
@@ -276,27 +301,21 @@ namespace tao::pq
auto connection::get_result( const std::chrono::steady_clock::time_point end ) -> std::unique_ptr< PGresult, decltype( &PQclear ) >
{
+ if( m_log && m_log->connection.get_result ) {
+ m_log->connection.get_result( *this, end );
+ }
bool wait_for_write = true;
while( is_busy() ) {
if( wait_for_write ) {
- switch( PQflush( m_pgconn.get() ) ) {
- case 0:
- wait_for_write = false;
- break;
-
- // LCOV_EXCL_START
- case 1:
- break;
-
- default:
- throw pq::error( std::format( "PQflush() failed: {}", error_message() ) );
- // LCOV_EXCL_STOP
- }
+ wait_for_write = flush();
}
connection::wait( wait_for_write, end );
}
std::unique_ptr< PGresult, decltype( &PQclear ) > result( PQgetResult( m_pgconn.get() ), &PQclear );
+ if( m_log && m_log->connection.get_result.result ) {
+ m_log->connection.get_result.result( *this, result.get() );
+ }
handle_notifications();
return result;
}
@@ -409,10 +428,10 @@ namespace tao::pq
}
}
- connection::connection( const private_key /*unused*/, const std::string& connection_info, std::function< poll::callback > poll_cb )
+ connection::connection( const private_key /*unused*/, const std::string& connection_info )
: m_pgconn( PQconnectdb( connection_info.c_str() ), &PQfinish ),
m_current_transaction( nullptr ),
- m_poll( std::move( poll_cb ) )
+ m_poll( internal::poll )
{
if( !is_open() ) {
// note that we can not access the sqlstate after PQconnectdb(),
@@ -425,9 +444,9 @@ namespace tao::pq
}
}
- auto connection::create( const std::string& connection_info, std::function< poll::callback > poll_cb ) -> std::shared_ptr< connection >
+ auto connection::create( const std::string& connection_info ) -> std::shared_ptr< connection >
{
- return std::make_shared< connection >( private_key(), connection_info, std::move( poll_cb ) );
+ return std::make_shared< connection >( private_key(), connection_info );
}
auto connection::error_message() const -> const char*
@@ -435,26 +454,6 @@ namespace tao::pq
return PQerrorMessage( m_pgconn.get() );
}
- auto connection::poll_callback() const noexcept -> const std::function< poll::callback >&
- {
- return m_poll;
- }
-
- void connection::set_poll_callback( std::function< poll::callback > poll_cb ) noexcept
- {
- m_poll = std::move( poll_cb );
- }
-
- void connection::reset_poll_callback()
- {
- m_poll = internal::poll;
- }
-
- auto connection::notification_handler() const -> std::function< void( const notification& ) >
- {
- return m_notification_handler;
- }
-
auto connection::notification_handler( const std::string_view channel ) const -> std::function< void( const char* payload ) >
{
const auto it = m_notification_handlers.find( channel );
@@ -464,24 +463,17 @@ namespace tao::pq
return {};
}
- void connection::set_notification_handler( const std::function< void( const notification& ) >& handler )
- {
- m_notification_handler = handler;
- }
-
void connection::set_notification_handler( const std::string_view channel, const std::function< void( const char* payload ) >& handler )
{
m_notification_handlers[ std::string( channel ) ] = handler;
}
- void connection::reset_notification_handler() noexcept
- {
- m_notification_handler = nullptr;
- }
-
void connection::reset_notification_handler( const std::string_view channel ) noexcept
{
- m_notification_handlers.erase( std::string( channel ) );
+ const auto it = m_notification_handlers.find( channel );
+ if( it != m_notification_handlers.end() ) {
+ m_notification_handlers.erase( it );
+ }
}
auto connection::status() const noexcept -> connection_status
@@ -501,28 +493,85 @@ namespace tao::pq
void connection::enter_pipeline_mode()
{
- if( PQenterPipelineMode( m_pgconn.get() ) == 0 ) {
+ const auto result = PQenterPipelineMode( m_pgconn.get() );
+ if( m_log && m_log->connection.enter_pipeline_mode.result ) {
+ m_log->connection.enter_pipeline_mode.result( *this, result );
+ }
+ if( result == 0 ) {
throw pq::connection_error( "unable to enter pipeline mode" );
}
}
void connection::exit_pipeline_mode()
{
- if( PQexitPipelineMode( m_pgconn.get() ) == 0 ) {
+ if( m_log && m_log->connection.exit_pipeline_mode ) {
+ m_log->connection.exit_pipeline_mode( *this );
+ }
+ const auto result = PQexitPipelineMode( m_pgconn.get() );
+ if( m_log && m_log->connection.exit_pipeline_mode.result ) {
+ m_log->connection.exit_pipeline_mode.result( *this, result );
+ }
+ if( result == 0 ) {
throw pq::connection_error( error_message() );
}
}
void connection::pipeline_sync()
{
- if( PQpipelineSync( m_pgconn.get() ) == 0 ) {
+ if( m_log && m_log->connection.pipeline_sync ) {
+ m_log->connection.pipeline_sync( *this );
+ }
+ const auto result = PQpipelineSync( m_pgconn.get() );
+ if( m_log && m_log->connection.pipeline_sync.result ) {
+ m_log->connection.pipeline_sync.result( *this, result );
+ }
+ if( result == 0 ) {
throw pq::connection_error( "unable to sync pipeline" );
}
}
auto connection::is_busy() const noexcept -> bool
{
- return PQisBusy( m_pgconn.get() ) != 0;
+ const auto result = PQisBusy( m_pgconn.get() );
+ if( m_log && m_log->connection.is_busy.result ) {
+ m_log->connection.is_busy.result( *this, result );
+ }
+ return result != 0;
+ }
+
+ auto connection::flush() -> bool
+ {
+ if( m_log && m_log->connection.flush ) {
+ m_log->connection.flush( *this );
+ }
+ const auto result = PQflush( m_pgconn.get() );
+ if( m_log && m_log->connection.flush.result ) {
+ m_log->connection.flush.result( *this, result );
+ }
+ switch( result ) {
+ case 0:
+ return false;
+
+ case 1:
+ return true;
+
+ default:
+ throw pq::error( std::format( "PQflush() failed: {}", error_message() ) );
+ }
+ }
+
+ void connection::consume_input()
+ {
+ if( m_log && m_log->connection.consume_input ) {
+ m_log->connection.consume_input( *this );
+ }
+ const auto result = PQconsumeInput( m_pgconn.get() );
+ if( m_log && m_log->connection.consume_input.result ) {
+ m_log->connection.consume_input.result( *this, result );
+ }
+ if( result == 0 ) {
+ throw pq::connection_error( error_message() );
+ }
}
auto connection::direct() -> std::shared_ptr< pq::transaction >
@@ -632,9 +681,7 @@ namespace tao::pq
void connection::get_notifications()
{
- if( PQconsumeInput( m_pgconn.get() ) == 0 ) {
- throw pq::connection_error( error_message() );
- }
+ consume_input();
handle_notifications();
}
@@ -647,16 +694,6 @@ namespace tao::pq
return fd;
}
- void connection::set_timeout( const std::chrono::milliseconds timeout )
- {
- m_timeout = timeout;
- }
-
- void connection::reset_timeout() noexcept
- {
- m_timeout = std::nullopt;
- }
-
auto connection::password( const internal::zsv passwd, const internal::zsv user, const internal::zsv algorithm ) -> std::string
{
const std::unique_ptr< char, decltype( &PQfreemem ) > buffer( PQencryptPasswordConn( m_pgconn.get(), passwd, user, algorithm ), &PQfreemem );
diff --git a/src/lib/pq/connection_pool.cpp b/src/lib/pq/connection_pool.cpp
index 2bb8939..f9486ea 100644
--- a/src/lib/pq/connection_pool.cpp
+++ b/src/lib/pq/connection_pool.cpp
@@ -1,60 +1,30 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
#include
-#include
-#include
#include
-#include
#include
-#include
#include
#include
-#include
namespace tao::pq
{
auto connection_pool::v_create() const -> std::unique_ptr< pq::connection >
{
- return std::make_unique< pq::connection >( pq::connection::private_key(), m_connection_info, m_poll );
+ return std::make_unique< pq::connection >( pq::connection::private_key(), m_connection_info );
}
- connection_pool::connection_pool( const private_key /*unused*/, const std::string_view connection_info, std::function< poll::callback > poll_cb )
+ connection_pool::connection_pool( const private_key /*unused*/, const std::string_view connection_info )
: m_connection_info( connection_info ),
- m_poll( std::move( poll_cb ) )
+ m_poll( internal::poll )
{}
- void connection_pool::set_timeout( const std::chrono::milliseconds timeout ) noexcept
- {
- m_timeout = timeout;
- }
-
- void connection_pool::reset_timeout() noexcept
- {
- m_timeout = std::nullopt;
- }
-
- auto connection_pool::poll_callback() const noexcept -> const std::function< poll::callback >&
- {
- return m_poll;
- }
-
- void connection_pool::set_poll_callback( std::function< poll::callback > poll_cb ) noexcept
- {
- m_poll = std::move( poll_cb );
- }
-
- void connection_pool::reset_poll_callback()
- {
- m_poll = internal::poll;
- }
-
auto connection_pool::connection() -> std::shared_ptr< pq::connection >
{
- auto result = get();
+ auto result = internal::pool< pq::connection >::get();
if( m_timeout ) {
result->set_timeout( *m_timeout );
}
diff --git a/src/lib/pq/exception.cpp b/src/lib/pq/exception.cpp
index 52f96be..04ca9e5 100644
--- a/src/lib/pq/exception.cpp
+++ b/src/lib/pq/exception.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/field.cpp b/src/lib/pq/field.cpp
index 4ade4d3..3cf6c53 100644
--- a/src/lib/pq/field.cpp
+++ b/src/lib/pq/field.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/internal/demangle.cpp b/src/lib/pq/internal/demangle.cpp
index 6709eb3..01507b8 100644
--- a/src/lib/pq/internal/demangle.cpp
+++ b/src/lib/pq/internal/demangle.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/internal/poll.cpp b/src/lib/pq/internal/poll.cpp
index 63689e8..7740fdf 100644
--- a/src/lib/pq/internal/poll.cpp
+++ b/src/lib/pq/internal/poll.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/internal/strtox.cpp b/src/lib/pq/internal/strtox.cpp
index b16f870..626b98f 100644
--- a/src/lib/pq/internal/strtox.cpp
+++ b/src/lib/pq/internal/strtox.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/large_object.cpp b/src/lib/pq/large_object.cpp
index 348195b..80aee01 100644
--- a/src/lib/pq/large_object.cpp
+++ b/src/lib/pq/large_object.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/parameter_traits.cpp b/src/lib/pq/parameter_traits.cpp
index 9315338..5001793 100644
--- a/src/lib/pq/parameter_traits.cpp
+++ b/src/lib/pq/parameter_traits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/pipeline.cpp b/src/lib/pq/pipeline.cpp
index 896936c..2a1f170 100644
--- a/src/lib/pq/pipeline.cpp
+++ b/src/lib/pq/pipeline.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -10,7 +10,7 @@
namespace tao::pq
{
- pipeline::pipeline( const std::shared_ptr< pq::connection >& connection )
+ pipeline::pipeline( const pipeline::private_key /*unused*/, const std::shared_ptr< pq::connection >& connection )
: transaction_base( connection ),
m_previous( current_transaction()->shared_from_this() )
{
diff --git a/src/lib/pq/result.cpp b/src/lib/pq/result.cpp
index dc44fe7..1a24ea3 100644
--- a/src/lib/pq/result.cpp
+++ b/src/lib/pq/result.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/result_traits.cpp b/src/lib/pq/result_traits.cpp
index 5892384..198605c 100644
--- a/src/lib/pq/result_traits.cpp
+++ b/src/lib/pq/result_traits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/result_traits_array.cpp b/src/lib/pq/result_traits_array.cpp
index bc7db40..cc51297 100644
--- a/src/lib/pq/result_traits_array.cpp
+++ b/src/lib/pq/result_traits_array.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/row.cpp b/src/lib/pq/row.cpp
index 39432fe..7907fe7 100644
--- a/src/lib/pq/row.cpp
+++ b/src/lib/pq/row.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/table_field.cpp b/src/lib/pq/table_field.cpp
index cf53cff..5f5c584 100644
--- a/src/lib/pq/table_field.cpp
+++ b/src/lib/pq/table_field.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/table_reader.cpp b/src/lib/pq/table_reader.cpp
index c4647ae..4fd2797 100644
--- a/src/lib/pq/table_reader.cpp
+++ b/src/lib/pq/table_reader.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/table_row.cpp b/src/lib/pq/table_row.cpp
index 14b84db..5e4e5df 100644
--- a/src/lib/pq/table_row.cpp
+++ b/src/lib/pq/table_row.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/table_writer.cpp b/src/lib/pq/table_writer.cpp
index 9a2b976..6c0f6dc 100644
--- a/src/lib/pq/table_writer.cpp
+++ b/src/lib/pq/table_writer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/lib/pq/transaction.cpp b/src/lib/pq/transaction.cpp
index b774802..e171dd9 100644
--- a/src/lib/pq/transaction.cpp
+++ b/src/lib/pq/transaction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
@@ -6,7 +6,6 @@
#include
#include
-#include
#include
#include
#include
@@ -33,17 +32,7 @@ namespace tao::pq
~top_level_subtransaction() override
{
if( m_connection && m_connection->attempt_rollback() ) {
- try {
- rollback();
- }
- // LCOV_EXCL_START
- catch( const std::exception& ) { // NOLINT(bugprone-empty-catch)
- // TAO_LOG( WARNING, "unable to rollback transaction, swallowing exception: " + std::string( e.what() ) );
- }
- catch( ... ) { // NOLINT(bugprone-empty-catch)
- // TAO_LOG( WARNING, "unable to rollback transaction, swallowing unknown exception" );
- }
- // LCOV_EXCL_STOP
+ rollback_in_dtor();
}
}
@@ -79,14 +68,7 @@ namespace tao::pq
~nested_subtransaction() override
{
if( m_connection && m_connection->attempt_rollback() ) {
- try {
- rollback();
- }
- // LCOV_EXCL_START
- catch( ... ) { // NOLINT(bugprone-empty-catch)
- // TODO: How to handle this case properly?
- }
- // LCOV_EXCL_STOP
+ rollback_in_dtor();
}
}
@@ -125,13 +107,13 @@ namespace tao::pq
auto transaction::pipeline() -> std::shared_ptr< pq::pipeline >
{
check_current_transaction();
- return std::make_shared< pq::pipeline >( m_connection );
+ return std::make_shared< pq::pipeline >( pq::pipeline::private_key(), m_connection );
}
void transaction::commit()
{
- check_current_transaction();
try {
+ check_current_transaction();
v_commit();
}
// LCOV_EXCL_START
@@ -145,8 +127,8 @@ namespace tao::pq
void transaction::rollback()
{
- check_current_transaction();
try {
+ check_current_transaction();
v_rollback();
}
// LCOV_EXCL_START
@@ -158,4 +140,20 @@ namespace tao::pq
v_reset();
}
+ void transaction::rollback_in_dtor() noexcept
+ {
+ try {
+ check_current_transaction();
+ v_rollback();
+ }
+ // LCOV_EXCL_START
+ catch( ... ) {
+ if( m_connection->m_log && m_connection->m_log->transaction.destructor_rollback_failed ) {
+ m_connection->m_log->transaction.destructor_rollback_failed( *this );
+ }
+ }
+ // LCOV_EXCL_STOP
+ v_reset();
+ }
+
} // namespace tao::pq
diff --git a/src/lib/pq/transaction_base.cpp b/src/lib/pq/transaction_base.cpp
index e187507..37cd7e9 100644
--- a/src/lib/pq/transaction_base.cpp
+++ b/src/lib/pq/transaction_base.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/compare.hpp b/src/test/compare.hpp
index 99db069..79b1210 100644
--- a/src/test/compare.hpp
+++ b/src/test/compare.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/getenv.hpp b/src/test/getenv.hpp
index 42f0dc0..bc730f8 100644
--- a/src/test/getenv.hpp
+++ b/src/test/getenv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/macros.hpp b/src/test/macros.hpp
index a1d37d3..6a71d4e 100644
--- a/src/test/macros.hpp
+++ b/src/test/macros.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/aggregate.cpp b/src/test/pq/aggregate.cpp
index b52f135..7716587 100644
--- a/src/test/pq/aggregate.cpp
+++ b/src/test/pq/aggregate.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/array.cpp b/src/test/pq/array.cpp
index f5a3acb..87247a0 100644
--- a/src/test/pq/array.cpp
+++ b/src/test/pq/array.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/basic_datatypes.cpp b/src/test/pq/basic_datatypes.cpp
index 4bd7948..1398d8a 100644
--- a/src/test/pq/basic_datatypes.cpp
+++ b/src/test/pq/basic_datatypes.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/chunk_mode.cpp b/src/test/pq/chunk_mode.cpp
index 67ae6a1..eb5dec6 100644
--- a/src/test/pq/chunk_mode.cpp
+++ b/src/test/pq/chunk_mode.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/connection.cpp b/src/test/pq/connection.cpp
index 104b84c..592f509 100644
--- a/src/test/pq/connection.cpp
+++ b/src/test/pq/connection.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/connection_pool.cpp b/src/test/pq/connection_pool.cpp
index 66c332a..045afc8 100644
--- a/src/test/pq/connection_pool.cpp
+++ b/src/test/pq/connection_pool.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/example.cpp b/src/test/pq/example.cpp
index f9bc488..c2849ac 100644
--- a/src/test/pq/example.cpp
+++ b/src/test/pq/example.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/exception.cpp b/src/test/pq/exception.cpp
index 691a3d0..3407a0f 100644
--- a/src/test/pq/exception.cpp
+++ b/src/test/pq/exception.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/getenv.cpp b/src/test/pq/getenv.cpp
index e900ea0..d70a8a6 100644
--- a/src/test/pq/getenv.cpp
+++ b/src/test/pq/getenv.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/large_object.cpp b/src/test/pq/large_object.cpp
index 988dcf1..c53eacf 100644
--- a/src/test/pq/large_object.cpp
+++ b/src/test/pq/large_object.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/log.cpp b/src/test/pq/log.cpp
new file mode 100644
index 0000000..6dacd0b
--- /dev/null
+++ b/src/test/pq/log.cpp
@@ -0,0 +1,151 @@
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
+
+#include "../getenv.hpp"
+#include "../macros.hpp"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace
+{
+ [[nodiscard]] auto to_millis( std::chrono::steady_clock::time_point end ) noexcept
+ {
+ return std::chrono::duration_cast< std::chrono::milliseconds >( end - std::chrono::steady_clock::now() ).count();
+ }
+
+ void run()
+ {
+ // overwrite the default with an environment variable if needed
+ const auto connection_string = tao::pq::internal::getenv( "TAOPQ_TEST_DATABASE", "dbname=template1" );
+
+ // open a connection to the database
+ const auto conn = tao::pq::connection::create( connection_string );
+
+ // attach a log receiver
+ const auto log = std::make_shared< tao::pq::log >();
+
+ log->connection.send_query = []( tao::pq::connection& c, const char* s, int n, const Oid types[], const char* const values[], const int lengths[], const int formats[] ) {
+ std::ignore = types;
+ std::ignore = lengths;
+ std::ignore = formats;
+ std::cout << std::format( "send_query(connection={}, statement={}, n_params={})", static_cast< const void* >( &c ), s, n ) << '\n';
+ for( int i = 0; i != n; ++i ) {
+ std::cout << std::format( " parameter[{}]={}", i, values[ i ] ) << '\n';
+ }
+ };
+ log->connection.send_query.result = []( tao::pq::connection& c, int r ) {
+ std::cout << std::format( "send_query(connection={}) -> {}", static_cast< const void* >( &c ), r ) << '\n';
+ };
+ log->connection.send_query_prepared = []( tao::pq::connection& c, const char* s, int n, const char* const values[], const int lengths[], const int formats[] ) {
+ std::ignore = lengths;
+ std::ignore = formats;
+ std::cout << std::format( "send_query_prepared(connection={}, statement={}, n_params={})", static_cast< const void* >( &c ), s, n ) << '\n';
+ for( int i = 0; i != n; ++i ) {
+ std::cout << std::format( " parameter[{}]={}", i, values[ i ] ) << '\n';
+ }
+ };
+ log->connection.send_query_prepared.result = []( tao::pq::connection& c, int r ) {
+ std::cout << std::format( "send_query_prepared(connection={}) -> {}", static_cast< const void* >( &c ), r ) << '\n';
+ };
+ log->connection.wait = []( tao::pq::connection& c, bool w, std::chrono::steady_clock::time_point e ) {
+ std::cout << std::format( "wait(connection={}, wait_for_write={}, timeout={} ms)", static_cast< const void* >( &c ), w, to_millis( e ) ) << '\n';
+ };
+ log->connection.poll = []( tao::pq::connection& c, int s, bool w, int t ) {
+ std::cout << std::format( "poll(connection={},socket={}, wait_for_write={}, timeout={} ms)", static_cast< const void* >( &c ), s, w, t ) << '\n';
+ };
+ log->connection.poll.result = []( tao::pq::connection& c, int s, tao::pq::poll::status r ) {
+ std::cout << std::format( "poll(connection={},socket={}) -> {}", static_cast< const void* >( &c ), s, r ) << '\n';
+ };
+ log->connection.is_busy.result = []( const tao::pq::connection& c, int r ) {
+ std::cout << std::format( "is_busy(connection={}) -> {}", static_cast< const void* >( &c ), r ) << '\n';
+ };
+ log->connection.consume_input = []( tao::pq::connection& c ) {
+ std::cout << std::format( "consume_input(connection={})", static_cast< const void* >( &c ) ) << '\n';
+ };
+ log->connection.consume_input.result = []( tao::pq::connection& c, int r ) {
+ std::cout << std::format( "consume_input(connection={}) -> {}", static_cast< const void* >( &c ), r ) << '\n';
+ };
+ log->connection.flush = []( tao::pq::connection& c ) {
+ std::cout << std::format( "flush(connection={})", static_cast< const void* >( &c ) ) << '\n';
+ };
+ log->connection.flush.result = []( tao::pq::connection& c, int r ) {
+ std::cout << std::format( "flush(connection={}) -> {}", static_cast< const void* >( &c ), r ) << '\n';
+ };
+ log->connection.get_result = []( tao::pq::connection& c, std::chrono::steady_clock::time_point e ) {
+ std::cout << std::format( "get_result(connection={}, timeout={} ms)", static_cast< const void* >( &c ), to_millis( e ) ) << '\n';
+ };
+ log->connection.get_result.result = []( tao::pq::connection& c, PGresult* r ) {
+ std::cout << std::format( "get_result(connection={}) -> {}", static_cast< const void* >( &c ), static_cast< const void* >( r ) ) << '\n';
+ if( r != nullptr ) {
+ const auto st = PQresultStatus( r );
+ std::cout << std::format( " status={}", PQresStatus( st ) ) << '\n';
+ const auto cols = PQnfields( r );
+ if( cols != 0 ) {
+ std::cout << std::format( " columns={}, rows={}", cols, PQntuples( r ) ) << '\n';
+ }
+ else {
+ const char* str = PQcmdTuples( r );
+ if( str[ 0 ] != '\0' ) {
+ std::cout << std::format( " rows_affected={}", str ) << '\n';
+ }
+ }
+ }
+ };
+
+ conn->set_log_handler( log );
+
+ // execute statements
+ conn->execute( "DROP TABLE IF EXISTS tao_example" );
+ conn->execute( "CREATE TABLE tao_example ( name TEXT PRIMARY KEY, age INTEGER NOT NULL )" );
+
+ // prepare statements
+ conn->prepare( "insert_user", "INSERT INTO tao_example ( name, age ) VALUES ( $1, $2 )" );
+
+ {
+ // begin transaction
+ const auto tr = conn->transaction();
+
+ // execute previously prepared statements
+ tr->execute( "insert_user", "Daniel", 42 );
+ tr->execute( "insert_user", "Tom", 41 );
+ tr->execute( "insert_user", "Jerry", 29 );
+
+ // commit transaction
+ tr->commit();
+ }
+
+ // query data
+ const auto users = conn->execute( "SELECT name, age FROM tao_example WHERE age >= $1", 40 );
+
+ // iterate and convert results
+ for( const auto& row : users ) {
+ std::cout << row[ "name" ].as< std::string >() << " is "
+ << row[ "age" ].as< unsigned >() << " years old.\n";
+ }
+ }
+
+} // namespace
+
+auto main() -> int
+{
+ try {
+ run();
+ }
+ // LCOV_EXCL_START
+ catch( const std::exception& e ) {
+ std::cerr << "exception: " << e.what() << '\n';
+ throw;
+ }
+ catch( ... ) {
+ std::cerr << "unknown exception\n";
+ throw;
+ }
+ // LCOV_EXCL_STOP
+}
diff --git a/src/test/pq/notifications.cpp b/src/test/pq/notifications.cpp
index a6ec036..d9c002c 100644
--- a/src/test/pq/notifications.cpp
+++ b/src/test/pq/notifications.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/parameter.cpp b/src/test/pq/parameter.cpp
index 111c49c..38c8d0a 100644
--- a/src/test/pq/parameter.cpp
+++ b/src/test/pq/parameter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/parameter_type.cpp b/src/test/pq/parameter_type.cpp
index 0ce3e60..4a0d9b5 100644
--- a/src/test/pq/parameter_type.cpp
+++ b/src/test/pq/parameter_type.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/password.cpp b/src/test/pq/password.cpp
index 4a46095..75a5b1a 100644
--- a/src/test/pq/password.cpp
+++ b/src/test/pq/password.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/pipeline_mode.cpp b/src/test/pq/pipeline_mode.cpp
index ccca866..31e5465 100644
--- a/src/test/pq/pipeline_mode.cpp
+++ b/src/test/pq/pipeline_mode.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2024-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/resize_uninitialized.cpp b/src/test/pq/resize_uninitialized.cpp
index 7e51656..229f161 100644
--- a/src/test/pq/resize_uninitialized.cpp
+++ b/src/test/pq/resize_uninitialized.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/result.cpp b/src/test/pq/result.cpp
index 01dce31..09e72ca 100644
--- a/src/test/pq/result.cpp
+++ b/src/test/pq/result.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/result_type.cpp b/src/test/pq/result_type.cpp
index 20fd9c1..01f268b 100644
--- a/src/test/pq/result_type.cpp
+++ b/src/test/pq/result_type.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2023-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2023-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/row.cpp b/src/test/pq/row.cpp
index 3a73572..23af8d4 100644
--- a/src/test/pq/row.cpp
+++ b/src/test/pq/row.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/single_row_mode.cpp b/src/test/pq/single_row_mode.cpp
index 8e806b5..7d58b50 100644
--- a/src/test/pq/single_row_mode.cpp
+++ b/src/test/pq/single_row_mode.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/strtox.cpp b/src/test/pq/strtox.cpp
index 39a9d2a..b9c0b31 100644
--- a/src/test/pq/strtox.cpp
+++ b/src/test/pq/strtox.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/table_reader.cpp b/src/test/pq/table_reader.cpp
index bcfa5c7..efb91bd 100644
--- a/src/test/pq/table_reader.cpp
+++ b/src/test/pq/table_reader.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2021-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/table_writer.cpp b/src/test/pq/table_writer.cpp
index de95574..7f77256 100644
--- a/src/test/pq/table_writer.cpp
+++ b/src/test/pq/table_writer.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/traits.cpp b/src/test/pq/traits.cpp
index f3e181c..ec05d1e 100644
--- a/src/test/pq/traits.cpp
+++ b/src/test/pq/traits.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2020-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2020-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/test/pq/transaction.cpp b/src/test/pq/transaction.cpp
index 2706e01..23b3e82 100644
--- a/src/test/pq/transaction.cpp
+++ b/src/test/pq/transaction.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2024 Daniel Frey and Dr. Colin Hirsch
+// Copyright (c) 2016-2025 Daniel Frey and Dr. Colin Hirsch
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)