24#define pgsql_success(x) (((x) == PGRES_EMPTY_QUERY) \
25 || ((x) == PGRES_COMMAND_OK) \
26 || ((x) == PGRES_TUPLES_OK))
54 Error(
"TPgSQLServer",
"malformed db argument %s", db);
60 Error(
"TPgSQLServer",
"protocol in db argument should be pgsql it is %s",
66 const char *dbase = url.
GetFile();
71 fPgSQL = PQsetdbLogin(url.
GetHost(), port.
Data(),
nullptr,
nullptr, dbase, uid, pw);
73 fPgSQL = PQsetdbLogin(url.
GetHost(),
nullptr,
nullptr,
nullptr, dbase, uid, pw);
76 if (PQstatus(
fPgSQL) != CONNECTION_BAD) {
84 static const char *sql =
"select setting from pg_settings where name='server_version'";
86 int stat = PQresultStatus(res);
87 if (stat == PGRES_TUPLES_OK && PQntuples(res)) {
88 char *vers = PQgetvalue(res,0,0);
92 fSrvInfo +=
"unknown version number";
95 Error(
"TPgSQLServer",
"connection to %s failed", url.
GetHost());
129 Error(
"Query",
"not connected");
135 if ((PQresultStatus(res) != PGRES_COMMAND_OK) &&
136 (PQresultStatus(res) != PGRES_TUPLES_OK)) {
137 Error(
"Query",
"%s",PQresultErrorMessage(res));
156 Error(
"SelectDataBase",
"not connected");
170 opts.
Data(),
nullptr, dbname,
173 if (PQstatus(
fPgSQL) == CONNECTION_OK) {
177 Error(
"SelectDataBase",
"%s",PQerrorMessage(
fPgSQL));
193 Error(
"GetDataBases",
"not connected");
197 TString sql =
"SELECT pg_database.datname FROM pg_database";
213 Error(
"GetTables",
"not connected");
218 Error(
"GetTables",
"no such database %s", dbname);
222 TString sql =
"SELECT relname FROM pg_class where relkind='r'";
239 Error(
"GetColumns",
"not connected");
244 Error(
"GetColumns",
"no such database %s", dbname);
250 sql.
Form(
"select a.attname,t.typname,a.attnotnull \
251 from pg_attribute a, pg_class c, pg_type t \
252 where c.oid=a.attrelid and c.relname='%s' and \
253 a.atttypid=t.oid and a.attnum>0 \
254 and a.attname like '%s' order by a.attnum ", table, wild);
256 sql.
Form(
"select a.attname,t.typname,a.attnotnull \
257 from pg_attribute a, pg_class c, pg_type t \
258 where c.oid=a.attrelid and c.relname='%s' and \
259 a.atttypid=t.oid and a.attnum>0 order by a.attnum", table);
270 Error(
"CreateDataBase",
"not connected");
274 sql.
Form(
"CREATE DATABASE %s", dbname);
287 Error(
"DropDataBase",
"not connected");
291 sql.
Form(
"DROP DATABASE %s", dbname);
304 Error(
"Reload",
"not connected");
308 Error(
"Reload",
"not implemented");
319 Error(
"Shutdown",
"not connected");
323 Error(
"Shutdown",
"not implemented");
333 Error(
"ServerInfo",
"not connected");
365 SetError(-1,
"no query string specified",
"Statement");
371 SetError(-1,
"cannot allocate PgSQL_Stmt_t",
"Statement");
374 stmt->
fConn = fPgSQL;
375 stmt->
fRes = PQprepare(fPgSQL,
"preparedstmt", sql, 0, (
const Oid*)0);
377 ExecStatusType stat = PQresultStatus(stmt->
fRes);
382 SetError(stat, PQresultErrorMessage(stmt->
fRes),
"Statement");
383 stmt->
fConn =
nullptr;
388 Error(
"Statement",
"not implemented for pgsql < 8.2");
399 Error(
"GetColumns",
"not connected");
404 if (!tablename || (*tablename==0))
410 if ((PQresultStatus(res) != PGRES_COMMAND_OK) &&
411 (PQresultStatus(res) != PGRES_TUPLES_OK)) {
412 Error(
"Query",
"%s",PQresultErrorMessage(res));
420 PGresult *res_type = PQexec(
fPgSQL,
"SELECT OID, TYPNAME FROM PG_TYPE;");
422 if ((PQresultStatus(res_type) != PGRES_COMMAND_OK) &&
423 (PQresultStatus(res_type) != PGRES_TUPLES_OK)) {
424 Error(
"Query",
"%s", PQresultErrorMessage(res_type));
430 Int_t nOids = PQntuples(res_type);
431 for (
Int_t oid=0; oid<nOids; oid++) {
433 char* oidString = PQgetvalue(res_type, oid, 0);
434 char* typeString = PQgetvalue(res_type, oid, 1);
435 if (sscanf(oidString,
"%10d", &tOid) != 1) {
436 Error(
"GetTableInfo",
"Bad non-numeric oid '%s' for type '%s'", oidString, typeString);
443 TList * lst =
nullptr;
445 Int_t nfields = PQnfields(res);
447 for (
Int_t col=0;col<nfields;col++){
449 Int_t data_size = -1;
450 Int_t data_length = -1;
451 Int_t data_scale = -1;
452 Int_t data_sign = -1;
455 const char* column_name = PQfname(res,col);
456 const char* type_name;
457 int imod = PQfmod(res,col);
460 int oid_code = PQftype(res,col);
463 std::map<Int_t,std::string>::iterator lookupOid =
fOidTypNameMap.find(oid_code);
468 type_name =
"NUMERIC";
470 }
else if (lookupOid->second ==
"int2"){
474 }
else if (lookupOid->second ==
"int4"){
478 }
else if (lookupOid->second ==
"int8"){
482 }
else if (lookupOid->second ==
"float4"){
486 }
else if (lookupOid->second ==
"float8"){
488 type_name =
"DOUBLE";
490 }
else if (lookupOid->second ==
"bool"){
494 }
else if (lookupOid->second ==
"char"){
498 }
else if (lookupOid->second ==
"varchar"){
500 type_name =
"VARCHAR";
502 }
else if (lookupOid->second ==
"text"){
504 type_name =
"VARCHAR";
506 }
else if (lookupOid->second ==
"name"){
508 type_name =
"VARCHAR";
510 }
else if (lookupOid->second ==
"date"){
512 type_name =
"TIMESTAMP";
514 }
else if (lookupOid->second ==
"time"){
516 type_name =
"TIMESTAMP";
518 }
else if (lookupOid->second ==
"timetz"){
520 type_name =
"TIMESTAMP";
522 }
else if (lookupOid->second ==
"timestamp"){
524 type_name =
"TIMESTAMP";
526 }
else if (lookupOid->second ==
"timestamptz"){
528 type_name =
"TIMESTAMP";
530 }
else if (lookupOid->second ==
"interval"){
532 type_name =
"TIMESTAMP";
534 }
else if (lookupOid->second ==
"bytea"){
536 type_name =
"BINARY";
538 }
else if (lookupOid->second ==
""){
540 type_name =
"UNKNOWN";
545 type_name =
"NUMERIC";
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
struct pg_result PGresult
TSQLServer * ROOT_Plugin_TPgSQLServer(const char *db, const char *uid, const char *pw)
PluginManager generator function.
void Add(TObject *obj) override
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
TSQLResult * GetTables(const char *dbname, const char *wild=nullptr) final
List all tables in the specified database.
Int_t CreateDataBase(const char *dbname) final
Create a database. Returns 0 if successful, non-zero otherwise.
TSQLResult * Query(const char *sql) final
Execute SQL command.
const char * ServerInfo() final
Return server info.
Int_t SelectDataBase(const char *dbname) final
Select a database. Returns 0 if successful, non-zero otherwise.
Bool_t HasStatement() const final
PG_VERSION_NUM conveniently only started being #defined at 8.2.3 which is the first version of libpq ...
TSQLTableInfo * GetTableInfo(const char *tablename) final
Produce TSQLTableInfo.
std::map< Int_t, std::string > fOidTypNameMap
Int_t Reload() final
Reload permission tables.
Int_t Shutdown() final
Shutdown the database server.
Int_t DropDataBase(const char *dbname) final
Drop (i.e.
TSQLResult * GetDataBases(const char *wild=nullptr) final
List all available databases.
void Close(Option_t *opt="") final
Close connection to PgSQL DB server.
TPgSQLServer(const char *db, const char *uid, const char *pw)
Open a connection to a PgSQL DB server.
TSQLStatement * Statement(const char *sql, Int_t=100) final
Produce TPgSQLStatement.
~TPgSQLServer()
Close connection to PgSQL DB server.
TSQLResult * GetColumns(const char *dbname, const char *table, const char *wild=nullptr) final
List all columns in specified table in the specified database.
virtual Bool_t IsConnected() const
Int_t Atoi() const
Return integer value of string.
const char * Data() const
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
This class represents a WWW compatible URL.
const char * GetFile() const
const char * GetHost() const
const char * GetProtocol() const