25 TSQLServer* ROOT_Plugin_TPgSQLServer(
const char* db,
const char* uid,
const char* pw) {
26 return new TPgSQLServer(db, uid, pw);
30 ClassImp(TPgSQLServer);
38 TPgSQLServer::TPgSQLServer(
const char *db,
const char *uid,
const char *pw)
46 Error(
"TPgSQLServer",
"malformed db argument %s", db);
51 if (strncmp(url.GetProtocol(),
"pgsql", 5)) {
52 Error(
"TPgSQLServer",
"protocol in db argument should be pgsql it is %s",
58 const char *dbase = url.GetFile();
62 port += url.GetPort();
63 fPgSQL = PQsetdbLogin(url.GetHost(), port, 0, 0, dbase, uid, pw);
65 fPgSQL = PQsetdbLogin(url.GetHost(), 0, 0, 0, dbase, uid, pw);
68 if (PQstatus(fPgSQL) != CONNECTION_BAD) {
70 fHost = url.GetHost();
72 fPort = url.GetPort();
75 fSrvInfo =
"postgres ";
76 static const char *sql =
"select setting from pg_settings where name='server_version'";
77 PGresult *res = PQexec(fPgSQL, sql);
78 int stat = PQresultStatus(res);
79 if (stat == PGRES_TUPLES_OK && PQntuples(res)) {
80 char *vers = PQgetvalue(res,0,0);
84 fSrvInfo +=
"unknown version number";
87 Error(
"TPgSQLServer",
"connection to %s failed", url.GetHost());
95 TPgSQLServer::~TPgSQLServer()
104 void TPgSQLServer::Close(Option_t *)
118 TSQLResult *TPgSQLServer::Query(
const char *sql)
120 if (!IsConnected()) {
121 Error(
"Query",
"not connected");
125 PGresult *res = PQexec(fPgSQL, sql);
128 if ((PQresultStatus(res) != PGRES_COMMAND_OK) &&
129 (PQresultStatus(res) != PGRES_TUPLES_OK)) {
130 Error(
"Query",
"%s",PQresultErrorMessage(res));
135 return new TPgSQLResult(res);
141 Int_t TPgSQLServer::SelectDataBase(
const char *dbname)
148 if (!IsConnected()) {
149 Error(
"SelectDataBase",
"not connected");
156 usr = PQuser(fPgSQL);
157 pwd = PQpass(fPgSQL);
158 port = PQport(fPgSQL);
159 opts = PQoptions(fPgSQL);
162 fPgSQL = PQsetdbLogin(fHost.Data(), port.Data(),
163 opts.Data(), 0, dbname,
164 usr.Data(), pwd.Data());
166 if (PQstatus(fPgSQL) == CONNECTION_OK) {
170 Error(
"SelectDataBase",
"%s",PQerrorMessage(fPgSQL));
183 TSQLResult *TPgSQLServer::GetDataBases(
const char *wild)
185 if (!IsConnected()) {
186 Error(
"GetDataBases",
"not connected");
190 TString sql =
"SELECT pg_database.datname FROM pg_database";
192 sql += Form(
" WHERE pg_database.datname LIKE '%s'", wild);
203 TSQLResult *TPgSQLServer::GetTables(
const char *dbname,
const char *wild)
205 if (!IsConnected()) {
206 Error(
"GetTables",
"not connected");
210 if (SelectDataBase(dbname) != 0) {
211 Error(
"GetTables",
"no such database %s", dbname);
215 TString sql =
"SELECT relname FROM pg_class where relkind='r'";
217 sql += Form(
" AND relname LIKE '%s'", wild);
228 TSQLResult *TPgSQLServer::GetColumns(
const char *dbname,
const char *table,
231 if (!IsConnected()) {
232 Error(
"GetColumns",
"not connected");
236 if (SelectDataBase(dbname) != 0) {
237 Error(
"GetColumns",
"no such database %s", dbname);
243 sql = Form(
"select a.attname,t.typname,a.attnotnull \
244 from pg_attribute a, pg_class c, pg_type t \
245 where c.oid=a.attrelid and c.relname='%s' and \
246 a.atttypid=t.oid and a.attnum>0 \
247 and a.attname like '%s' order by a.attnum ", table,wild);
249 sql = Form(
"select a.attname,t.typname,a.attnotnull \
250 from pg_attribute a, pg_class c, pg_type t \
251 where c.oid=a.attrelid and c.relname='%s' and \
252 a.atttypid=t.oid and a.attnum>0 order by a.attnum",table);
260 Int_t TPgSQLServer::CreateDataBase(
const char *dbname)
262 if (!IsConnected()) {
263 Error(
"CreateDataBase",
"not connected");
267 sql = Form(
"CREATE DATABASE %s", dbname);
268 PGresult *res = PQexec(fPgSQL, sql);
277 Int_t TPgSQLServer::DropDataBase(
const char *dbname)
279 if (!IsConnected()) {
280 Error(
"DropDataBase",
"not connected");
284 sql = Form(
"DROP DATABASE %s", dbname);
285 PGresult *res = PQexec(fPgSQL, sql);
294 Int_t TPgSQLServer::Reload()
296 if (!IsConnected()) {
297 Error(
"Reload",
"not connected");
301 Error(
"Reload",
"not implemented");
309 Int_t TPgSQLServer::Shutdown()
311 if (!IsConnected()) {
312 Error(
"Shutdown",
"not connected");
316 Error(
"Shutdown",
"not implemented");
323 const char *TPgSQLServer::ServerInfo()
325 if (!IsConnected()) {
326 Error(
"ServerInfo",
"not connected");
330 return fSrvInfo.Data();
338 Bool_t TPgSQLServer::HasStatement()
const
340 #ifdef PG_VERSION_NUM
350 #ifdef PG_VERSION_NUM
351 TSQLStatement* TPgSQLServer::Statement(
const char *sql, Int_t)
353 TSQLStatement* TPgSQLServer::Statement(
const char *, Int_t)
356 #ifdef PG_VERSION_NUM
358 SetError(-1,
"no query string specified",
"Statement");
362 PgSQL_Stmt_t *stmt =
new PgSQL_Stmt_t;
364 SetError(-1,
"cannot allocate PgSQL_Stmt_t",
"Statement");
367 stmt->fConn = fPgSQL;
368 stmt->fRes = PQprepare(fPgSQL,
"preparedstmt", sql, 0, (
const Oid*)0);
370 ExecStatusType stat = PQresultStatus(stmt->fRes);
371 if (pgsql_success(stat)) {
373 return new TPgSQLStatement(stmt, fErrorOut);
375 SetError(stat, PQresultErrorMessage(stmt->fRes),
"Statement");
381 Error(
"Statement",
"not implemented for pgsql < 8.2");
389 TSQLTableInfo *TPgSQLServer::GetTableInfo(
const char* tablename)
391 if (!IsConnected()) {
392 Error(
"GetColumns",
"not connected");
397 if ((tablename==0) || (*tablename==0))
return 0;
399 PGresult *res = PQexec(fPgSQL, TString::Format(
"SELECT * FROM %s LIMIT 1;", tablename));
401 if ((PQresultStatus(res) != PGRES_COMMAND_OK) &&
402 (PQresultStatus(res) != PGRES_TUPLES_OK)) {
403 Error(
"Query",
"%s",PQresultErrorMessage(res));
408 if (fOidTypNameMap.empty()) {
411 PGresult *res_type = PQexec(fPgSQL,
"SELECT OID, TYPNAME FROM PG_TYPE;");
413 if ((PQresultStatus(res_type) != PGRES_COMMAND_OK) &&
414 (PQresultStatus(res_type) != PGRES_TUPLES_OK)) {
415 Error(
"Query",
"%s", PQresultErrorMessage(res_type));
421 Int_t nOids = PQntuples(res_type);
422 for (Int_t oid=0; oid<nOids; oid++) {
424 char* oidString = PQgetvalue(res_type, oid, 0);
425 char* typeString = PQgetvalue(res_type, oid, 1);
426 if (sscanf(oidString,
"%10d", &tOid) != 1) {
427 Error(
"GetTableInfo",
"Bad non-numeric oid '%s' for type '%s'", oidString, typeString);
429 fOidTypNameMap[tOid]=std::string(typeString);
436 Int_t nfields = PQnfields(res);
438 for (Int_t col=0;col<nfields;col++){
439 Int_t sqltype = kSQL_NONE;
440 Int_t data_size = -1;
441 Int_t data_length = -1;
442 Int_t data_scale = -1;
443 Int_t data_sign = -1;
446 const char* column_name = PQfname(res,col);
447 const char* type_name;
448 int imod = PQfmod(res,col);
451 int oid_code = PQftype(res,col);
454 std::map<Int_t,std::string>::iterator lookupOid = fOidTypNameMap.find(oid_code);
455 if (lookupOid == fOidTypNameMap.end()) {
458 sqltype = kSQL_NUMERIC;
459 type_name =
"NUMERIC";
461 }
else if (lookupOid->second ==
"int2"){
462 sqltype = kSQL_INTEGER;
465 }
else if (lookupOid->second ==
"int4"){
466 sqltype = kSQL_INTEGER;
469 }
else if (lookupOid->second ==
"int8"){
470 sqltype = kSQL_INTEGER;
473 }
else if (lookupOid->second ==
"float4"){
474 sqltype = kSQL_FLOAT;
477 }
else if (lookupOid->second ==
"float8"){
478 sqltype = kSQL_DOUBLE;
479 type_name =
"DOUBLE";
481 }
else if (lookupOid->second ==
"bool"){
482 sqltype = kSQL_INTEGER;
485 }
else if (lookupOid->second ==
"char"){
489 }
else if (lookupOid->second ==
"varchar"){
490 sqltype = kSQL_VARCHAR;
491 type_name =
"VARCHAR";
493 }
else if (lookupOid->second ==
"text"){
494 sqltype = kSQL_VARCHAR;
495 type_name =
"VARCHAR";
497 }
else if (lookupOid->second ==
"name"){
498 sqltype = kSQL_VARCHAR;
499 type_name =
"VARCHAR";
501 }
else if (lookupOid->second ==
"date"){
502 sqltype = kSQL_TIMESTAMP;
503 type_name =
"TIMESTAMP";
505 }
else if (lookupOid->second ==
"time"){
506 sqltype = kSQL_TIMESTAMP;
507 type_name =
"TIMESTAMP";
509 }
else if (lookupOid->second ==
"timetz"){
510 sqltype = kSQL_TIMESTAMP;
511 type_name =
"TIMESTAMP";
513 }
else if (lookupOid->second ==
"timestamp"){
514 sqltype = kSQL_TIMESTAMP;
515 type_name =
"TIMESTAMP";
517 }
else if (lookupOid->second ==
"timestamptz"){
518 sqltype = kSQL_TIMESTAMP;
519 type_name =
"TIMESTAMP";
521 }
else if (lookupOid->second ==
"interval"){
522 sqltype = kSQL_TIMESTAMP;
523 type_name =
"TIMESTAMP";
525 }
else if (lookupOid->second ==
"bytea"){
526 sqltype = kSQL_BINARY;
527 type_name =
"BINARY";
529 }
else if (lookupOid->second ==
""){
531 type_name =
"UNKNOWN";
535 sqltype = kSQL_NUMERIC;
536 type_name =
"NUMERIC";
544 lst->Add(
new TSQLColumnInfo(column_name,
555 return (
new TSQLTableInfo(tablename,lst));