libpqxx  7.0.2
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
stream_from(transaction_base &, std::string_view table_name)
Definition: stream_from.cxx:58
Definition: transaction_base.hxx:42
auto iter()
Iterate over this stream. Supports range-based "for" loops.
Definition: stream_from.hxx:68
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
bool operator!() const noexcept
Definition: stream_from.hxx:45
Dedicated namespace for helper types related to prepared statements.
Definition: array.hxx:25
Efficiently pull data directly out of a table.
Definition: stream_from.hxx:30
bool get_raw_line(std::string &)
Definition: stream_from.cxx:80
stream_from & operator>>(Tuple &)
Definition: stream_from.hxx:128