libpqxx 3.1.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes

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
55 pqxx::internal::pq::PGresult *data;
56
58 int protocol;
59
61 PGSTD::string query;
62
63 int encoding_code;
64
65 // TODO: Locking for result copy-construction etc. also goes here
66
67 result_data();
68 result_data(pqxx::internal::pq::PGresult *,
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<
116 const internal::result_data, internal::freemem_result_data> super;
117 public:
118 class const_iterator;
119 class const_fielditerator;
120 class const_reverse_fielditerator;
121 class tuple;
122 class field;
123 typedef unsigned long size_type;
124 typedef signed long difference_type;
125 typedef tuple reference;
126 typedef const_iterator pointer;
127
129
140 class PQXX_LIBEXPORT tuple
141 {
142 public:
143 typedef unsigned int size_type;
144 typedef signed int difference_type;
145 typedef const_fielditerator const_iterator;
146 typedef const_iterator iterator;
147 typedef field reference;
148 typedef const_fielditerator pointer;
149 typedef const_reverse_fielditerator const_reverse_iterator;
150 typedef const_reverse_iterator reverse_iterator;
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;
466 tuple::size_type m_col;
467 };
468
469 typedef PGSTD::iterator<PGSTD::random_access_iterator_tag,
470 const tuple,
471 result::difference_type,
472 const_iterator,
473 tuple>
474 const_iterator_base;
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;
488 typedef result::size_type size_type;
489 typedef result::difference_type difference_type;
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
552 operator+(difference_type, const_iterator); //[t12]
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
563 typedef const_iterator iterator;
564
565 class PQXX_LIBEXPORT const_reverse_iterator : private const_iterator
566 {
567 public:
568 typedef pqxx::result::const_iterator super;
569 typedef pqxx::result::const_iterator iterator_type;
570 using iterator_type::iterator_category;
571 using iterator_type::difference_type;
572 using iterator_type::pointer;
573 #ifndef _MSC_VER
574 using iterator_type::value_type;
575 using iterator_type::reference;
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
582 const_reverse_iterator(const const_reverse_iterator &rhs) : //[t75]
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]
609 const_reverse_iterator &operator+=(difference_type i) //[t75]
610 { iterator_type::operator-=(i); return *this; }
611 const_reverse_iterator &operator-=(difference_type i) //[t75]
612 { iterator_type::operator+=(i); return *this; }
614
619 const_reverse_iterator operator+(difference_type i) const //[t75]
620 { return const_reverse_iterator(base()-i); }
621 const_reverse_iterator operator-(difference_type i) //[t75]
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
647 typedef const_reverse_iterator reverse_iterator;
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;
660 typedef tuple::size_type size_type;
661 typedef tuple::difference_type difference_type;
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
715 friend const_fielditerator operator+(difference_type,
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:
726 typedef const_fielditerator super;
727 typedef const_fielditerator iterator_type;
728 using iterator_type::iterator_category;
729 using iterator_type::difference_type;
730 using iterator_type::pointer;
731 #ifndef _MSC_VER
732 using iterator_type::value_type;
733 using iterator_type::reference;
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
740 const_reverse_fielditerator(const const_reverse_fielditerator &r) : //[t82]
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
760 const_reverse_fielditerator &
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]
769 const_reverse_fielditerator &operator+=(difference_type i) //[t82]
770 { iterator_type::operator-=(i); return *this; }
771 const_reverse_fielditerator &operator-=(difference_type i) //[t82]
772 { iterator_type::operator+=(i); return *this; }
774
779 const_reverse_fielditerator operator+(difference_type i) const //[t82]
780 { return const_reverse_fielditerator(base()-i); }
781 const_reverse_fielditerator operator-(difference_type i) //[t82]
782 { return const_reverse_fielditerator(base()+i); }
783 difference_type
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
1041 inline result::tuple::const_reverse_iterator result::tuple::rbegin() const
1042 { return const_reverse_fielditerator(end()); }
1043 inline result::tuple::const_reverse_iterator result::tuple::rend() const
1044 { return const_reverse_fielditerator(begin()); }
1045
1046 inline result::const_iterator
1047 result::const_iterator::operator+(difference_type o) const
1048 {
1049 return const_iterator(m_Home, size_type(difference_type(m_Index) + o));
1050 }
1051
1052 inline result::const_iterator
1053 operator+(result::const_iterator::difference_type o, result::const_iterator i)
1054 { return i + o; }
1055
1056 inline result::const_iterator
1057 result::const_iterator::operator-(difference_type o) const
1058 {
1059 return const_iterator(m_Home, size_type(difference_type(m_Index) - o));
1060 }
1061
1062 inline result::const_iterator::difference_type
1063 result::const_iterator::operator-(const_iterator i) const
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
1070 inline result::const_reverse_iterator
1071 operator+(result::const_reverse_iterator::difference_type n,
1072 const result::const_reverse_iterator &i)
1073 { return result::const_reverse_iterator(i.base() - n); }
1074
1075 inline result::const_fielditerator
1076 result::const_fielditerator::operator+(difference_type o) const
1077 {
1078 return const_fielditerator(m_tup, size_type(difference_type(col()) + o));
1079 }
1080
1081 inline result::const_fielditerator
1082 operator+(result::const_fielditerator::difference_type o,
1083 result::const_fielditerator i)
1084 { return i + o; }
1085
1086 inline result::const_fielditerator
1087 result::const_fielditerator::operator-(difference_type o) const
1088 {
1089 return const_fielditerator(m_tup, size_type(difference_type(col()) - o));
1090 }
1091
1092 inline result::const_fielditerator::difference_type
1093 result::const_fielditerator::operator-(const_fielditerator i) const
1094 { return difference_type(num()) - difference_type(i.num()); }
1095
1096
1097 template<typename CHAR=char, typename TRAITS=PGSTD::char_traits<CHAR> >
1098 class field_streambuf :
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> >
1160 class basic_fieldstream :
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:
1184 field_streambuf<CHAR, TRAITS> m_Buf;
1185 };
1186
1187 typedef basic_fieldstream<char> fieldstream;
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