libpqxx
stream_from.hxx
1 
13 #ifndef PQXX_H_STREAM_FROM
14 #define PQXX_H_STREAM_FROM
15 
16 #include "pqxx/compiler-public.hxx"
17 #include "pqxx/compiler-internal-pre.hxx"
18 #include "pqxx/transaction_base.hxx"
19 #include "pqxx/stream_base.hxx"
20 #include "pqxx/internal/type_utils.hxx"
21 
22 #include <string>
23 
24 
25 namespace pqxx
26 {
27 
29 class PQXX_LIBEXPORT stream_from : public stream_base
30 {
31 public:
34  const std::string &table_name
35  );
36  template<typename Columns> stream_from(
38  const std::string &table_name,
39  const Columns& columns
40  );
41  template<typename Iter> stream_from(
43  const std::string &table_name,
44  Iter columns_begin,
45  Iter columns_end
46  );
47 
48  ~stream_from() noexcept;
49 
50  void complete() override;
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  std::string m_current_line;
58  bool m_retry_line;
59 
60  void set_up(transaction_base &, const std::string &table_name);
61  void set_up(
63  const std::string &table_name,
64  const std::string &columns
65  );
66 
67  void close() override;
68 
69  bool extract_field(
70  const std::string &,
71  std::string::size_type &,
72  std::string &
73  ) const;
74 
75  template<typename Tuple, std::size_t I> auto tokenize_ith(
76  const std::string &,
77  Tuple &,
78  std::string::size_type,
79  std::string &
80  ) const -> typename std::enable_if<(
81  std::tuple_size<Tuple>::value > I
82  )>::type;
83  template<typename Tuple, std::size_t I> auto tokenize_ith(
84  const std::string &,
85  Tuple &,
86  std::string::size_type,
87  std::string &
88  ) const -> typename std::enable_if<(
89  std::tuple_size<Tuple>::value <= I
90  )>::type;
91 
92  template<typename T> void extract_value(
93  const std::string &line,
94  T& t,
95  std::string::size_type &here,
96  std::string &workspace
97  ) const;
98 };
99 
100 
101 template<typename Columns> stream_from::stream_from(
102  transaction_base &tb,
103  const std::string &table_name,
104  const Columns& columns
105 ) : stream_from{
106  tb,
107  table_name,
108  std::begin(columns),
109  std::end(columns)
110 } {}
111 
112 
113 template<typename Iter> stream_from::stream_from(
114  transaction_base &tb,
115  const std::string &table_name,
116  Iter columns_begin,
117  Iter columns_end
118 ) :
119  namedclass{"stream_from", table_name},
120  stream_base{tb}
121 {
122  set_up(
123  tb,
124  table_name,
125  columnlist(columns_begin, columns_end)
126  );
127 }
128 
129 
130 template<typename Tuple> stream_from & stream_from::operator>>(
131  Tuple &t
132 )
133 {
134  if (m_retry_line or get_raw_line(m_current_line))
135  {
136  std::string workspace;
137  try
138  {
139  tokenize_ith<Tuple, 0>(m_current_line, t, 0, workspace);
140  m_retry_line = false;
141  }
142  catch (...)
143  {
144  m_retry_line = true;
145  throw;
146  }
147  }
148  return *this;
149 }
150 
151 
152 template<typename Tuple, std::size_t I> auto stream_from::tokenize_ith(
153  const std::string &line,
154  Tuple &t,
155  std::string::size_type here,
156  std::string &workspace
157 ) const -> typename std::enable_if<(
158  std::tuple_size<Tuple>::value > I
159 )>::type
160 {
161  if (here >= line.size())
162  throw usage_error{"Too few fields to extract from stream_from line."};
163 
164  extract_value(line, std::get<I>(t), here, workspace);
165  tokenize_ith<Tuple, I+1>(line, t, here, workspace);
166 }
167 
168 
169 template<typename Tuple, std::size_t I> auto stream_from::tokenize_ith(
170  const std::string &line,
171  Tuple & /* t */,
172  std::string::size_type here,
173  std::string & /* workspace */
174 ) const -> typename std::enable_if<(
175  std::tuple_size<Tuple>::value <= I
176 )>::type
177 {
178  // Zero-column line may still have a trailing newline
179  if (
180  here < line.size() and
181  not (here == line.size() - 1 and line[here] == '\n'))
182  throw usage_error{"Not all fields extracted from stream_from line"};
183 }
184 
185 
186 template<typename T> void stream_from::extract_value(
187  const std::string &line,
188  T& t,
189  std::string::size_type &here,
190  std::string &workspace
191 ) const
192 {
193  if (extract_field(line, here, workspace))
194  from_string<T>(workspace, t);
195  else
196  t = internal::null_value<T>();
197 }
198 
199 template<> void stream_from::extract_value<std::nullptr_t>(
200  const std::string &line,
201  std::nullptr_t&,
202  std::string::size_type &here,
203  std::string &workspace
204 ) const;
205 
206 } // namespace pqxx
207 
208 
209 #include "pqxx/compiler-internal-post.hxx"
210 #endif
bool get_raw_line(std::string &)
Definition: stream_from.cxx:72
Efficiently pull data directly out of a table.
Definition: stream_from.hxx:29
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:218
Definition: stream_base.hxx:27
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:136
namedclass(const std::string &Classname)
Definition: util.hxx:236
stream_from(transaction_base &, const std::string &table_name)
Definition: stream_from.cxx:41
stream_from & operator>>(Tuple &)
Definition: stream_from.hxx:130
static std::string columnlist(const C &)
Definition: stream_base.hxx:48
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25