libpqxx
largeobject.hxx
1
13#ifndef PQXX_H_LARGEOBJECT
14#define PQXX_H_LARGEOBJECT
15
16#include "pqxx/compiler-public.hxx"
17#include "pqxx/compiler-internal-pre.hxx"
18
19#include <streambuf>
20
21#include "pqxx/dbtransaction.hxx"
22
23
24namespace pqxx
25{
27
34class PQXX_LIBEXPORT largeobject
35{
36public:
38
40 largeobject() noexcept =default; //[t48]
41
43
45 explicit largeobject(dbtransaction &T); //[t48]
46
48
52 explicit largeobject(oid O) noexcept : m_id{O} {} //[t48]
53
55
59 largeobject(dbtransaction &T, const std::string &File); //[t53]
60
62
66 largeobject(const largeobjectaccess &O) noexcept; //[t50]
67
69
73 oid id() const noexcept { return m_id; } //[t48]
74
84
85 bool operator==(const largeobject &other) const //[t51]
86 { return m_id == other.m_id; }
88
89 bool operator!=(const largeobject &other) const //[t51]
90 { return m_id != other.m_id; }
92
93 bool operator<=(const largeobject &other) const //[t51]
94 { return m_id <= other.m_id; }
96
97 bool operator>=(const largeobject &other) const //[t51]
98 { return m_id >= other.m_id; }
100
101 bool operator<(const largeobject &other) const //[t51]
102 { return m_id < other.m_id; }
104
105 bool operator>(const largeobject &other) const //[t51]
106 { return m_id > other.m_id; }
108
110
114 void to_file(dbtransaction &T, const std::string &File) const; //[t52]
115
117
121 void remove(dbtransaction &T) const; //[t48]
122
123protected:
124 PQXX_PURE static internal::pq::PGconn *raw_connection(
125 const dbtransaction &T);
126
127 PQXX_PRIVATE std::string reason(const connection_base &, int err) const;
128
129private:
130 oid m_id = oid_none;
131};
132
133
134// TODO: New hierarchy with separate read / write / mixed-mode access
135
137class PQXX_LIBEXPORT largeobjectaccess : private largeobject
138{
139public:
141 using off_type = long;
143
145
149 using openmode = std::ios::openmode;
150
152
156 using seekdir = std::ios::seekdir;
157
159
163 explicit largeobjectaccess( //[t51]
164 dbtransaction &T,
165 openmode mode=std::ios::in|std::ios::out);
166
168
174 largeobjectaccess( //[t52]
175 dbtransaction &T,
176 oid O,
177 openmode mode=std::ios::in|std::ios::out);
178
180
185 largeobjectaccess( //[t50]
186 dbtransaction &T,
187 largeobject O,
188 openmode mode=std::ios::in|std::ios::out);
189
191
196 largeobjectaccess( //[t55]
197 dbtransaction &T,
198 const std::string &File,
199 openmode mode=std::ios::in|std::ios::out);
200
201 ~largeobjectaccess() noexcept { close(); }
202
204
207 using largeobject::id;
208
210
213 void to_file(const std::string &File) const //[t54]
214 { largeobject::to_file(m_trans, File); }
215
217
223
227 void write(const char Buf[], size_type Len); //[t51]
228
230
233 void write(const std::string &Buf) //[t50]
234 { write(Buf.c_str(), static_cast<size_type>(Buf.size())); }
235
237
243 size_type read(char Buf[], size_type Len); //[t50]
244
246
249 size_type seek(size_type dest, seekdir dir); //[t51]
250
252
255 size_type tell() const; //[t50]
257
268
276 pos_type cseek(off_type dest, seekdir dir) noexcept; //[t50]
277
279
285 off_type cwrite(const char Buf[], size_type Len) noexcept; //[t50]
286
288
294 off_type cread(char Buf[], size_type Len) noexcept; //[t50]
295
297
301 pos_type ctell() const noexcept; //[t50]
303
309 void process_notice(const std::string &) noexcept; //[t50]
311
312 using largeobject::remove;
313
314 using largeobject::operator==;
315 using largeobject::operator!=;
316 using largeobject::operator<;
317 using largeobject::operator<=;
318 using largeobject::operator>;
319 using largeobject::operator>=;
320
321private:
322 PQXX_PRIVATE std::string reason(int err) const;
323 internal::pq::PGconn *raw_connection() const
324 { return largeobject::raw_connection(m_trans); }
325
326 PQXX_PRIVATE void open(openmode mode);
327 void close() noexcept;
328
329 dbtransaction &m_trans;
330 int m_fd = -1;
331
332 largeobjectaccess() =delete;
333 largeobjectaccess(const largeobjectaccess &) =delete;
334 largeobjectaccess operator=(const largeobjectaccess &) =delete;
335};
336
337
339
347template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
349 public std::basic_streambuf<CHAR, TRAITS>
350{
351 using size_type = long;
352public:
353 using char_type = CHAR;
354 using traits_type = TRAITS;
355 using int_type = typename traits_type::int_type;
356 using pos_type = typename traits_type::pos_type;
357 using off_type = typename traits_type::off_type;
360
362 dbtransaction &T,
363 largeobject O,
364 openmode mode=std::ios::in|std::ios::out,
365 size_type BufSize=512) :
366 m_bufsize{BufSize},
367 m_obj{T, O, mode},
368 m_g{nullptr},
369 m_p{nullptr}
370 { initialize(mode); }
371
373 dbtransaction &T,
374 oid O,
375 openmode mode=std::ios::in|std::ios::out,
376 size_type BufSize=512) :
377 m_bufsize{BufSize},
378 m_obj{T, O, mode},
379 m_g{nullptr},
380 m_p{nullptr}
381 { initialize(mode); }
382
383 virtual ~largeobject_streambuf() noexcept
384 { delete [] m_p; delete [] m_g; }
385
386
388 void process_notice(const std::string &s) { m_obj.process_notice(s); }
389
390protected:
391 virtual int sync() override
392 {
393 // setg() sets eback, gptr, egptr
394 this->setg(this->eback(), this->eback(), this->egptr());
395 return overflow(EoF());
396 }
397
399 off_type offset,
400 seekdir dir,
401 openmode)
402 override
403 {
404 return AdjustEOF(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
405 }
406
407 virtual pos_type seekpos(pos_type pos, openmode) override
408 {
409 const largeobjectaccess::pos_type newpos = m_obj.cseek(
411 std::ios::beg);
412 return AdjustEOF(newpos);
413 }
414
415 virtual int_type overflow(int_type ch = EoF()) override
416 {
417 char *const pp = this->pptr();
418 if (pp == nullptr) return EoF();
419 char *const pb = this->pbase();
420 int_type res = 0;
421
422 if (pp > pb) res = int_type(AdjustEOF(m_obj.cwrite(pb, pp-pb)));
423 this->setp(m_p, m_p + m_bufsize);
424
425 // Write that one more character, if it's there.
426 if (ch != EoF())
427 {
428 *this->pptr() = char(ch);
429 this->pbump(1);
430 }
431 return res;
432 }
433
434 virtual int_type underflow() override
435 {
436 if (this->gptr() == nullptr) return EoF();
437 char *const eb = this->eback();
438 const int_type res(static_cast<int_type>(
439 AdjustEOF(m_obj.cread(this->eback(), m_bufsize))));
440 this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res));
441 return ((res == 0) or (res == EoF())) ? EoF() : *eb;
442 }
443
444private:
446 static int_type EoF() { return traits_type::eof(); }
447
449 template<typename INTYPE>
450 static std::streampos AdjustEOF(INTYPE pos)
451 { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); }
452
453 void initialize(openmode mode)
454 {
455 if (mode & std::ios::in)
456 {
457 m_g = new char_type[unsigned(m_bufsize)];
458 this->setg(m_g, m_g, m_g);
459 }
460 if (mode & std::ios::out)
461 {
462 m_p = new char_type[unsigned(m_bufsize)];
463 this->setp(m_p, m_p + m_bufsize);
464 }
465 }
466
467 const size_type m_bufsize;
468 largeobjectaccess m_obj;
469
471 char_type *m_g, *m_p;
472};
473
474
476
484template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
486 public std::basic_istream<CHAR, TRAITS>
487{
488 using super = std::basic_istream<CHAR, TRAITS>;
489
490public:
491 using char_type = CHAR;
492 using traits_type = TRAITS;
493 using int_type = typename traits_type::int_type;
494 using pos_type = typename traits_type::pos_type;
495 using off_type = typename traits_type::off_type;
496
498
504 dbtransaction &T,
505 largeobject O,
506 largeobject::size_type BufSize=512) :
507 super{nullptr},
508 m_buf{T, O, std::ios::in, BufSize}
509 { super::init(&m_buf); }
510
512
518 dbtransaction &T,
519 oid O,
520 largeobject::size_type BufSize=512) :
521 super{nullptr},
522 m_buf{T, O, std::ios::in, BufSize}
523 { super::init(&m_buf); }
524
525private:
527};
528
530
531
533
541template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
543 public std::basic_ostream<CHAR, TRAITS>
544{
545 using super = std::basic_ostream<CHAR, TRAITS>;
546public:
547 using char_type = CHAR;
548 using traits_type = TRAITS;
549 using int_type = typename traits_type::int_type;
550 using pos_type = typename traits_type::pos_type;
551 using off_type = typename traits_type::off_type;
552
554
560 dbtransaction &T,
561 largeobject O,
562 largeobject::size_type BufSize=512) :
563 super{nullptr},
564 m_buf{T, O, std::ios::out, BufSize}
565 { super::init(&m_buf); }
566
568
574 dbtransaction &T,
575 oid O,
576 largeobject::size_type BufSize=512) :
577 super{nullptr},
578 m_buf{T, O, std::ios::out, BufSize}
579 { super::init(&m_buf); }
580
582 {
583 try
584 {
585 m_buf.pubsync(); m_buf.pubsync();
586 }
587 catch (const std::exception &e)
588 {
589 m_buf.process_notice(e.what());
590 }
591 }
592
593private:
595};
596
598
599
601
609template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
611 public std::basic_iostream<CHAR, TRAITS>
612{
613 using super = std::basic_iostream<CHAR, TRAITS>;
614
615public:
616 using char_type = CHAR;
617 using traits_type = TRAITS;
618 using int_type = typename traits_type::int_type;
619 using pos_type = typename traits_type::pos_type;
620 using off_type = typename traits_type::off_type;
621
623
629 dbtransaction &T,
630 largeobject O,
631 largeobject::size_type BufSize=512) :
632 super{nullptr},
633 m_buf{T, O, std::ios::in | std::ios::out, BufSize}
634 { super::init(&m_buf); }
635
637
643 dbtransaction &T,
644 oid O,
645 largeobject::size_type BufSize=512) :
646 super{nullptr},
647 m_buf{T, O, std::ios::in | std::ios::out, BufSize}
648 { super::init(&m_buf); }
649
651 {
652 try
653 {
654 m_buf.pubsync(); m_buf.pubsync();
655 }
656 catch (const std::exception &e)
657 {
658 m_buf.process_notice(e.what());
659 }
660 }
661
662private:
664};
665
667
668} // namespace pqxx
669
670#include "pqxx/compiler-internal-post.hxx"
671
672#endif
STL namespace.
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
long large_object_size_type
Number of bytes in a large object. (Unusual: it's signed.)
Definition: types.hxx:33
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:77
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:140
Abstract base class responsible for bracketing a backend transaction.
Definition: dbtransaction.hxx:63
Identity of a large object.
Definition: largeobject.hxx:35
static PQXX_PURE internal::pq::PGconn * raw_connection(const dbtransaction &T)
Definition: largeobject.cxx:134
large_object_size_type size_type
Definition: largeobject.hxx:37
bool operator<(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:101
bool operator==(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:85
void to_file(dbtransaction &T, const std::string &File) const
Export large object's contents to a local file.
Definition: largeobject.cxx:106
bool operator>(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:105
bool operator<=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:93
largeobject() noexcept=default
Refer to a nonexistent large object (similar to what a null pointer does)
bool operator!=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:89
bool operator>=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:97
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:73
Accessor for large object's contents.
Definition: largeobject.hxx:138
size_type pos_type
Definition: largeobject.hxx:142
std::ios::openmode openmode
Open mode: in, out (can be combined with the "or" operator)
Definition: largeobject.hxx:149
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:156
void write(const std::string &Buf)
Write string to large object.
Definition: largeobject.hxx:233
long off_type
Definition: largeobject.hxx:141
~largeobjectaccess() noexcept
Definition: largeobject.hxx:201
void to_file(const std::string &File) const
Export large object's contents to a local file.
Definition: largeobject.hxx:213
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:350
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:398
TRAITS traits_type
Definition: largeobject.hxx:354
typename traits_type::int_type int_type
Definition: largeobject.hxx:355
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:407
void process_notice(const std::string &s)
For use by large object stream classes.
Definition: largeobject.hxx:388
CHAR char_type
Definition: largeobject.hxx:353
typename traits_type::off_type off_type
Definition: largeobject.hxx:357
largeobject_streambuf(dbtransaction &T, largeobject O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:361
largeobject_streambuf(dbtransaction &T, oid O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:372
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:383
virtual int sync() override
Definition: largeobject.hxx:391
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:359
virtual int_type underflow() override
Definition: largeobject.hxx:434
virtual int_type overflow(int_type ch=EoF()) override
Definition: largeobject.hxx:415
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:358
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:356
Input stream that gets its data from a large object.
Definition: largeobject.hxx:487
CHAR char_type
Definition: largeobject.hxx:491
basic_ilostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:503
typename traits_type::int_type int_type
Definition: largeobject.hxx:493
TRAITS traits_type
Definition: largeobject.hxx:492
typename traits_type::off_type off_type
Definition: largeobject.hxx:495
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:494
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:517
Output stream that writes data back to a large object.
Definition: largeobject.hxx:544
typename traits_type::off_type off_type
Definition: largeobject.hxx:551
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:550
typename traits_type::int_type int_type
Definition: largeobject.hxx:549
~basic_olostream()
Definition: largeobject.hxx:581
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:559
CHAR char_type
Definition: largeobject.hxx:547
TRAITS traits_type
Definition: largeobject.hxx:548
basic_olostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:573
Stream that reads and writes a large object.
Definition: largeobject.hxx:612
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:619
~basic_lostream()
Definition: largeobject.hxx:650
basic_lostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:642
typename traits_type::int_type int_type
Definition: largeobject.hxx:618
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:628
typename traits_type::off_type off_type
Definition: largeobject.hxx:620
TRAITS traits_type
Definition: largeobject.hxx:617
CHAR char_type
Definition: largeobject.hxx:616