libpqxx  7.0.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 "pqxx/separated_list.hxx"
20 #include "pqxx/transaction_base.hxx"
21 
22 
23 namespace pqxx
24 {
27 {
28 public:
29  stream_from(transaction_base &, std::string_view table_name);
30  template<typename Columns>
32  transaction_base &, std::string_view table_name, Columns const &columns);
33  template<typename Iter>
35  transaction_base &, std::string_view table_name, Iter columns_begin,
36  Iter columns_end);
37 
38  ~stream_from() noexcept;
39 
40  [[nodiscard]] operator bool() const noexcept { return not m_finished; }
41  [[nodiscard]] bool operator!() const noexcept { return m_finished; }
42 
44 
50  void complete();
51 
52  bool get_raw_line(std::string &);
53  template<typename Tuple> stream_from &operator>>(Tuple &);
54 
55 private:
56  internal::encoding_group m_copy_encoding =
57  internal::encoding_group::MONOBYTE;
58  std::string m_current_line;
59  bool m_finished = false;
60  bool m_retry_line = false;
61 
62  void set_up(transaction_base &, std::string_view table_name);
63  void set_up(
64  transaction_base &, std::string_view table_name,
65  std::string const &columns);
66 
67  void close();
68 
69  bool extract_field(
70  std::string const &, std::string::size_type &, std::string &) const;
71 
72  template<typename Tuple, std::size_t I>
73  auto tokenize_ith(
74  std::string const &, Tuple &, std::string::size_type, std::string &) const
75  -> typename std::enable_if<(std::tuple_size<Tuple>::value > I)>::type;
76  template<typename Tuple, std::size_t I>
77  auto tokenize_ith(
78  std::string const &, Tuple &, std::string::size_type, std::string &) const
79  -> typename std::enable_if<(std::tuple_size<Tuple>::value <= I)>::type;
80 
81  template<typename T>
82  void extract_value(
83  std::string const &line, T &t, std::string::size_type &here,
84  std::string &workspace) const;
85 };
86 
87 
88 template<typename Columns>
90  transaction_base &tb, std::string_view table_name, Columns const &columns) :
91  stream_from{tb, table_name, std::begin(columns), std::end(columns)}
92 {}
93 
94 
95 template<typename Iter>
97  transaction_base &tb, std::string_view table_name, Iter columns_begin,
98  Iter columns_end) :
99  namedclass{"stream_from", table_name},
100  transactionfocus{tb}
101 {
102  set_up(tb, table_name, separated_list(",", columns_begin, columns_end));
103 }
104 
105 
106 template<typename Tuple> stream_from &stream_from::operator>>(Tuple &t)
107 {
108  if (m_retry_line or get_raw_line(m_current_line))
109  {
110  std::string workspace;
111  try
112  {
113  tokenize_ith<Tuple, 0>(m_current_line, t, 0, workspace);
114  m_retry_line = false;
115  }
116  catch (...)
117  {
118  m_retry_line = true;
119  throw;
120  }
121  }
122  return *this;
123 }
124 
125 
126 template<typename Tuple, std::size_t I>
127 auto stream_from::tokenize_ith(
128  std::string const &line, Tuple &t, std::string::size_type here,
129  std::string &workspace) const ->
130  typename std::enable_if<(std::tuple_size<Tuple>::value > I)>::type
131 {
132  if (here >= line.size())
133  throw usage_error{"Too few fields to extract from stream_from line."};
134 
135  extract_value(line, std::get<I>(t), here, workspace);
136  tokenize_ith<Tuple, I + 1>(line, t, here, workspace);
137 }
138 
139 
140 template<typename Tuple, std::size_t I>
141 auto stream_from::tokenize_ith(
142  std::string const &line, Tuple & /* t */, std::string::size_type here,
143  std::string & /* workspace */
144  ) const ->
145  typename std::enable_if<(std::tuple_size<Tuple>::value <= I)>::type
146 {
147  // Zero-column line may still have a trailing newline
148  if (
149  here < line.size() and not(here == line.size() - 1 and line[here] == '\n'))
150  throw usage_error{"Not all fields extracted from stream_from line"};
151 }
152 
153 
154 template<typename T>
155 void stream_from::extract_value(
156  std::string const &line, T &t, std::string::size_type &here,
157  std::string &workspace) const
158 {
159  if (extract_field(line, here, workspace))
160  t = from_string<T>(workspace);
161  else if constexpr (nullness<T>::has_null)
162  t = nullness<T>::null();
163  else
164  internal::throw_null_conversion(type_name<T>);
165 }
166 
167 template<>
168 void PQXX_LIBEXPORT stream_from::extract_value<std::nullptr_t>(
169  std::string const &line, std::nullptr_t &, std::string::size_type &here,
170  std::string &workspace) const;
171 } // namespace pqxx
172 
173 #include "pqxx/internal/compiler-internal-post.hxx"
174 #endif
Efficiently pull data directly out of a table.
Definition: stream_from.hxx:26
bool get_raw_line(std::string &)
Definition: stream_from.cxx:80
bool operator!() const noexcept
Definition: stream_from.hxx:41
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
namedclass(std::string_view classname)
Definition: util.hxx:211
stream_from & operator>>(Tuple &)
Definition: stream_from.hxx:106
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
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:97
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
static TYPE null()
Return a null value.
void throw_null_conversion(std::string const &type)
Definition: strconv.cxx:241
Definition: transaction_base.hxx:42
stream_from(transaction_base &, std::string_view table_name)
Definition: stream_from.cxx:58
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:156