00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "pqxx/compiler-public.hxx"
00019
00020 #include <cstdio>
00021 #include <cctype>
00022 #include <sstream>
00023 #include <stdexcept>
00024 #include <string>
00025 #include <typeinfo>
00026 #include <vector>
00027
00065
00066 namespace pqxx {}
00067
00069
00074 namespace PGSTD {}
00075
00076 #include <pqxx/libpq-forward.hxx>
00077
00078
00079 namespace pqxx
00080 {
00082 const oid oid_none = 0;
00083
00106
00108
00121 template<typename T> void error_unsupported_type_in_string_conversion(T);
00122
00123
00125
00131 template<typename T> PGSTD::string error_ambiguous_string_conversion(T);
00132
00133
00134
00135
00136
00138
00150 template<typename T> void from_string(const char Str[], T &Obj);
00151
00152 template<> void PQXX_LIBEXPORT from_string(const char Str[], long &);
00153 template<>
00154 void PQXX_LIBEXPORT from_string(const char Str[], unsigned long &);
00155 template<> void PQXX_LIBEXPORT from_string(const char Str[], int &);
00156 template<>
00157 void PQXX_LIBEXPORT from_string(const char Str[], unsigned int &);
00158 template<> void PQXX_LIBEXPORT from_string(const char Str[], short &);
00159 template<>
00160 void PQXX_LIBEXPORT from_string(const char Str[], unsigned short &);
00161 template<> void PQXX_LIBEXPORT from_string(const char Str[], float &);
00162 template<> void PQXX_LIBEXPORT from_string(const char Str[], double &);
00163 template<> void PQXX_LIBEXPORT from_string(const char Str[], bool &);
00164 #if defined(PQXX_HAVE_LONG_DOUBLE)
00165 template<>
00166 void PQXX_LIBEXPORT from_string(const char Str[], long double &);
00167 #endif
00168
00169
00170 template<> inline void from_string(const char Str[],PGSTD::string &Obj)
00171 { Obj = Str; }
00172
00173 template<>
00174 inline void from_string(const char Str[], PGSTD::stringstream &Obj)
00175 { Obj.clear(); Obj << Str; }
00176
00177 template<typename T>
00178 inline void from_string(const PGSTD::string &Str, T &Obj)
00179 { from_string(Str.c_str(), Obj); }
00180
00181 template<typename T>
00182 inline void from_string(const PGSTD::stringstream &Str, T &Obj)
00183 { from_string(Str.str(), Obj); }
00184
00185 template<> inline void
00186 from_string(const PGSTD::string &Str, PGSTD::string &Obj)
00187 { Obj = Str; }
00188
00189 template<> inline void
00190 from_string(const char [], char &Obj)
00191 { error_ambiguous_string_conversion(Obj); }
00192 template<> inline void
00193 from_string(const char [], signed char &Obj)
00194 { error_ambiguous_string_conversion(Obj); }
00195 template<> inline void
00196 from_string(const char [], unsigned char &Obj)
00197 { error_ambiguous_string_conversion(Obj); }
00198
00199 template<> inline void
00200 from_string(const PGSTD::string &, char &Obj)
00201 { error_ambiguous_string_conversion(Obj); }
00202 template<> inline void
00203 from_string(const PGSTD::string &, signed char &Obj)
00204 { error_ambiguous_string_conversion(Obj); }
00205 template<> inline void
00206 from_string(const PGSTD::string &, unsigned char &Obj)
00207 { error_ambiguous_string_conversion(Obj); }
00208
00209
00210 namespace internal
00211 {
00213 inline int digit_to_number(char c) throw () { return c-'0'; }
00214 inline char number_to_digit(int i) throw () { return static_cast<char>(i)+'0'; }
00215 }
00216
00217
00219
00223 template<typename T> PGSTD::string to_string(const T &);
00224
00225 template<> PGSTD::string PQXX_LIBEXPORT to_string(const short &);
00226 template<>
00227 PGSTD::string PQXX_LIBEXPORT to_string(const unsigned short &);
00228 template<> PGSTD::string PQXX_LIBEXPORT to_string(const int &);
00229 template<>
00230 PGSTD::string PQXX_LIBEXPORT to_string(const unsigned int &);
00231 template<> PGSTD::string PQXX_LIBEXPORT to_string(const long &);
00232 template<>
00233 PGSTD::string PQXX_LIBEXPORT to_string(const unsigned long &);
00234 template<> PGSTD::string PQXX_LIBEXPORT to_string(const float &);
00235 template<> PGSTD::string PQXX_LIBEXPORT to_string(const double &);
00236 template<> PGSTD::string PQXX_LIBEXPORT to_string(const bool &);
00237 #if defined(PQXX_HAVE_LONG_DOUBLE)
00238 template<> PGSTD::string PQXX_LIBEXPORT to_string(const long double &);
00239 #endif
00240
00241 inline PGSTD::string to_string(const char Obj[])
00242 { return PGSTD::string(Obj); }
00243
00244 inline PGSTD::string to_string(const PGSTD::stringstream &Obj)
00245 { return Obj.str(); }
00246
00247 inline PGSTD::string to_string(const PGSTD::string &Obj) {return Obj;}
00248
00249 template<> PGSTD::string PQXX_LIBEXPORT to_string(const char &);
00250
00251
00252 template<> inline PGSTD::string to_string(const signed char &Obj)
00253 { return error_ambiguous_string_conversion(Obj); }
00254 template<> inline PGSTD::string to_string(const unsigned char &Obj)
00255 { return error_ambiguous_string_conversion(Obj); }
00257
00259
00281 template<typename T=PGSTD::string, typename CONT=PGSTD::vector<T> >
00282 class items : public CONT
00283 {
00284 public:
00286 items() : CONT() {}
00288 explicit items(const T &t) : CONT() { push_back(t); }
00289 items(const T &t1, const T &t2) : CONT()
00290 { push_back(t1); push_back(t2); }
00291 items(const T &t1, const T &t2, const T &t3) : CONT()
00292 { push_back(t1); push_back(t2); push_back(t3); }
00293 items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()
00294 { push_back(t1); push_back(t2); push_back(t3); push_back(t4); }
00295 items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()
00296 {push_back(t1);push_back(t2);push_back(t3);push_back(t4);push_back(t5);}
00298 items(const CONT &c) : CONT(c) {}
00299
00301 items &operator()(const T &t)
00302 {
00303 push_back(t);
00304 return *this;
00305 }
00306 };
00307
00308
00309 namespace internal
00310 {
00311
00313 template<typename ITER> struct dereference
00314 {
00315 typename ITER::value_type operator()(ITER i) const { return *i; }
00316 };
00317 template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
00318 }
00319
00320
00322
00328 template<typename ITER, typename ACCESS> inline
00329 PGSTD::string separated_list(const PGSTD::string &sep,
00330 ITER begin,
00331 ITER end,
00332 ACCESS access)
00333 {
00334 PGSTD::string result;
00335 if (begin != end)
00336 {
00337 result = to_string(access(begin));
00338 for (++begin; begin != end; ++begin)
00339 {
00340 result += sep;
00341 result += to_string(access(begin));
00342 }
00343 }
00344 return result;
00345 }
00346
00351
00353 template<typename ITER> inline PGSTD::string
00354 separated_list(const PGSTD::string &sep, ITER begin, ITER end)
00355 { return separated_list(sep,begin,end,internal::dereference<ITER>()); }
00356
00357
00359 template<typename OBJ> inline PGSTD::string
00360 separated_list(const PGSTD::string &sep, OBJ *begin, OBJ *end)
00361 { return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }
00362
00363
00365 template<typename CONTAINER> inline PGSTD::string
00366 separated_list(const PGSTD::string &sep, const CONTAINER &c)
00367 { return separated_list(sep, c.begin(), c.end()); }
00369
00371
00380 namespace internal
00381 {
00382 typedef unsigned long result_size_type;
00383 typedef long result_difference_type;
00384
00386
00394 template<typename T> inline const char *FmtString(T t) PQXX_DEPRECATED
00395 {
00396 error_unsupported_type_in_string_conversion(t);
00397 return 0;
00398 }
00399
00400 template<> inline const char *FmtString(short) { return "%hd"; }
00401 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00402 template<> inline const char *FmtString(int) { return "%i"; }
00403 template<> inline const char *FmtString(long) { return "%li"; }
00404 template<> inline const char *FmtString(unsigned) { return "%u"; }
00405 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00406 template<> inline const char *FmtString(float) { return "%f"; }
00407 template<> inline const char *FmtString(double) { return "%lf"; }
00408 template<> inline const char *FmtString(char) { return "%c"; }
00409 template<> inline const char *FmtString(unsigned char) { return "%c"; }
00410 #if defined(PQXX_HAVE_LONG_DOUBLE)
00411 template<> inline const char *FmtString(long double) { return "%Lf"; }
00412 #endif
00413
00414 }
00415
00417
00425 template<typename T> inline PGSTD::string ToString(const T &Obj) PQXX_DEPRECATED
00426 {
00427
00428 char Buf[500];
00429 sprintf(Buf, internal::FmtString(Obj), Obj);
00430 return PGSTD::string(Buf);
00431 }
00432
00433
00434 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00435 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00436 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00437
00438 template<> inline PGSTD::string ToString(const unsigned char *const &Obj)
00439 {
00440 return reinterpret_cast<const char *>(Obj);
00441 }
00442
00443 template<> inline PGSTD::string ToString(const bool &Obj)
00444 {
00445 return ToString(unsigned(Obj));
00446 }
00447
00448 template<> inline PGSTD::string ToString(const short &Obj)
00449 {
00450 return ToString(int(Obj));
00451 }
00452
00453 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00454 {
00455 return ToString(unsigned(Obj));
00456 }
00457
00458
00460
00468 template<typename T> inline void FromString(const char Str[], T &Obj)
00469 PQXX_DEPRECATED
00470 {
00471 if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00472 PGSTD::string(typeid(T).name()));
00473
00474 if (sscanf(Str, internal::FmtString(Obj), &Obj) != 1)
00475 throw PGSTD::runtime_error("Cannot convert value '" +
00476 PGSTD::string(Str) +
00477 "' to " + typeid(T).name());
00478 }
00479
00480
00481 namespace internal
00482 {
00484
00486 PGSTD::string escape_string(const char str[], size_t maxlen);
00487
00489
00491 void PQXX_LIBEXPORT FromString_string(const char Str[], PGSTD::string &Obj)
00492 PQXX_DEPRECATED;
00493
00495
00497 void PQXX_LIBEXPORT FromString_ucharptr(const char Str[],
00498 const unsigned char *&Obj)
00499 PQXX_DEPRECATED;
00500
00502 PGSTD::string PQXX_LIBEXPORT Quote_string(const PGSTD::string &Obj,
00503 bool EmptyIsNull);
00504
00506 PGSTD::string PQXX_LIBEXPORT Quote_charptr(const char Obj[], bool EmptyIsNull);
00507 }
00508
00509
00510 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00511 {
00512 internal::FromString_string(Str, Obj);
00513 }
00514
00515 template<> inline void FromString(const char Str[], const char *&Obj)
00516 {
00517 if (!Str) throw PGSTD::runtime_error("Attempt to read NULL string");
00518 Obj = Str;
00519 }
00520
00521 template<> inline void FromString(const char Str[], const unsigned char *&Obj)
00522 {
00523 internal::FromString_ucharptr(Str, Obj);
00524 }
00525
00526 template<> inline void FromString(const char Str[], bool &Obj)
00527 {
00528 from_string(Str, Obj);
00529 }
00530
00531
00598
00599
00611 PGSTD::string PQXX_LIBEXPORT sqlesc(const char str[]);
00612
00614
00627 PGSTD::string PQXX_LIBEXPORT sqlesc(const char str[], size_t maxlen);
00628
00630
00636 PGSTD::string PQXX_LIBEXPORT sqlesc(const PGSTD::string &);
00637
00638
00640
00645 template<typename T> PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00646 PQXX_DEPRECATED;
00647
00648
00650
00652 template<>
00653 inline PGSTD::string Quote(const PGSTD::string &Obj, bool EmptyIsNull)
00654 PQXX_DEPRECATED
00655 {
00656 return internal::Quote_string(Obj, EmptyIsNull);
00657 }
00658
00660
00662 template<> inline PGSTD::string Quote(const char *const & Obj, bool EmptyIsNull)
00663 PQXX_DEPRECATED
00664 {
00665 return internal::Quote_charptr(Obj, EmptyIsNull);
00666 }
00667
00668
00670
00677 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00678 bool EmptyIsNull)
00679 PQXX_DEPRECATED
00680 {
00681 return internal::Quote_charptr(Obj, EmptyIsNull);
00682 }
00683
00684
00687 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00688 PQXX_DEPRECATED
00689 {
00690 return Quote(ToString(Obj), EmptyIsNull);
00691 }
00692
00693
00695
00699 template<typename T> inline PGSTD::string Quote(T Obj) PQXX_DEPRECATED
00700 {
00701 return Quote(Obj, false);
00702 }
00704
00705
00706 namespace internal
00707 {
00708 void PQXX_LIBEXPORT freepqmem(void *);
00709
00711
00725 template<typename T> class PQXX_LIBEXPORT PQAlloc
00726 {
00727 T *m_Obj;
00728 mutable const PQAlloc *m_l, *m_r;
00729 public:
00730 typedef T content_type;
00731
00732 PQAlloc() throw () : m_Obj(0), m_l(this), m_r(this) {}
00733 PQAlloc(const PQAlloc &rhs) throw () :
00734 m_Obj(0), m_l(this), m_r(this) { makeref(rhs); }
00735 ~PQAlloc() throw () { loseref(); }
00736
00737 PQAlloc &operator=(const PQAlloc &rhs) throw ()
00738 { redoref(rhs); return *this; }
00739
00741
00743 explicit PQAlloc(T *obj) throw () : m_Obj(obj), m_l(this), m_r(this) {}
00744
00745 void swap(PQAlloc &rhs) throw ()
00746 {
00747 PQAlloc tmp(*this);
00748 *this = rhs;
00749 rhs = tmp;
00750 }
00751
00752 PQAlloc &operator=(T *obj) throw () { redoref(obj); return *this; }
00753
00755 operator bool() const throw () { return m_Obj != 0; }
00756
00758 bool operator!() const throw () { return !m_Obj; }
00759
00761
00763 T *operator->() const throw (PGSTD::logic_error)
00764 {
00765 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00766 return m_Obj;
00767 }
00768
00770
00772 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00773
00775
00777 T *c_ptr() const throw () { return m_Obj; }
00778
00779 void clear() throw () { loseref(); }
00780
00781 private:
00782 void makeref(T *p) throw () { m_Obj = p; }
00783
00784 void makeref(const PQAlloc &rhs) throw ()
00785 {
00786
00787 m_l = &rhs;
00788 m_r = rhs.m_r;
00789 m_Obj = rhs.m_Obj;
00790 m_l->m_r = m_r->m_l = this;
00791 }
00792
00794 void loseref() throw ()
00795 {
00796
00797 if (m_l == this && m_Obj) freemem();
00798 m_Obj = 0;
00799 m_l->m_r = m_r;
00800 m_r->m_l = m_l;
00801 m_l = m_r = this;
00802 }
00803
00804
00805 void redoref(const PQAlloc &rhs) throw ()
00806 { if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
00807 void redoref(T *obj) throw ()
00808 { if (obj != m_Obj) { loseref(); makeref(obj); } }
00809
00810 void freemem() throw () { freepqmem(m_Obj); }
00811 };
00812
00813
00814 void PQXX_LIBEXPORT freemem_result(pq::PGresult *) throw ();
00815 template<> inline void PQAlloc<pq::PGresult>::freemem() throw ()
00816 { freemem_result(m_Obj); }
00817
00818 void PQXX_LIBEXPORT freemem_notif(pq::PGnotify *) throw ();
00819 template<> inline void PQAlloc<pq::PGnotify>::freemem() throw ()
00820 { freemem_notif(m_Obj); }
00821
00822
00823
00824 template<typename T> class scoped_array
00825 {
00826 T *m_ptr;
00827 public:
00828 typedef size_t size_type;
00829 typedef long difference_type;
00830
00831 scoped_array() : m_ptr(0) {}
00832 explicit scoped_array(size_type n) : m_ptr(new T[n]) {}
00833 explicit scoped_array(T *t) : m_ptr(t) {}
00834 ~scoped_array() { delete [] m_ptr; }
00835
00836 T *c_ptr() const throw () { return m_ptr; }
00837 T &operator*() const throw () { return *m_ptr; }
00838 T &operator[](difference_type i) const throw () { return m_ptr[i]; }
00839
00840 scoped_array &operator=(T *t) throw ()
00841 {
00842 if (t != m_ptr)
00843 {
00844 delete [] m_ptr;
00845 m_ptr = t;
00846 }
00847 return *this;
00848 }
00849
00850 private:
00852 scoped_array(const scoped_array &);
00853 scoped_array &operator=(const scoped_array &);
00854 };
00855
00856
00857 class PQXX_LIBEXPORT namedclass
00858 {
00859 public:
00860 namedclass(const PGSTD::string &Classname, const PGSTD::string &Name="") :
00861 m_Classname(Classname),
00862 m_Name(Name)
00863 {
00864 }
00865
00866 const PGSTD::string &name() const throw () { return m_Name; }
00867 const PGSTD::string &classname() const throw () {return m_Classname;}
00868 PGSTD::string description() const;
00869
00870 private:
00871 PGSTD::string m_Classname, m_Name;
00872 };
00873
00874
00875 void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
00876 void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);
00877
00878
00880
00883 template<typename GUEST>
00884 class unique
00885 {
00886 public:
00887 unique() : m_Guest(0) {}
00888
00889 GUEST *get() const throw () { return m_Guest; }
00890
00891 void Register(GUEST *G)
00892 {
00893 CheckUniqueRegistration(G, m_Guest);
00894 m_Guest = G;
00895 }
00896
00897 void Unregister(GUEST *G)
00898 {
00899 CheckUniqueUnregistration(G, m_Guest);
00900 m_Guest = 0;
00901 }
00902
00903 private:
00904 GUEST *m_Guest;
00905
00907 unique(const unique &);
00909 unique &operator=(const unique &);
00910 };
00911
00913
00916 void PQXX_LIBEXPORT sleep_seconds(int);
00917
00919 typedef const char *cstring;
00920
00922
00931 cstring PQXX_LIBEXPORT strerror_wrapper(int err, char buf[], PGSTD::size_t len)
00932 throw ();
00933
00934
00936 extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];
00937
00938 }
00939 }
00940