libpqxx
The C++ client library for PostgreSQL
stream_from.hxx
Go to the documentation of this file.
1 /* Definition of the pqxx::stream_from class.
2  *
3  * pqxx::stream_from enables optimized batch reads from a database table.
4  *
5  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
6  *
7  * Copyright (c) 2000-2026, Jeroen T. Vermeulen.
8  *
9  * See COPYING for copyright license. If you did not receive a file called
10  * COPYING with this source code, please notify the distributor of this
11  * mistake, or contact the author.
12  */
13 #ifndef PQXX_STREAM_FROM_HXX
14 #define PQXX_STREAM_FROM_HXX
15 
16 #if !defined(PQXX_HEADER_PRE)
17 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18 #endif
19 
20 #include <cassert>
21 #include <format>
22 #include <variant>
23 
24 #include "pqxx/connection.hxx"
25 #include "pqxx/encoding_group.hxx"
26 #include "pqxx/except.hxx"
28 #include "pqxx/separated_list.hxx"
30 
31 
32 namespace pqxx
33 {
34 class transaction_base;
35 
36 
38 
42 
45 
46 
48 
79 {
80 public:
81  using raw_line =
82  std::pair<std::unique_ptr<char[], void (*)(void const *)>, std::size_t>;
83 
85 
94  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
95  query(transaction_base &tx, std::string_view q)
96  {
98  return {tx, from_query, q};
100  }
101 
112 
114 
130  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
131  raw_table(
132  transaction_base &tx, std::string_view path,
133  std::string_view columns = ""sv);
134 
136 
138  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
139  table(
140  transaction_base &tx, table_path path,
141  std::initializer_list<std::string_view> columns = {});
143 
145 
147  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
148  transaction_base &, from_query_t, std::string_view query);
149 
151 
153  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
154  transaction_base &, from_table_t, std::string_view table);
155 
157 
159  template<typename Iter>
160  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
161  transaction_base &, from_table_t, std::string_view table,
162  Iter columns_begin, Iter columns_end);
163 
165 
167  template<typename Columns>
168  [[deprecated("Use transaction_base::stream() instead.")]] stream_from(
169  transaction_base &tx, from_table_t, std::string_view table,
170  Columns const &columns);
171 
174  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
175  transaction_base &tx, std::string_view table) :
176  stream_from{tx, from_table, table}
177  {}
179 
181  template<typename Columns>
182  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
183  transaction_base &tx, std::string_view table, Columns const &columns) :
184  stream_from{tx, from_table, table, columns}
185  {}
186 
188  template<typename Iter>
189  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
190  transaction_base &, std::string_view table, Iter columns_begin,
191  Iter columns_end);
192 
193  stream_from(stream_from const &) = delete;
194  stream_from(stream_from &&) = delete;
195  ~stream_from() noexcept;
196 
197  stream_from &operator=(stream_from const &) = delete;
198  stream_from &operator=(stream_from &&) = delete;
199 
200  // NOLINTBEGIN(google-explicit-constructor,hicpp-explicit-conversions)
201  // LCOV_EXCL_START
203  [[nodiscard]] constexpr operator bool() const noexcept
204  {
205  return not m_finished;
206  }
207  // LCOV_EXCL_STOP
208  // NOLINTEND(google-explicit-constructor,hicpp-explicit-conversions)
209 
211  [[nodiscard]] constexpr bool operator!() const noexcept
212  {
213  return m_finished;
214  }
215 
217 
223  void complete(sl = sl::current());
224 
226 
233  template<typename Tuple> stream_from &operator>>(Tuple &);
234 
236  template<typename... Vs>
237  stream_from &operator>>(std::variant<Vs...> &) = delete;
238 
240 
244  template<typename... TYPE> [[nodiscard]] auto iter() &
245  {
246  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
247  }
248 
250 
262  std::vector<std::string_view> const *read_row(sl loc = sl::current()) &;
263 
265 
266  raw_line get_raw_line(sl);
267 
268 private:
269  // TODO: Clean up this signature once we cull the deprecated constructors.
271  stream_from(
272  transaction_base &tx, std::string_view table, std::string_view columns,
273  from_table_t);
274 
275  // TODO: Clean up this signature once we cull the deprecated constructors.
277  stream_from(
278  transaction_base &, std::string_view unquoted_table,
279  std::string_view columns, from_table_t, int);
280 
281  template<typename Tuple, std::size_t... indexes>
282  void extract_fields(Tuple &t, std::index_sequence<indexes...>, sl loc) const
283  {
284  (extract_value<Tuple, indexes>(t, loc), ...);
285  }
286 
287  pqxx::internal::char_finder_func *m_char_finder;
288 
290  std::string m_row;
291 
293  std::vector<std::string_view> m_fields;
294 
295  bool m_finished = false;
296 
297  void close();
298 
299  template<typename Tuple, std::size_t index>
300  void extract_value(Tuple &, sl loc) const;
301 
303  void parse_line(sl);
304 };
305 
306 
307 template<typename Columns>
309  transaction_base &tx, from_table_t, std::string_view table_name,
310  Columns const &columns) :
311  stream_from{
312  tx, from_table, table_name, std::begin(columns), std::end(columns)}
313 {}
314 
315 
316 template<typename Iter>
318  transaction_base &tx, from_table_t, std::string_view table,
319  Iter columns_begin, Iter columns_end) :
320  stream_from{
321  tx, table, separated_list(",", columns_begin, columns_end),
322  from_table, 1}
323 {}
324 
325 
326 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
327 {
328  sl const loc{sl::current()};
329  if (m_finished) [[unlikely]]
330  return *this;
331  static constexpr auto tup_size{std::tuple_size_v<Tuple>};
332  m_fields.reserve(tup_size);
333  parse_line(loc);
334  if (m_finished) [[unlikely]]
335  return *this;
336 
337  if (std::size(m_fields) != tup_size)
338  throw usage_error{std::format(
339  "Tried to extract {} field(s) from a stream of {}.", tup_size,
340  std::size(m_fields))};
341 
342  extract_fields(t, std::make_index_sequence<tup_size>{}, loc);
343  return *this;
344 }
345 
346 
347 template<typename Tuple, std::size_t index>
348 inline void stream_from::extract_value(Tuple &t, sl loc) const
349 {
350  using field_type = std::remove_cvref_t<decltype(std::get<index>(t))>;
351  assert(index < std::size(m_fields));
352  if constexpr (always_null<field_type>())
353  {
354  if (std::data(m_fields[index]) != nullptr)
355  throw conversion_error{"Streaming non-null value into null field.", loc};
356  }
357  else if (std::data(m_fields[index]) == nullptr)
358  {
359  if constexpr (has_null<field_type>())
360  std::get<index>(t) = make_null<field_type>();
361  else
362  internal::throw_null_conversion(name_type<field_type>(), loc);
363  }
364  else
365  {
366  // Don't ever try to convert a non-null value to nullptr_t!
367  std::get<index>(t) = from_string<field_type>(m_fields[index]);
368  }
369 }
370 } // namespace pqxx
371 #endif
Iteration over a stream_query.
Definition: stream_iterator.hxx:87
Stream data from the database.
Definition: stream_from.hxx:79
std::pair< std::unique_ptr< char[], void(*)(void const *)>, std::size_t > raw_line
Definition: stream_from.hxx:82
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:95
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:41
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:326
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:182
stream_from(stream_from const &)=delete
stream_from(stream_from &&)=delete
stream_from(transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end)
stream_from & operator>>(std::variant< Vs... > &)=delete
Doing this with a std::variant is going to be horrifically borked.
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:174
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:244
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:211
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:29
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:612
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:580
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:151
#define PQXX_LIBEXPORT
Definition: header-pre.hxx:206
void throw_null_conversion(std::string const &type, sl loc)
Throw exception for attempt to convert SQL NULL to given type.
Definition: strconv.cxx:142
std::size_t(std::string_view haystack, std::size_t start, sl) char_finder_func
Function type: "find first occurrence of any of these ASCII characters.".
Definition: encoding_group.hxx:110
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:44
constexpr TYPE make_null() requires(pqxx
Return a null value of TYPE.
Definition: strconv.hxx:781
std::source_location sl
Convenience alias for std::source_location. It's just too long.
Definition: types.hxx:38
constexpr std::string_view name_type() noexcept
Return human-readable name for TYPE.
Definition: types.hxx:277
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:34
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:240
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access, ctx c={})
Represent sequence of values as a string, joined by a given separator.
Definition: separated_list.hxx:41
format
Format code: is data text or binary?
Definition: types.hxx:121
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:226
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:220