libpqxx  7.7.0
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 #include <cassert>
17 #include <functional>
18 #include <variant>
19 
20 #include "pqxx/connection.hxx"
21 #include "pqxx/except.hxx"
22 #include "pqxx/internal/concat.hxx"
23 #include "pqxx/internal/encoding_group.hxx"
24 #include "pqxx/internal/stream_iterator.hxx"
25 #include "pqxx/separated_list.hxx"
26 #include "pqxx/transaction_focus.hxx"
27 
28 
29 namespace pqxx
30 {
31 class transaction_base;
32 
33 
34 // C++20: constinit.
36 
39 // C++20: constinit.
41 
44 
45 
47 
71 class PQXX_LIBEXPORT stream_from : transaction_focus
72 {
73 public:
74  using raw_line =
75  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
76 
78 
87  static stream_from query(transaction_base &tx, std::string_view q)
88  {
89 #include "pqxx/internal/ignore-deprecated-pre.hxx"
90  return {tx, from_query, q};
91 #include "pqxx/internal/ignore-deprecated-post.hxx"
92  }
93 
104 
106 
122  static stream_from raw_table(
123  transaction_base &tx, std::string_view path,
124  std::string_view columns = ""sv);
125 
127 
129  static stream_from table(
130  transaction_base &tx, table_path path,
131  std::initializer_list<std::string_view> columns = {});
133 
135 
137  [[deprecated("Use query() factory instead.")]] stream_from(
138  transaction_base &, from_query_t, std::string_view query);
139 
141 
143  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
144  transaction_base &, from_table_t, std::string_view table);
145 
147 
149  template<typename Iter>
150  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
151  transaction_base &, from_table_t, std::string_view table,
152  Iter columns_begin, Iter columns_end);
153 
155 
157  template<typename Columns>
158  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
159  transaction_base &tx, from_table_t, std::string_view table,
160  Columns const &columns);
161 
162 #include "pqxx/internal/ignore-deprecated-pre.hxx"
164  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
165  transaction_base &tx, std::string_view table) :
166  stream_from{tx, from_table, table}
167  {}
168 #include "pqxx/internal/ignore-deprecated-post.hxx"
169 
171  template<typename Columns>
172  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
173  transaction_base &tx, std::string_view table, Columns const &columns) :
174  stream_from{tx, from_table, table, columns}
175  {}
176 
178  template<typename Iter>
179  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
180  transaction_base &, std::string_view table, Iter columns_begin,
181  Iter columns_end);
182 
183  ~stream_from() noexcept;
184 
186  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
188  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
189 
191 
197  void complete();
198 
200 
207  template<typename Tuple> stream_from &operator>>(Tuple &);
208 
210  template<typename... Vs>
211  stream_from &operator>>(std::variant<Vs...> &) = delete;
212 
214 
218  template<typename... TYPE> [[nodiscard]] auto iter() &
219  {
220  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
221  }
222 
224 
240  std::vector<zview> const *read_row() &;
241 
243 
244  raw_line get_raw_line();
245 
246 private:
247  // TODO: Clean up this signature once we cull the deprecated constructors.
249  stream_from(
250  transaction_base &tx, std::string_view table, std::string_view columns,
251  from_table_t);
252 
253  // TODO: Clean up this signature once we cull the deprecated constructors.
255  stream_from(
256  transaction_base &, std::string_view unquoted_table,
257  std::string_view columns, from_table_t, int);
258 
259  template<typename Tuple, std::size_t... indexes>
260  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
261  {
262  (extract_value<Tuple, indexes>(t), ...);
263  }
264 
265  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
266 
268  std::string m_row;
269 
271  std::vector<zview> m_fields;
272 
273  bool m_finished = false;
274 
275  void close();
276 
277  template<typename Tuple, std::size_t index>
278  void extract_value(Tuple &) const;
279 
281  void parse_line();
282 };
283 
284 
285 template<typename Columns>
287  transaction_base &tx, from_table_t, std::string_view table_name,
288  Columns const &columns) :
289  stream_from{
290  tx, from_table, table_name, std::begin(columns), std::end(columns)}
291 {}
292 
293 
294 template<typename Iter>
296  transaction_base &tx, from_table_t, std::string_view table,
297  Iter columns_begin, Iter columns_end) :
298  stream_from{
299  tx, table, separated_list(",", columns_begin, columns_end),
300  from_table, 1}
301 {}
302 
303 
304 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
305 {
306  if (m_finished)
307  return *this;
308  // C++20: constinit.
309  constexpr auto tup_size{std::tuple_size_v<Tuple>};
310  m_fields.reserve(tup_size);
311  parse_line();
312  if (m_finished)
313  return *this;
314 
315  if (std::size(m_fields) != tup_size)
316  throw usage_error{internal::concat(
317  "Tried to extract ", tup_size, " field(s) from a stream of ",
318  std::size(m_fields), ".")};
319 
320  extract_fields(t, std::make_index_sequence<tup_size>{});
321  return *this;
322 }
323 
324 
325 template<typename Tuple, std::size_t index>
326 inline void stream_from::extract_value(Tuple &t) const
327 {
328  using field_type = strip_t<decltype(std::get<index>(t))>;
329  using nullity = nullness<field_type>;
330  assert(index < std::size(m_fields));
331  if constexpr (nullity::always_null)
332  {
333  if (std::data(m_fields[index]) != nullptr)
334  throw conversion_error{"Streaming non-null value into null field."};
335  }
336  else if (std::data(m_fields[index]) == nullptr)
337  {
338  if constexpr (nullity::has_null)
339  std::get<index>(t) = nullity::null();
340  else
341  internal::throw_null_conversion(type_name<field_type>);
342  }
343  else
344  {
345  // Don't ever try to convert a non-null value to nullptr_t!
346  std::get<index>(t) = from_string<field_type>(m_fields[index]);
347  }
348 }
349 } // namespace pqxx
350 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:23
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:39
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: types.hxx:87
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:43
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:31
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:119
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:252
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:162
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:176
Traits describing a type's "null value," if any.
Definition: strconv.hxx:89
Stream data from the database.
Definition: stream_from.hxx:72
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:87
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:75
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:37
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:304
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:172
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.
bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:188
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:164
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:218
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:73
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:25
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:64
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:70