libpqxx
The C++ client library for PostgreSQL
blob.hxx
1 /* Binary Large Objects interface.
2  *
3  * Read or write large objects, stored in their own storage on the server.
4  *
5  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
6  *
7  * Copyright (c) 2000-2025, Jeroen T. Vermeulen.
8  *
9  * See COPYING for copyright license. If you did not receive a file called
10  * COPYING with this source code, please notify the distributor of this
11  * mistake, or contact the author.
12  */
13 #ifndef PQXX_H_BLOB
14 #define PQXX_H_BLOB
15 
16 #if !defined(PQXX_HEADER_PRE)
17 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18 #endif
19 
20 #include <cstdint>
21 
22 #if defined(PQXX_HAVE_PATH)
23 # include <filesystem>
24 #endif
25 
26 // C++20: Assume support.
27 #if defined(PQXX_HAVE_RANGES)
28 # include <ranges>
29 #endif
30 
31 // C++20: Assume support.
32 #if __has_include(<span>)
33 # include <span>
34 #endif
35 
36 #include "pqxx/dbtransaction.hxx"
37 
38 
39 namespace pqxx
40 {
54 class PQXX_LIBEXPORT blob
55 {
56 public:
58 
62  [[nodiscard]] static oid create(dbtransaction &, oid = 0);
63 
65  static void remove(dbtransaction &, oid);
66 
68  [[nodiscard]] static blob open_r(dbtransaction &, oid);
69  // Open blob for writing. Any attempt to read from it will fail.
70  [[nodiscard]] static blob open_w(dbtransaction &, oid);
71  // Open blob for reading and/or writing.
72  [[nodiscard]] static blob open_rw(dbtransaction &, oid);
73 
75 
78  blob() = default;
79 
81  blob(blob &&);
83  blob &operator=(blob &&);
84 
85  blob(blob const &) = delete;
86  blob &operator=(blob const &) = delete;
87  ~blob();
88 
90 
96  static constexpr std::size_t chunk_limit = 0x7fffffff;
97 
99 
107  std::size_t read(bytes &buf, std::size_t size);
108 
109 #if defined(PQXX_HAVE_SPAN)
110 
116  template<std::size_t extent = std::dynamic_extent>
117  std::span<std::byte> read(std::span<std::byte, extent> buf)
118  {
119  return buf.subspan(0, raw_read(std::data(buf), std::size(buf)));
120  }
121 #endif // PQXX_HAVE_SPAN
122 
123 #if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_RANGES) && \
124  defined(PQXX_HAVE_SPAN)
125 
131  template<binary DATA> std::span<std::byte> read(DATA &buf)
132  {
133  return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
134  }
135 #else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
136 
149  template<typename ALLOC> bytes_view read(std::vector<std::byte, ALLOC> &buf)
150  {
151  return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
152  }
153 #endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
154 
155 #if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_RANGES)
156 
175  template<binary DATA> void write(DATA const &data)
176  {
177  raw_write(std::data(data), std::size(data));
178  }
179 #else
180 
199  template<typename DATA> void write(DATA const &data)
200  {
201  raw_write(std::data(data), std::size(data));
202  }
203 #endif
204 
206 
212  void resize(std::int64_t size);
213 
215  [[nodiscard]] std::int64_t tell() const;
216 
218 
219  std::int64_t seek_abs(std::int64_t offset = 0);
221 
225  std::int64_t seek_rel(std::int64_t offset = 0);
227 
231  std::int64_t seek_end(std::int64_t offset = 0);
232 
234 
237  static oid from_buf(dbtransaction &tx, bytes_view data, oid id = 0);
238 
240 
242  static void append_from_buf(dbtransaction &tx, bytes_view data, oid id);
243 
245  [[nodiscard]] static oid from_file(dbtransaction &, char const path[]);
246 
247 #if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
248 
252  [[nodiscard]] static oid
253  from_file(dbtransaction &tx, std::filesystem::path const &path)
254  {
255  return from_file(tx, path.c_str());
256  }
257 #endif
258 
260 
263  static oid from_file(dbtransaction &, char const path[], oid);
264 
265 #if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
266 
273  static oid
274  from_file(dbtransaction &tx, std::filesystem::path const &path, oid id)
275  {
276  return from_file(tx, path.c_str(), id);
277  }
278 #endif
279 
281 
284  static void to_buf(dbtransaction &, oid, bytes &, std::size_t max_size);
285 
287 
293  static std::size_t append_to_buf(
294  dbtransaction &tx, oid id, std::int64_t offset, bytes &buf,
295  std::size_t append_max);
296 
298  static void to_file(dbtransaction &, oid, char const path[]);
299 
300 #if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
301 
305  static void
306  to_file(dbtransaction &tx, oid id, std::filesystem::path const &path)
307  {
308  to_file(tx, id, path.c_str());
309  }
310 #endif
311 
313 
324  void close();
325 
326 private:
327  PQXX_PRIVATE blob(connection &cx, int fd) noexcept : m_conn{&cx}, m_fd{fd} {}
328  static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int);
329  static PQXX_PRIVATE pqxx::internal::pq::PGconn *
330  raw_conn(pqxx::connection *) noexcept;
331  static PQXX_PRIVATE pqxx::internal::pq::PGconn *
332  raw_conn(pqxx::dbtransaction const &) noexcept;
333  static PQXX_PRIVATE std::string errmsg(connection const *);
334  static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx)
335  {
336  return errmsg(&tx.conn());
337  }
338  PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); }
339  PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence);
340  std::size_t raw_read(std::byte buf[], std::size_t size);
341  void raw_write(std::byte const buf[], std::size_t size);
342 
343  connection *m_conn = nullptr;
344  int m_fd = -1;
345 };
346 } // namespace pqxx
347 #endif
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
Definition: blob.hxx:54
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:53
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
std::conditional< has_generic_bytes_char_traits, std::basic_string< std::byte >, std::basic_string< std::byte, byte_char_traits >>::type bytes
Type alias for a container containing bytes.
Definition: util.hxx:375
unsigned int oid
PostgreSQL database row identifier.
Definition: libpq-forward.hxx:33
std::conditional< has_generic_bytes_char_traits, std::basic_string_view< std::byte >, std::basic_string_view< std::byte, byte_char_traits >>::type bytes_view
Type alias for a view of bytes.
Definition: util.hxx:385
void write(DATA const &data)
Write data large object, at the current position.
Definition: blob.hxx:199
Connection to a database.
Definition: connection.hxx:278
bytes_view read(std::vector< std::byte, ALLOC > &buf)
Read up to std::size(buf) bytes from the object.
Definition: blob.hxx:149