From ed1cc0723d34bc5629c2c92a7519c0b8bb0f0aba Mon Sep 17 00:00:00 2001 From: Fons Rademakers <Fons.Rademakers@cern.ch> Date: Thu, 9 Jan 2014 18:14:57 +0100 Subject: [PATCH] Implemention of the TPgSQLServer::GetTableInfo(const char*) method (ROOT-5897). Fix by Denis Bertini. --- sql/pgsql/inc/TPgSQLServer.h | 3 + sql/pgsql/src/TPgSQLServer.cxx | 159 +++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/sql/pgsql/inc/TPgSQLServer.h b/sql/pgsql/inc/TPgSQLServer.h index 1fbb582a7c5..08d36195de5 100644 --- a/sql/pgsql/inc/TPgSQLServer.h +++ b/sql/pgsql/inc/TPgSQLServer.h @@ -17,7 +17,9 @@ #endif #if !defined(__CINT__) +#include <postgres.h> #include <libpq-fe.h> +#include <catalog/pg_type.h> #else struct PGconn; #endif @@ -42,6 +44,7 @@ public: TSQLResult *GetDataBases(const char *wild = 0); TSQLResult *GetTables(const char *dbname, const char *wild = 0); TSQLResult *GetColumns(const char *dbname, const char *table, const char *wild = 0); + TSQLTableInfo *GetTableInfo(const char *tablename); Int_t CreateDataBase(const char *dbname); Int_t DropDataBase(const char *dbname); Int_t Reload(); diff --git a/sql/pgsql/src/TPgSQLServer.cxx b/sql/pgsql/src/TPgSQLServer.cxx index 3c52abf2f9f..c4ebafda07a 100644 --- a/sql/pgsql/src/TPgSQLServer.cxx +++ b/sql/pgsql/src/TPgSQLServer.cxx @@ -12,8 +12,19 @@ #include "TPgSQLServer.h" #include "TPgSQLResult.h" #include "TPgSQLStatement.h" + +#include "TSQLColumnInfo.h" +#include "TSQLTableInfo.h" +#include "TSQLRow.h" #include "TUrl.h" +#include "TList.h" +#include "TObjString.h" +#include "TObjArray.h" + +#include<iostream> + +using namespace std; ClassImp(TPgSQLServer) @@ -111,6 +122,7 @@ TSQLResult *TPgSQLServer::Query(const char *sql) } PGresult *res = PQexec(fPgSQL, sql); + //cout << " Query called " << sql << ":" << PQntuples(res) << endl; if ((PQresultStatus(res) != PGRES_COMMAND_OK) && (PQresultStatus(res) != PGRES_TUPLES_OK)) { @@ -369,3 +381,150 @@ TSQLStatement* TPgSQLServer::Statement(const char *, Int_t) #endif return 0; } + +//______________________________________________________________________________ +TSQLTableInfo *TPgSQLServer::GetTableInfo(const char *tablename) +{ + if (!IsConnected()) { + Error("GetColumns", "not connected"); + return 0; + } + + // Check table name + if ((tablename == 0) || (*tablename == 0)) return 0; + + // Query first row ( works same way as MySQL) + TString sql; + sql.Form("SELECT * FROM %s LIMIT 1;", tablename); + PGresult *res = PQexec(fPgSQL, sql); + + if ((PQresultStatus(res) != PGRES_COMMAND_OK) && + (PQresultStatus(res) != PGRES_TUPLES_OK)) { + Error("Query", "%s", PQresultErrorMessage(res)); + PQclear(res); + return 0; + } + + TList *lst = 0; + Int_t sqltype = kSQL_NONE; + Int_t data_size = -1; // size in bytes + Int_t data_length = -1; // declaration like VARCHAR(n) or NUMERIC(n) + Int_t data_scale = -1; // second argument in declaration + Int_t data_sign = -1; // signed type or not + Bool_t nullable = 0; + + Int_t nfields = PQnfields(res); + Int_t ibin = PQbinaryTuples(res); + + for (Int_t col = 0; col < nfields; col++) { + + const char *column_name = PQfname(res, col); + const char *type_name; + int imod = PQfmod(res, col); + int isize = PQfsize(res, col); + + switch (PQftype(res, col)) { + case INT2OID: + sqltype = kSQL_INTEGER; + type_name = "INT"; + data_size = 2; + break; + case INT4OID: + sqltype = kSQL_INTEGER; + type_name = "INT"; + data_size = 4; + break; + case INT8OID: + sqltype = kSQL_INTEGER; + type_name = "INT"; + data_size = 8; + break; + case FLOAT4OID: + sqltype = kSQL_FLOAT; + type_name = "FLOAT"; + data_size = 4; + break; + case FLOAT8OID: + sqltype = kSQL_DOUBLE; + type_name = "DOUBLE"; + data_size = 8; + break; + case BOOLOID: + sqltype = kSQL_INTEGER; + type_name = "BOOL"; + data_size = 4; + break; + case CHAROID: + sqltype = kSQL_CHAR; + type_name = "CHAR"; + data_size = 1; + break; + case NAMEOID: + sqltype = kSQL_VARCHAR; + type_name = "VARCHAR"; + data_size = imod; + break; + case TEXTOID: + sqltype = kSQL_VARCHAR; + type_name = "VARCHAR"; + data_size = imod; + break; + case VARCHAROID: + sqltype = kSQL_VARCHAR; + type_name = "VARCHAR"; + data_size = imod; + break; + case DATEOID: + sqltype = kSQL_TIMESTAMP; + type_name = "TIMESTAMP"; + data_size = 4; + break; + case TIMEOID: + sqltype = kSQL_TIMESTAMP; + type_name = "TIMESTAMP"; + data_size = 8; + break; + case TIMETZOID: + sqltype = kSQL_TIMESTAMP; + type_name = "TIMESTAMP"; + data_size = 8; + break; + case TIMESTAMPOID: + sqltype = kSQL_TIMESTAMP; + type_name = "TIMESTAMP"; + data_size = 8; + break; + case TIMESTAMPTZOID: + sqltype = kSQL_TIMESTAMP; + type_name = "TIMESTAMP"; + data_size = 8; + break; + case BYTEAOID: + sqltype = kSQL_BINARY; + type_name = "BINARY"; + break; + default: + sqltype = kSQL_NUMERIC; + type_name = "NUMERIC"; + break; + } + + //cout << " -I- ibin# " << ibin << "col# " << col << " cname: " + // << column_name << " sqltype:" << sqltype << " imod: " + // << imod << " isize:" << isize << endl; + + if (!lst) + lst = new TList; + lst->Add(new TSQLColumnInfo(column_name, + type_name, + nullable, + sqltype, + data_size, + data_length, + data_scale, + data_sign)); + } //! ( cols) + + PQclear(res); + return (new TSQLTableInfo(tablename, lst)); +} -- GitLab