13#ifndef PQXX_H_STREAM_TO
14#define PQXX_H_STREAM_TO
16#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
105 static stream_to raw_table(
106 transaction_base &tx, std::string_view path, std::string_view columns =
"")
108 return {tx, path, columns};
121 static stream_to table(
122 transaction_base &tx, table_path path,
123 std::initializer_list<std::string_view> columns = {})
125 auto const &cx{tx.conn()};
126 return raw_table(tx, cx.quote_table(path), cx.quote_columns(columns));
129#if defined(PQXX_HAVE_CONCEPTS)
138 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
140 table(transaction_base &tx, table_path path, COLUMNS
const &columns)
142 auto const &cx{tx.conn()};
143 return stream_to::raw_table(
144 tx, cx.quote_table(path), tx.conn().quote_columns(columns));
155 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
157 table(transaction_base &tx, std::string_view path, COLUMNS
const &columns)
159 return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns));
163 explicit stream_to(stream_to &&other) :
166 transaction_focus{std::move(other)},
167 m_finished{other.m_finished},
168 m_buffer{std::move(other.m_buffer)},
169 m_field_buf{std::move(other.m_field_buf)},
170 m_finder{other.m_finder}
172 other.m_finished =
true;
174 ~stream_to() noexcept;
177 [[nodiscard]] constexpr operator
bool() const noexcept
179 return not m_finished;
182 [[nodiscard]]
constexpr bool operator!() const noexcept
206 template<
typename Row> stream_to &
operator<<(Row
const &row)
226 template<
typename Row>
void write_row(Row
const &row)
236 template<
typename... Ts>
void write_values(Ts
const &...fields)
238 fill_buffer(fields...);
252 [[deprecated(
"Use table() or raw_table() factory.")]] stream_to(
253 transaction_base &tx, std::string_view table_name) :
254 stream_to{tx, table_name,
""sv}
260 template<
typename Columns>
261 [[deprecated(
"Use table() or raw_table() factory.")]] stream_to(
262 transaction_base &, std::string_view table_name, Columns
const &columns);
267 transaction_base &tx, std::string_view path, std::string_view columns);
269 bool m_finished =
false;
272 std::string m_buffer;
275 std::string m_field_buf;
278 internal::char_finder_func *m_finder;
281 void write_raw_line(std::string_view);
289 static constexpr std::string_view null_field{
"\\N\t"};
293 static std::enable_if_t<nullness<T>::always_null, std::size_t>
294 estimate_buffer(T
const &)
296 return std::size(null_field);
304 static std::enable_if_t<not nullness<T>::always_null, std::size_t>
305 estimate_buffer(T
const &field)
311 void escape_field_to_buffer(std::string_view data);
320 template<
typename Field>
321 std::enable_if_t<not nullness<Field>::always_null>
322 append_to_buffer(Field
const &f)
330 m_buffer.append(null_field);
336 using traits = string_traits<Field>;
337 auto const budget{estimate_buffer(f)};
338 auto const offset{std::size(m_buffer)};
340 if constexpr (std::is_arithmetic_v<Field>)
348 auto const total{offset + budget};
349 m_buffer.resize(total);
350 auto const data{m_buffer.data()};
351 char *
const end{traits::into_buf(data + offset, data + total, f)};
354 m_buffer.resize(
static_cast<std::size_t
>(end - data));
357 std::is_same_v<Field, std::string> or
358 std::is_same_v<Field, std::string_view> or
359 std::is_same_v<Field, zview>)
362 m_field_buf.resize(budget);
363 escape_field_to_buffer(f);
366 std::is_same_v<Field, std::optional<std::string>> or
367 std::is_same_v<Field, std::optional<std::string_view>> or
368 std::is_same_v<Field, std::optional<zview>>)
372 m_field_buf.resize(budget);
373 escape_field_to_buffer(f.value());
377 std::is_same_v<Field, std::unique_ptr<std::string>> or
378 std::is_same_v<Field, std::unique_ptr<std::string_view>> or
379 std::is_same_v<Field, std::unique_ptr<zview>> or
380 std::is_same_v<Field, std::shared_ptr<std::string>> or
381 std::is_same_v<Field, std::shared_ptr<std::string_view>> or
382 std::is_same_v<Field, std::shared_ptr<zview>>)
387 m_field_buf.resize(budget);
388 escape_field_to_buffer(*f);
394 m_field_buf.resize(budget);
395 auto const data{m_field_buf.data()};
396 escape_field_to_buffer(
397 traits::to_buf(data, data + std::size(m_field_buf), f));
409 template<
typename Field>
410 std::enable_if_t<nullness<Field>::always_null>
411 append_to_buffer(Field
const &)
413 m_buffer.append(null_field);
417 template<
typename Container>
418 std::enable_if_t<not std::is_same_v<typename Container::value_type, char>>
419 fill_buffer(Container
const &c)
424 std::size_t budget{0};
425 for (
auto const &f : c) budget += estimate_buffer(f);
426 m_buffer.reserve(budget);
427 for (
auto const &f : c) append_to_buffer(f);
431 template<
typename Tuple, std::size_t... indexes>
433 budget_tuple(Tuple
const &t, std::index_sequence<indexes...>)
435 return (estimate_buffer(std::get<indexes>(t)) + ...);
439 template<
typename Tuple, std::size_t... indexes>
440 void append_tuple(Tuple
const &t, std::index_sequence<indexes...>)
442 (append_to_buffer(std::get<indexes>(t)), ...);
446 template<
typename... Elts>
void fill_buffer(std::tuple<Elts...>
const &t)
448 using indexes = std::make_index_sequence<
sizeof...(Elts)>;
450 m_buffer.reserve(budget_tuple(t, indexes{}));
451 append_tuple(t, indexes{});
455 template<
typename... Ts>
void fill_buffer(
const Ts &...fields)
457 (..., append_to_buffer(fields));
460 constexpr static std::string_view s_classname{
"stream_to"};
464template<
typename Columns>
465inline stream_to::stream_to(
466 transaction_base &tx, std::string_view table_name, Columns
const &columns) :
467 stream_to{tx, table_name, std::begin(columns), std::end(columns)}
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:537
std::size_t size_buffer(TYPE const &...value) noexcept
Estimate how much buffer space is needed to represent values as a string.
Definition strconv.hxx:527
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition strconv.hxx:516