libpqxx  3.1.1
result.hxx
1 /*-------------------------------------------------------------------------
2  *
3  * FILE
4  * pqxx/result.hxx
5  *
6  * DESCRIPTION
7  * definitions for the pqxx::result class and support classes.
8  * pqxx::result represents the set of result tuples from a database query
9  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
10  *
11  * Copyright (c) 2001-2013, Jeroen T. Vermeulen <jtv@xs4all.nl>
12  *
13  * See COPYING for copyright license. If you did not receive a file called
14  * COPYING with this source code, please notify the distributor of this mistake,
15  * or contact the author.
16  *
17  *-------------------------------------------------------------------------
18  */
19 #ifndef PQXX_H_RESULT
20 #define PQXX_H_RESULT
21 
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24 
25 #ifdef PQXX_HAVE_IOS
26 #include <ios>
27 #endif
28 
29 #include <stdexcept>
30 
31 #include "pqxx/except"
32 #include "pqxx/strconv"
33 #include "pqxx/util"
34 
35 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
36  */
37 
38 // TODO: Support SQL arrays
39 
40 namespace pqxx
41 {
42 class result;
43 
44 namespace internal
45 {
46 class sql_cursor;
47 
49 struct PQXX_PRIVATE result_data
50 {
52 
56 
58  int protocol;
59 
61  PGSTD::string query;
62 
64 
65  // TODO: Locking for result copy-construction etc. also goes here
66 
67  result_data();
69  int protocol,
70  const PGSTD::string &,
71  int encoding_code);
72  ~result_data();
73 };
74 
75 void PQXX_LIBEXPORT freemem_result_data(const result_data *) throw ();
76 } // namespace internal
77 
78 
79 namespace internal
80 {
81 namespace gate
82 {
83 class result_connection;
84 class result_creation;
85 class result_sql_cursor;
86 } // namespace internal::gate
87 } // namespace internal
88 
89 
91 
111 class PQXX_LIBEXPORT result :
112  private internal::PQAlloc<
113  const internal::result_data, internal::freemem_result_data>
114 {
115  typedef internal::PQAlloc<
117 public:
118  class const_iterator;
119  class const_fielditerator;
121  class tuple;
122  class field;
123  typedef unsigned long size_type;
124  typedef signed long difference_type;
125  typedef tuple reference;
127 
129 
140  class PQXX_LIBEXPORT tuple
141  {
142  public:
143  typedef unsigned int size_type;
144  typedef signed int difference_type;
147  typedef field reference;
151 
153  tuple(const result *r, result::size_type i) throw () :
154  m_Home(r), m_Index(i), m_Begin(0), m_End(r ? r->columns() : 0) {}
155 
156  ~tuple() throw () {} // Yes Scott Meyers, you're absolutely right[1]
157 
162  bool operator==(const tuple &) const throw (); //[t75]
163  bool operator!=(const tuple &rhs) const throw () //[t75]
164  { return !operator==(rhs); }
166 
167  const_iterator begin() const throw () //[t82]
168  { return const_iterator(*this, m_Begin); }
169  const_iterator end() const throw () //[t82]
170  { return const_iterator(*this, m_End); }
171 
176  reference front() const throw () { return field(*this, m_Begin); } //[t74]
177  reference back() const throw () { return field(*this, m_End-1); } //[t75]
178 
179  const_reverse_fielditerator rbegin() const; //[t82]
180  const_reverse_fielditerator rend() const; //[t82]
181 
182  reference operator[](size_type i) const throw () //[t11]
183  { return field(*this, m_Begin+i); }
184  reference operator[](int i) const throw () //[t2]
185  { return operator[](size_type(i)); }
186  reference operator[](const char f[]) const //[t11]
187  { return at(f); }
188  reference operator[](const PGSTD::string &s) const //[t11]
189  { return operator[](s.c_str()); }
190  reference at(size_type) const throw (range_error); //[t11]
191  reference at(int i) const throw (range_error) //[t11]
192  { return at(size_type(i)); }
193  reference at(const char[]) const; //[t11]
194  reference at(const PGSTD::string &s) const //[t11]
195  { return at(s.c_str()); }
197 
198  size_type size() const throw () { return m_End-m_Begin; } //[t11]
199 
200  void swap(tuple &) throw (); //[t11]
201 
202  result::size_type rownumber() const throw () { return m_Index; } //[t11]
203 
208 
209  size_type column_number(const PGSTD::string &ColName) const //[t30]
210  { return column_number(ColName.c_str()); }
211 
213  size_type column_number(const char[]) const; //[t30]
214 
216  oid column_type(size_type ColNum) const //[t7]
217  { return m_Home->column_type(m_Begin+ColNum); }
218 
220  oid column_type(int ColNum) const //[t7]
221  { return column_type(size_type(ColNum)); }
222 
224  oid column_type(const PGSTD::string &ColName) const //[t7]
225  { return column_type(column_number(ColName)); }
226 
228  oid column_type(const char ColName[]) const //[t7]
229  { return column_type(column_number(ColName)); }
230 
232 
239  oid column_table(size_type ColNum) const //[t2]
240  { return m_Home->column_table(m_Begin+ColNum); }
242 
249  oid column_table(int ColNum) const //[t2]
250  { return column_table(size_type(ColNum)); }
252 
259  oid column_table(const PGSTD::string &ColName) const //[t2]
260  { return column_table(column_number(ColName)); }
261 
263 
273  size_type table_column(size_type ColNum) const //[t93]
274  { return m_Home->table_column(m_Begin+ColNum); }
275 
277  size_type table_column(int ColNum) const //[t93]
278  { return table_column(size_type(ColNum)); }
279 
281  size_type table_column(const PGSTD::string &ColName) const //[t93]
282  { return table_column(column_number(ColName)); }
284 
285  result::size_type num() const { return rownumber(); } //[t1]
286 
299  tuple slice(size_type Begin, size_type End) const;
300 
301  // Is this an empty slice?
302  bool empty() const throw ();
303 
304  protected:
305  friend class field;
306  const result *m_Home;
307  result::size_type m_Index;
308  size_type m_Begin;
309  size_type m_End;
310 
311  private:
312  // Not allowed:
313  tuple();
314  };
315 
317 
320  class PQXX_LIBEXPORT field
321  {
322  public:
323  typedef size_t size_type;
324 
326 
330  field(const tuple &T, tuple::size_type C) throw () : //[t1]
331  m_tup(T), m_col(C) {}
332 
337 
338 
354  bool operator==(const field &) const; //[t75]
355 
357 
359  bool operator!=(const field &rhs) const {return !operator==(rhs);} //[t82]
361 
366 
367  const char *name() const { return home()->column_name(col()); } //[t11]
368 
370  oid type() const { return home()->column_type(col()); } //[t7]
371 
373 
380  oid table() const { return home()->column_table(col()); } //[t2]
381 
382  tuple::size_type num() const { return col(); } //[t82]
383 
385  tuple::size_type table_column() const //[t93]
386  { return home()->table_column(col()); }
388 
393 
394 
399  const char *c_str() const { return home()->GetValue(idx(),col()); } //[t2]
400 
402  template<typename T> bool to(T &Obj) const //[t3]
403  {
404  const char *const bytes = c_str();
405  if (!bytes[0] && is_null()) return false;
406  from_string(bytes, Obj);
407  return true;
408  }
409 
411  template<typename T> bool operator>>(T &Obj) const //[t7]
412  { return to(Obj); }
413 
414 #ifdef PQXX_NO_PARTIAL_CLASS_TEMPLATE_SPECIALISATION
415 
416  template<> bool to<PGSTD::string>(PGSTD::string &Obj) const;
417 
419 
422  template<> bool to<const char *>(const char *&Obj) const;
423 #endif
424 
426  template<typename T> bool to(T &Obj, const T &Default) const //[t12]
427  {
428  const bool NotNull = to(Obj);
429  if (!NotNull) Obj = Default;
430  return NotNull;
431  }
432 
434 
437  template<typename T> T as(const T &Default) const //[t1]
438  {
439  T Obj;
440  to(Obj, Default);
441  return Obj;
442  }
443 
445  template<typename T> T as() const //[t45]
446  {
447  T Obj;
448  const bool NotNull = to(Obj);
449  if (!NotNull) Obj = string_traits<T>::null();
450  return Obj;
451  }
452 
453  bool is_null() const { return home()->GetIsNull(idx(), col()); } //[t12]
454  size_type size() const throw () //[t11]
455  { return home()->GetLength(idx(),col()); }
457 
458 
459  private:
460  const result *home() const throw () { return m_tup.m_Home; }
461  result::size_type idx() const throw () { return m_tup.m_Index; }
462 
463  protected:
464  tuple::size_type col() const throw () { return m_col; }
465  tuple m_tup;
467  };
468 
469  typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
470  const tuple,
473  tuple>
475 
477 
481  class PQXX_LIBEXPORT const_iterator :
482  public const_iterator_base,
483  public tuple
484  {
485  public:
486  typedef const tuple *pointer;
487  typedef tuple reference;
490 
491  const_iterator() throw () : tuple(0,0) {}
492  const_iterator(const tuple &t) throw () : tuple(t) {}
493 
509  pointer operator->() const { return this; } //[t12]
510  reference operator*() const { return tuple(*this); } //[t12]
512 
517  const_iterator operator++(int); //[t12]
518  const_iterator &operator++() { ++m_Index; return *this; } //[t1]
519  const_iterator operator--(int); //[t12]
520  const_iterator &operator--() { --m_Index; return *this; } //[t12]
521 
522  const_iterator &operator+=(difference_type i) //[t12]
523  { m_Index = size_type(difference_type(m_Index) + i); return *this; }
524  const_iterator &operator-=(difference_type i) //[t12]
525  { m_Index = size_type(difference_type(m_Index) - i); return *this; }
527 
532  bool operator==(const const_iterator &i) const //[t12]
533  {return m_Index==i.m_Index;}
534  bool operator!=(const const_iterator &i) const //[t12]
535  {return m_Index!=i.m_Index;}
536  bool operator<(const const_iterator &i) const //[t12]
537  {return m_Index<i.m_Index;}
538  bool operator<=(const const_iterator &i) const //[t12]
539  {return m_Index<=i.m_Index;}
540  bool operator>(const const_iterator &i) const //[t12]
541  {return m_Index>i.m_Index;}
542  bool operator>=(const const_iterator &i) const //[t12]
543  {return m_Index>=i.m_Index;}
545 
550  inline const_iterator operator+(difference_type) const; //[t12]
551  friend const_iterator
553  inline const_iterator operator-(difference_type) const; //[t12]
554  inline difference_type operator-(const_iterator) const; //[t12]
556 
557  private:
558  friend class pqxx::result;
559  const_iterator(const pqxx::result *r, result::size_type i) throw () :
560  tuple(r, i) {}
561  };
562 
564 
565  class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
566  {
567  public:
570  using iterator_type::iterator_category;
573 #ifndef _MSC_VER
574  using iterator_type::value_type;
576 #else
577  // Workaround for Visual C++.NET 2003, which has access problems
578  typedef const tuple &reference;
579  typedef tuple value_type;
580 #endif
581 
583  const_iterator(rhs) {}
584  explicit const_reverse_iterator(const const_iterator &rhs) : //[t75]
585  const_iterator(rhs) { super::operator--(); }
586 
587  iterator_type base() const throw (); //[t75]
588 
593  using const_iterator::operator->; //[t75]
594  using const_iterator::operator*; //[t75]
596 
601  const_reverse_iterator &operator=(const const_reverse_iterator &r) //[t75]
602  { iterator_type::operator=(r); return *this; }
603  const_reverse_iterator operator++() //[t75]
604  { iterator_type::operator--(); return *this; }
605  const_reverse_iterator operator++(int); //[t75]
606  const_reverse_iterator &operator--() //[t75]
607  { iterator_type::operator++(); return *this; }
608  const_reverse_iterator operator--(int); //[t75]
610  { iterator_type::operator-=(i); return *this; }
612  { iterator_type::operator+=(i); return *this; }
614 
620  { return const_reverse_iterator(base()-i); }
622  { return const_reverse_iterator(base()+i); }
623  difference_type operator-(const const_reverse_iterator &rhs) const //[t75]
624  { return rhs.const_iterator::operator-(*this); }
626 
631  bool operator==(const const_reverse_iterator &rhs) const throw () //[t75]
632  { return iterator_type::operator==(rhs); }
633  bool operator!=(const const_reverse_iterator &rhs) const throw () //[t75]
634  { return !operator==(rhs); }
635 
636  bool operator<(const const_reverse_iterator &rhs) const //[t75]
637  { return iterator_type::operator>(rhs); }
638  bool operator<=(const const_reverse_iterator &rhs) const //[t75]
639  { return iterator_type::operator>=(rhs); }
640  bool operator>(const const_reverse_iterator &rhs) const //[t75]
641  { return iterator_type::operator<(rhs); }
642  bool operator>=(const const_reverse_iterator &rhs) const //[t75]
643  { return iterator_type::operator<=(rhs); }
645  };
646 
648 
649  class PQXX_LIBEXPORT const_fielditerator :
650  public PGSTD::iterator<PGSTD::random_access_iterator_tag,
651  const field,
652  tuple::size_type>,
653  public field
654  {
655  typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
656  const field,
657  tuple::size_type> it;
658  public:
659  using it::pointer;
662  typedef field reference;
663 
664  const_fielditerator(const tuple &T, tuple::size_type C) throw () : //[t82]
665  field(T, C) {}
666  const_fielditerator(const field &F) throw () : field(F) {} //[t82]
667 
672  pointer operator->() const { return this; } //[t82]
673  reference operator*() const { return field(*this); } //[t82]
675 
680  const_fielditerator operator++(int); //[t82]
681  const_fielditerator &operator++() { ++m_col; return *this; } //[t82]
682  const_fielditerator operator--(int); //[t82]
683  const_fielditerator &operator--() { --m_col; return *this; } //[t82]
684 
685  const_fielditerator &operator+=(difference_type i) //[t82]
686  { m_col = size_type(difference_type(m_col) + i); return *this; }
687  const_fielditerator &operator-=(difference_type i) //[t82]
688  { m_col = size_type(difference_type(m_col) - i); return *this; }
690 
695  bool operator==(const const_fielditerator &i) const //[t82]
696  {return col()==i.col();}
697  bool operator!=(const const_fielditerator &i) const //[t82]
698  {return col()!=i.col();}
699  bool operator<(const const_fielditerator &i) const //[t82]
700  {return col()<i.col();}
701  bool operator<=(const const_fielditerator &i) const //[t82]
702  {return col()<=i.col();}
703  bool operator>(const const_fielditerator &i) const //[t82]
704  {return col()>i.col();}
705  bool operator>=(const const_fielditerator &i) const //[t82]
706  {return col()>=i.col();}
708 
713  inline const_fielditerator operator+(difference_type) const; //[t82]
714 
716  const_fielditerator); //[t82]
717 
718  inline const_fielditerator operator-(difference_type) const; //[t82]
719  inline difference_type operator-(const_fielditerator) const; //[t82]
721  };
722 
723  class PQXX_LIBEXPORT const_reverse_fielditerator : private const_fielditerator
724  {
725  public:
728  using iterator_type::iterator_category;
730  using iterator_type::pointer;
731 #ifndef _MSC_VER
732  using iterator_type::value_type;
734 #else
735  // Workaround for Visual C++.NET 2003, which has access problems
736  typedef field value_type;
737  typedef const field &reference;
738 #endif
739 
741  const_fielditerator(r) {}
742  explicit
743  const_reverse_fielditerator(const super &rhs) throw() : //[t82]
744  const_fielditerator(rhs) { super::operator--(); }
745 
746  iterator_type base() const throw (); //[t82]
747 
752  using iterator_type::operator->; //[t82]
753  using iterator_type::operator*; //[t82]
755 
761  operator=(const const_reverse_fielditerator &r) //[t82]
762  { iterator_type::operator=(r); return *this; }
763  const_reverse_fielditerator operator++() //[t82]
764  { iterator_type::operator--(); return *this; }
765  const_reverse_fielditerator operator++(int); //[t82]
766  const_reverse_fielditerator &operator--() //[t82]
767  { iterator_type::operator++(); return *this; }
768  const_reverse_fielditerator operator--(int); //[t82]
770  { iterator_type::operator-=(i); return *this; }
772  { iterator_type::operator+=(i); return *this; }
774 
780  { return const_reverse_fielditerator(base()-i); }
782  { return const_reverse_fielditerator(base()+i); }
784  operator-(const const_reverse_fielditerator &rhs) const //[t82]
785  { return rhs.const_fielditerator::operator-(*this); }
787 
792  bool
793  operator==(const const_reverse_fielditerator &rhs) const throw () //[t82]
794  { return iterator_type::operator==(rhs); }
795  bool
796  operator!=(const const_reverse_fielditerator &rhs) const throw () //[t82]
797  { return !operator==(rhs); }
798 
799  bool operator<(const const_reverse_fielditerator &rhs) const //[t82]
800  { return iterator_type::operator>(rhs); }
801  bool operator<=(const const_reverse_fielditerator &rhs) const //[t82]
802  { return iterator_type::operator>=(rhs); }
803  bool operator>(const const_reverse_fielditerator &rhs) const //[t82]
804  { return iterator_type::operator<(rhs); }
805  bool operator>=(const const_reverse_fielditerator &rhs) const //[t82]
806  { return iterator_type::operator<=(rhs); }
808  };
809 
810 
811  result() throw () : super(), m_data(0) {} //[t3]
812  result(const result &rhs) throw () : //[t1]
813  super(rhs), m_data(rhs.m_data) {}
814 
815  result &operator=(const result &rhs) throw () //[t10]
816  { super::operator=(rhs); m_data=rhs.m_data; return *this; }
817 
822  bool operator==(const result &) const throw (); //[t70]
823  bool operator!=(const result &rhs) const throw () //[t70]
824  { return !operator==(rhs); }
826 
827  const_reverse_iterator rbegin() const //[t75]
828  { return const_reverse_iterator(end()); }
829  const_reverse_iterator rend() const //[t75]
830  { return const_reverse_iterator(begin()); }
831 
832  const_iterator begin() const throw () //[t1]
833  { return const_iterator(this, 0); }
834  inline const_iterator end() const throw (); //[t1]
835 
836  reference front() const throw () { return tuple(this,0); } //[t74]
837  reference back() const throw () {return tuple(this,size()-1);} //[t75]
838 
839  size_type size() const throw (); //[t2]
840  bool empty() const throw (); //[t11]
841  size_type capacity() const throw () { return size(); } //[t20]
842 
843  void swap(result &) throw (); //[t77]
844 
845  const tuple operator[](size_type i) const throw () //[t2]
846  { return tuple(this, i); }
847  const tuple at(size_type) const throw (range_error); //[t10]
848 
849  void clear() throw () { super::reset(); m_data = 0; } //[t20]
850 
855 
856  tuple::size_type columns() const throw (); //[t11]
857 
859  tuple::size_type column_number(const char ColName[]) const; //[t11]
860 
862  tuple::size_type column_number(const PGSTD::string &Name) const //[t11]
863  {return column_number(Name.c_str());}
864 
866  const char *column_name(tuple::size_type Number) const; //[t11]
867 
869  oid column_type(tuple::size_type ColNum) const; //[t7]
871  oid column_type(int ColNum) const //[t7]
872  { return column_type(tuple::size_type(ColNum)); }
873 
875  oid column_type(const PGSTD::string &ColName) const //[t7]
876  { return column_type(column_number(ColName)); }
877 
879  oid column_type(const char ColName[]) const //[t7]
880  { return column_type(column_number(ColName)); }
881 
883 
890  oid column_table(tuple::size_type ColNum) const; //[t2]
891 
893 
900  oid column_table(int ColNum) const //[t2]
901  { return column_table(tuple::size_type(ColNum)); }
902 
904 
911  oid column_table(const PGSTD::string &ColName) const //[t2]
912  { return column_table(column_number(ColName)); }
913 
915  tuple::size_type table_column(tuple::size_type ColNum) const; //[t93]
916 
918  tuple::size_type table_column(int ColNum) const //[t93]
919  { return table_column(tuple::size_type(ColNum)); }
920 
922  tuple::size_type table_column(const PGSTD::string &ColName) const //[t93]
923  { return table_column(column_number(ColName)); }
925 
927  const PGSTD::string &query() const throw (); //[t70]
928 
930 
933  oid inserted_oid() const; //[t13]
934 
935 
937 
940  size_type affected_rows() const; //[t7]
941 
942 
943 private:
944  friend class pqxx::result::field;
945  const char *GetValue(size_type Row, tuple::size_type Col) const;
946  bool GetIsNull(size_type Row, tuple::size_type Col) const;
947  field::size_type GetLength(size_type, tuple::size_type) const throw ();
948 
949  friend class pqxx::internal::gate::result_creation;
950  result(internal::pq::PGresult *rhs,
951  int protocol,
952  const PGSTD::string &Query,
953  int encoding_code);
954  void PQXX_PRIVATE CheckStatus() const;
955 
956  friend class pqxx::internal::gate::result_connection;
957  bool operator!() const throw () { return !m_data; }
958  operator bool() const throw () { return m_data != 0; }
959 
960  void PQXX_PRIVATE ThrowSQLError(const PGSTD::string &Err,
961  const PGSTD::string &Query) const;
962  int PQXX_PRIVATE errorposition() const throw ();
963  PGSTD::string PQXX_PRIVATE StatusError() const;
964 
965  friend class pqxx::internal::gate::result_sql_cursor;
966  const char *CmdStatus() const throw ();
967 
969  pqxx::internal::pq::PGresult *m_data;
970 
971  static const PGSTD::string PQXX_PRIVATE s_empty_string;
972 };
973 
974 
976 
996 template<typename CHAR>
997 inline PGSTD::basic_ostream<CHAR> &operator<<(
998  PGSTD::basic_ostream<CHAR> &S, const pqxx::result::field &F) //[t46]
999 {
1000  S.write(F.c_str(), F.size());
1001  return S;
1002 }
1003 
1004 
1006 template<typename T>
1007 inline void from_string(const result::field &F, T &Obj) //[t46]
1008  { from_string(F.c_str(), Obj, F.size()); }
1009 
1011 template<>
1012 inline PGSTD::string to_string(const result::field &Obj) //[t74]
1013  { return PGSTD::string(Obj.c_str(), Obj.size()); }
1014 
1015 
1017 template<>
1018 inline bool result::field::to<PGSTD::string>(PGSTD::string &Obj) const
1019 {
1020  const char *const bytes = c_str();
1021  if (!bytes[0] && is_null()) return false;
1022  Obj = PGSTD::string(bytes, size());
1023  return true;
1024 }
1025 
1027 
1032 template<>
1033 inline bool result::field::to<const char *>(const char *&Obj) const
1034 {
1035  if (is_null()) return false;
1036  Obj = c_str();
1037  return true;
1038 }
1039 
1040 
1042  { return const_reverse_fielditerator(end()); }
1044  { return const_reverse_fielditerator(begin()); }
1045 
1048 {
1049  return const_iterator(m_Home, size_type(difference_type(m_Index) + o));
1050 }
1051 
1054  { return i + o; }
1055 
1056 inline result::const_iterator
1058 {
1059  return const_iterator(m_Home, size_type(difference_type(m_Index) - o));
1060 }
1061 
1064  { return difference_type(num()) - difference_type(i.num()); }
1065 
1066 inline result::const_iterator result::end() const throw ()
1067  { return const_iterator(this, size()); }
1068 
1069 
1073  { return result::const_reverse_iterator(i.base() - n); }
1074 
1075 inline result::const_fielditerator
1077 {
1078  return const_fielditerator(m_tup, size_type(difference_type(col()) + o));
1079 }
1080 
1084  { return i + o; }
1085 
1086 inline result::const_fielditerator
1088 {
1089  return const_fielditerator(m_tup, size_type(difference_type(col()) - o));
1090 }
1091 
1094  { return difference_type(num()) - difference_type(i.num()); }
1095 
1096 
1097 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
1099 #ifdef PQXX_HAVE_STREAMBUF
1100  public PGSTD::basic_streambuf<CHAR, TRAITS>
1101 #else
1102  public PGSTD::streambuf
1103 #endif
1104 {
1105 public:
1106  typedef CHAR char_type;
1107  typedef TRAITS traits_type;
1108  typedef typename traits_type::int_type int_type;
1109 #ifdef PQXX_HAVE_STREAMBUF
1110  typedef typename traits_type::pos_type pos_type;
1111  typedef typename traits_type::off_type off_type;
1112 #else
1113  typedef streamoff off_type;
1114  typedef streampos pos_type;
1115 #endif
1116  typedef PGSTD::ios::openmode openmode;
1117  typedef PGSTD::ios::seekdir seekdir;
1118 
1119  explicit field_streambuf(const result::field &F) : //[t74]
1120  m_Field(F)
1121  {
1122  initialize();
1123  }
1124 
1125 #ifdef PQXX_HAVE_STREAMBUF
1126 protected:
1127 #endif
1128  virtual int sync() { return traits_type::eof(); }
1129 
1130 protected:
1131  virtual pos_type seekoff(off_type, seekdir, openmode)
1132  { return traits_type::eof(); }
1133  virtual pos_type seekpos(pos_type, openmode) {return traits_type::eof();}
1134  virtual int_type overflow(int_type) { return traits_type::eof(); }
1135  virtual int_type underflow() { return traits_type::eof(); }
1136 
1137 private:
1138  const result::field &m_Field;
1139 
1140  int_type initialize()
1141  {
1142  char_type *G =
1143  reinterpret_cast<char_type *>(const_cast<char *>(m_Field.c_str()));
1144  this->setg(G, G, G + m_Field.size());
1145  return int_type(m_Field.size());
1146  }
1147 };
1148 
1149 
1151 
1159 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
1161 #ifdef PQXX_HAVE_STREAMBUF
1162  public PGSTD::basic_istream<CHAR, TRAITS>
1163 #else
1164  public PGSTD::istream
1165 #endif
1166 {
1167 #ifdef PQXX_HAVE_STREAMBUF
1168  typedef PGSTD::basic_istream<CHAR, TRAITS> super;
1169 #else
1170  typedef PGSTD::istream super;
1171 #endif
1172 
1173 public:
1174  typedef CHAR char_type;
1175  typedef TRAITS traits_type;
1176  typedef typename traits_type::int_type int_type;
1177  typedef typename traits_type::pos_type pos_type;
1178  typedef typename traits_type::off_type off_type;
1179 
1180  basic_fieldstream(const result::field &F) : super(0), m_Buf(F)
1181  { super::init(&m_Buf); }
1182 
1183 private:
1185 };
1186 
1188 
1189 } // namespace pqxx
1190 
1191 
1192 
1193 /*
1194 [1] Scott Meyers, in one of his essential books, "Effective C++" and "More
1195 Effective C++", points out that it is good style to have any class containing
1196 a member of pointer type define a destructor--just to show that it knows what it
1197 is doing with the pointer. This helps prevent nasty memory leak / double
1198 deletion bugs typically resulting from programmers' omission to deal with such
1199 issues in their destructors.
1200 
1201 The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's
1202 style guidelines, and hence necessitates the definition of this destructor,
1203 trivial as it may be.
1204 */
1205 
1206 
1207 #include "pqxx/compiler-internal-post.hxx"
1208 
1209 #endif
1210