13#ifndef PQXX_H_STREAM_QUERY
14#define PQXX_H_STREAM_QUERY
16#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
24#include "pqxx/connection.hxx"
25#include "pqxx/except.hxx"
26#include "pqxx/internal/concat.hxx"
27#include "pqxx/internal/encoding_group.hxx"
28#include "pqxx/internal/encodings.hxx"
29#include "pqxx/internal/gates/connection-stream_from.hxx"
30#include "pqxx/internal/stream_iterator.hxx"
31#include "pqxx/separated_list.hxx"
32#include "pqxx/transaction_base.hxx"
33#include "pqxx/transaction_focus.hxx"
34#include "pqxx/util.hxx"
39class transaction_base;
82 using line_handle = std::unique_ptr<char, void (*)(
void const *)>;
96 catch (std::exception
const &e)
98 reg_pending_error(e.what());
103 bool done() const & noexcept {
return m_char_finder ==
nullptr; }
106 inline auto begin() &;
119 auto const line_size{std::size(line)};
129 m_row.resize(line_size + 1);
131 std::size_t offset{0u};
132 char *write{m_row.data()};
139 std::tuple<TYPE...> data{parse_field<TYPE>(line, offset, write)...};
141 assert(offset == line_size + 1u);
146 std::pair<line_handle, std::size_t>
read_line() &;
170 std::tuple<std::size_t, char *, zview>
171 read_field(
zview line, std::size_t offset,
char *write)
174 auto const line_size{std::size(line)};
177 assert(offset <= line_size);
179 char const *lp{std::data(line)};
183 assert(lp[line_size] ==
'\t');
184 assert(lp[line_size + 1] ==
'\0');
186 if ((lp[offset] ==
'\\') and (lp[offset + 1] ==
'N'))
190 assert(offset <= (line_size + 1));
191 assert(lp[offset - 1] ==
'\t');
193 return {offset, write, {}};
197 char const *
const field_begin{write};
206 while (lp[offset] !=
'\t')
208 assert(lp[offset] !=
'\0');
211 auto const stop_char{m_char_finder(line, offset)};
212 PQXX_ASSUME(stop_char > offset);
213 assert(stop_char < (line_size + 1));
216 std::memcpy(write, &lp[offset], stop_char - offset);
217 write += (stop_char - offset);
221 char const special{lp[offset]};
227 assert(offset < line_size);
231 char const escaped{lp[offset]};
232 assert((escaped >> 7) == 0);
239 assert(special ==
'\t');
244 assert(lp[offset] ==
'\t');
248 return {offset, write, {field_begin, write - field_begin - 1}};
265 template<
typename TARGET>
266 TARGET parse_field(zview line, std::size_t &offset,
char *&write)
268 using field_type = strip_t<TARGET>;
269 using nullity = nullness<field_type>;
271 assert(offset <= std::size(line));
273 auto [new_offset, new_write, text]{read_field(line, offset, write)};
274 PQXX_ASSUME(new_offset > offset);
275 PQXX_ASSUME(new_write >= write);
278 if constexpr (nullity::always_null)
280 if (std::data(text) !=
nullptr)
281 throw conversion_error{
concat(
282 "Streaming a non-null value into a ", type_name<field_type>,
283 ", which must always be null.")};
285 else if (std::data(text) ==
nullptr)
287 if constexpr (nullity::has_null)
288 return nullity::null();
295 return from_string<field_type>(text);
300 void close() noexcept
304 m_char_finder =
nullptr;
Stream query results from the database. Used by transaction_base::stream.
Definition: stream_query.hxx:80
bool done() const &noexcept
Has this stream reached the end of its data?
Definition: stream_query.hxx:103
stream_query(transaction_base &tx, std::string_view query)
Execute query on tx, stream results.
Definition: stream_query_impl.hxx:12
std::tuple< TYPE... > parse_line(zview line) &
Parse and convert the latest line of data we received.
Definition: stream_query.hxx:115
auto begin() &
Begin iterator. Only for use by "range for.".
Definition: stream_query_impl.hxx:153
std::pair< line_handle, std::size_t > read_line() &
Read a COPY line from the server.
Definition: stream_query_impl.hxx:161
auto end() const &
End iterator. Only for use by "range for.".
Definition: stream_query.hxx:112
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:29
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:150
Internal items for libpqxx' own use. Do not use these yourself.
Definition: encodings.cxx:33
std::string concat(TYPE... item)
Efficiently combine a bunch of items into one big string.
Definition: concat.hxx:31
void throw_null_conversion(std::string const &type)
Throw exception for attempt to convert SQL NULL to given type.
Definition: strconv.cxx:255
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:71
constexpr char unescape_char(char escaped) noexcept
Return original byte for escaped character.
Definition: util.hxx:633
The end() iterator for a stream_query.
Definition: stream_query.hxx:47
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:27