00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "pqxx/config.h"
00019 #include "pqxx/compiler.h"
00020
00021 #include <cstdio>
00022 #include <cctype>
00023 #include <stdexcept>
00024 #include <string>
00025 #include <typeinfo>
00026
00027 extern "C"
00028 {
00029 #include "libpq-fe.h"
00030 }
00031
00032
00033 namespace pqxx
00034 {
00035 typedef long result_size_type;
00036 typedef int tuple_size_type;
00037
00039 typedef Oid oid;
00040
00042 const oid oid_none = InvalidOid;
00043
00044
00047 template<typename T> inline const char *FmtString(T);
00048
00049
00050
00051
00052 template<> inline const char *FmtString(short) { return "%hd"; }
00053 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00054 template<> inline const char *FmtString(int) { return "%i"; }
00055 template<> inline const char *FmtString(long) { return "%li"; }
00056 template<> inline const char *FmtString(unsigned) { return "%u"; }
00057 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00058 template<> inline const char *FmtString(float) { return "%f"; }
00059 template<> inline const char *FmtString(double) { return "%lf"; }
00060 template<> inline const char *FmtString(long double) { return "%Lf"; }
00061 template<> inline const char *FmtString(char) { return "%c"; }
00062 template<> inline const char *FmtString(unsigned char) { return "%c"; }
00063
00064
00066
00073 template<typename T> inline PGSTD::string ToString(const T &Obj)
00074 {
00075
00076 char Buf[500];
00077 sprintf(Buf, FmtString(Obj), Obj);
00078 return PGSTD::string(Buf);
00079 }
00080
00081
00082
00083 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00084 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00085 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00086
00087 template<> inline PGSTD::string ToString(const bool &Obj)
00088 {
00089 return ToString(unsigned(Obj));
00090 }
00091
00092 template<> inline PGSTD::string ToString(const short &Obj)
00093 {
00094 return ToString(int(Obj));
00095 }
00096
00097 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00098 {
00099 return ToString(unsigned(Obj));
00100 }
00101
00102
00104
00111 template<typename T> inline void FromString(const char Str[], T &Obj)
00112 {
00113 if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00114 PGSTD::string(typeid(T).name()));
00115
00116 if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00117 throw PGSTD::runtime_error("Cannot convert value '" +
00118 PGSTD::string(Str) +
00119 "' to " + typeid(T).name());
00120 }
00121
00122
00123 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00124 {
00125 if (!Str)
00126 throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00127 "string");
00128 Obj = Str;
00129 }
00130
00131
00132 template<> inline void FromString(const char Str[], const char *&Obj)
00133 {
00134 if (!Str)
00135 throw PGSTD::runtime_error("Attempt to read NULL string");
00136 Obj = Str;
00137 }
00138
00139 template<> inline void FromString(const char Str[], bool &Obj)
00140 {
00141 if (!Str)
00142 throw PGSTD::runtime_error("Attempt to read NULL string");
00143
00144 switch (Str[0])
00145 {
00146 case 0:
00147 case 'f':
00148 Obj = false;
00149 break;
00150 case '0':
00151 {
00152 int I;
00153 FromString(Str, I);
00154 Obj = (I != 0);
00155 }
00156 break;
00157 default:
00158 Obj = true;
00159 }
00160 }
00161
00162
00164
00167 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00168
00170 template<> inline PGSTD::string Quote(const PGSTD::string &Obj,
00171 bool EmptyIsNull)
00172 {
00173 if (EmptyIsNull && Obj.empty()) return "null";
00174
00175 PGSTD::string Result;
00176 Result.reserve(Obj.size() + 2);
00177 Result += "'";
00178
00179 #ifdef HAVE_PQESCAPESTRING
00180
00181 char *const Buf = new char[2*Obj.size() + 1];
00182 try
00183 {
00184 PQescapeString(Buf, Obj.c_str(), Obj.size());
00185 Result += Buf;
00186 }
00187 catch (const PGSTD::exception &)
00188 {
00189 delete [] Buf;
00190 throw;
00191 }
00192 delete [] Buf;
00193
00194 #else
00195
00196 for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00197 {
00198 if (isgraph(Obj[i]))
00199 {
00200 switch (Obj[i])
00201 {
00202 case '\'':
00203 case '\\':
00204 Result += '\\';
00205 }
00206 Result += Obj[i];
00207 }
00208 else
00209 {
00210 char s[10];
00211 sprintf(s,
00212 "\\%03o",
00213 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00214 Result.append(s, 4);
00215 }
00216 }
00217
00218 #endif
00219
00220 return Result + '\'';
00221 }
00222
00223
00226 template<> inline PGSTD::string Quote(const char *const & Obj,
00227 bool EmptyIsNull)
00228 {
00229 if (!Obj) return "null";
00230 return Quote(PGSTD::string(Obj), EmptyIsNull);
00231 }
00232
00233
00235
00240 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00241 bool EmptyIsNull)
00242 {
00243 return Quote(PGSTD::string(Obj), EmptyIsNull);
00244 }
00245
00246
00250 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00251 {
00252 return Quote(ToString(Obj), EmptyIsNull);
00253 }
00254
00255
00257
00259 template<typename T> inline PGSTD::string Quote(T Obj)
00260 {
00261 return Quote(Obj, false);
00262 }
00263
00264
00266 template<typename T> PGSTD::string Classname(const T *);
00267
00268
00270
00276 template<typename T> class PQAlloc
00277 {
00278 T *m_Obj;
00279 public:
00280 PQAlloc() : m_Obj(0) {}
00281
00283 explicit PQAlloc(T *obj) : m_Obj(obj) {}
00284
00285 ~PQAlloc() { close(); }
00286
00288
00290 PQAlloc &operator=(T *obj) throw ()
00291 {
00292 if (obj != m_Obj)
00293 {
00294 close();
00295 m_Obj = obj;
00296 }
00297 return *this;
00298 }
00299
00301 operator bool() const throw () { return m_Obj != 0; }
00302
00304 bool operator!() const throw () { return !m_Obj; }
00305
00307
00309 T *operator->() const throw (PGSTD::logic_error)
00310 {
00311 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00312 return m_Obj;
00313 }
00314
00316
00318 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00319
00321
00323 T *c_ptr() const throw () { return m_Obj; }
00324
00326 void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00327
00328 private:
00329 void freemem() throw ()
00330 {
00331 #if defined(HAVE_PQFREEMEM)
00332 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00333 #else
00334 free(m_Obj);
00335 #endif
00336 }
00337
00338 PQAlloc(const PQAlloc &);
00339 PQAlloc &operator=(const PQAlloc &);
00340 };
00341
00342
00344 template<> inline void PQAlloc<PGnotify>::freemem() throw ()
00345 {
00346 #if defined(HAVE_PQFREEMEM)
00347 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00348 #elif defined(HAVE_PQFREENOTIFY)
00349 PQfreeNotify(m_Obj);
00350 #else
00351 free(m_Obj);
00352 #endif
00353 }
00354
00355
00356
00358
00365 template<typename GUEST>
00366 class unique
00367 {
00368 public:
00369 unique() : m_Guest(0) {}
00370
00371 GUEST *get() const throw () { return m_Guest; }
00372
00373 void Register(GUEST *G)
00374 {
00375 if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " +
00376 Classname(G));
00377
00378 if (m_Guest)
00379 {
00380 if (G == m_Guest)
00381 throw PGSTD::logic_error(Classname(G) +
00382 " '" +
00383 G->name() +
00384 "' started more than once without closing");
00385
00386 throw PGSTD::logic_error("Started " +
00387 Classname(G) +
00388 " '" +
00389 G->name() +
00390 "' while '" +
00391 m_Guest->name() +
00392 "' was still active");
00393 }
00394
00395 m_Guest = G;
00396 }
00397
00398 void Unregister(GUEST *G)
00399 {
00400 if (G != m_Guest)
00401 {
00402 if (!G)
00403 throw PGSTD::logic_error("Closing NULL " + Classname(G));
00404 else if (!m_Guest)
00405 throw PGSTD::logic_error("Closing " +
00406 Classname(G) +
00407 " '" +
00408 G->name() +
00409 "' which wasn't open");
00410 else
00411 throw PGSTD::logic_error("Closing wrong " +
00412 Classname(G) +
00413 "; expected '" +
00414 m_Guest->name() +
00415 "' but got '" +
00416 G->name() +
00417 "'");
00418 }
00419
00420 m_Guest = 0;
00421 }
00422
00423 private:
00424 GUEST *m_Guest;
00425
00426
00427 unique(const unique &);
00428 unique &operator=(const unique &);
00429 };
00430
00431 }
00432
00433