libpqxx 7.7.0
largeobject.hxx
1/* Large Objects interface. Deprecated; use blob instead.
2 *
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
4 *
5 * Copyright (c) 2000-2022, Jeroen T. Vermeulen.
6 *
7 * See COPYING for copyright license. If you did not receive a file called
8 * COPYING with this source code, please notify the distributor of this
9 * mistake, or contact the author.
10 */
11#ifndef PQXX_H_LARGEOBJECT
12#define PQXX_H_LARGEOBJECT
13
14#include <streambuf>
15
16#include "pqxx/dbtransaction.hxx"
17
18
19namespace pqxx
20{
22
29class PQXX_LIBEXPORT largeobject
30{
31public:
33
36 [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
37
39
41 [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
42
44
48 [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
49 m_id{o}
50 {}
51
53
57 [[deprecated("Use blob instead.")]] largeobject(
58 dbtransaction &t, std::string_view file);
59
61
65 [[deprecated("Use blob instead.")]] largeobject(
66 largeobjectaccess const &o) noexcept;
67
69
73 [[nodiscard]] oid id() const noexcept { return m_id; }
74
84
85 [[nodiscard]] bool operator==(largeobject const &other) const
86 {
87 return m_id == other.m_id;
88 }
90
91 [[nodiscard]] bool operator!=(largeobject const &other) const
92 {
93 return m_id != other.m_id;
94 }
96
97 [[nodiscard]] bool operator<=(largeobject const &other) const
98 {
99 return m_id <= other.m_id;
100 }
102
103 [[nodiscard]] bool operator>=(largeobject const &other) const
104 {
105 return m_id >= other.m_id;
106 }
108
109 [[nodiscard]] bool operator<(largeobject const &other) const
110 {
111 return m_id < other.m_id;
112 }
114
115 [[nodiscard]] bool operator>(largeobject const &other) const
116 {
117 return m_id > other.m_id;
118 }
120
122
126 void to_file(dbtransaction &t, std::string_view file) const;
127
129
133 void remove(dbtransaction &t) const;
134
135protected:
136 PQXX_PURE static internal::pq::PGconn *
137 raw_connection(dbtransaction const &T);
138
139 PQXX_PRIVATE std::string reason(connection const &, int err) const;
140
141private:
142 oid m_id = oid_none;
143};
144
145
147
149class PQXX_LIBEXPORT largeobjectaccess : private largeobject
150{
151public:
155
157
164 using openmode = std::ios::openmode;
165
167 static constexpr auto default_mode{
168 std::ios::in | std::ios::out | std::ios::binary};
169
171 using seekdir = std::ios::seekdir;
172
174
179 [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
180 dbtransaction &t, openmode mode = default_mode);
181
183
190 [[deprecated("Use blob instead.")]] largeobjectaccess(
191 dbtransaction &t, oid o, openmode mode = default_mode);
192
194
200 [[deprecated("Use blob instead.")]] largeobjectaccess(
201 dbtransaction &t, largeobject o, openmode mode = default_mode);
202
204
209 [[deprecated("Use blob instead.")]] largeobjectaccess(
210 dbtransaction &t, std::string_view file, openmode mode = default_mode);
211
212 ~largeobjectaccess() noexcept { close(); }
213
215
218 using largeobject::id;
219
221
224 void to_file(std::string_view file) const
225 {
226 largeobject::to_file(m_trans, file);
227 }
228
230
236
241 void write(char const buf[], std::size_t len);
242
244
247 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
248
250
256 size_type read(char buf[], std::size_t len);
257
259
262 size_type seek(size_type dest, seekdir dir);
263
265
268 [[nodiscard]] size_type tell() const;
270
284
292 pos_type cseek(off_type dest, seekdir dir) noexcept;
293
295
301 off_type cwrite(char const buf[], std::size_t len) noexcept;
302
304
310 off_type cread(char buf[], std::size_t len) noexcept;
311
313
317 [[nodiscard]] pos_type ctell() const noexcept;
319
325 void process_notice(zview) noexcept;
327
328 using largeobject::remove;
329
330 using largeobject::operator==;
331 using largeobject::operator!=;
332 using largeobject::operator<;
333 using largeobject::operator<=;
334 using largeobject::operator>;
335 using largeobject::operator>=;
336
339 largeobjectaccess operator=(largeobjectaccess const &) = delete;
340
341private:
342 PQXX_PRIVATE std::string reason(int err) const;
343 internal::pq::PGconn *raw_connection() const
344 {
345 return largeobject::raw_connection(m_trans);
346 }
347
348 PQXX_PRIVATE void open(openmode mode);
349 void close() noexcept;
350
351 dbtransaction &m_trans;
352 int m_fd = -1;
353};
354
355
357
368template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
369class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
370{
371 using size_type = largeobject::size_type;
372
373public:
374 using char_type = CHAR;
375 using traits_type = TRAITS;
376 using int_type = typename traits_type::int_type;
377 using pos_type = typename traits_type::pos_type;
378 using off_type = typename traits_type::off_type;
381
383 static constexpr auto default_mode{
384 std::ios::in | std::ios::out | std::ios::binary};
385
386 [[deprecated("Use blob instead.")]] largeobject_streambuf(
387 dbtransaction &t, largeobject o, openmode mode = default_mode,
388 size_type buf_size = 512) :
389 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
390 {
391 initialize(mode);
392 }
393
394 [[deprecated("Use blob instead.")]] largeobject_streambuf(
395 dbtransaction &t, oid o, openmode mode = default_mode,
396 size_type buf_size = 512) :
397 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
398 {
399 initialize(mode);
400 }
401
402 virtual ~largeobject_streambuf() noexcept
403 {
404 delete[] m_p;
405 delete[] m_g;
406 }
407
409 void process_notice(zview const &s) { m_obj.process_notice(s); }
410
411protected:
412 virtual int sync() override
413 {
414 // setg() sets eback, gptr, egptr.
415 this->setg(this->eback(), this->eback(), this->egptr());
416 return overflow(eof());
417 }
418
419 virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
420 {
421 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
422 }
423
424 virtual pos_type seekpos(pos_type pos, openmode) override
425 {
426 largeobjectaccess::pos_type const newpos{
427 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
428 return adjust_eof(newpos);
429 }
430
431 virtual int_type overflow(int_type ch) override
432 {
433 auto *const pp{this->pptr()};
434 if (pp == nullptr)
435 return eof();
436 auto *const pb{this->pbase()};
437 int_type res{0};
438
439 if (pp > pb)
440 {
441 auto const write_sz{pp - pb};
442 auto const written_sz{
443 m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
444 if (internal::cmp_less_equal(written_sz, 0))
445 throw internal_error{
446 "pqxx::largeobject: write failed "
447 "(is transaction still valid on write or flush?), "
448 "libpq reports error"};
449 else if (write_sz != written_sz)
450 throw internal_error{
451 "pqxx::largeobject: write failed "
452 "(is transaction still valid on write or flush?), " +
453 std::to_string(written_sz) + "/" + std::to_string(write_sz) +
454 " bytes written"};
455 auto const out{adjust_eof(written_sz)};
456
457 if constexpr (std::is_arithmetic_v<decltype(out)>)
458 res = check_cast<int_type>(out, "largeobject position"sv);
459 else
460 res = int_type(out);
461 }
462 this->setp(m_p, m_p + m_bufsize);
463
464 // Write that one more character, if it's there.
465 if (ch != eof())
466 {
467 *this->pptr() = static_cast<char_type>(ch);
468 this->pbump(1);
469 }
470 return res;
471 }
472
473 virtual int_type overflow() { return overflow(eof()); }
474
475 virtual int_type underflow() override
476 {
477 if (this->gptr() == nullptr)
478 return eof();
479 auto *const eb{this->eback()};
480 auto const res{adjust_eof(
481 m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
482 this->setg(
483 eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
484 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
485 }
486
487private:
489 static int_type eof() { return traits_type::eof(); }
490
492 template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
493 {
494 bool const at_eof{pos == -1};
495 if constexpr (std::is_arithmetic_v<std::streampos>)
496 {
497 return check_cast<std::streampos>(
498 (at_eof ? eof() : pos), "large object seek"sv);
499 }
500 else
501 {
502 return std::streampos(at_eof ? eof() : pos);
503 }
504 }
505
506 void initialize(openmode mode)
507 {
508 if ((mode & std::ios::in) != 0)
509 {
510 m_g = new char_type[unsigned(m_bufsize)];
511 this->setg(m_g, m_g, m_g);
512 }
513 if ((mode & std::ios::out) != 0)
514 {
515 m_p = new char_type[unsigned(m_bufsize)];
516 this->setp(m_p, m_p + m_bufsize);
517 }
518 }
519
520 size_type const m_bufsize;
521 largeobjectaccess m_obj;
522
524 char_type *m_g, *m_p;
525};
526
527
529
538template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
539class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
540{
541 using super = std::basic_istream<CHAR, TRAITS>;
542
543public:
544 using char_type = CHAR;
545 using traits_type = TRAITS;
546 using int_type = typename traits_type::int_type;
547 using pos_type = typename traits_type::pos_type;
548 using off_type = typename traits_type::off_type;
549
551
556 [[deprecated("Use blob instead.")]] basic_ilostream(
557 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
558 super{nullptr},
559 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
560 {
561 super::init(&m_buf);
562 }
563
565
570 [[deprecated("Use blob instead.")]] basic_ilostream(
571 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
572 super{nullptr},
573 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
574 {
575 super::init(&m_buf);
576 }
577
578private:
580};
581
583
584
586
594template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
595class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
596{
597 using super = std::basic_ostream<CHAR, TRAITS>;
598
599public:
600 using char_type = CHAR;
601 using traits_type = TRAITS;
602 using int_type = typename traits_type::int_type;
603 using pos_type = typename traits_type::pos_type;
604 using off_type = typename traits_type::off_type;
605
607
612 [[deprecated("Use blob instead.")]] basic_olostream(
613 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
614 super{nullptr},
615 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
616 {
617 super::init(&m_buf);
618 }
619
621
626 [[deprecated("Use blob instead.")]] basic_olostream(
627 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
628 super{nullptr},
629 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
630 {
631 super::init(&m_buf);
632 }
633
635 {
636 try
637 {
638 m_buf.pubsync();
639 m_buf.pubsync();
640 }
641 catch (std::exception const &e)
642 {
643 m_buf.process_notice(e.what());
644 }
645 }
646
647private:
649};
650
652
653
655
664template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
665class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
666{
667 using super = std::basic_iostream<CHAR, TRAITS>;
668
669public:
670 using char_type = CHAR;
671 using traits_type = TRAITS;
672 using int_type = typename traits_type::int_type;
673 using pos_type = typename traits_type::pos_type;
674 using off_type = typename traits_type::off_type;
675
677
682 [[deprecated("Use blob instead.")]] basic_lostream(
683 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
684 super{nullptr},
685 m_buf{
686 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
687 {
688 super::init(&m_buf);
689 }
690
692
697 [[deprecated("Use blob instead.")]] basic_lostream(
698 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
699 super{nullptr},
700 m_buf{
701 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
702 {
703 super::init(&m_buf);
704 }
705
707 {
708 try
709 {
710 m_buf.pubsync();
711 m_buf.pubsync();
712 }
713 catch (std::exception const &e)
714 {
715 m_buf.process_notice(e.what());
716 }
717 }
718
719private:
721};
722
724} // namespace pqxx
725#endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:23
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:328
int64_t large_object_size_type
Number of bytes in a large object.
Definition: types.hxx:39
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs)
C++20 std::cmp_less_equal, or workaround if not available.
Definition: util.hxx:84
Definition: blob.hxx:49
Connection to a database.
Definition: connection.hxx:181
Abstract transaction base class: bracket transactions on the database.
Definition: dbtransaction.hxx:50
Internal error in libpqxx library.
Definition: except.hxx:155
Identity of a large object.
Definition: largeobject.hxx:30
bool operator==(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:85
bool operator>=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:103
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition: largeobject.cxx:136
bool operator<=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:97
large_object_size_type size_type
Definition: largeobject.hxx:32
bool operator<(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:109
largeobject() noexcept=default
void to_file(dbtransaction &t, std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.cxx:104
bool operator!=(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:91
bool operator>(largeobject const &other) const
Compare object identities.
Definition: largeobject.hxx:115
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:73
Accessor for large object's contents.
Definition: largeobject.hxx:150
size_type pos_type
Definition: largeobject.hxx:154
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition: largeobject.hxx:164
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:171
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition: largeobject.hxx:224
~largeobjectaccess() noexcept
Definition: largeobject.hxx:212
void write(std::string_view buf)
Write string to large object.
Definition: largeobject.hxx:247
size_type off_type
Definition: largeobject.hxx:153
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:370
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:419
virtual int_type overflow(int_type ch) override
Definition: largeobject.hxx:431
TRAITS traits_type
Definition: largeobject.hxx:375
typename traits_type::int_type int_type
Definition: largeobject.hxx:376
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:424
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:394
CHAR char_type
Definition: largeobject.hxx:374
typename traits_type::off_type off_type
Definition: largeobject.hxx:378
virtual int_type overflow()
Definition: largeobject.hxx:473
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:402
void process_notice(zview const &s)
For use by large object stream classes.
Definition: largeobject.hxx:409
virtual int sync() override
Definition: largeobject.hxx:412
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:380
virtual int_type underflow() override
Definition: largeobject.hxx:475
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:379
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:377
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition: largeobject.hxx:386
Input stream that gets its data from a large object.
Definition: largeobject.hxx:540
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:570
CHAR char_type
Definition: largeobject.hxx:544
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition: largeobject.hxx:556
typename traits_type::int_type int_type
Definition: largeobject.hxx:546
TRAITS traits_type
Definition: largeobject.hxx:545
typename traits_type::off_type off_type
Definition: largeobject.hxx:548
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:547
Output stream that writes data back to a large object.
Definition: largeobject.hxx:596
typename traits_type::off_type off_type
Definition: largeobject.hxx:604
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:603
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:612
typename traits_type::int_type int_type
Definition: largeobject.hxx:602
~basic_olostream()
Definition: largeobject.hxx:634
CHAR char_type
Definition: largeobject.hxx:600
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition: largeobject.hxx:626
TRAITS traits_type
Definition: largeobject.hxx:601
Stream that reads and writes a large object.
Definition: largeobject.hxx:666
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:673
~basic_lostream()
Definition: largeobject.hxx:706
typename traits_type::int_type int_type
Definition: largeobject.hxx:672
typename traits_type::off_type off_type
Definition: largeobject.hxx:674
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:682
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition: largeobject.hxx:697
TRAITS traits_type
Definition: largeobject.hxx:671
CHAR char_type
Definition: largeobject.hxx:670
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38