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
00046 template<typename T> inline const char *FmtString(T);
00047
00048
00049
00050
00051 template<> inline const char *FmtString(short) { return "%hd"; }
00052 template<> inline const char *FmtString(unsigned short){ return "%hu"; }
00053 template<> inline const char *FmtString(int) { return "%i"; }
00054 template<> inline const char *FmtString(long) { return "%li"; }
00055 template<> inline const char *FmtString(unsigned) { return "%u"; }
00056 template<> inline const char *FmtString(unsigned long) { return "%lu"; }
00057 template<> inline const char *FmtString(float) { return "%f"; }
00058 template<> inline const char *FmtString(double) { return "%lf"; }
00059 template<> inline const char *FmtString(long double) { return "%Lf"; }
00060 template<> inline const char *FmtString(char) { return "%c"; }
00061 template<> inline const char *FmtString(unsigned char) { return "%c"; }
00062
00063
00065
00072 template<typename T> inline PGSTD::string ToString(const T &Obj)
00073 {
00074
00075 char Buf[500];
00076 sprintf(Buf, FmtString(Obj), Obj);
00077 return PGSTD::string(Buf);
00078 }
00079
00080
00081
00082 template<> inline PGSTD::string ToString(const PGSTD::string &Obj) {return Obj;}
00083 template<> inline PGSTD::string ToString(const char *const &Obj) { return Obj; }
00084 template<> inline PGSTD::string ToString(char *const &Obj) { return Obj; }
00085
00086 template<> inline PGSTD::string ToString(const bool &Obj)
00087 {
00088 return ToString(unsigned(Obj));
00089 }
00090
00091 template<> inline PGSTD::string ToString(const short &Obj)
00092 {
00093 return ToString(int(Obj));
00094 }
00095
00096 template<> inline PGSTD::string ToString(const unsigned short &Obj)
00097 {
00098 return ToString(unsigned(Obj));
00099 }
00100
00101
00103
00110 template<typename T> inline void FromString(const char Str[], T &Obj)
00111 {
00112 if (!Str) throw PGSTD::runtime_error("Attempt to convert NULL string to " +
00113 PGSTD::string(typeid(T).name()));
00114
00115 if (sscanf(Str, FmtString(Obj), &Obj) != 1)
00116 throw PGSTD::runtime_error("Cannot convert value '" +
00117 PGSTD::string(Str) +
00118 "' to " + typeid(T).name());
00119 }
00120
00121
00122 template<> inline void FromString(const char Str[], PGSTD::string &Obj)
00123 {
00124 if (!Str)
00125 throw PGSTD::runtime_error("Attempt to convert NULL C string to C++ "
00126 "string");
00127 Obj = Str;
00128 }
00129
00130
00131 template<> inline void FromString(const char Str[], const char *&Obj)
00132 {
00133 if (!Str)
00134 throw PGSTD::runtime_error("Attempt to read NULL string");
00135 Obj = Str;
00136 }
00137
00138 template<> inline void FromString(const char Str[], bool &Obj)
00139 {
00140 if (!Str)
00141 throw PGSTD::runtime_error("Attempt to read NULL string");
00142
00143 switch (Str[0])
00144 {
00145 case 0:
00146 case 'f':
00147 Obj = false;
00148 break;
00149 case '0':
00150 {
00151 int I;
00152 FromString(Str, I);
00153 Obj = (I != 0);
00154 }
00155 break;
00156 default:
00157 Obj = true;
00158 }
00159 }
00160
00161
00163
00166 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull);
00167
00169 template<> inline PGSTD::string Quote(const PGSTD::string &Obj,
00170 bool EmptyIsNull)
00171 {
00172 if (EmptyIsNull && Obj.empty()) return "null";
00173
00174 PGSTD::string Result;
00175 Result.reserve(Obj.size() + 2);
00176 Result += "'";
00177
00178 #ifdef PQXX_HAVE_PQESCAPESTRING
00179
00180 char *const Buf = new char[2*Obj.size() + 1];
00181 try
00182 {
00183 PQescapeString(Buf, Obj.c_str(), Obj.size());
00184 Result += Buf;
00185 }
00186 catch (const PGSTD::exception &)
00187 {
00188 delete [] Buf;
00189 throw;
00190 }
00191 delete [] Buf;
00192
00193 #else
00194
00195 for (PGSTD::string::size_type i=0; i < Obj.size(); ++i)
00196 {
00197 if (isgraph(Obj[i]))
00198 {
00199 switch (Obj[i])
00200 {
00201 case '\'':
00202 case '\\':
00203 Result += '\\';
00204 }
00205 Result += Obj[i];
00206 }
00207 else
00208 {
00209 char s[10];
00210 sprintf(s,
00211 "\\%03o",
00212 static_cast<unsigned int>(static_cast<unsigned char>(Obj[i])));
00213 Result.append(s, 4);
00214 }
00215 }
00216
00217 #endif
00218
00219 return Result + '\'';
00220 }
00221
00222
00225 template<> inline PGSTD::string Quote(const char *const & Obj,
00226 bool EmptyIsNull)
00227 {
00228 if (!Obj) return "null";
00229 return Quote(PGSTD::string(Obj), EmptyIsNull);
00230 }
00231
00232
00234
00239 template<int LEN> inline PGSTD::string Quote(const char (&Obj)[LEN],
00240 bool EmptyIsNull)
00241 {
00242 return Quote(PGSTD::string(Obj), EmptyIsNull);
00243 }
00244
00245
00249 template<typename T> inline PGSTD::string Quote(const T &Obj, bool EmptyIsNull)
00250 {
00251 return Quote(ToString(Obj), EmptyIsNull);
00252 }
00253
00254
00256
00258 template<typename T> inline PGSTD::string Quote(T Obj)
00259 {
00260 return Quote(Obj, false);
00261 }
00262
00263
00265 template<typename T> PGSTD::string Classname(const T *);
00266
00267
00269
00275 template<typename T> class PQAlloc
00276 {
00277 T *m_Obj;
00278 public:
00279 PQAlloc() : m_Obj(0) {}
00280
00282 explicit PQAlloc(T *obj) : m_Obj(obj) {}
00283
00284 ~PQAlloc() { close(); }
00285
00287
00289 PQAlloc &operator=(T *obj) throw ()
00290 {
00291 if (obj != m_Obj)
00292 {
00293 close();
00294 m_Obj = obj;
00295 }
00296 return *this;
00297 }
00298
00300 operator bool() const throw () { return m_Obj != 0; }
00301
00303 bool operator!() const throw () { return !m_Obj; }
00304
00306
00308 T *operator->() const throw (PGSTD::logic_error)
00309 {
00310 if (!m_Obj) throw PGSTD::logic_error("Null pointer dereferenced");
00311 return m_Obj;
00312 }
00313
00315
00317 T &operator*() const throw (PGSTD::logic_error) { return *operator->(); }
00318
00320
00322 T *c_ptr() const throw () { return m_Obj; }
00323
00325 void close() throw () { if (m_Obj) freemem(); m_Obj = 0; }
00326
00327 private:
00328 void freemem() throw ()
00329 {
00330 #if defined(PQXX_HAVE_PQFREEMEM)
00331 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00332 #else
00333 free(m_Obj);
00334 #endif
00335 }
00336
00337 PQAlloc(const PQAlloc &);
00338 PQAlloc &operator=(const PQAlloc &);
00339 };
00340
00341
00343 template<> inline void PQAlloc<PGnotify>::freemem() throw ()
00344 {
00345 #if defined(PQXX_HAVE_PQFREEMEM)
00346 PQfreemem(reinterpret_cast<unsigned char *>(m_Obj));
00347 #elif defined(PQXX_HAVE_PQFREENOTIFY)
00348 PQfreeNotify(m_Obj);
00349 #else
00350 free(m_Obj);
00351 #endif
00352 }
00353
00354
00355
00357
00364 template<typename GUEST>
00365 class unique
00366 {
00367 public:
00368 unique() : m_Guest(0) {}
00369
00370 GUEST *get() const throw () { return m_Guest; }
00371
00372 void Register(GUEST *G)
00373 {
00374 if (!G) throw PGSTD::logic_error("Internal libpqxx error: NULL " +
00375 Classname(G));
00376
00377 if (m_Guest)
00378 {
00379 if (G == m_Guest)
00380 throw PGSTD::logic_error(Classname(G) +
00381 " '" +
00382 G->name() +
00383 "' started more than once without closing");
00384
00385 throw PGSTD::logic_error("Started " +
00386 Classname(G) +
00387 " '" +
00388 G->name() +
00389 "' while '" +
00390 m_Guest->name() +
00391 "' was still active");
00392 }
00393
00394 m_Guest = G;
00395 }
00396
00397 void Unregister(GUEST *G)
00398 {
00399 if (G != m_Guest)
00400 {
00401 if (!G)
00402 throw PGSTD::logic_error("Closing NULL " + Classname(G));
00403 else if (!m_Guest)
00404 throw PGSTD::logic_error("Closing " +
00405 Classname(G) +
00406 " '" +
00407 G->name() +
00408 "' which wasn't open");
00409 else
00410 throw PGSTD::logic_error("Closing wrong " +
00411 Classname(G) +
00412 "; expected '" +
00413 m_Guest->name() +
00414 "' but got '" +
00415 G->name() +
00416 "'");
00417 }
00418
00419 m_Guest = 0;
00420 }
00421
00422 private:
00423 GUEST *m_Guest;
00424
00425
00426 unique(const unique &);
00427 unique &operator=(const unique &);
00428 };
00429
00430 }
00431
00432