libpqxx  7.8.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-2023, 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 <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 
78 class PQXX_LIBEXPORT stream_from : transaction_focus
79 {
80 public:
81  using raw_line =
82  std::pair<std::unique_ptr<char, void(*)(void const *)>, std::size_t>;
83 
84  stream_from(stream_from &&) = delete;
86 
88 
97  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
98  query(transaction_base &tx, std::string_view q)
99  {
100 #include "pqxx/internal/ignore-deprecated-pre.hxx"
101  return {tx, from_query, q};
102 #include "pqxx/internal/ignore-deprecated-post.hxx"
103  }
104 
115 
117 
133  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
134  raw_table(
135  transaction_base &tx, std::string_view path,
136  std::string_view columns = ""sv);
137 
139 
141  [[deprecated("Use transaction_base::stream instead.")]] static stream_from
142  table(
143  transaction_base &tx, table_path path,
144  std::initializer_list<std::string_view> columns = {});
146 
148 
150  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
151  transaction_base &, from_query_t, std::string_view query);
152 
154 
156  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
157  transaction_base &, from_table_t, std::string_view table);
158 
160 
162  template<typename Iter>
163  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
164  transaction_base &, from_table_t, std::string_view table,
165  Iter columns_begin, Iter columns_end);
166 
168 
170  template<typename Columns>
171  [[deprecated("Use transaction_base::stream() instead.")]] stream_from(
172  transaction_base &tx, from_table_t, std::string_view table,
173  Columns const &columns);
174 
175 #include "pqxx/internal/ignore-deprecated-pre.hxx"
177  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
178  transaction_base &tx, std::string_view table) :
179  stream_from{tx, from_table, table}
180  {}
181 #include "pqxx/internal/ignore-deprecated-post.hxx"
182 
184  template<typename Columns>
185  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
186  transaction_base &tx, std::string_view table, Columns const &columns) :
187  stream_from{tx, from_table, table, columns}
188  {}
189 
191  template<typename Iter>
192  [[deprecated("Use transaction_base::stream instead.")]] stream_from(
193  transaction_base &, std::string_view table, Iter columns_begin,
194  Iter columns_end);
195 
196  ~stream_from() noexcept;
197 
199  [[nodiscard]] constexpr operator bool() const noexcept
200  {
201  return not m_finished;
202  }
204  [[nodiscard]] constexpr bool operator!() const noexcept
205  {
206  return m_finished;
207  }
208 
210 
216  void complete();
217 
219 
226  template<typename Tuple> stream_from &operator>>(Tuple &);
227 
229  template<typename... Vs>
230  stream_from &operator>>(std::variant<Vs...> &) = delete;
231 
233 
237  template<typename... TYPE> [[nodiscard]] auto iter() &
238  {
239  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
240  }
241 
243 
259  std::vector<zview> const *read_row() &;
260 
262 
263  raw_line get_raw_line();
264 
265 private:
266  // TODO: Clean up this signature once we cull the deprecated constructors.
268  stream_from(
269  transaction_base &tx, std::string_view table, std::string_view columns,
270  from_table_t);
271 
272  // TODO: Clean up this signature once we cull the deprecated constructors.
274  stream_from(
275  transaction_base &, std::string_view unquoted_table,
276  std::string_view columns, from_table_t, int);
277 
278  template<typename Tuple, std::size_t... indexes>
279  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
280  {
281  (extract_value<Tuple, indexes>(t), ...);
282  }
283 
284  pqxx::internal::char_finder_func *m_char_finder;
285 
287  std::string m_row;
288 
290  std::vector<zview> m_fields;
291 
292  bool m_finished = false;
293 
294  void close();
295 
296  template<typename Tuple, std::size_t index>
297  void extract_value(Tuple &) const;
298 
300  void parse_line();
301 };
302 
303 
304 template<typename Columns>
306  transaction_base &tx, from_table_t, std::string_view table_name,
307  Columns const &columns) :
308  stream_from{
309  tx, from_table, table_name, std::begin(columns), std::end(columns)}
310 {}
311 
312 
313 template<typename Iter>
315  transaction_base &tx, from_table_t, std::string_view table,
316  Iter columns_begin, Iter columns_end) :
317  stream_from{
318  tx, table, separated_list(",", columns_begin, columns_end),
319  from_table, 1}
320 {}
321 
322 
323 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
324 {
325  if (m_finished)
326  PQXX_UNLIKELY return *this;
327  static constexpr auto tup_size{std::tuple_size_v<Tuple>};
328  m_fields.reserve(tup_size);
329  parse_line();
330  if (m_finished)
331  PQXX_UNLIKELY return *this;
332 
333  if (std::size(m_fields) != tup_size)
334  throw usage_error{internal::concat(
335  "Tried to extract ", tup_size, " field(s) from a stream of ",
336  std::size(m_fields), ".")};
337 
338  extract_fields(t, std::make_index_sequence<tup_size>{});
339  return *this;
340 }
341 
342 
343 template<typename Tuple, std::size_t index>
344 inline void stream_from::extract_value(Tuple &t) const
345 {
346  using field_type = strip_t<decltype(std::get<index>(t))>;
347  using nullity = nullness<field_type>;
348  assert(index < std::size(m_fields));
349  if constexpr (nullity::always_null)
350  {
351  if (std::data(m_fields[index]) != nullptr)
352  throw conversion_error{"Streaming non-null value into null field."};
353  }
354  else if (std::data(m_fields[index]) == nullptr)
355  {
356  if constexpr (nullity::has_null)
357  std::get<index>(t) = nullity::null();
358  else
359  internal::throw_null_conversion(type_name<field_type>);
360  }
361  else
362  {
363  // Don't ever try to convert a non-null value to nullptr_t!
364  std::get<index>(t) = from_string<field_type>(m_fields[index]);
365  }
366 }
367 } // namespace pqxx
368 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
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:44
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: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:185
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:238
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:268
Traits describing a type's "null value," if any.
Definition: strconv.hxx:93
Stream data from the database.
Definition: stream_from.hxx:79
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition: stream_from.hxx:98
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:323
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:185
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.
std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t > raw_line
Definition: stream_from.hxx:82
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:177
stream_from & operator=(stream_from &&)=delete
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:237
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:204
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:88
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