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>."
20 #include "pqxx/separated_list.hxx"
21 #include "pqxx/transaction_base.hxx"
107 return {tx, path, columns};
122 std::initializer_list<std::string_view> columns = {})
124 auto const &cx{tx.
conn()};
125 return raw_table(tx, cx.quote_table(path), cx.quote_columns(columns));
128 #if defined(PQXX_HAVE_CONCEPTS)
137 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
139 table(transaction_base &tx,
table_path path, COLUMNS
const &columns)
141 auto const &cx{tx.conn()};
143 tx, cx.quote_table(path), tx.conn().quote_columns(columns));
154 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
156 table(transaction_base &tx, std::string_view path, COLUMNS
const &columns)
160 #endif // PQXX_HAVE_CONCEPTS
162 explicit stream_to(stream_to &&other) :
165 transaction_focus{std::move(other)},
166 m_finished{other.m_finished},
167 m_buffer{std::move(other.m_buffer)},
168 m_field_buf{std::move(other.m_field_buf)},
169 m_finder{other.m_finder}
171 other.m_finished =
true;
173 ~stream_to() noexcept;
176 [[nodiscard]] constexpr operator
bool() const noexcept
178 return not m_finished;
237 fill_buffer(fields...);
251 [[deprecated(
"Use table() or raw_table() factory.")]]
stream_to(
259 template<
typename Columns>
260 [[deprecated(
"Use table() or raw_table() factory.")]] stream_to(
261 transaction_base &, std::string_view table_name, Columns
const &columns);
266 transaction_base &tx, std::string_view path, std::string_view columns);
268 bool m_finished =
false;
271 std::string m_buffer;
274 std::string m_field_buf;
280 void write_raw_line(std::string_view);
288 static constexpr std::string_view null_field{
"\\N\t"};
292 static std::enable_if_t<nullness<T>::always_null, std::size_t>
293 estimate_buffer(T
const &)
295 return std::size(null_field);
303 static std::enable_if_t<not nullness<T>::always_null, std::size_t>
304 estimate_buffer(T
const &field)
310 void escape_field_to_buffer(std::string_view data);
319 template<
typename Field>
320 std::enable_if_t<not nullness<Field>::always_null>
321 append_to_buffer(Field
const &f)
329 m_buffer.append(null_field);
335 using traits = string_traits<Field>;
336 auto const budget{estimate_buffer(f)};
337 auto const offset{std::size(m_buffer)};
339 if constexpr (std::is_arithmetic_v<Field>)
347 auto const total{offset + budget};
348 m_buffer.resize(total);
349 auto const data{m_buffer.data()};
350 char *
const end{traits::into_buf(data + offset, data + total, f)};
353 m_buffer.resize(static_cast<std::size_t>(end - data));
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);
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);
372 escape_field_to_buffer(f.value());
376 std::is_same_v<Field, std::unique_ptr<std::string>> or
377 std::is_same_v<Field, std::unique_ptr<std::string_view>> or
378 std::is_same_v<Field, std::unique_ptr<zview>> or
379 std::is_same_v<Field, std::shared_ptr<std::string>> or
380 std::is_same_v<Field, std::shared_ptr<std::string_view>> or
381 std::is_same_v<Field, std::shared_ptr<zview>>)
386 m_field_buf.resize(budget);
387 escape_field_to_buffer(*f);
393 m_field_buf.resize(budget);
394 auto const data{m_field_buf.data()};
395 escape_field_to_buffer(
408 template<
typename Field>
409 std::enable_if_t<nullness<Field>::always_null>
410 append_to_buffer(Field
const &)
412 m_buffer.append(null_field);
416 template<
typename Container>
417 std::enable_if_t<not std::is_same_v<typename Container::value_type, char>>
418 fill_buffer(Container
const &c)
423 std::size_t budget{0};
424 for (
auto const &f : c) budget += estimate_buffer(f);
425 m_buffer.reserve(budget);
426 for (
auto const &f : c) append_to_buffer(f);
430 template<
typename Tuple, std::size_t... indexes>
432 budget_tuple(Tuple
const &t, std::index_sequence<indexes...>)
434 return (estimate_buffer(std::get<indexes>(t)) + ...);
438 template<
typename Tuple, std::size_t... indexes>
439 void append_tuple(Tuple
const &t, std::index_sequence<indexes...>)
441 (append_to_buffer(std::get<indexes>(t)), ...);
445 template<
typename... Elts>
void fill_buffer(std::tuple<Elts...>
const &t)
447 using indexes = std::make_index_sequence<
sizeof...(Elts)>;
449 m_buffer.reserve(budget_tuple(t, indexes{}));
450 append_tuple(t, indexes{});
454 template<
typename... Ts>
void fill_buffer(
const Ts &...fields)
456 (..., append_to_buffer(fields));
459 constexpr
static std::string_view s_classname{
"stream_to"};
463 template<
typename Columns>
464 inline stream_to::stream_to(
465 transaction_base &tx, std::string_view table_name, Columns
const &columns) :
466 stream_to{tx, table_name, std::begin(columns), std::end(columns)}
static stream_to raw_table(transaction_base &tx, std::string_view path, std::string_view columns="")
Stream data to a pre-quoted table and columns.
Definition: stream_to.hxx:104
void write_values(Ts const &...fields)
Insert values as a row.
Definition: stream_to.hxx:235
Efficiently write data directly to a database table.
Definition: stream_to.hxx:80
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:526
Reference to one row in a result.
Definition: row.hxx:46
Base class for things that monopolise a transaction's attention.
Definition: transaction_focus.hxx:28
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition: transaction_base.hxx:1005
std::vector< std::string_view > to_buf(char *here, char const *end, TYPE...value)
Convert multiple values to strings inside a single buffer.
Definition: strconv.hxx:493
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:515
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
stream_to & operator<<(Row const &row)
Insert a row of data.
Definition: stream_to.hxx:205
Stream data from the database.
Definition: stream_from.hxx:78
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition: connection.hxx:231
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
stream_to(transaction_base &tx, std::string_view table_name)
Create a stream, without specifying columns.
Definition: stream_to.hxx:251
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
void write_row(Row const &row)
Insert a row of data, given in the form of a std::tuple or container.
Definition: stream_to.hxx:225
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:120
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:150
constexpr bool operator!() const noexcept
Has this stream been through its concluding complete()?
Definition: stream_to.hxx:181