stream_from.hxx
/* Definition of the pqxx::stream_from class.
*
* pqxx::stream_from enables optimized batch reads from a database table.
*
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
*
* Copyright (c) 2000-2023, Jeroen T. Vermeulen.
*
* See COPYING for copyright license. If you did not receive a file called
* COPYING with this source code, please notify the distributor of this
* mistake, or contact the author.
*/
#ifndef PQXX_H_STREAM_FROM
#define PQXX_H_STREAM_FROM
#if !defined(PQXX_HEADER_PRE)
# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
#endif
#include <cassert>
#include <variant>
#include "pqxx/connection.hxx"
#include "pqxx/except.hxx"
#include "pqxx/internal/concat.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/internal/stream_iterator.hxx"
#include "pqxx/separated_list.hxx"
#include "pqxx/transaction_focus.hxx"
namespace pqxx
{
class transaction_base;
constexpr from_table_t from_table;
constexpr from_query_t from_query;
class PQXX_LIBEXPORT stream_from : transaction_focus
{
public:
using raw_line =
std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>;
stream_from(stream_from &&) = delete;
stream_from &operator=(stream_from &&) = delete;
[[deprecated("Use transaction_base::stream instead.")]] static stream_from
query(transaction_base &tx, std::string_view q)
{
#include "pqxx/internal/ignore-deprecated-pre.hxx"
return {tx, from_query, q};
#include "pqxx/internal/ignore-deprecated-post.hxx"
}
[[deprecated("Use transaction_base::stream instead.")]] static stream_from
raw_table(
transaction_base &tx, std::string_view path,
std::string_view columns = ""sv);
[[deprecated("Use transaction_base::stream instead.")]] static stream_from
table(
transaction_base &tx, table_path path,
std::initializer_list<std::string_view> columns = {});
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &, from_query_t, std::string_view query);
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &, from_table_t, std::string_view table);
template<typename Iter>
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &, from_table_t, std::string_view table,
Iter columns_begin, Iter columns_end);
template<typename Columns>
[[deprecated("Use transaction_base::stream() instead.")]] stream_from(
transaction_base &tx, from_table_t, std::string_view table,
Columns const &columns);
#include "pqxx/internal/ignore-deprecated-pre.hxx"
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &tx, std::string_view table) :
stream_from{tx, from_table, table}
{}
#include "pqxx/internal/ignore-deprecated-post.hxx"
template<typename Columns>
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &tx, std::string_view table, Columns const &columns) :
stream_from{tx, from_table, table, columns}
{}
template<typename Iter>
[[deprecated("Use transaction_base::stream instead.")]] stream_from(
transaction_base &, std::string_view table, Iter columns_begin,
Iter columns_end);
~stream_from() noexcept;
[[nodiscard]] constexpr operator bool() const noexcept
{
return not m_finished;
}
[[nodiscard]] constexpr bool operator!() const noexcept
{
return m_finished;
}
void complete();
template<typename Tuple> stream_from &operator>>(Tuple &);
template<typename... Vs>
stream_from &operator>>(std::variant<Vs...> &) = delete;
template<typename... TYPE> [[nodiscard]] auto iter() &
{
return pqxx::internal::stream_input_iteration<TYPE...>{*this};
}
std::vector<zview> const *read_row() &;
raw_line get_raw_line();
private:
// TODO: Clean up this signature once we cull the deprecated constructors.
stream_from(
transaction_base &tx, std::string_view table, std::string_view columns,
from_table_t);
// TODO: Clean up this signature once we cull the deprecated constructors.
stream_from(
transaction_base &, std::string_view unquoted_table,
std::string_view columns, from_table_t, int);
template<typename Tuple, std::size_t... indexes>
void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
{
(extract_value<Tuple, indexes>(t), ...);
}
pqxx::internal::char_finder_func *m_char_finder;
std::string m_row;
std::vector<zview> m_fields;
bool m_finished = false;
void close();
template<typename Tuple, std::size_t index>
void extract_value(Tuple &) const;
void parse_line();
};
template<typename Columns>
inline stream_from::stream_from(
transaction_base &tx, from_table_t, std::string_view table_name,
Columns const &columns) :
stream_from{
tx, from_table, table_name, std::begin(columns), std::end(columns)}
{}
template<typename Iter>
inline stream_from::stream_from(
transaction_base &tx, from_table_t, std::string_view table,
Iter columns_begin, Iter columns_end) :
stream_from{
tx, table, separated_list(",", columns_begin, columns_end),
from_table, 1}
{}
template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
{
if (m_finished)
PQXX_UNLIKELY return *this;
static constexpr auto tup_size{std::tuple_size_v<Tuple>};
m_fields.reserve(tup_size);
parse_line();
if (m_finished)
PQXX_UNLIKELY return *this;
if (std::size(m_fields) != tup_size)
throw usage_error{internal::concat(
"Tried to extract ", tup_size, " field(s) from a stream of ",
std::size(m_fields), ".")};
extract_fields(t, std::make_index_sequence<tup_size>{});
return *this;
}
template<typename Tuple, std::size_t index>
inline void stream_from::extract_value(Tuple &t) const
{
using field_type = strip_t<decltype(std::get<index>(t))>;
using nullity = nullness<field_type>;
assert(index < std::size(m_fields));
if constexpr (nullity::always_null)
{
if (std::data(m_fields[index]) != nullptr)
throw conversion_error{"Streaming non-null value into null field."};
}
else if (std::data(m_fields[index]) == nullptr)
{
if constexpr (nullity::has_null)
std::get<index>(t) = nullity::null();
else
internal::throw_null_conversion(type_name<field_type>);
}
else
{
// Don't ever try to convert a non-null value to nullptr_t!
std::get<index>(t) = from_string<field_type>(m_fields[index]);
}
}
} // namespace pqxx
#endif
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
pqxx::separated_list
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:44
pqxx::strip_t
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
pqxx::from_query
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition stream_from.hxx:44
pqxx::from_table
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition stream_from.hxx:40
pqxx::table_path
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
pqxx::internal::throw_null_conversion
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
pqxx::usage_error
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
pqxx::conversion_error
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
pqxx::nullness
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
pqxx::stream_from
Stream data from the database.
Definition stream_from.hxx:79
pqxx::stream_from::query
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition stream_from.hxx:98
pqxx::stream_from::operator>>
stream_from & operator>>(std::variant< Vs... > &)=delete
Doing this with a std::variant is going to be horrifically borked.
pqxx::stream_from::operator>>
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition stream_from.hxx:323
pqxx::stream_from::stream_from
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition stream_from.hxx:185
pqxx::stream_from::raw_line
std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t > raw_line
Definition stream_from.hxx:82
pqxx::stream_from::stream_from
stream_from(stream_from &&)=delete
pqxx::stream_from::stream_from
stream_from(transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end)
pqxx::stream_from::operator=
stream_from & operator=(stream_from &&)=delete
pqxx::stream_from::stream_from
stream_from(transaction_base &tx, std::string_view table)
Definition stream_from.hxx:177
pqxx::stream_from::iter
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition stream_from.hxx:237
pqxx::stream_from::operator!
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition stream_from.hxx:204
pqxx::transaction_base
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
pqxx::transaction_focus
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
pqxx::from_table_t
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:68
pqxx::from_query_t
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:74