libpqxx  7.7.2
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 {
36 
37 
39 
41 constexpr from_table_t from_table;
43 
46 
47 
49 
73 class PQXX_LIBEXPORT stream_from : transaction_focus
74 {
75 public:
76  using raw_line =
77  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
78 
80 
89  static stream_from query(transaction_base &tx, std::string_view q)
90  {
91 #include "pqxx/internal/ignore-deprecated-pre.hxx"
92  return {tx, from_query, q};
93 #include "pqxx/internal/ignore-deprecated-post.hxx"
94  }
95 
106 
108 
124  static stream_from raw_table(
125  transaction_base &tx, std::string_view path,
126  std::string_view columns = ""sv);
127 
129 
131  static stream_from table(
132  transaction_base &tx, table_path path,
133  std::initializer_list<std::string_view> columns = {});
135 
137 
139  [[deprecated("Use query() factory instead.")]] stream_from(
140  transaction_base &, from_query_t, std::string_view query);
141 
143 
145  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
146  transaction_base &, from_table_t, std::string_view table);
147 
149 
151  template<typename Iter>
152  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
153  transaction_base &, from_table_t, std::string_view table,
154  Iter columns_begin, Iter columns_end);
155 
157 
159  template<typename Columns>
160  [[deprecated("Use table() or raw_table() factory instead.")]] stream_from(
161  transaction_base &tx, from_table_t, std::string_view table,
162  Columns const &columns);
163 
164 #include "pqxx/internal/ignore-deprecated-pre.hxx"
166  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
167  transaction_base &tx, std::string_view table) :
168  stream_from{tx, from_table, table}
169  {}
170 #include "pqxx/internal/ignore-deprecated-post.hxx"
171 
173  template<typename Columns>
174  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
175  transaction_base &tx, std::string_view table, Columns const &columns) :
176  stream_from{tx, from_table, table, columns}
177  {}
178 
180  template<typename Iter>
181  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
182  transaction_base &, std::string_view table, Iter columns_begin,
183  Iter columns_end);
184 
185  ~stream_from() noexcept;
186 
188  [[nodiscard]] constexpr operator bool() const noexcept
189  {
190  return not m_finished;
191  }
193  [[nodiscard]] constexpr bool operator!() const noexcept
194  {
195  return m_finished;
196  }
197 
199 
205  void complete();
206 
208 
215  template<typename Tuple> stream_from &operator>>(Tuple &);
216 
218  template<typename... Vs>
219  stream_from &operator>>(std::variant<Vs...> &) = delete;
220 
222 
226  template<typename... TYPE> [[nodiscard]] auto iter() &
227  {
228  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
229  }
230 
232 
248  std::vector<zview> const *read_row() &;
249 
251 
252  raw_line get_raw_line();
253 
254 private:
255  // TODO: Clean up this signature once we cull the deprecated constructors.
257  stream_from(
258  transaction_base &tx, std::string_view table, std::string_view columns,
259  from_table_t);
260 
261  // TODO: Clean up this signature once we cull the deprecated constructors.
263  stream_from(
264  transaction_base &, std::string_view unquoted_table,
265  std::string_view columns, from_table_t, int);
266 
267  template<typename Tuple, std::size_t... indexes>
268  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
269  {
270  (extract_value<Tuple, indexes>(t), ...);
271  }
272 
273  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
274 
276  std::string m_row;
277 
279  std::vector<zview> m_fields;
280 
281  bool m_finished = false;
282 
283  void close();
284 
285  template<typename Tuple, std::size_t index>
286  void extract_value(Tuple &) const;
287 
289  void parse_line();
290 };
291 
292 
293 template<typename Columns>
295  transaction_base &tx, from_table_t, std::string_view table_name,
296  Columns const &columns) :
297  stream_from{
298  tx, from_table, table_name, std::begin(columns), std::end(columns)}
299 {}
300 
301 
302 template<typename Iter>
304  transaction_base &tx, from_table_t, std::string_view table,
305  Iter columns_begin, Iter columns_end) :
306  stream_from{
307  tx, table, separated_list(",", columns_begin, columns_end),
308  from_table, 1}
309 {}
310 
311 
312 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
313 {
314  if (m_finished)
315  return *this;
316  static constexpr auto tup_size{std::tuple_size_v<Tuple>};
317  m_fields.reserve(tup_size);
318  parse_line();
319  if (m_finished)
320  return *this;
321 
322  if (std::size(m_fields) != tup_size)
323  throw usage_error{internal::concat(
324  "Tried to extract ", tup_size, " field(s) from a stream of ",
325  std::size(m_fields), ".")};
326 
327  extract_fields(t, std::make_index_sequence<tup_size>{});
328  return *this;
329 }
330 
331 
332 template<typename Tuple, std::size_t index>
333 inline void stream_from::extract_value(Tuple &t) const
334 {
335  using field_type = strip_t<decltype(std::get<index>(t))>;
336  using nullity = nullness<field_type>;
337  assert(index < std::size(m_fields));
338  if constexpr (nullity::always_null)
339  {
340  if (std::data(m_fields[index]) != nullptr)
341  throw conversion_error{"Streaming non-null value into null field."};
342  }
343  else if (std::data(m_fields[index]) == nullptr)
344  {
345  if constexpr (nullity::has_null)
346  std::get<index>(t) = nullity::null();
347  else
348  internal::throw_null_conversion(type_name<field_type>);
349  }
350  else
351  {
352  // Don't ever try to convert a non-null value to nullptr_t!
353  std::get<index>(t) = from_string<field_type>(m_fields[index]);
354  }
355 }
356 } // namespace pqxx
357 #endif
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
End a code block started by "ignore-deprecated-pre.hxx".
Definition: stream_from.hxx:174
Stream data from the database.
Definition: stream_from.hxx:73
Base class for things that monopolise a transaction&#39;s attention.
Definition: transaction_focus.hxx:28
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:166
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:312
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:89
static stream_from table(transaction_base &tx, table_path path, std::initializer_list< std::string_view > columns={})
Factory: Stream data from a given table.
Definition: stream_from.cxx:88
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:253
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:35
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:45
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:77
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:73
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:173
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:76
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
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:187
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:67
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:39
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:92
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::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:124
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:226
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:193