Result/row iterator rewrite
(Updated 2025-05-26)
The whole way you navigate a result
object changes radically in libpqxx 8.
It's still mostly compatible, but depending on how you access fields, you may
need to adapt your code.
(Yes, I am profoundly sorry for this. The main pain point is in complying with the C++ standard. Read on.)
What's changed?
A great many things:
- You now only use
row
andfield
in rare cases where you need to keep aresult
object alive in memory without owning a reference to it. These classes behave like reference-counted smart pointers to the actual data. - Instead, you get
row_ref
andfield_ref
. These behave like plain pointers, and to theresult
object — not to the underlying data. So you must ensure that theresult
stays valid, unchanged, and unmoved in memory. - Iterators, too, now behave more like pointers. Do not assign, destroy, or
move a
result
while iterating it. (But you probably weren't doing that anyway, were you?) - A result iterator points at a row. In the old API you could use the array
index operator on the iterator to get at a field in that row. This was
nice in that it made the result feel more like a 2-dimensional C array.
Unfortunately it always violated the C++ standard. In the new API, the
index operator gets you not to a field but to another row:
iter[n] == *(iter + n)
. - The
result
androw
iterators now satisfy therandom_access_iterator
concept. Believe it or not, it was a bug report about this that started the whole undertaking. - Working with these classes is going to be less work for the computer, so probably faster.
- The new
field_ref
class doesn't fully implement the API thatfield
supports. Let's see what's actually needed in practice. - Gone are the deep, confusing inheritance hierarchies. A reverse iterator inherits from its forward counterpart, but that's it.
What do I need to change in my code?
Hopefully, not too much in practice. But potentially...
- First thing you're likely to run into is the change in getting to a field
from an iterator pointing at a row:
it[col]
no longer works. But a result iterator still acts like a pointer to a row, so try(*it)[col]
, or useit->at(col)
. - The lifetime rules are stricter. So run your code through all the
verification tools you can, and have a good critical look at how you
navigate libpqxx
result
objects. The major compilers have features called "analyzers": compile your project with these enabled, and run it. See whether the binary reports any runtime errors. - Of course some features that you use may have become deprecated. Run your compiler with flags to warn about this, and to treat warnings as errors. The deprecation notices will generally give you some indication of what to do.
- If you were using deprecated features that are now gone, try doing the same thing with an older version of libpqxx.
- You may need to work around some
field
features thatfield_ref
does not have. These are generally pretty simple. You can construct afield
from thefield_ref
, or if the missing feature is simple enough, write your own code based on the old function. Or, ask me to implement the feature.