libpqxx
The C++ client library for PostgreSQL
Loading...
Searching...
No Matches
stream_from.hxx
Go to the documentation of this file.
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-2025, 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#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18#endif
19
20#include <cassert>
21#include <optional>
22#include <variant>
23
24#include "pqxx/connection.hxx"
25#include "pqxx/except.hxx"
31
32
33namespace pqxx
34{
35class transaction_base;
36
37
39
43
46
47
49
79class PQXX_LIBEXPORT stream_from : transaction_focus
80{
81public:
82 using raw_line =
83 std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>;
84
85 stream_from(stream_from &&) = delete;
86 stream_from &operator=(stream_from &&) = delete;
87
89
98 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
99 query(transaction_base &tx, std::string_view q)
100 {
102 return {tx, from_query, q};
104 }
105
116
118
134 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
135 raw_table(
136 transaction_base &tx, std::string_view path,
137 std::string_view columns = ""sv);
138
140
142 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
143 table(
144 transaction_base &tx, table_path path,
145 std::initializer_list<std::string_view> columns = {});
147
149
151 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
152 transaction_base &, from_query_t, std::string_view query);
153
155
157 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
158 transaction_base &, from_table_t, std::string_view table);
159
161
163 template<typename Iter>
164 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
165 transaction_base &, from_table_t, std::string_view table,
166 Iter columns_begin, Iter columns_end);
167
169
171 template<typename Columns>
172 [[deprecated("Use transaction_base::stream() instead.")]] stream_from(
173 transaction_base &tx, from_table_t, std::string_view table,
174 Columns const &columns);
175
178 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
179 transaction_base &tx, std::string_view table) :
180 stream_from{tx, from_table, table}
181 {}
183
185 template<typename Columns>
186 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
187 transaction_base &tx, std::string_view table, Columns const &columns) :
188 stream_from{tx, from_table, table, columns}
189 {}
190
192 template<typename Iter>
193 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
194 transaction_base &, std::string_view table, Iter columns_begin,
195 Iter columns_end);
196
197 ~stream_from() noexcept;
198
200 [[nodiscard]] constexpr operator bool() const noexcept
201 {
202 return not m_finished;
203 }
205 [[nodiscard]] constexpr bool operator!() const noexcept
206 {
207 return m_finished;
208 }
209
211
217 void complete();
218
220
227 template<typename Tuple> stream_from &operator>>(Tuple &);
228
230 template<typename... Vs>
231 stream_from &operator>>(std::variant<Vs...> &) = delete;
232
234
238 template<typename... TYPE> [[nodiscard]] auto iter() &
239 {
240 return pqxx::internal::stream_input_iteration<TYPE...>{*this};
241 }
242
244
260 std::vector<zview> const *read_row() &;
261
263
264 raw_line get_raw_line();
265
266private:
267 // TODO: Clean up this signature once we cull the deprecated constructors.
269 stream_from(
270 transaction_base &tx, std::string_view table, std::string_view columns,
272
273 // TODO: Clean up this signature once we cull the deprecated constructors.
275 stream_from(
276 transaction_base &, std::string_view unquoted_table,
277 std::string_view columns, from_table_t, int);
278
279 template<typename Tuple, std::size_t... indexes>
280 void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
281 {
282 (extract_value<Tuple, indexes>(t), ...);
283 }
284
286
288 std::string m_row;
289
291 std::vector<zview> m_fields;
292
293 bool m_finished = false;
294
295 void close();
296
297 template<typename Tuple, std::size_t index>
298 void extract_value(Tuple &) const;
299
301 void parse_line();
302};
303
304
305template<typename Columns>
306inline stream_from::stream_from(
307 transaction_base &tx, from_table_t, std::string_view table_name,
308 Columns const &columns) :
309 stream_from{
310 tx, from_table, table_name, std::begin(columns), std::end(columns)}
311{}
312
313
314template<typename Iter>
315inline stream_from::stream_from(
316 transaction_base &tx, from_table_t, std::string_view table,
317 Iter columns_begin, Iter columns_end) :
318 stream_from{
319 tx, table, separated_list(",", columns_begin, columns_end),
320 from_table, 1}
321{}
322
323
324template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
325{
326 if (m_finished)
327 PQXX_UNLIKELY return *this;
328 static constexpr auto tup_size{std::tuple_size_v<Tuple>};
329 m_fields.reserve(tup_size);
330 parse_line();
331 if (m_finished)
332 PQXX_UNLIKELY return *this;
333
334 if (std::size(m_fields) != tup_size)
335 throw usage_error{internal::concat(
336 "Tried to extract ", tup_size, " field(s) from a stream of ",
337 std::size(m_fields), ".")};
338
339 extract_fields(t, std::make_index_sequence<tup_size>{});
340 return *this;
341}
342
343
344template<typename Tuple, std::size_t index>
345inline void stream_from::extract_value(Tuple &t) const
346{
347 using field_type = strip_t<decltype(std::get<index>(t))>;
348 using nullity = nullness<field_type>;
349 assert(index < std::size(m_fields));
350 if constexpr (nullity::always_null)
351 {
352 if (std::data(m_fields[index]) != nullptr)
353 throw conversion_error{"Streaming non-null value into null field."};
354 }
355 else if (std::data(m_fields[index]) == nullptr)
356 {
357 if constexpr (nullity::has_null)
358 std::get<index>(t) = nullity::null();
359 else
360 internal::throw_null_conversion(type_name<field_type>);
361 }
362 else
363 {
364 // Don't ever try to convert a non-null value to nullptr_t!
365 std::get<index>(t) = from_string<field_type>(m_fields[index]);
366 }
367}
368} // namespace pqxx
369#endif
Iteration over a stream_query.
Definition stream_iterator.hxx:79
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
#define PQXX_LIBEXPORT
Definition header-pre.hxx:157
#define PQXX_UNLIKELY
Definition header-pre.hxx:181
std::size_t(std::string_view haystack, std::size_t start) char_finder_func
Function type: "find first occurrence of specific any of ASCII characters.".
Definition encoding_group.hxx:70
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
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:46
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition stream_from.hxx:45
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition stream_from.hxx:41
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:232
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:171
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:165