libpqxx  7.1.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-2020, 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/encoding_group.hxx"
25 #include "pqxx/internal/stream_iterator.hxx"
26 #include "pqxx/internal/transaction_focus.hxx"
27 #include "pqxx/separated_list.hxx"
28 #include "pqxx/transaction_base.hxx"
29 
30 
31 namespace pqxx
32 {
37 
38 
40 
60 class PQXX_LIBEXPORT stream_from : internal::transactionfocus
61 {
62 public:
63  using raw_line =
64  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
65 
67 
76  stream_from(transaction_base &, from_query_t, std::string_view query);
77 
79  stream_from(transaction_base &, from_table_t, std::string_view table);
80 
82  template<typename Iter>
84  transaction_base &, from_table_t, std::string_view table,
85  Iter columns_begin, Iter columns_end);
86 
88  template<typename Columns>
90  transaction_base &tx, from_table_t, std::string_view table,
91  Columns const &columns);
92 
94  stream_from(transaction_base &tx, std::string_view table) :
95  stream_from{tx, from_table, table}
96  {}
97 
99  template<typename Columns>
101  transaction_base &tx, std::string_view table, Columns const &columns) :
102  stream_from{tx, from_table, table, columns}
103  {}
104 
106  template<typename Iter>
107  stream_from(
108  transaction_base &, std::string_view table, Iter columns_begin,
109  Iter columns_end);
110 
111  ~stream_from() noexcept;
112 
113  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
114  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
115 
117 
123  void complete();
124 
126 
133  raw_line get_raw_line();
134  template<typename Tuple> stream_from &operator>>(Tuple &);
135 
137  template<typename... Vs>
138  stream_from &operator>>(std::variant<Vs...> &) = delete;
139 
141 
145  template<typename... TYPE>[[nodiscard]] auto iter()
146  {
147  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
148  }
149 
150 private:
151  stream_from(
152  transaction_base &tx, std::string_view table, std::string &&columns,
153  from_table_t);
154 
155  template<typename Tuple, std::size_t... indexes>
156  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
157  {
158  (extract_value<Tuple, indexes>(t), ...);
159  }
160 
161  static std::string compose_query(
162  transaction_base const &tx, std::string_view table,
163  std::string const &columns);
164 
165  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
166 
168  std::string m_row;
169 
171  std::vector<zview> m_fields;
172 
173  bool m_finished = false;
174 
175  void close();
176 
177  template<typename Tuple, std::size_t index>
178  void extract_value(Tuple &) const;
179 
181  void parse_line();
182 };
183 
184 
185 template<typename Columns>
187  transaction_base &tb, from_table_t, std::string_view table_name,
188  Columns const &columns) :
189  stream_from{tb, from_table, table_name, std::begin(columns),
190  std::end(columns)}
191 {}
192 
193 
194 template<typename Iter>
196  transaction_base &tx, from_table_t, std::string_view table,
197  Iter columns_begin, Iter columns_end) :
198  stream_from{tx, table, separated_list(",", columns_begin, columns_end),
199  from_table}
200 {}
201 
202 
203 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
204 {
205  if (m_finished)
206  return *this;
207  constexpr auto tup_size{std::tuple_size_v<Tuple>};
208  m_fields.reserve(tup_size);
209  parse_line();
210  if (m_finished)
211  return *this;
212 
213  if (m_fields.size() != tup_size)
214  throw usage_error{"Tried to extract " + to_string(tup_size) +
215  " field(s) from a stream of " +
216  to_string(m_fields.size()) + "."};
217 
218  extract_fields(t, std::make_index_sequence<tup_size>{});
219  return *this;
220 }
221 
222 
223 template<typename Tuple, std::size_t index>
224 inline void stream_from::extract_value(Tuple &t) const
225 {
226  using field_type = strip_t<decltype(std::get<index>(t))>;
227  using nullity = nullness<field_type>;
228  assert(index < m_fields.size());
229  if constexpr (nullity::always_null)
230  {
231  if (m_fields[index].data() != nullptr)
232  throw conversion_error{"Streaming non-null value into null field."};
233  }
234  else if (m_fields[index].data() == nullptr)
235  {
236  if constexpr (nullity::has_null)
237  std::get<index>(t) = nullity::null();
238  else
239  internal::throw_null_conversion(type_name<field_type>);
240  }
241  else
242  {
243  // Don't ever try to convert a non-null value to nullptr_t!
244  std::get<index>(t) = from_string<field_type>(m_fields[index]);
245  }
246 }
247 } // namespace pqxx
248 
249 #include "pqxx/internal/compiler-internal-post.hxx"
250 #endif
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:64
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:56
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:145
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:477
bool operator!() const noexcept
Definition: stream_from.hxx:114
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:117
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:100
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
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:36
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:55
Stream data from the database.
Definition: stream_from.hxx:60
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:94
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:241
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:67
stream_from & operator>>(Tuple &)
Definition: stream_from.hxx:203
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:34
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:164
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:59
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:178