libpqxx  7.3.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/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 
61 class PQXX_LIBEXPORT stream_from : internal::transactionfocus
62 {
63 public:
64  using raw_line =
65  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>;
66 
68 
77  stream_from(transaction_base &, from_query_t, std::string_view query);
78 
80 
83  stream_from(transaction_base &, from_table_t, std::string_view table);
84 
86 
89  template<typename Iter>
91  transaction_base &, from_table_t, std::string_view table,
92  Iter columns_begin, Iter columns_end);
93 
95 
98  template<typename Columns>
100  transaction_base &tx, from_table_t, std::string_view table,
101  Columns const &columns);
102 
104  stream_from(transaction_base &tx, std::string_view table) :
105  stream_from{tx, from_table, table}
106  {}
107 
109  template<typename Columns>
111  transaction_base &tx, std::string_view table, Columns const &columns) :
112  stream_from{tx, from_table, table, columns}
113  {}
114 
116  template<typename Iter>
118  transaction_base &, std::string_view table, Iter columns_begin,
119  Iter columns_end);
120 
121  ~stream_from() noexcept;
122 
123  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
124  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
125 
127 
133  void complete();
134 
136 
143  template<typename Tuple> stream_from &operator>>(Tuple &);
144 
146  template<typename... Vs>
147  stream_from &operator>>(std::variant<Vs...> &) = delete;
148 
150 
154  template<typename... TYPE> [[nodiscard]] auto iter()
155  {
156  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
157  }
158 
160 
176  std::vector<zview> const *read_row();
177 
179 
180  raw_line get_raw_line();
181 
182 private:
183  stream_from(
184  transaction_base &tx, std::string_view table, std::string &&columns,
185  from_table_t);
186 
187  template<typename Tuple, std::size_t... indexes>
188  void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
189  {
190  (extract_value<Tuple, indexes>(t), ...);
191  }
192 
193  pqxx::internal::glyph_scanner_func *m_glyph_scanner;
194 
196  std::string m_row;
197 
199  std::vector<zview> m_fields;
200 
201  bool m_finished = false;
202 
203  void close();
204 
205  template<typename Tuple, std::size_t index>
206  void extract_value(Tuple &) const;
207 
209  void parse_line();
210 };
211 
212 
213 template<typename Columns>
215  transaction_base &tb, from_table_t, std::string_view table_name,
216  Columns const &columns) :
217  stream_from{
218  tb, from_table, table_name, std::begin(columns), std::end(columns)}
219 {}
220 
221 
222 template<typename Iter>
224  transaction_base &tx, from_table_t, std::string_view table,
225  Iter columns_begin, Iter columns_end) :
226  stream_from{
227  tx, table, separated_list(",", columns_begin, columns_end),
228  from_table}
229 {}
230 
231 
232 template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
233 {
234  if (m_finished)
235  return *this;
236  constexpr auto tup_size{std::tuple_size_v<Tuple>};
237  m_fields.reserve(tup_size);
238  parse_line();
239  if (m_finished)
240  return *this;
241 
242  if (std::size(m_fields) != tup_size)
243  throw usage_error{internal::concat(
244  "Tried to extract ", tup_size, " field(s) from a stream of ",
245  std::size(m_fields), ".")};
246 
247  extract_fields(t, std::make_index_sequence<tup_size>{});
248  return *this;
249 }
250 
251 
252 template<typename Tuple, std::size_t index>
253 inline void stream_from::extract_value(Tuple &t) const
254 {
255  using field_type = strip_t<decltype(std::get<index>(t))>;
256  using nullity = nullness<field_type>;
257  assert(index < std::size(m_fields));
258  if constexpr (nullity::always_null)
259  {
260  if (m_fields[index].data() != nullptr)
261  throw conversion_error{"Streaming non-null value into null field."};
262  }
263  else if (m_fields[index].data() == nullptr)
264  {
265  if constexpr (nullity::has_null)
266  std::get<index>(t) = nullity::null();
267  else
268  internal::throw_null_conversion(type_name<field_type>);
269  }
270  else
271  {
272  // Don't ever try to convert a non-null value to nullptr_t!
273  std::get<index>(t) = from_string<field_type>(m_fields[index]);
274  }
275 }
276 } // namespace pqxx
277 
278 #include "pqxx/internal/compiler-internal-post.hxx"
279 #endif
pqxx::stream_from::raw_line
std::pair< std::unique_ptr< char, std::function< void(char *)> >, std::size_t > raw_line
Definition: stream_from.hxx:65
pqxx::from_table_t
Marker for stream_from constructors: "stream from table.".
Definition: types.hxx:56
pqxx::nullness
Traits describing a type's "null value," if any.
Definition: strconv.hxx:87
pqxx::conversion_error
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:179
pqxx::stream_from::stream_from
stream_from(transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end)
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
pqxx::stream_from::~stream_from
~stream_from() noexcept
Definition: stream_from.cxx:67
pqxx::stream_from::stream_from
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition: stream_from.hxx:110
pqxx::stream_from::operator!
bool operator!() const noexcept
Definition: stream_from.hxx:124
pqxx::internal::enc_group
encoding_group enc_group(int libpq_enc_id)
Definition: encodings.cxx:571
pqxx::internal::throw_null_conversion
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:242
pqxx::stream_from::get_raw_line
raw_line get_raw_line()
Read a raw line of text from the COPY command.
Definition: stream_from.cxx:80
pqxx::connection::encoding_id
int encoding_id() const
Get the connection's encoding, as a PostgreSQL-defined code.
Definition: connection.cxx:1071
pqxx::stream_from::complete
void complete()
Finish this stream. Call this before continuing to use the connection.
Definition: stream_from.cxx:115
pqxx::stream_from::read_row
std::vector< zview > const * read_row()
Read a row. Return fields as views, valid until you read the next row.
Definition: stream_from.cxx:285
pqxx::stream_from::operator>>
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition: stream_from.hxx:232
pqxx::usage_error
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:165
pqxx::stream_from::stream_from
stream_from(transaction_base &tx, std::string_view table)
Definition: stream_from.hxx:104
pqxx::internal::get_glyph_scanner
PQXX_PURE glyph_scanner_func * get_glyph_scanner(encoding_group enc)
Definition: encodings.cxx:670
pqxx::broken_connection
Exception class for lost or failed backend connection.
Definition: except.hxx:68
pqxx::transaction_base
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:72
pqxx::transaction_base::conn
connection & conn() const
The connection in which this transaction lives.
Definition: transaction_base.hxx:451
pqxx::stream_from::iter
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:154
pqxx::from_query
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition: stream_from.hxx:37
pqxx::transaction_base::exec0
result exec0(zview query, std::string_view desc=std::string_view{})
Execute query, which should zero rows of data.
Definition: transaction_base.hxx:221
pqxx::separated_list
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
pqxx::from_table
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition: stream_from.hxx:35
pqxx::from_query_t
Marker for stream_from constructors: "stream from query.".
Definition: types.hxx:60
pqxx::stream_from::stream_from
stream_from(transaction_base &, from_query_t, std::string_view query)
Execute query, and stream over the results.
Definition: stream_from.cxx:36
pqxx::stream_from
Stream data from the database.
Definition: stream_from.hxx:62
pqxx::stream_from::operator>>
stream_from & operator>>(std::variant< Vs... > &)=delete
Doing this with a std::variant is going to be horrifically borked.
pqxx::ignore_unused
void ignore_unused(T &&...)
Suppress compiler warning about an unused item.
Definition: util.hxx:67
pqxx::strip_t
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