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 
24 namespace pqxx
25 {
27 
34 class PQXX_LIBEXPORT largeobject
35 {
36 public:
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 
83 
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 
123 protected:
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 
129 private:
130  oid m_id = oid_none;
131 };
132 
133 
134 // TODO: New hierarchy with separate read / write / mixed-mode access
135 
137 class PQXX_LIBEXPORT largeobjectaccess : private largeobject
138 {
139 public:
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 
216  using largeobject::to_file;
217 
222 
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 
267 
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 
308  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 
321 private:
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 
347 template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>>
349  public std::basic_streambuf<CHAR, TRAITS>
350 {
351  using size_type = long;
352 public:
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 
390 protected:
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 
398  virtual pos_type seekoff(
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 
444 private:
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 
484 template<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 
490 public:
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 
525 private:
526  largeobject_streambuf<CHAR,TRAITS> m_buf;
527 };
528 
530 
531 
533 
541 template<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>;
546 public:
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 
593 private:
595 };
596 
598 
599 
601 
609 template<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 
615 public:
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 
628  basic_lostream( //[t59]
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 
642  basic_lostream( //[t59]
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 
662 private:
664 };
665 
667 
668 } // namespace pqxx
669 
670 #include "pqxx/compiler-internal-post.hxx"
671 
672 #endif
pqxx::largeobjectaccess::cwrite
off_type cwrite(const char Buf[], size_type Len) noexcept
Write to large object's data stream.
Definition: largeobject.cxx:213
pqxx::largeobjectaccess::~largeobjectaccess
~largeobjectaccess() noexcept
Definition: largeobject.hxx:201
pqxx::basic_olostream::int_type
typename traits_type::int_type int_type
Definition: largeobject.hxx:549
pqxx::largeobject_streambuf::seekoff
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition: largeobject.hxx:398
pqxx::largeobject::to_file
void to_file(dbtransaction &T, const std::string &File) const
Export large object's contents to a local file.
Definition: largeobject.cxx:106
pqxx::largeobject::reason
std::string reason(const connection_base &, int err) const
Definition: largeobject.cxx:141
pqxx::basic_olostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:548
pqxx::largeobjectaccess
Accessor for large object's contents.
Definition: largeobject.hxx:137
pqxx::largeobject_streambuf::~largeobject_streambuf
virtual ~largeobject_streambuf() noexcept
Definition: largeobject.hxx:383
pqxx::largeobject_streambuf< char, std::char_traits< char > >::traits_type
std::char_traits< char > traits_type
Definition: largeobject.hxx:354
pqxx::basic_olostream::char_type
CHAR char_type
Definition: largeobject.hxx:547
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:642
pqxx::internal
Private namespace for libpqxx's internal use; do not access.
Definition: connection_base.hxx:43
pqxx::large_object_size_type
long large_object_size_type
Number of bytes in a large object. (Unusual: it's signed.)
Definition: types.hxx:33
pqxx::largeobjectaccess::to_file
void to_file(const std::string &File) const
Export large object's contents to a local file.
Definition: largeobject.hxx:213
pqxx::largeobjectaccess::size_type
large_object_size_type size_type
Definition: largeobject.hxx:37
pqxx::largeobject_streambuf< char, std::char_traits< char > >::char_type
char char_type
Definition: largeobject.hxx:353
pqxx::largeobject_streambuf::overflow
virtual int_type overflow(int_type ch=EoF()) override
Definition: largeobject.hxx:415
pqxx::largeobject::largeobject
largeobject() noexcept=default
Refer to a nonexistent large object (similar to what a null pointer does)
pqxx::largeobject_streambuf::largeobject_streambuf
largeobject_streambuf(dbtransaction &T, largeobject O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:361
pqxx::largeobject::id
oid id() const noexcept
Object identifier.
Definition: largeobject.hxx:73
pqxx::failure
Run-time failure encountered by libpqxx, similar to std::runtime_error.
Definition: except.hxx:89
pqxx::basic_ilostream::off_type
typename traits_type::off_type off_type
Definition: largeobject.hxx:495
pqxx::largeobjectaccess::seekdir
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition: largeobject.hxx:156
pqxx::largeobject::operator>=
bool operator>=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:97
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:517
pqxx::largeobjectaccess::cread
off_type cread(char Buf[], size_type Len) noexcept
Read from large object's data stream.
Definition: largeobject.cxx:223
pqxx::largeobject::size_type
large_object_size_type size_type
Definition: largeobject.hxx:37
pqxx::largeobject_streambuf::underflow
virtual int_type underflow() override
Definition: largeobject.hxx:434
pqxx::basic_lostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:617
pqxx::basic_ilostream
Input stream that gets its data from a large object.
Definition: largeobject.hxx:485
pqxx::basic_lostream::~basic_lostream
~basic_lostream()
Definition: largeobject.hxx:650
pqxx::largeobject::remove
void remove(dbtransaction &T) const
Delete large object from database.
Definition: largeobject.cxx:121
pqxx::largeobject::raw_connection
static PQXX_PURE internal::pq::PGconn * raw_connection(const dbtransaction &T)
Definition: largeobject.cxx:134
pqxx::largeobjectaccess::process_notice
void process_notice(const std::string &) noexcept
Issue message to transaction's notice processor.
Definition: largeobject.cxx:310
pqxx::largeobject_streambuf::process_notice
void process_notice(const std::string &s)
For use by large object stream classes.
Definition: largeobject.hxx:388
pqxx::basic_olostream::~basic_olostream
~basic_olostream()
Definition: largeobject.hxx:581
pqxx::basic_lostream
Stream that reads and writes a large object.
Definition: largeobject.hxx:610
pqxx::largeobjectaccess::seek
size_type seek(size_type dest, seekdir dir)
Seek in large object's data stream.
Definition: largeobject.cxx:191
pqxx::largeobject_streambuf::seekpos
virtual pos_type seekpos(pos_type pos, openmode) override
Definition: largeobject.hxx:407
pqxx::largeobject::operator==
bool operator==(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:85
pqxx::largeobject_streambuf
Streambuf to use large objects in standard I/O streams.
Definition: largeobject.hxx:348
pqxx::basic_lostream::off_type
typename traits_type::off_type off_type
Definition: largeobject.hxx:620
pqxx::basic_ilostream::pos_type
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:494
pqxx::basic_lostream::basic_lostream
basic_lostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_lostream.
Definition: largeobject.hxx:628
pqxx::basic_olostream::pos_type
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:550
pqxx::basic_lostream::int_type
typename traits_type::int_type int_type
Definition: largeobject.hxx:618
pqxx::largeobjectaccess::pos_type
size_type pos_type
Definition: largeobject.hxx:142
pqxx::largeobject::operator!=
bool operator!=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:89
pqxx::largeobjectaccess::write
void write(const std::string &Buf)
Write string to large object.
Definition: largeobject.hxx:233
pqxx::basic_ilostream::char_type
CHAR char_type
Definition: largeobject.hxx:491
pqxx::basic_ilostream::basic_ilostream
basic_ilostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_ilostream.
Definition: largeobject.hxx:503
pqxx::largeobject_streambuf< char, std::char_traits< char > >::int_type
typename traits_type::int_type int_type
Definition: largeobject.hxx:355
pqxx::largeobject_streambuf< char, std::char_traits< char > >::seekdir
largeobjectaccess::seekdir seekdir
Definition: largeobject.hxx:359
pqxx::oid_none
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:77
pqxx::largeobjectaccess::read
size_type read(char Buf[], size_type Len)
Read data from large object.
Definition: largeobject.cxx:260
pqxx::transaction_base::conn
connection_base & conn() const
Connection this transaction is running in.
Definition: transaction_base.hxx:492
pqxx::largeobject::operator<=
bool operator<=(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:93
pqxx::largeobjectaccess::ctell
pos_type ctell() const noexcept
Report current position in large object's data stream.
Definition: largeobject.cxx:230
pqxx::basic_ilostream::int_type
typename traits_type::int_type int_type
Definition: largeobject.hxx:493
pqxx::basic_ilostream::traits_type
TRAITS traits_type
Definition: largeobject.hxx:492
pqxx::largeobject::operator>
bool operator>(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:105
pqxx::largeobject_streambuf< char, std::char_traits< char > >::off_type
typename traits_type::off_type off_type
Definition: largeobject.hxx:357
pqxx::basic_olostream::off_type
typename traits_type::off_type off_type
Definition: largeobject.hxx:551
pqxx::largeobjectaccess::cseek
pos_type cseek(off_type dest, seekdir dir) noexcept
Seek in large object's data stream.
Definition: largeobject.cxx:206
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &T, largeobject O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:559
pqxx::largeobject_streambuf< char, std::char_traits< char > >::openmode
largeobjectaccess::openmode openmode
Definition: largeobject.hxx:358
pqxx::basic_lostream::pos_type
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:619
pqxx::largeobject_streambuf< char, std::char_traits< char > >::pos_type
typename traits_type::pos_type pos_type
Definition: largeobject.hxx:356
pqxx::to_string
std::string to_string(const field &Obj)
Convert a field to a string.
Definition: result.cxx:451
pqxx::largeobject
Identity of a large object.
Definition: largeobject.hxx:34
pqxx::connection_base
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:139
pqxx::basic_olostream
Output stream that writes data back to a large object.
Definition: largeobject.hxx:542
pqxx::dbtransaction
Abstract base class responsible for bracketing a backend transaction.
Definition: dbtransaction.hxx:62
pqxx::largeobjectaccess::write
void write(const char Buf[], size_type Len)
Write data to large object.
Definition: largeobject.cxx:236
pqxx::largeobject_streambuf::largeobject_streambuf
largeobject_streambuf(dbtransaction &T, oid O, openmode mode=std::ios::in|std::ios::out, size_type BufSize=512)
Definition: largeobject.hxx:372
pqxx::largeobjectaccess::openmode
std::ios::openmode openmode
Open mode: in, out (can be combined with the "or" operator)
Definition: largeobject.hxx:149
pqxx::basic_olostream::basic_olostream
basic_olostream(dbtransaction &T, oid O, largeobject::size_type BufSize=512)
Create a basic_olostream.
Definition: largeobject.hxx:573
pqxx::largeobjectaccess::largeobjectaccess
largeobjectaccess(dbtransaction &T, openmode mode=std::ios::in|std::ios::out)
Create new large object and open it.
Definition: largeobject.cxx:149
pqxx::largeobjectaccess::tell
size_type tell() const
Report current position in large object's data stream.
Definition: largeobject.cxx:295
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
pqxx::basic_lostream::char_type
CHAR char_type
Definition: largeobject.hxx:616
pqxx::largeobject_streambuf::sync
virtual int sync() override
Definition: largeobject.hxx:391
pqxx::largeobjectaccess::off_type
long off_type
Definition: largeobject.hxx:141
pqxx::largeobject::operator<
bool operator<(const largeobject &other) const
Compare object identities.
Definition: largeobject.hxx:101