TPgSQLServer.cxx

Go to the documentation of this file.
00001 // @(#)root/pgsql:$Id: TPgSQLServer.cxx 34313 2010-07-03 14:29:15Z brun $
00002 // Author: g.p.ciceri <gp.ciceri@acm.org> 01/06/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
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    // Open a connection to a PgSQL DB server. The db arguments should be
00024    // of the form "pgsql://<host>[:<port>][/<database>]", e.g.:
00025    // "pgsql://pcroot.cern.ch:3456/test". The uid is the username and pw
00026    // the password that should be used for the connection.
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    // Close connection to PgSQL DB server.
00070 
00071    if (IsConnected())
00072       Close();
00073 }
00074 
00075 //______________________________________________________________________________
00076 void TPgSQLServer::Close(Option_t *)
00077 {
00078    // Close connection to PgSQL DB server.
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    // Execute SQL command. Result object must be deleted by the user.
00091    // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
00092    // The result object must be deleted by the user.
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    // Select a database. Returns 0 if successful, non-zero otherwise.
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    // List all available databases. Wild is for wildcarding "t%" list all
00154    // databases starting with "t".
00155    // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
00156    // The result object must be deleted by the user.
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    // List all tables in the specified database. Wild is for wildcarding
00174    // "t%" list all tables starting with "t".
00175    // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
00176    // The result object must be deleted by the user.
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    // List all columns in specified table in the specified database.
00200    // Wild is for wildcarding "t%" list all columns starting with "t".
00201    // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
00202    // The result object must be deleted by the user.
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    // Create a database. Returns 0 if successful, non-zero otherwise.
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    // Drop (i.e. delete) a database. Returns 0 if successful, non-zero
00250    // otherwise.
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    // Reload permission tables. Returns 0 if successful, non-zero
00267    // otherwise. User must have reload permissions.
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    // Shutdown the database server. Returns 0 if successful, non-zero
00282    // otherwise. User must have shutdown permissions.
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    // Return server info.
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    // PG_VERSION_NUM conveniently only started being #defined at 8.2.3
00320    // which is the first version of libpq which explicitly supports prepared
00321    // statements
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   // Produce TPgSQLStatement.
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 }

Generated on Tue Jul 5 15:14:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1