libpqxx  7.3.1
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/except.hxx"
24 #include "pqxx/internal/concat.hxx"
25 #include "pqxx/internal/encoding_group.hxx"
26 #include "pqxx/internal/stream_iterator.hxx"
27 #include "pqxx/internal/transaction_focus.hxx"
28 #include "pqxx/separated_list.hxx"
29 #include "pqxx/transaction_base.hxx"
30 
31 
32 namespace pqxx
33 {
38 
39 
41 
67 class PQXX_LIBEXPORT stream_from : internal::transactionfocus
68 {
69 public:
70  using raw_line =
71  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
72 
88  static stream_from query(transaction_base &tx, std::string_view q)
90  {
91  return stream_from{tx, from_query, q};
92  }
93 
95 
100  stream_from(transaction_base &, from_query_t, std::string_view query);
102 
113  // TODO: Replace constructors with factories. Use Concepts.
114 
116  stream_from(transaction_base &, from_table_t, std::string_view table);
117 
119  template<typename Iter>
120  stream_from(
121  transaction_base &, from_table_t, std::string_view table,
122  Iter columns_begin, Iter columns_end);
123 
125  template<typename Columns>
126  stream_from(
127  transaction_base &tx, from_table_t, std::string_view table,
128  Columns const &columns);
129 
131  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
132  transaction_base &tx, std::string_view table) :
133  stream_from{tx, from_table, table}
134  {}
135 
137  template<typename Columns>
138  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
139  transaction_base &tx, std::string_view table, Columns const &columns) :
140  stream_from{tx, from_table, table, columns}
141  {}
142 
144  template<typename Iter>
145  [[deprecated("Use the from_table_t overload instead.")]] stream_from(
146  transaction_base &, std::string_view table, Iter columns_begin,
147  Iter columns_end);
149 
150  ~stream_from() noexcept;
151 
153  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
155  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
156 
158 
164  void complete();
165 
167 
174  template<typename Tuple> stream_from &operator>>(Tuple &);
175 
177  template<typename... Vs>
178  stream_from &operator>>(std::variant<Vs...> &) = delete;
179 
180  // TODO: Hide this from the public.
182 
186  template<typename... TYPE> [[nodiscard]] auto iter()
187  {
188  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
189  }
190 
192 
208  std::vector<zview> const *read_row();
209 
211 
212  raw_line get_raw_line();
213 
214 private:
215  stream_from(
216  transaction_base &tx, std::string_view table, std::string &&columns,
217  from_table_t);
218 
219  template<typename Tuple, std::size_t... indexes>
220  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
221  {
222  (extract_value<Tuple, indexes>(t), ...);
223  }
224 
225  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
226 
228  std::string m_row;
229 
231  std::vector<zview> m_fields;
232 
233  bool m_finished = false;
234 
235  void close();
236 
237  template<typename Tuple, std::size_t index>
238  void extract_value(Tuple &) const;
239 
241  void parse_line();
242 };
243 
244 
245 template<typename Columns>
247  transaction_base &tb, from_table_t, std::string_view table_name,
248  Columns const &columns) :
249  stream_from{
250  tb, from_table, table_name, std::begin(columns), std::end(columns)}
251 {}
252 
253 
254 template<typename Iter>
256  transaction_base &tx, from_table_t, std::string_view table,
257  Iter columns_begin, Iter columns_end) :
258  stream_from{
259  tx, table, separated_list(",", columns_begin, columns_end),
260  from_table}
261 {}
262 
263 
264 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
265 {
266  if (m_finished)
267  return *this;
268  constexpr auto tup_size{std::tuple_size_v<Tuple>};
269  m_fields.reserve(tup_size);
270  parse_line();
271  if (m_finished)
272  return *this;
273 
274  if (std::size(m_fields) != tup_size)
275  throw usage_error{internal::concat(
276  "Tried to extract ", tup_size, " field(s) from a stream of ",
277  std::size(m_fields), ".")};
278 
279  extract_fields(t, std::make_index_sequence<tup_size>{});
280  return *this;
281 }
282 
283 
284 template<typename Tuple, std::size_t index>
285 inline void stream_from::extract_value(Tuple &t) const
286 {
287  using field_type = strip_t<decltype(std::get<index>(t))>;
288  using nullity = nullness<field_type>;
289  assert(index < std::size(m_fields));
290  if constexpr (nullity::always_null)
291  {
292  if (m_fields[index].data() != nullptr)
293  throw conversion_error{"Streaming non-null value into null field."};
294  }
295  else if (m_fields[index].data() == nullptr)
296  {
297  if constexpr (nullity::has_null)
298  std::get<index>(t) = nullity::null();
299  else
300  internal::throw_null_conversion(type_name<field_type>);
301  }
302  else
303  {
304  // Don't ever try to convert a non-null value to nullptr_t!
305  std::get<index>(t) = from_string<field_type>(m_fields[index]);
306  }
307 }
308 } // namespace pqxx
309 
310 #include "pqxx/internal/compiler-internal-post.hxx"
311 #endif
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:178
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:71
bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition: stream_from.hxx:155
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:35
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
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:40
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:59
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:138
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:164
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:264
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:55
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:143
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:36
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:186
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:131
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:242
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:71
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:37
Stream data from the database.
Definition: stream_from.hxx:67