00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TPgSQLServer.h"
00013 #include "TPgSQLResult.h"
00014 #include "TPgSQLStatement.h"
00015 #include "TUrl.h"
00016
00017
00018 ClassImp(TPgSQLServer)
00019
00020
00021 TPgSQLServer::TPgSQLServer(const char *db, const char *uid, const char *pw)
00022 {
00023
00024
00025
00026
00027
00028 fPgSQL = 0;
00029
00030 TUrl url(db);
00031
00032 if (!url.IsValid()) {
00033 Error("TPgSQLServer", "malformed db argument %s", db);
00034 MakeZombie();
00035 return;
00036 }
00037
00038 if (strncmp(url.GetProtocol(), "pgsql", 5)) {
00039 Error("TPgSQLServer", "protocol in db argument should be pgsql it is %s",
00040 url.GetProtocol());
00041 MakeZombie();
00042 return;
00043 }
00044
00045 const char *dbase = url.GetFile();
00046
00047 if (url.GetPort()) {
00048 TString port;
00049 port += url.GetPort();
00050 fPgSQL = PQsetdbLogin(url.GetHost(), port, 0, 0, dbase, uid, pw);
00051 } else
00052 fPgSQL = PQsetdbLogin(url.GetHost(), 0, 0, 0, dbase, uid, pw);
00053
00054
00055 if (PQstatus(fPgSQL) != CONNECTION_BAD) {
00056 fType = "PgSQL";
00057 fHost = url.GetHost();
00058 fDB = dbase;
00059 fPort = url.GetPort();
00060 } else {
00061 Error("TPgSQLServer", "connection to %s failed", url.GetHost());
00062 MakeZombie();
00063 }
00064 }
00065
00066
00067 TPgSQLServer::~TPgSQLServer()
00068 {
00069
00070
00071 if (IsConnected())
00072 Close();
00073 }
00074
00075
00076 void TPgSQLServer::Close(Option_t *)
00077 {
00078
00079
00080 if (!fPgSQL)
00081 return;
00082
00083 PQfinish(fPgSQL);
00084 fPort = -1;
00085 }
00086
00087
00088 TSQLResult *TPgSQLServer::Query(const char *sql)
00089 {
00090
00091
00092
00093
00094 if (!IsConnected()) {
00095 Error("Query", "not connected");
00096 return 0;
00097 }
00098
00099 PGresult *res = PQexec(fPgSQL, sql);
00100
00101 if ((PQresultStatus(res) != PGRES_COMMAND_OK) &&
00102 (PQresultStatus(res) != PGRES_TUPLES_OK)) {
00103 Error("Query", "%s",PQresultErrorMessage(res));
00104 PQclear(res);
00105 return 0;
00106 }
00107
00108 return new TPgSQLResult(res);
00109 }
00110
00111
00112 Int_t TPgSQLServer::SelectDataBase(const char *dbname)
00113 {
00114
00115
00116 TString usr;
00117 TString pwd;
00118 TString port;
00119 TString opts;
00120
00121 if (!IsConnected()) {
00122 Error("SelectDataBase", "not connected");
00123 return -1;
00124 }
00125
00126 if (dbname == fDB) {
00127 return 0;
00128 } else {
00129 usr = PQuser(fPgSQL);
00130 pwd = PQpass(fPgSQL);
00131 port = PQport(fPgSQL);
00132 opts = PQoptions(fPgSQL);
00133
00134 Close();
00135 fPgSQL = PQsetdbLogin(fHost.Data(), port.Data(),
00136 opts.Data(), 0, dbname,
00137 usr.Data(), pwd.Data());
00138
00139 if (PQstatus(fPgSQL) == CONNECTION_OK) {
00140 fDB=dbname;
00141 fPort=port.Atoi();
00142 } else {
00143 Error("SelectDataBase", "%s",PQerrorMessage(fPgSQL));
00144 return -1;
00145 }
00146 }
00147 return 0;
00148 }
00149
00150
00151 TSQLResult *TPgSQLServer::GetDataBases(const char *wild)
00152 {
00153
00154
00155
00156
00157
00158 if (!IsConnected()) {
00159 Error("GetDataBases", "not connected");
00160 return 0;
00161 }
00162
00163 TString sql = "SELECT pg_database.datname FROM pg_database";
00164 if (wild)
00165 sql += Form(" WHERE pg_database.datname LIKE '%s'", wild);
00166
00167 return Query(sql);
00168 }
00169
00170
00171 TSQLResult *TPgSQLServer::GetTables(const char *dbname, const char *wild)
00172 {
00173
00174
00175
00176
00177
00178 if (!IsConnected()) {
00179 Error("GetTables", "not connected");
00180 return 0;
00181 }
00182
00183 if (SelectDataBase(dbname) != 0) {
00184 Error("GetTables", "no such database %s", dbname);
00185 return 0;
00186 }
00187
00188 TString sql = "SELECT relname FROM pg_class where relkind='r'";
00189 if (wild)
00190 sql += Form(" AND relname LIKE '%s'", wild);
00191
00192 return Query(sql);
00193 }
00194
00195
00196 TSQLResult *TPgSQLServer::GetColumns(const char *dbname, const char *table,
00197 const char *wild)
00198 {
00199
00200
00201
00202
00203
00204 if (!IsConnected()) {
00205 Error("GetColumns", "not connected");
00206 return 0;
00207 }
00208
00209 if (SelectDataBase(dbname) != 0) {
00210 Error("GetColumns", "no such database %s", dbname);
00211 return 0;
00212 }
00213
00214 char *sql;
00215 if (wild)
00216 sql = Form("select a.attname,t.typname,a.attnotnull \
00217 from pg_attribute a, pg_class c, pg_type t \
00218 where c.oid=a.attrelid and c.relname='%s' and \
00219 a.atttypid=t.oid and a.attnum>0 \
00220 and a.attname like '%s' order by a.attnum ", table,wild);
00221 else
00222 sql = Form("select a.attname,t.typname,a.attnotnull \
00223 from pg_attribute a, pg_class c, pg_type t \
00224 where c.oid=a.attrelid and c.relname='%s' and \
00225 a.atttypid=t.oid and a.attnum>0 order by a.attnum",table);
00226
00227 return Query(sql);
00228 }
00229
00230
00231 Int_t TPgSQLServer::CreateDataBase(const char *dbname)
00232 {
00233
00234
00235 if (!IsConnected()) {
00236 Error("CreateDataBase", "not connected");
00237 return -1;
00238 }
00239 char *sql;
00240 sql = Form("CREATE DATABASE %s", dbname);
00241 PGresult *res = PQexec(fPgSQL, sql);
00242 PQclear(res);
00243 return 0;
00244 }
00245
00246
00247 Int_t TPgSQLServer::DropDataBase(const char *dbname)
00248 {
00249
00250
00251
00252 if (!IsConnected()) {
00253 Error("DropDataBase", "not connected");
00254 return -1;
00255 }
00256 char *sql;
00257 sql = Form("DROP DATABASE %s", dbname);
00258 PGresult *res = PQexec(fPgSQL, sql);
00259 PQclear(res);
00260 return 0;
00261 }
00262
00263
00264 Int_t TPgSQLServer::Reload()
00265 {
00266
00267
00268
00269 if (!IsConnected()) {
00270 Error("Reload", "not connected");
00271 return -1;
00272 }
00273
00274 Error("Reload", "not implemented");
00275 return 0;
00276 }
00277
00278
00279 Int_t TPgSQLServer::Shutdown()
00280 {
00281
00282
00283
00284 if (!IsConnected()) {
00285 Error("Shutdown", "not connected");
00286 return -1;
00287 }
00288
00289 Error("Shutdown", "not implemented");
00290 return 0;
00291 }
00292
00293
00294 const char *TPgSQLServer::ServerInfo()
00295 {
00296
00297
00298 TString svrinfo = "postgres ";
00299 if (!IsConnected()) {
00300 Error("ServerInfo", "not connected");
00301 return 0;
00302 }
00303
00304 static const char *sql = "select setting from pg_settings where name='server_version'";
00305 PGresult *res = PQexec(fPgSQL, sql);
00306 int stat = PQresultStatus(res);
00307 if (stat == PGRES_TUPLES_OK && PQntuples(res)) {
00308 char *vers = PQgetvalue(res,0,0);
00309 svrinfo += vers;
00310 } else
00311 svrinfo += "unknown version number";
00312
00313 return svrinfo;
00314 }
00315
00316
00317 Bool_t TPgSQLServer::HasStatement() const
00318 {
00319
00320
00321
00322
00323 #ifdef PG_VERSION_NUM
00324 return kTRUE;
00325 #else
00326 return kFALSE;
00327 #endif
00328 }
00329
00330
00331 #ifdef PG_VERSION_NUM
00332 TSQLStatement* TPgSQLServer::Statement(const char *sql, Int_t)
00333 #else
00334 TSQLStatement* TPgSQLServer::Statement(const char *, Int_t)
00335 #endif
00336 {
00337
00338
00339 #ifdef PG_VERSION_NUM
00340 if (!sql || !*sql) {
00341 SetError(-1, "no query string specified","Statement");
00342 return 0;
00343 }
00344
00345 PgSQL_Stmt_t *stmt = new PgSQL_Stmt_t;
00346 if (!stmt){
00347 SetError(-1, "cannot allocate PgSQL_Stmt_t", "Statement");
00348 return 0;
00349 }
00350 stmt->fConn = fPgSQL;
00351 stmt->fRes = PQprepare(fPgSQL, "", sql, 0, (const Oid*)0);
00352
00353 ExecStatusType stat = PQresultStatus(stmt->fRes);
00354 if (pgsql_success(stat)) {
00355 fErrorOut = stat;
00356 return new TPgSQLStatement(stmt, fErrorOut);
00357 } else {
00358 SetError(stat, PQresultErrorMessage(stmt->fRes), "Statement");
00359 stmt->fConn = 0;
00360 delete stmt;
00361 return 0;
00362 }
00363 #else
00364 Error("Statement", "not implemented for pgsql < 8.2");
00365 #endif
00366 return 0;
00367 }