libpqxx  7.5.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-2021, 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 "pqxx/compiler-public.hxx"
17 #include "pqxx/internal/compiler-internal-pre.hxx"
18 
19 #include <cassert>
20 #include <functional>
21 #include <variant>
22 
23 #include "pqxx/connection.hxx"
24 #include "pqxx/except.hxx"
25 #include "pqxx/internal/concat.hxx"
26 #include "pqxx/internal/encoding_group.hxx"
27 #include "pqxx/internal/stream_iterator.hxx"
28 #include "pqxx/separated_list.hxx"
29 #include "pqxx/transaction_focus.hxx"
30 
31 
32 namespace pqxx
33 {
34 class transaction_base;
35 
36 
38 
42 
45 
46 
48 
72 class PQXX_LIBEXPORT stream_from : transaction_focus
73 {
74 public:
75  using raw_line =
76  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
77 
79 
88  static stream_from query(transaction_base &tx, std::string_view q)
89  {
90 #include "pqxx/internal/ignore-deprecated-pre.hxx"
91  return stream_from{tx, from_query, q};
92 #include "pqxx/internal/ignore-deprecated-post.hxx"
93  }
94 
105 
107 
123  static stream_from raw_table(
124  transaction_base &tx, std::string_view path,
125  std::string_view columns = ""sv);
126 
128 
131  transaction_base &tx, table_path path,
132  std::initializer_list<std::string_view> columns = {});
134 
136 
138  PQXX_DEPRECATED("Use query() factory instead.")
139  stream_from(transaction_base &, from_query_t, std::string_view query);
140 
142 
144  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
145  stream_from(transaction_base &, from_table_t, std::string_view table);
146 
148 
150  template<typename Iter>
151  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
152  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  PQXX_DEPRECATED("Use table() or raw_table() factory instead.")
161  stream_from(
162  transaction_base &tx, from_table_t, std::string_view table,
163  Columns const &columns);
164 
165 #include "pqxx/internal/ignore-deprecated-pre.hxx"
167  PQXX_DEPRECATED("Use the from_table_t overload instead.")
168  stream_from(transaction_base &tx, std::string_view table) :
169  stream_from{tx, from_table, table}
170  {}
171 #include "pqxx/internal/ignore-deprecated-post.hxx"
172 
174  template<typename Columns>
175  PQXX_DEPRECATED("Use the from_table_t overload instead.")
177  transaction_base &tx, std::string_view table, Columns const &columns) :
178  stream_from{tx, from_table, table, columns}
179  {}
180 
182  template<typename Iter>
183  PQXX_DEPRECATED("Use the from_table_t overload instead.")
185  transaction_base &, std::string_view table, Iter columns_begin,
186  Iter columns_end);
187 
188  ~stream_from() noexcept;
189 
191  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
193  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
194 
196 
202  void complete();
203 
205 
212  template<typename Tuple> stream_from &operator>>(Tuple &);
213 
215  template<typename... Vs>
216  stream_from &operator>>(std::variant<Vs...> &) = delete;
217 
219 
223  template<typename... TYPE> [[nodiscard]] auto iter()
224  {
225  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
226  }
227 
229 
245  std::vector<zview> const *read_row();
246 
248 
249  raw_line get_raw_line();
250 
251 private:
252  // TODO: Clean up this signature once we cull the deprecated constructors.
254  stream_from(
255  transaction_base &tx, std::string_view table, std::string_view columns,
256  from_table_t);
257 
258  // TODO: Clean up this signature once we cull the deprecated constructors.
260  stream_from(
261  transaction_base &, std::string_view unquoted_table,
262  std::string_view columns, from_table_t, int);
263 
264  template<typename Tuple, std::size_t... indexes>
265  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
266  {
267  (extract_value<Tuple, indexes>(t), ...);
268  }
269 
270  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
271 
273  std::string m_row;
274 
276  std::vector<zview> m_fields;
277 
278  bool m_finished = false;
279 
280  void close();
281 
282  template<typename Tuple, std::size_t index>
283  void extract_value(Tuple &) const;
284 
286  void parse_line();
287 };
288 
289 
290 template<typename Columns>
292  transaction_base &tx, from_table_t, std::string_view table_name,
293  Columns const &columns) :
294  stream_from{
295  tx, from_table, table_name, std::begin(columns), std::end(columns)}
296 {}
297 
298 
299 template<typename Iter>
301  transaction_base &tx, from_table_t, std::string_view table,
302  Iter columns_begin, Iter columns_end) :
303  stream_from{
304  tx, table, separated_list(",", columns_begin, columns_end),
305  from_table, 1}
306 {}
307 
308 
309 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
310 {
311  if (m_finished)
312  return *this;
313  constexpr auto tup_size{std::tuple_size_v<Tuple>};
314  m_fields.reserve(tup_size);
315  parse_line();
316  if (m_finished)
317  return *this;
318 
319  if (std::size(m_fields) != tup_size)
320  throw usage_error{internal::concat(
321  "Tried to extract ", tup_size, " field(s) from a stream of ",
322  std::size(m_fields), ".")};
323 
324  extract_fields(t, std::make_index_sequence<tup_size>{});
325  return *this;
326 }
327 
328 
329 template<typename Tuple, std::size_t index>
330 inline void stream_from::extract_value(Tuple &t) const
331 {
332  using field_type = strip_t<decltype(std::get<index>(t))>;
333  using nullity = nullness<field_type>;
334  assert(index < std::size(m_fields));
335  if constexpr (nullity::always_null)
336  {
337  if (m_fields[index].data() != nullptr)
338  throw conversion_error{"Streaming non-null value into null field."};
339  }
340  else if (m_fields[index].data() == nullptr)
341  {
342  if constexpr (nullity::has_null)
343  std::get<index>(t) = nullity::null();
344  else
345  internal::throw_null_conversion(type_name<field_type>);
346  }
347  else
348  {
349  // Don't ever try to convert a non-null value to nullptr_t!
350  std::get<index>(t) = from_string<field_type>(m_fields[index]);
351  }
352 }
353 } // namespace pqxx
354 
355 #include "pqxx/internal/compiler-internal-post.hxx"
356 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
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:42
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:147
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:44
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:122
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:242
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:165
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:179
Traits describing a type's "null value," if any.
Definition: strconv.hxx:87
Stream data from the database.
Definition: stream_from.hxx:73
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:88
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:76
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:309
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:193
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:223
Use the from_table_t overload instead stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:168
static stream_from table(transaction_base &tx, table_path path, std::initializer_list< std::string_view > columns={})
Factory: Stream data from a given table.
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:75
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:28
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:58
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:64