Commit 1e2a80ae authored by Pavel Vainerman's avatar Pavel Vainerman

(PGSQL): переделал интерфейс с "сишного" на использование официального с++ API(pqxx).

parent 8879fcfa
...@@ -89,7 +89,7 @@ AC_ARG_ENABLE(pgsql, AC_HELP_STRING([--disable-pgsql], [disable PostgreSQL suppo ...@@ -89,7 +89,7 @@ AC_ARG_ENABLE(pgsql, AC_HELP_STRING([--disable-pgsql], [disable PostgreSQL suppo
if test ${buildpgsql} = true; then if test ${buildpgsql} = true; then
AC_MSG_RESULT([enabled]) AC_MSG_RESULT([enabled])
PKG_CHECK_MODULES(PGSQL,libpq) PKG_CHECK_MODULES(PGSQL,libpqxx)
AC_SUBST(PGSQL_LIBS) AC_SUBST(PGSQL_LIBS)
AC_SUBST(PGSQL_CFLAGS) AC_SUBST(PGSQL_CFLAGS)
else else
......
...@@ -75,7 +75,6 @@ void DBServer_PostgreSQL::sysCommand( const UniSetTypes::SystemMessage* sm ) ...@@ -75,7 +75,6 @@ void DBServer_PostgreSQL::sysCommand( const UniSetTypes::SystemMessage* sm )
case SystemMessage::FoldUp: case SystemMessage::FoldUp:
{ {
activate = false; activate = false;
db->freeResult();
db->close(); db->close();
} }
break; break;
...@@ -104,7 +103,6 @@ void DBServer_PostgreSQL::confirmInfo( const UniSetTypes::ConfirmMessage* cem ) ...@@ -104,7 +103,6 @@ void DBServer_PostgreSQL::confirmInfo( const UniSetTypes::ConfirmMessage* cem )
if( !writeToBase(data.str()) ) if( !writeToBase(data.str()) )
{ {
ucrit << myname << "(update_confirm): db error: "<< db->error() << endl; ucrit << myname << "(update_confirm): db error: "<< db->error() << endl;
db->freeResult();
} }
} }
catch( const Exception& ex ) catch( const Exception& ex )
...@@ -146,10 +144,7 @@ bool DBServer_PostgreSQL::writeToBase( const string& query ) ...@@ -146,10 +144,7 @@ bool DBServer_PostgreSQL::writeToBase( const string& query )
// А теперь собственно запрос.. // А теперь собственно запрос..
if( db->insertAndSaveRowid(query) ) if( db->insertAndSaveRowid(query) )
{
db->freeResult();
return true; return true;
}
return false; return false;
} }
...@@ -200,7 +195,6 @@ void DBServer_PostgreSQL::sensorInfo( const UniSetTypes::SensorMessage *si ) ...@@ -200,7 +195,6 @@ void DBServer_PostgreSQL::sensorInfo( const UniSetTypes::SensorMessage *si )
if( !writeToBase(data.str()) ) if( !writeToBase(data.str()) )
{ {
ucrit << myname << "(insert) sensor msg error: "<< db->error() << endl; ucrit << myname << "(insert) sensor msg error: "<< db->error() << endl;
db->freeResult();
} }
} }
catch( const Exception& ex ) catch( const Exception& ex )
......
...@@ -6,17 +6,15 @@ ...@@ -6,17 +6,15 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace pqxx;
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
PostgreSQLInterface::PostgreSQLInterface(): PostgreSQLInterface::PostgreSQLInterface():
db(0),
result(0),
lastQ(""), lastQ(""),
lastE(""), lastE(""),
queryok(false),
connected(false),
last_inserted_id(0) last_inserted_id(0)
{ {
//db = make_shared<pqxx::connection>();
} }
PostgreSQLInterface::~PostgreSQLInterface() PostgreSQLInterface::~PostgreSQLInterface()
...@@ -27,33 +25,36 @@ PostgreSQLInterface::~PostgreSQLInterface() ...@@ -27,33 +25,36 @@ PostgreSQLInterface::~PostgreSQLInterface()
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::ping() bool PostgreSQLInterface::ping()
{ {
return db && ( PQstatus(db) == CONNECTION_OK ); return db && db->is_open();
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::connect( const string& host, const string& user, const string& pswd, const string& dbname) bool PostgreSQLInterface::connect( const string& host, const string& user, const string& pswd, const string& dbname)
{ {
if(connected == true) if( db )
return true; return true;
std::string conninfo ="dbname="+dbname+" host="+host+" user="+user+" password="+pswd; std::string conninfo ="dbname="+dbname+" host="+host+" user="+user+" password="+pswd;
db = PQconnectdb(conninfo.c_str());
if (PQstatus(db) == CONNECTION_BAD) {
connected = false;
return false;
}
connected = true; try
return true; {
db = make_shared<pqxx::connection>(conninfo);
return db->is_open();
}
catch( const std::exception &e )
{
cerr << e.what() << std::endl;
}
return false;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::close() bool PostgreSQLInterface::close()
{ {
if( db ) if( db )
{ {
freeResult(); db->disconnect();
PQfinish(db); db.reset();
db = 0;
} }
return true; return true;
...@@ -64,18 +65,20 @@ bool PostgreSQLInterface::insert( const string& q ) ...@@ -64,18 +65,20 @@ bool PostgreSQLInterface::insert( const string& q )
if( !db ) if( !db )
return false; return false;
result = PQexec(db, q.c_str()); try
ExecStatusType status = PQresultStatus(result); {
work w( *(db.get()) );
if( !checkResult(status) ){ w.exec(q);
freeResult(); w.commit();
queryok = false; return true;
return false; }
catch( const std::exception &e )
{
//cerr << e.what() << std::endl;
lastE = string(e.what());
} }
queryok = true; return false;
freeResult();
return true;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::insertAndSaveRowid( const string& q ) bool PostgreSQLInterface::insertAndSaveRowid( const string& q )
...@@ -84,41 +87,22 @@ bool PostgreSQLInterface::insertAndSaveRowid( const string& q ) ...@@ -84,41 +87,22 @@ bool PostgreSQLInterface::insertAndSaveRowid( const string& q )
return false; return false;
std::string qplus=q+" RETURNING id"; std::string qplus=q+" RETURNING id";
result = PQexec(db, qplus.c_str());
ExecStatusType status = PQresultStatus(result);
if( !checkResult(status) ){ try
queryok = false; {
freeResult(); work w( *(db.get()) );
return false; pqxx::result res = w.exec(qplus);
w.commit();
save_inserted_id(res);
return true;
}
catch( const std::exception &e )
{
//cerr << e.what() << std::endl;
lastE = string(e.what());
} }
save_inserted_id(result); return false;
queryok = true;
freeResult();
return true;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::checkResult( ExecStatusType rc )
{
if( rc == PGRES_BAD_RESPONSE || rc == PGRES_NONFATAL_ERROR || rc == PGRES_FATAL_ERROR )
return false;
/*
NORMAL
PGRES-COMMAND-OK -- Successful completion of a command returning no data
PGRES-TUPLES-OK -- The query successfully executed
PGRES-COPY-OUT -- Copy Out (from server) data transfer started
PGRES-COPY-IN -- Copy In (to server) data transfer started
PGRES-EMPTY-QUERY -- The string sent to the backend was empty
ERRORS:
PGRES-BAD-RESPONSE -- The server's response was not understood
PGRES-NONFATAL-ERROR
PGRES-FATAL-ERROR
*/
return true;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
PostgreSQLResult PostgreSQLInterface::query( const string& q ) PostgreSQLResult PostgreSQLInterface::query( const string& q )
...@@ -126,25 +110,24 @@ PostgreSQLResult PostgreSQLInterface::query( const string& q ) ...@@ -126,25 +110,24 @@ PostgreSQLResult PostgreSQLInterface::query( const string& q )
if( !db ) if( !db )
return PostgreSQLResult(); return PostgreSQLResult();
result = PQexec(db, q.c_str()); try
ExecStatusType status = PQresultStatus(result); {
nontransaction n(*(db.get()));
if( !checkResult(status) ) /* Execute SQL query */
result res( n.exec(q) );
return PostgreSQLResult(res);
}
catch( const std::exception &e )
{ {
queryok = false; lastE = string(e.what());
return PostgreSQLResult();
} }
lastQ = q; return PostgreSQLResult();
queryok = true;
return PostgreSQLResult(result);
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
string PostgreSQLInterface::error() string PostgreSQLInterface::error()
{ {
if( db )
lastE = PQerrorMessage(db);
return lastE; return lastE;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
...@@ -158,25 +141,15 @@ double PostgreSQLInterface::insert_id() ...@@ -158,25 +141,15 @@ double PostgreSQLInterface::insert_id()
return last_inserted_id; return last_inserted_id;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
void PostgreSQLInterface::save_inserted_id( PGresult* res ) void PostgreSQLInterface::save_inserted_id( const pqxx::result& res )
{ {
if( res && PQntuples(res) == 1 && PQnfields(res) == 1 ) if( res.size() > 0 && res[0].size() > 0 )
last_inserted_id = atoll(PQgetvalue(res, 0, 0)); last_inserted_id = res[0][0].as<int>();
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::isConnection() bool PostgreSQLInterface::isConnection()
{ {
return (db && PQstatus(db) == CONNECTION_OK); return (db && db->is_open());
// return connected;
}
// -----------------------------------------------------------------------------------------
void PostgreSQLInterface::freeResult()
{
if( !db || !result )
return;
PQclear(result);
result = 0;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
int num_cols( PostgreSQLResult::iterator& it ) int num_cols( PostgreSQLResult::iterator& it )
...@@ -228,25 +201,14 @@ PostgreSQLResult::~PostgreSQLResult() ...@@ -228,25 +201,14 @@ PostgreSQLResult::~PostgreSQLResult()
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
PostgreSQLResult::PostgreSQLResult( PGresult* res, bool clearRES ) PostgreSQLResult::PostgreSQLResult( const pqxx::result& res )
{ {
int rec_count = PQntuples(res); for (result::const_iterator c = res.begin(); c != res.end(); ++c)
int rec_fields = PQnfields(res); {
COL col;
for (int nrow=0; nrow<rec_count; nrow++) { for( int i=0; i<c.size(); i++ )
COL c; col.push_back( c[i].as<string>() );
for (int ncol=0; ncol<rec_fields; ncol++) { row.push_back(col);
char* p = (char*)PQgetvalue(res, nrow, ncol);
if( p )
c.push_back(p);
else
c.push_back("");
}
row.push_back(c);
} }
if( clearRES )
PQclear(res);
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <libpq-fe.h> #include <pqxx/pqxx>
#include <PassiveTimer.h> #include <PassiveTimer.h>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class PostgreSQLResult; class PostgreSQLResult;
...@@ -29,36 +29,25 @@ class PostgreSQLInterface ...@@ -29,36 +29,25 @@ class PostgreSQLInterface
bool insert( const std::string& q ); bool insert( const std::string& q );
bool insertAndSaveRowid( const std::string& q ); bool insertAndSaveRowid( const std::string& q );
double insert_id(); double insert_id();
void save_inserted_id(PGresult*); void save_inserted_id( const pqxx::result& res );
std::string error(); std::string error();
void freeResult();
protected: protected:
// bool wait( ExecStatusType rc );
static bool checkResult( ExecStatusType rc );
private: private:
PGconn* db; std::shared_ptr<pqxx::connection> db;
PGresult* result;
std::string lastQ; std::string lastQ;
std::string lastE; std::string lastE;
bool queryok; // успешность текущего запроса
bool connected;
double last_inserted_id; double last_inserted_id;
// timeout_t opTimeout;
// timeout_t opCheckPause;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
class PostgreSQLResult class PostgreSQLResult
{ {
public: public:
PostgreSQLResult(){} PostgreSQLResult(){}
PostgreSQLResult( PGresult *res, bool clear = true ); // clear - clear result (call PQclear) PostgreSQLResult( const pqxx::result& res );
~PostgreSQLResult(); ~PostgreSQLResult();
typedef std::vector<std::string> COL; typedef std::vector<std::string> COL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment