libpqxx  7.0.6
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 <variant>
20 
21 #include "pqxx/except.hxx"
22 #include "pqxx/internal/stream_iterator.hxx"
23 #include "pqxx/separated_list.hxx"
24 #include "pqxx/transaction_base.hxx"
25 
26 
27 namespace pqxx
28 {
31 {
32 public:
33  stream_from(transaction_base &, std::string_view table_name);
34  template<typename Columns>
36  transaction_base &, std::string_view table_name, Columns const &columns);
37  template<typename Iter>
39  transaction_base &, std::string_view table_name, Iter columns_begin,
40  Iter columns_end);
41 
42  ~stream_from() noexcept;
43 
44  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
45  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
46 
48 
54  void complete();
55 
56  bool get_raw_line(std::string &);
57  template<typename Tuple> stream_from &operator>>(Tuple &);
58 
60  template<typename... Vs>
61  stream_from &operator>>(std::variant<Vs...> &) = delete;
62 
64 
68  template<typename... TYPE>[[nodiscard]] auto iter()
69  {
70  return pqxx::internal::stream_input_iteration<TYPE...>{*this};
71  }
72 
73 private:
74  internal::encoding_group m_copy_encoding =
75  internal::encoding_group::MONOBYTE;
76  std::string m_current_line;
77  bool m_finished = false;
78  bool m_retry_line = false;
79 
80  void set_up(transaction_base &, std::string_view table_name);
81  void set_up(
82  transaction_base &, std::string_view table_name,
83  std::string const &columns);
84 
85  void close();
86 
87  bool extract_field(
88  std::string const &, std::string::size_type &, std::string &) const;
89 
90  template<typename T>
91  void extract_value(
92  std::string const &line, T &t, std::string::size_type &here,
93  std::string &workspace) const;
94 
95  template<typename Tuple, std::size_t... I>
96  void do_extract(
97  const std::string &line, Tuple &t, std::string &workspace,
98  std::index_sequence<I...>)
99  {
100  std::string::size_type here{};
101  (extract_value(line, std::get<I>(t), here, workspace), ...);
102  if (
103  here < line.size() and
104  not(here == line.size() - 1 and line[here] == '\n'))
105  throw usage_error{"Not all fields extracted from stream_from line"};
106  }
107 };
108 
109 
110 template<typename Columns>
112  transaction_base &tb, std::string_view table_name, Columns const &columns) :
113  stream_from{tb, table_name, std::begin(columns), std::end(columns)}
114 {}
115 
116 
117 template<typename Iter>
119  transaction_base &tb, std::string_view table_name, Iter columns_begin,
120  Iter columns_end) :
121  namedclass{"stream_from", table_name},
122  transactionfocus{tb}
123 {
124  set_up(tb, table_name, separated_list(",", columns_begin, columns_end));
125 }
126 
127 
128 template<typename Tuple> stream_from &stream_from::operator>>(Tuple &t)
129 {
130  if (m_retry_line or get_raw_line(m_current_line))
131  {
132  // This is just a scratchpad for functions further down to play with.
133  // We allocate it here so that we can keep re-using its buffer, rather
134  // than always allocating new ones.
135  std::string workspace;
136  try
137  {
138  constexpr auto tsize = std::tuple_size_v<Tuple>;
139  using indexes = std::make_index_sequence<tsize>;
140  do_extract(m_current_line, t, workspace, indexes{});
141  m_retry_line = false;
142  }
143  catch (...)
144  {
145  m_retry_line = true;
146  throw;
147  }
148  }
149  return *this;
150 }
151 
152 
153 template<typename T>
154 void stream_from::extract_value(
155  std::string const &line, T &t, std::string::size_type &here,
156  std::string &workspace) const
157 {
158  if (extract_field(line, here, workspace))
159  t = from_string<T>(workspace);
160  else if constexpr (nullness<T>::has_null)
161  t = nullness<T>::null();
162  else
163  internal::throw_null_conversion(type_name<T>);
164 }
165 
166 template<>
167 void PQXX_LIBEXPORT stream_from::extract_value<std::nullptr_t>(
168  std::string const &line, std::nullptr_t &, std::string::size_type &here,
169  std::string &workspace) const;
170 } // namespace pqxx
171 
172 #include "pqxx/internal/compiler-internal-post.hxx"
173 #endif
pqxx::is_null
bool is_null(TYPE const &value)
Is value null?
Definition: strconv.hxx:286
pqxx::conversion_error
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:178
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
pqxx::nullness::null
static TYPE null()
Return a null value.
pqxx::stream_from::get_raw_line
bool get_raw_line(std::string &)
Definition: stream_from.cxx:80
pqxx::internal::enc_group
encoding_group enc_group(int libpq_enc_id)
Definition: encodings.cxx:585
pqxx::internal::throw_null_conversion
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:241
pqxx::transaction_base::exec0
result exec0(std::string const &query, std::string const &desc=std::string{})
Execute query, which should zero rows of data.
Definition: transaction_base.hxx:251
pqxx::stream_from::operator!
bool operator!() const noexcept
Definition: stream_from.hxx:45
pqxx::transaction_base
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:97
pqxx::broken_connection
Exception class for lost or failed backend connection.
Definition: except.hxx:67
pqxx::stream_from::operator>>
stream_from & operator>>(Tuple &)
Definition: stream_from.hxx:128
pqxx::internal::find_with_encoding
std::string::size_type find_with_encoding(encoding_group enc, std::string_view haystack, char needle, std::string::size_type start)
Definition: encodings.cxx:728
pqxx::stream_from
Efficiently pull data directly out of a table.
Definition: stream_from.hxx:30
pqxx::stream_from::complete
void complete()
Finish this stream. Call this before continuing to use the connection.
Definition: stream_from.cxx:129
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::nullness
Traits describing a type's "null value," if any.
Definition: strconv.hxx:86
pqxx::stream_from::stream_from
stream_from(transaction_base &, std::string_view table_name)
Definition: stream_from.cxx:58
pqxx::stream_from::~stream_from
~stream_from() noexcept
Definition: stream_from.cxx:67
pqxx::internal::transactionfocus
Definition: transaction_base.hxx:42
pqxx::usage_error
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:164
pqxx::stream_from::iter
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:68