00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "pqxx/libcompiler.h"
00019
00020 #include <cstdio>
00021 #include <cctype>
00022 #include <stdexcept>
00023 #include <string>
00024 #include <typeinfo>
00025
00026 extern "C"
00027 {
00028 #include "libpq-fe.h"
00029 }
00030
00031
00032 namespace pqxx
00033 {
00034 typedef long result_size_type;
00035 typedef int tuple_size_type;
00036
00038 typedef Oid oid;
00039
00041 const oid oid_none = InvalidOid;
00042
00043
00045
00058 template<typename T> void error_unsupported_type_in_string_conversion(T);
00059
00060
00062
00068 template<typename T> inline const char *FmtString(T t)
00069 {
00070 error_unsupported_type_in_string_conversion(t);
00071 return 0;
00072 }
00073
00074
00075
00076
00077 template<> inline const char *FmtString(short) { return "%hd"; }
00078 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00079 template<> inline const char *FmtString(int) { return "%i"; }
00080 template<> inline const char *FmtString(long) { return "%li"; }
00081 template<> inline const char *FmtString(unsigned) { return "%u"; }
00082 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00083 template<> inline const char *FmtString(float) { return "%f"; }
00084 template<> inline const char *FmtString(double) { return "%lf"; }
00085 template<> inline const char *FmtString(long double) { return "%Lf"; }
00086 template<> inline const char *FmtString(char) { return "%c"; }
00087 template<> inline const char *FmtString(unsigned char) { return "%c"; }
00088
00089
00091
00098 template<typename T> inline PGSTD::string ToString(const T &Obj)
00099 {
00100
00101 char Buf[500];
00102 sprintf(Buf, FmtString(Obj), Obj);
00103 return PGSTD::string(Buf);
00104 }
00105
00106
00107
00108 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00109 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00110 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00111
00112 template<> inline PGSTD::string ToString(const unsigned char *const &Obj)
00113 {
00114 return reinterpret_cast<const char *>(Obj);
00115 }
00116
00117 template<> inline PGSTD::string ToString(const bool &Obj)
00118 {
00119 return ToString(unsigned(Obj));
00120 }
00121
00122 template<> inline PGSTD::string ToString(const short &Obj)
00123 {
00124 return ToString(int(Obj));
00125 }
00126
00127 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00128 {
00129 return ToString(unsigned(Obj));
00130 }
00131
00132
00134
00141 template<typename T> inline void FromString(const char Str[], T &Obj)
00142 {
00143 if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00144 PGSTD::string(typeid(T).name()));
00145
00146 if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00147 throw PGSTD::runtime_error("Cannot convert value '" +
00148 PGSTD::string(Str) +
00149 "' to " + typeid(T).name());
00150 }
00151
00152
00153 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00154 {
00155 if (!Str)
00156 throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00157 "string");
00158 Obj = Str;
00159 }
00160
00161
00162 template<> inline void FromString(const char Str[], const char *&Obj)
00163 {
00164 if (!Str)
00165 throw PGSTD::runtime_error("Attempt to read NULL string");
00166 Obj = Str;
00167 }
00168
00169 template<> inline void FromString(const char Str[], const unsigned char *&Obj)
00170 {
00171 const char *C;
00172 FromString(Str, C);
00173 Obj = reinterpret_cast<const unsigned char *>(C);
00174 }
00175
00176 template<> inline void FromString(const char Str[], bool &Obj)
00177 {
00178 if (!Str)
00179 throw PGSTD::runtime_error("Attempt to read NULL string");
00180
00181 switch (Str[0])
00182 {
00183 case 0:
00184 case 'f':
00185 Obj = false;
00186 break;
00187 case '0':
00188 {
00189 int I;
00190 FromString(Str, I);
00191 Obj = (I != 0);
00192 }
00193 break;
00194 default:
00195 Obj = true;
00196 }
00197 }
00198
00199
00201
00204 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00205
00207 template<> inline PGSTD::string Quote(const PGSTD::string &Obj,
00208 bool EmptyIsNull)
00209 {
00210 if (EmptyIsNull && Obj.empty()) return "null";
00211
00212 PGSTD::string Result;
00213 Result.reserve(Obj.size() + 2);
00214 Result += "'";
00215
00216 #ifdef PQXX_HAVE_PQESCAPESTRING
00217
00218 char *const Buf = new char[2*Obj.size() + 1];
00219 try
00220 {
00221 PQescapeString(Buf, Obj.c_str(), Obj.size());
00222 Result += Buf;
00223 }
00224 catch (const PGSTD::exception &)
00225 {
00226 delete [] Buf;
00227 throw;
00228 }
00229 delete [] Buf;
00230
00231 #else
00232
00233 for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00234 {
00235 if (isgraph(Obj[i]))
00236 {
00237 switch (Obj[i])
00238 {
00239 case '\'':
00240 case '\\':
00241 Result += '\\';
00242 }
00243 Result += Obj[i];
00244 }
00245 else
00246 {
00247 char s[10];
00248 sprintf(s,
00249 "\\%03o",
00250 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00251 Result.append(s, 4);
00252 }
00253 }
00254
00255 #endif
00256
00257 return Result + '\'';
00258 }
00259
00260
00263 template<> inline PGSTD::string Quote(const char *const & Obj,
00264 bool EmptyIsNull)
00265 {
00266 if (!Obj) return "null";
00267 return Quote(PGSTD::string(Obj), EmptyIsNull);
00268 }
00269
00270
00272
00277 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00278 bool EmptyIsNull)
00279 {
00280 return Quote(PGSTD::string(Obj), EmptyIsNull);
00281 }
00282
00283
00287 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00288 {
00289 return Quote(ToString(Obj), EmptyIsNull);
00290 }
00291
00292
00294
00296 template<typename T> inline PGSTD::string Quote(T Obj)
00297 {
00298 return Quote(Obj, false);
00299 }
00300
00301
00303 template<typename T> PGSTD::string Classname(const T *);
00304
00305
00307
00313 template<typename T> class PQAlloc
00314 {
00315 T *m_Obj;
00316 public:
00317 PQAlloc() : m_Obj(0) {}
00318
00320 explicit PQAlloc(T *obj) : m_Obj(obj) {}
00321
00322 ~PQAlloc() { close(); }
00323
00325
00327 PQAlloc &operator=(T *obj) throw ()
00328 {
00329 if (obj != m_Obj)
00330 {
00331 close();
00332 m_Obj = obj;
00333 }
00334 return *this;
00335 }
00336
00338 operator bool() const throw () { return m_Obj != 0; }
00339
00341 bool operator!() const throw () { return !m_Obj; }
00342
00344
00346 T *operator->() const throw (PGSTD::logic_error)
00347 {
00348 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00349 return m_Obj;
00350 }
00351
00353
00355 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00356
00358
00360 T *c_ptr() const throw () { return m_Obj; }
00361
00363 void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00364
00365 private:
00366 void freemem() throw ()
00367 {
00368 #if defined(PQXX_HAVE_PQFREEMEM)
00369 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00370 #else
00371 free(m_Obj);
00372 #endif
00373 }
00374
00375 PQAlloc(const PQAlloc &);
00376 PQAlloc &operator=(const PQAlloc &);
00377 };
00378
00379
00381 template<> inline void PQAlloc<PGnotify>::freemem() throw ()
00382 {
00383 #if defined(PQXX_HAVE_PQFREEMEM)
00384 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00385 #elif defined(PQXX_HAVE_PQFREENOTIFY)
00386 PQfreeNotify(m_Obj);
00387 #else
00388 free(m_Obj);
00389 #endif
00390 }
00391
00392
00393
00395
00402 template<typename GUEST>
00403 class unique
00404 {
00405 public:
00406 unique() : m_Guest(0) {}
00407
00408 GUEST *get() const throw () { return m_Guest; }
00409
00410 void Register(GUEST *G)
00411 {
00412 if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " +
00413 Classname(G));
00414
00415 if (m_Guest)
00416 {
00417 if (G == m_Guest)
00418 throw PGSTD::logic_error(Classname(G) +
00419 " '" +
00420 G->name() +
00421 "' started more than once without closing");
00422
00423 throw PGSTD::logic_error("Started " +
00424 Classname(G) +
00425 " '" +
00426 G->name() +
00427 "' while '" +
00428 m_Guest->name() +
00429 "' was still active");
00430 }
00431
00432 m_Guest = G;
00433 }
00434
00435 void Unregister(GUEST *G)
00436 {
00437 if (G != m_Guest)
00438 {
00439 if (!G)
00440 throw PGSTD::logic_error("Closing NULL " + Classname(G));
00441 else if (!m_Guest)
00442 throw PGSTD::logic_error("Closing " +
00443 Classname(G) +
00444 " '" +
00445 G->name() +
00446 "' which wasn't open");
00447 else
00448 throw PGSTD::logic_error("Closing wrong " +
00449 Classname(G) +
00450 "; expected '" +
00451 m_Guest->name() +
00452 "' but got '" +
00453 G->name() +
00454 "'");
00455 }
00456
00457 m_Guest = 0;
00458 }
00459
00460 private:
00461 GUEST *m_Guest;
00462
00463
00464 unique(const unique &);
00465 unique &operator=(const unique &);
00466 };
00467
00468 }
00469
00470