libpqxx  7.7.4
stream_from.hxx
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-2022, 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_H_STREAM_FROM
14 #define PQXX_H_STREAM_FROM
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 <functional>
22 #include <variant>
23 
24 #include "pqxx/connection.hxx"
25 #include "pqxx/except.hxx"
26 #include "pqxx/internal/concat.hxx"
27 #include "pqxx/internal/encoding_group.hxx"
28 #include "pqxx/internal/stream_iterator.hxx"
29 #include "pqxx/separated_list.hxx"
30 #include "pqxx/transaction_focus.hxx"
31 
32 
33 namespace pqxx
34 {
35 class transaction_base;
36 
37 
39 
43 
46 
47 
49 
77 class PQXX_LIBEXPORT stream_from : transaction_focus
78 {
79 public:
80  using raw_line =
81  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
82 
84 
93  static stream_from query(transaction_base &tx, std::string_view q)
94  {
95 #include "pqxx/internal/ignore-deprecated-pre.hxx"
96  return {tx, from_query, q};
97 #include "pqxx/internal/ignore-deprecated-post.hxx"
98  }
99 
110 
112 
128  static stream_from raw_table(
129  transaction_base &tx, std::string_view path,
130  std::string_view columns = ""sv);
131 
133 
135  static stream_from table(
136  transaction_base &tx, table_path path,
137  std::initializer_list<std::string_view> columns = {});
139 
141 
143  [[deprecated("Use query() factory instead.")]] stream_from(
144  transaction_base &, from_query_t, std::string_view query);
145 
147 
149  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
150  transaction_base &, from_table_t, std::string_view table);
151 
153 
155  template<typename Iter>
156  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
157  transaction_base &, from_table_t, std::string_view table,
158  Iter columns_begin, Iter columns_end);
159 
161 
163  template<typename Columns>
164  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
165  transaction_base &tx, from_table_t, std::string_view table,
166  Columns const &columns);
167 
168 #include "pqxx/internal/ignore-deprecated-pre.hxx"
170  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
171  transaction_base &tx, std::string_view table) :
172  stream_from{tx, from_table, table}
173  {}
174 #include "pqxx/internal/ignore-deprecated-post.hxx"
175 
177  template<typename Columns>
178  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
179  transaction_base &tx, std::string_view table, Columns const &columns) :
180  stream_from{tx, from_table, table, columns}
181  {}
182 
184  template<typename Iter>
185  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
186  transaction_base &, std::string_view table, Iter columns_begin,
187  Iter columns_end);
188 
189  ~stream_from() noexcept;
190 
192  [[nodiscard]] constexpr operator bool() const noexcept
193  {
194  return not m_finished;
195  }
197  [[nodiscard]] constexpr bool operator!() const noexcept
198  {
199  return m_finished;
200  }
201 
203 
209  void complete();
210 
212 
219  template<typename Tuple> stream_from &operator>>(Tuple &);
220 
222  template<typename... Vs>
223  stream_from &operator>>(std::variant<Vs...> &) = delete;
224 
226 
230  template<typename... TYPE> [[nodiscard]] auto iter() &
231  {
232  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
233  }
234 
236 
252  std::vector<zview> const *read_row() &;
253 
255 
256  raw_line get_raw_line();
257 
258 private:
259  // TODO: Clean up this signature once we cull the deprecated constructors.
261  stream_from(
262  transaction_base &tx, std::string_view table, std::string_view columns,
263  from_table_t);
264 
265  // TODO: Clean up this signature once we cull the deprecated constructors.
267  stream_from(
268  transaction_base &, std::string_view unquoted_table,
269  std::string_view columns, from_table_t, int);
270 
271  template<typename Tuple, std::size_t... indexes>
272  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
273  {
274  (extract_value<Tuple, indexes>(t), ...);
275  }
276 
277  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
278 
280  std::string m_row;
281 
283  std::vector<zview> m_fields;
284 
285  bool m_finished = false;
286 
287  void close();
288 
289  template<typename Tuple, std::size_t index>
290  void extract_value(Tuple &) const;
291 
293  void parse_line();
294 };
295 
296 
297 template<typename Columns>
299  transaction_base &tx, from_table_t, std::string_view table_name,
300  Columns const &columns) :
301  stream_from{
302  tx, from_table, table_name, std::begin(columns), std::end(columns)}
303 {}
304 
305 
306 template<typename Iter>
308  transaction_base &tx, from_table_t, std::string_view table,
309  Iter columns_begin, Iter columns_end) :
310  stream_from{
311  tx, table, separated_list(",", columns_begin, columns_end),
312  from_table, 1}
313 {}
314 
315 
316 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
317 {
318  if (m_finished)
319  return *this;
320  static constexpr auto tup_size{std::tuple_size_v<Tuple>};
321  m_fields.reserve(tup_size);
322  parse_line();
323  if (m_finished)
324  return *this;
325 
326  if (std::size(m_fields) != tup_size)
327  throw usage_error{internal::concat(
328  "Tried to extract ", tup_size, " field(s) from a stream of ",
329  std::size(m_fields), ".")};
330 
331  extract_fields(t, std::make_index_sequence<tup_size>{});
332  return *this;
333 }
334 
335 
336 template<typename Tuple, std::size_t index>
337 inline void stream_from::extract_value(Tuple &t) const
338 {
339  using field_type = strip_t<decltype(std::get<index>(t))>;
340  using nullity = nullness<field_type>;
341  assert(index < std::size(m_fields));
342  if constexpr (nullity::always_null)
343  {
344  if (std::data(m_fields[index]) != nullptr)
345  throw conversion_error{"Streaming non-null value into null field."};
346  }
347  else if (std::data(m_fields[index]) == nullptr)
348  {
349  if constexpr (nullity::has_null)
350  std::get<index>(t) = nullity::null();
351  else
352  internal::throw_null_conversion(type_name<field_type>);
353  }
354  else
355  {
356  // Don't ever try to convert a non-null value to nullptr_t!
357  std::get<index>(t) = from_string<field_type>(m_fields[index]);
358  }
359 }
360 } // namespace pqxx
361 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:27
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition: separated_list.hxx:43
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: types.hxx:91
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:45
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:35
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:123
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:253
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:174
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:188
Traits describing a type's "null value," if any.
Definition: strconv.hxx:93
Stream data from the database.
Definition: stream_from.hxx:78
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:93
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:81
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:39
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:316
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:178
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:170
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:230
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:197
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:77
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:29
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:68
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:74