Skip to content

libpqxx 7.9.0: important fixes and new features

Latest
Compare
Choose a tag to compare
@jtv jtv released this 18 Feb 20:29
· 85 commits to master since this release

This is a pretty big release. As things stand, this looks to be the last release which supports C++17. The plan is to move on to libpqxx 8.0 next, which will require C++20 as a baseline.

Here's what's changed.

Assertion failure while streaming data

There was a bug that triggered an assertion failure when a row in a streaming query result ended in a null string.

The assertions in the code were just a little too strict. It amazes me that this took to long to surface. It has now been fixed.

New type aliases for binary data

We've been using std::basic_string<std::byte> and std::basic_string_view<std::byte> to represent binary data. But @tambry noted that compilers aren't actually required to support this! Worse, libc++18 had already marked it as deprecated.

The authors seem to have changed their minds about that, but Raul contributed a fix anyway. After all the problem may well pop up again.

And so, from libpqxx 7.9.0 onwards, to represent binary data coming from or going into the database, use the new type aliases pqxx::bytes (for a std::string of std::byte) and pqxx::bytes_view (for a std::string_view of std::byte).

If your environment supports the old types, these are just aliases for those, and nothing changes. But if it doesn't, then the aliases will refer to slightly different types that work around the problem. (The alternative definitions use a custom char_traits. The fine print in the C++ standard said that you need this, and that the library is not obligated to offer a generic definition of these traits for std::byte.)

Consistent library naming in CMake

Building CMake projects using libpqxx became a little easier. Thanks to @alexv-ds, you can now just use shared_link_libraries([...] libpqxx::pqxx).

The library name used to vary depending on whether you use find_package() or add_subdirectory() to add libpqxx to your project. Now it's just always libpqxx::pqxx.

Exception-related link errors

If you had a libpqxx built in C++17, and linked it into a project built using C++20, or vice versa, you'd get a lot of link errors about missing classes. They were related to exceptions, such as std::runtime_error.

Linking code built in one C++ version to code built in another is categorically dangerous. Please don't do it. There is no guarantee that it will work. Sadly though all package managers deal with this issue by sticking their heads in the sand.

It turns out that in practice the linking often worked, and various pre-built packaged versions of libpqxx shipped just one binary for all C++ versions. If you built your project in a different C++ version than was used to build libpqxx, two recent changes conspired to break your build:

  1. For C++20 and up, I added source_location information to exceptions. If your compiler didn't support that, you just didn't get it — but it affected how an exception object was laid out in memory.
  2. Instead of generating a header listing which C++ features were available when you built libpqxx, I just detected features at compile time. But that breaks down when the language changes between inbetween the libpqxx build and your own project's build!

The new release works around this using all-new code to generate a configuration header at build configuration time. The enw code is much more regular, and easier for me to extend and maintain. This should make it easier to add support for most new C++ features in the future. I also believe the build became just slightly faster.

Conversion from std::string_view to SQL string

Converting a std::string_view to an SQL string never actually worked. It wasn't a priority in part because pqxx::zview is likely to be much faster.

Still, this was an annoying irregularity and it has been fixed. You can now pass a std::vector<std::string_view> to a prepared statement, for example.

Expect future libpqxx versions to be a bit more liberal in allowing conversions of various view types. Which does mean that...

  • sometimes the conversion may do a bit of extra work under the bonnet and it will be up to you to avoid this when performance is critical; and
  • it will be your responsibility to ensure that the data underlying a view or span is still valid whenever you make use of its SQL conversion.

Parameterised versions of query() etc.

It has long bothered me that libpqxx has separate functions for executing a query, and for executing a query with parameters.

There are good reasons why you can't just pass any additional arguments to these functions and have them all converted into SQL parameters. It makes it easier to write code that doesn't mean what you might expect. It also complicates overloading, especially in a future where every query execution function also takes an implicit std::source_location to improve error reporting.

As of libpqxx 7.9.0 however you can now pass a pqxx::params when executing a query, and it will be unambiguously clear that it should be interpreted as a bundle of SQL parameters.

Streaming queries and C++20 pipelines

A streaming query can now act as a std::input_iterator. This removes an obstacle to building C++20 statement pipelines using streaming queries.

Clearer documentation for defining your own data types

The updated documentation makes it a bit easier to see how to go about defining SQL conversions for your own data types, so you can convert them between their SQL and C++ representations.

These conversions are particularly important when you want to pass them to parameterised or prepared statements.

Support for std::span as SQL arrays

This is still somewhat experimental, but libpqxx 8.0 will rely a lot more on std::span.

Thanks to @alexolog and @fallenworld1 you should now be able to pass any std::span (over a supported type of course) as a parameter to a prepared or parameterised statement, and it will automatically convert into an SQL array.

Support for PQfsize() and PQfmod()

You can now query a column's storage size and type modifier. This code was contributed by @TeamPlatform1.

These are only useful for low-level coders. Touch only if you know what you're doing.

Thanks

As you can see, various code changes have been contributed directly by libpqxx users. Others were requested in bug tickets. It would be a bit redundant for me to name them all here, but I am grateful: after all a good bug report is not so much a "customer complaint" as it is real-world feedback on what can be improved.

Further thanks go out to everyone who contributed, and not to forget — the tireless @tt4g and @KayEss who have stepped in to help time and again when people ran into problems.