13 #ifndef PQXX_STREAM_TO_HXX
14 #define PQXX_STREAM_TO_HXX
16 #if !defined(PQXX_HEADER_PRE)
17 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
95 std::initializer_list<std::string_view> columns = {})
97 auto const &cx{tx.
conn()};
98 return raw_table(tx, cx.quote_table(path), cx.quote_columns(columns));
109 template<pqxx::
char_
strings COLUMNS>
113 auto const &cx{tx.
conn()};
126 template<pqxx::
char_
strings COLUMNS>
156 sl loc = sl::current())
158 return {tx, path, columns, loc};
174 m_buffer{std::move(other.m_buffer)},
175 m_field_buf{std::move(other.m_field_buf)},
176 m_finder{other.m_finder},
177 m_created_loc{other.m_created_loc},
178 m_finished{other.m_finished}
180 other.m_finished =
true;
191 [[nodiscard]] constexpr operator
bool() const noexcept
193 return not m_finished;
210 void complete(
sl loc = sl::current());
224 write_row(
row, m_created_loc);
255 fill_buffer(fields...);
256 write_buffer(m_created_loc);
265 std::string m_buffer;
268 std::string m_field_buf;
277 bool m_finished =
false;
280 void write_raw_line(std::string_view,
sl);
285 void write_buffer(
sl);
288 static constexpr std::string_view null_field{
"\\N\t"};
292 static constexpr std::size_t estimate_buffer(T
const &)
295 return std::size(null_field);
303 static constexpr std::size_t estimate_buffer(T
const &field)
304 requires(not pqxx::always_null<T>())
310 void escape_field_to_buffer(std::string_view data,
sl loc);
319 template<
typename Field>
320 void append_to_buffer(Field
const &f,
ctx c)
321 requires(not pqxx::always_null<Field>())
329 m_buffer.append(null_field);
334 auto const budget{estimate_buffer(f)};
338 if constexpr (std::is_arithmetic_v<Field>)
343 auto const offset{std::size(m_buffer)};
345 auto const total{offset + budget + 1};
346 m_buffer.resize(total);
347 auto const data{m_buffer.data()};
348 std::size_t
const end{
349 offset +
into_buf({data + offset, data + total}, f, c)};
350 assert((end + 1) < std::size(m_buffer));
351 m_buffer[end] =
'\t';
353 m_buffer.resize(end + 1);
356 std::is_same_v<Field, std::string> or
357 std::is_same_v<Field, std::string_view> or
358 std::is_same_v<Field, zview>)
361 m_field_buf.resize(budget);
362 escape_field_to_buffer(f, c.loc);
365 std::is_same_v<Field, std::optional<std::string>> or
366 std::is_same_v<Field, std::optional<std::string_view>> or
367 std::is_same_v<Field, std::optional<zview>>)
371 m_field_buf.resize(budget);
375 escape_field_to_buffer(f.value(), c.loc);
379 std::is_same_v<Field, std::unique_ptr<std::string>> or
380 std::is_same_v<Field, std::unique_ptr<std::string_view>> or
381 std::is_same_v<Field, std::unique_ptr<zview>> or
382 std::is_same_v<Field, std::shared_ptr<std::string>> or
383 std::is_same_v<Field, std::shared_ptr<std::string_view>> or
384 std::is_same_v<Field, std::shared_ptr<zview>>)
389 m_field_buf.resize(budget);
390 escape_field_to_buffer(*f, c.loc);
396 m_field_buf.resize(budget);
397 escape_field_to_buffer(
to_buf(m_field_buf, f, c), c.loc);
409 template<
typename Field>
410 void append_to_buffer(Field
const &,
ctx)
411 requires(pqxx::always_null<Field>())
413 m_buffer.append(null_field);
417 template<
typename Container>
418 void fill_buffer(Container
const &cont,
ctx c)
420 std::remove_cv_t<typename Container::value_type>,
char>)
425 std::size_t budget{0};
426 for (
auto const &f : cont) budget += estimate_buffer(f);
427 m_buffer.reserve(budget);
428 for (
auto const &f : cont) append_to_buffer(f, c);
432 template<
typename Tuple, std::size_t... indexes>
434 budget_tuple(Tuple
const &t, std::index_sequence<indexes...>)
436 return (estimate_buffer(std::get<indexes>(t)) + ...);
440 template<
typename Tuple, std::size_t... indexes>
441 void append_tuple(Tuple
const &t, std::index_sequence<indexes...>,
ctx c)
443 (append_to_buffer(std::get<indexes>(t), c), ...);
447 template<
typename... Elts>
448 void fill_buffer(std::tuple<Elts...>
const &t,
ctx c)
450 using indexes = std::make_index_sequence<
sizeof...(Elts)>;
452 m_buffer.reserve(budget_tuple(t, indexes{}));
453 append_tuple(t, indexes{}, c);
457 template<
typename... Ts>
void fill_buffer(
const Ts &...fields)
459 conversion_context
const c{
460 trans().conn().get_encoding_group(m_created_loc), m_created_loc};
461 (..., append_to_buffer(fields, c));
464 static constexpr std::string_view s_classname{
"stream_to"};
std::string quote_columns(STRINGS const &columns, sl=sl::current()) const
Quote and comma-separate a series of column names.
Definition: connection.hxx:1610
Reference to one row in a result.
Definition: row.hxx:415
Stream data from the database.
Definition: stream_from.hxx:79
Efficiently write data directly to a database table.
Definition: stream_to.hxx:81
stream_to & operator<<(Row const &row)
Insert a row of data.
Definition: stream_to.hxx:222
constexpr bool operator!() const noexcept
Has this stream been through its concluding complete()?
Definition: stream_to.hxx:198
static stream_to table(transaction_base &tx, table_path path, std::initializer_list< std::string_view > columns={})
Create a stream_to writing to a named table and columns.
Definition: stream_to.hxx:93
void write_values(Ts const &...fields)
Insert values as a row.
Definition: stream_to.hxx:253
static stream_to table(transaction_base &tx, table_path path, COLUMNS const &columns)
Create a stream_to writing to a named table and columns.
Definition: stream_to.hxx:111
void write_row(Row const &row, sl loc=sl::current())
Insert a row of data, given in the form of a std::tuple or container.
Definition: stream_to.hxx:242
stream_to(stream_to &&other)
Definition: stream_to.hxx:170
stream_to(stream_to const &)=delete
static stream_to table(transaction_base &tx, std::string_view path, COLUMNS const &columns)
Create a stream_to writing to a named table and columns.
Definition: stream_to.hxx:128
static stream_to raw_table(transaction_base &tx, std::string_view path, std::string_view columns="", sl loc=sl::current())
Stream data to a pre-quoted table and columns.
Definition: stream_to.hxx:154
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:29
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition: transaction_base.hxx:1118
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:151
std::size_t(std::string_view haystack, std::size_t start, sl) char_finder_func
Function type: "find first occurrence of any of these ASCII characters.".
Definition: encoding_group.hxx:110
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
std::string_view to_buf(std::span< char > buf, TYPE const &value, ctx c={})
Represent value as SQL text, optionally using buf as storage.
Definition: strconv.hxx:430
std::source_location sl
Convenience alias for std::source_location. It's just too long.
Definition: types.hxx:38
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:240
constexpr 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:399
constexpr bool is_null(TYPE const &value) noexcept
Is value a null?
Definition: strconv.hxx:764
requires(pqxx::internal::to_buf_7< TYPE > or pqxx::internal::to_buf_8< TYPE >) const eval bool supports_to_buf_8()
Is the libpqxx 8 version of to_buf() supported for TYPE?
Definition: strconv.hxx:417
std::size_t into_buf(std::span< char > buf, TYPE const &value, ctx c={})
Write an SQL representation of value into buf.
Definition: strconv.hxx:454
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:820
conversion_context const & ctx
Convenience alias: const reference to a pqxx::conversion_context.
Definition: strconv.hxx:201
Contextual parameters for string conversions implementations.
Definition: strconv.hxx:163