Commit bf5e0138 authored by Pavel Vainerman's avatar Pavel Vainerman

(DBInterface): рефакторинг DBInterface:

- переименовал в MySQLInterface - Упростил, убрал лишние функции - добавил класс MySQLResult
parent da30e9ae
......@@ -8,7 +8,7 @@
Name: libuniset2
Version: 2.0
Release: alt0.6
Release: alt0.7
Summary: UniSet - library for building distributed industrial control systems
......@@ -333,6 +333,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
%exclude %_pkgconfigdir/libUniSet2.pc
%changelog
* Sun Feb 02 2014 Pavel Vainerman <pv@altlinux.ru> 2.0-alt0.7
- refactoring DBInterface (rename to MySQLInterface, add MySQLResult class,..)
* Sun Feb 02 2014 Pavel Vainerman <pv@altlinux.ru> 2.0-alt0.6
- add thresholds processing for ModbusMaster (TCP and RTU)
- minor fixes
......
......@@ -39,7 +39,7 @@ const Debug::type DBLEVEL = Debug::LEVEL1;
// --------------------------------------------------------------------------
DBServer_MySQL::DBServer_MySQL(ObjectId id):
DBServer(id),
db(new DBInterface()),
db(new MySQLInterface()),
PingTime(300000),
ReconnectTime(180000),
connect_ok(false),
......@@ -59,7 +59,7 @@ DBServer_MySQL::DBServer_MySQL(ObjectId id):
DBServer_MySQL::DBServer_MySQL():
DBServer(conf->getDBServer()),
db(new DBInterface()),
db(new MySQLInterface()),
PingTime(300000),
ReconnectTime(180000),
connect_ok(false),
......@@ -82,7 +82,6 @@ DBServer_MySQL::~DBServer_MySQL()
{
if( db != NULL )
{
db->freeResult();
db->close();
delete db;
}
......@@ -98,7 +97,6 @@ void DBServer_MySQL::sysCommand( const UniSetTypes::SystemMessage *sm )
case SystemMessage::Finish:
{
activate = false;
db->freeResult();
db->close();
}
break;
......@@ -106,7 +104,6 @@ void DBServer_MySQL::sysCommand( const UniSetTypes::SystemMessage *sm )
case SystemMessage::FoldUp:
{
activate = false;
db->freeResult();
db->close();
}
break;
......@@ -136,7 +133,6 @@ void DBServer_MySQL::confirmInfo( const UniSetTypes::ConfirmMessage* cem )
if( !writeToBase(data.str()) )
{
ucrit << myname << "(update_confirm): db error: "<< db->error() << endl;
db->freeResult();
}
}
catch( Exception& ex )
......@@ -183,14 +179,11 @@ bool DBServer_MySQL::writeToBase( const string& query )
// Дело в том что на INSERT И UPDATE запросы
// db->query() может возвращать false и надо самому
// отдельно проверять действительно ли произошла ошибка
// см. DBInterface::query.
// см. MySQLInterface::query.
string err(db->error());
if( err.empty() )
{
db->freeResult();
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------
......@@ -206,11 +199,9 @@ void DBServer_MySQL::flushBuffer()
// Дело в том что на INSERT И UPDATE запросы
// db->query() может возвращать false и надо самому
// отдельно проверять действительно ли произошла ошибка
// см. DBInterface::query.
// см. MySQLInterface::query.
string err(db->error());
if( err.empty() )
db->freeResult();
else
if( !err.empty() )
ucrit << myname << "(writeToBase): error: " << err <<
" lost query: " << qbuf.front() << endl;
......@@ -247,7 +238,6 @@ void DBServer_MySQL::sensorInfo( const UniSetTypes::SensorMessage* si )
if( !writeToBase(data.str()) )
{
ucrit << myname << "(insert) sensor msg error: "<< db->error() << endl;
db->freeResult();
}
}
catch( Exception& ex )
......@@ -340,7 +330,7 @@ void DBServer_MySQL::init_dbserver()
}
}
//--------------------------------------------------------------------------------------------
void DBServer_MySQL::createTables( DBInterface *db )
void DBServer_MySQL::createTables( MySQLInterface *db )
{
UniXML_iterator it( conf->getNode("Tables") );
if(!it)
......
......@@ -27,7 +27,7 @@
#include <map>
#include <queue>
#include "UniSetTypes.h"
#include "DBInterface.h"
#include "MySQLInterface.h"
#include "DBServer.h"
//------------------------------------------------------------------------------------------
/*!
......@@ -144,7 +144,7 @@ class DBServer_MySQL:
protected:
typedef std::map<int, std::string> DBTableMap;
virtual void initDB(DBInterface *db){};
virtual void initDB(MySQLInterface *db){};
virtual void initDBTableMap(DBTableMap& tblMap){};
virtual void timerInfo( const UniSetTypes::TimerMessage* tm );
......@@ -154,7 +154,7 @@ class DBServer_MySQL:
bool writeToBase( const string& query );
virtual void init_dbserver();
void createTables( DBInterface* db );
void createTables( MySQLInterface* db );
inline const char* tblName(int key)
{
......@@ -169,7 +169,7 @@ class DBServer_MySQL:
};
DBInterface *db;
MySQLInterface *db;
int PingTime;
int ReconnectTime;
bool connect_ok; /*! признак наличия соеднинения с сервером БД */
......
......@@ -6,13 +6,17 @@ UMYSQL_VER=@LIBVER@
lib_LTLIBRARIES = libUniSet2-mysql.la
libUniSet2_mysql_la_LDFLAGS = -version-info $(UMYSQL_VER)
libUniSet2_mysql_la_SOURCES = DBInterface.cc DBServer_MySQL.cc
libUniSet2_mysql_la_SOURCES = MySQLInterface.cc DBServer_MySQL.cc
libUniSet2_mysql_la_LIBADD = $(top_builddir)/lib/libUniSet2.la -lmysqlclient
bin_PROGRAMS = @PACKAGE@-mysql-dbserver
@PACKAGE@_mysql_dbserver_LDADD = libUniSet2-mysql.la $(top_builddir)/lib/libUniSet2.la
@PACKAGE@_mysql_dbserver_SOURCES = main.cc
noinst_PROGRAMS = mysql-test
mysql_test_LDADD = libUniSet2-mysql.la $(top_builddir)/lib/libUniSet2.la
mysql_test_SOURCES = test.cc
# install
devel_include_HEADERS = *.h
devel_includedir = $(includedir)/@PACKAGE@/mysql
......
......@@ -22,32 +22,32 @@
*/
// --------------------------------------------------------------------------
#include <sstream>
#include "DBInterface.h"
#include "UniSetTypes.h"
#include "MySQLInterface.h"
using namespace std;
using namespace UniSetTypes;
// -----------------------------------------------------------------------------------------
DBInterface::DBInterface():
result(0),
MySQLInterface::MySQLInterface():
lastQ(""),
queryok(false),
connected(false)
{
{
mysql = new MYSQL();
mysql_init(mysql);
// mysql_options(mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
mysql_options(mysql,MYSQL_OPT_COMPRESS,0);
}
DBInterface::~DBInterface()
{
MySQLInterface::~MySQLInterface()
{
close();
delete mysql;
}
// -----------------------------------------------------------------------------------------
bool DBInterface::connect( const string& host, const string& user, const string& pswd, const string& dbname)
bool MySQLInterface::connect( const string& host, const string& user, const string& pswd, const string& dbname)
{
if (!mysql_real_connect(mysql,host.c_str(), user.c_str(),pswd.c_str(),dbname.c_str(),0,NULL,0))
if( !mysql_real_connect(mysql,host.c_str(), user.c_str(),pswd.c_str(),dbname.c_str(),0,NULL,0) )
{
cout << error() << endl;
mysql_close(mysql);
......@@ -58,83 +58,73 @@ bool DBInterface::connect( const string& host, const string& user, const string&
return true;
}
// -----------------------------------------------------------------------------------------
bool DBInterface::close()
bool MySQLInterface::close()
{
mysql_close(mysql);
return true;
}
// -----------------------------------------------------------------------------------------
bool DBInterface::insert( const string& q )
bool MySQLInterface::insert( const string& q )
{
if( !mysql )
return false;
if( mysql_query(mysql,q.c_str()) )
{
queryok=false;
return false;
}
queryok=true;
return true;
}
// -----------------------------------------------------------------------------------------
bool DBInterface::query( const string& q )
// -----------------------------------------------------------------------------------------
MySQLResult MySQLInterface::query( const std::string& q )
{
if( !mysql )
return false;
return MySQLResult();
if( mysql_query(mysql,q.c_str()) )
{
queryok=false;
return false;
cerr << error() << endl;
return MySQLResult();
}
lastQ = q;
result = mysql_store_result(mysql); // _use_result - некорректно работает с _num_rows
if( numRows()==0 )
{
queryok=false;
return false;
}
MYSQL_RES* res = mysql_store_result(mysql); // _use_result - некорректно работает с _num_rows
if( mysql_num_rows(res)==0 )
return MySQLResult();
queryok=true;
return true;
return MySQLResult(res,true);
}
// -----------------------------------------------------------------------------------------
bool DBInterface::nextRecord()
bool MySQLInterface::query_ok( const string& q )
{
if( !mysql || !result || !queryok )
if( !mysql )
return false;
Row = mysql_fetch_row(result);
if( Row )
return true;
if( mysql_query(mysql,q.c_str()) )
return false;
return false;
}
lastQ = q;
MYSQL_RES* res = mysql_store_result(mysql); // _use_result - некорректно работает с _num_rows
if( mysql_num_rows(res)==0 )
{
mysql_free_result(res);
return false;
}
mysql_free_result(res);
return true;
}
// -----------------------------------------------------------------------------------------
const string DBInterface::error()
const string MySQLInterface::error()
{
return mysql_error(mysql);
}
// -----------------------------------------------------------------------------------------
const string DBInterface::lastQuery()
const string MySQLInterface::lastQuery()
{
return lastQ;
}
// -----------------------------------------------------------------------------------------
void DBInterface::freeResult()
{
if( !mysql || !result || !queryok )
return;
queryok = false;
mysql_free_result( result );
}
// -----------------------------------------------------------------------------------------
int DBInterface::insert_id()
int MySQLInterface::insert_id()
{
if( !mysql )
return 0;
......@@ -142,104 +132,104 @@ int DBInterface::insert_id()
return mysql_insert_id(mysql);
}
// -----------------------------------------------------------------------------------------
unsigned int DBInterface::numCols()
const char* MySQLInterface::gethostinfo()
{
if( result )
return mysql_num_fields(result);
return 0;
return mysql_get_host_info(mysql);
}
// -----------------------------------------------------------------------------------------
unsigned int DBInterface::numRows()
bool MySQLInterface::ping()
{
if( result )
return mysql_num_rows(result);
return 0;
if( !mysql || !connected )
return false;
// внимание mysql_ping возвращает 0
// если всё хорошо.... (поэтому мы инвертируем)
return !mysql_ping(mysql);
}
// -----------------------------------------------------------------------------------------
const MYSQL_ROW DBInterface::getRow()
// -----------------------------------------------------------------------------------------
bool MySQLInterface::isConnection()
{
return Row;
return ping(); //!mysql;
}
// -----------------------------------------------------------------------------------------
string MySQLInterface::addslashes( const string& str )
{
ostringstream tmp;
for( unsigned int i=0; i<str.size(); i++ )
{
// if( !strcmp(str[i],'\'') )
if( str[i] == '\'' )
tmp << "\\";
tmp << str[i];
}
// -----------------------------------------------------------------------------------------
const char* DBInterface::gethostinfo()
return tmp.str();
}
// -----------------------------------------------------------------------------------------
int num_cols( MySQLResult::iterator& it )
{
return mysql_get_host_info(mysql);
return it->size();
}
// -----------------------------------------------------------------------------------------
/*
bool DBInterface::createDB(const string dbname)
// -----------------------------------------------------------------------------------------
int as_int( MySQLResult::iterator& it, int col )
{
if(!mysql)
return false;
if( mysql_create_db(mysql, dbname.c_str()) )
return true;
return false;
// if( col<0 || col >it->size() )
// return 0;
return uni_atoi( (*it)[col] );
}
// -----------------------------------------------------------------------------------------
bool DBInterface::dropDB(const string dbname)
double as_double( MySQLResult::iterator& it, int col )
{
if( mysql_drop_db(mysql, dbname.c_str()))
return true;
return false;
return atof( ((*it)[col]).c_str() );
}
*/
// -----------------------------------------------------------------------------------------
MYSQL_RES* DBInterface::listFields( const string& table, const string& wild )
string as_string( MySQLResult::iterator& it, int col )
{
if( !mysql || !result )
return 0;
MYSQL_RES *res = mysql_list_fields(mysql, table.c_str(),wild.c_str());
unsigned int cols = mysql_num_fields(result); // numCols();
MYSQL_ROW row=mysql_fetch_row(res);
// MYSQL_FIELD *field = mysql_fetch_fields(res);
// cout << field << " | ";
for( unsigned int i = 0; i<cols; i++)
{
cout << row[i] << " | ";
}
return res; // mysql_list_fields(mysql, table,wild);
return ((*it)[col]);
}
// -----------------------------------------------------------------------------------------
bool DBInterface::moveToRow(int ind)
int as_int( MySQLResult::COL::iterator& it )
{
if(!mysql || !result)
return false;
mysql_data_seek(result, ind);
return true;
return uni_atoi( (*it) );
}
// -----------------------------------------------------------------------------------------
bool DBInterface::ping()
double as_double( MySQLResult::COL::iterator& it )
{
if( !mysql || !connected )
return false;
// внимание mysql_ping возвращает 0
// если всё хорошо.... (поэтому мы инвертируем)
return !mysql_ping(mysql);
return atof( (*it).c_str() );
}
// -----------------------------------------------------------------------------------------
bool DBInterface::isConnection()
std::string as_string( MySQLResult::COL::iterator& it )
{
return ping(); //!mysql;
return (*it);
}
// -----------------------------------------------------------------------------------------
string DBInterface::addslashes( const string& str )
#if 0
MySQLResult::COL get_col( MySQLResult::ROW::iterator& it )
{
return (*it);
}
#endif
// -----------------------------------------------------------------------------------------
MySQLResult::~MySQLResult()
{
ostringstream tmp;
for( unsigned int i=0; i<str.size(); i++ )
}
// -----------------------------------------------------------------------------------------
MySQLResult::MySQLResult( MYSQL_RES* myres, bool finalize )
{
MYSQL_ROW row;
unsigned int nfields = mysql_num_fields(myres);
while( (row = mysql_fetch_row(myres)) )
{
// if( !strcmp(str[i],'\'') )
if( str[i] == '\'' )
tmp << "\\";
tmp << str[i];
COL c;
for( unsigned int i = 0; i<nfields; i++ )
c.push_back( (row[i]!=0 ? string(row[i]):"") );
res.push_back(c);
}
return tmp.str();
if( finalize )
mysql_free_result(myres);
}
// -----------------------------------------------------------------------------------------
......@@ -21,34 +21,39 @@
* \author Pavel Vainerman
*/
//----------------------------------------------------------------------------
#ifndef DBInterface_H_
#define DBInterface_H_
#ifndef MySQLInterface_H_
#define MySQLInterface_H_
// ---------------------------------------------------------------------------
#include <string>
#include <vector>
#include <deque>
#include <iostream>
//#warning Для использования mysql_create нужен define USE_OLD_FUNCTIONS
//#define USE_OLD_FUNCTIONS
#include <mysql/mysql.h>
// ----------------------------------------------------------------------------
class DBInterface
class MySQLResult;
// ----------------------------------------------------------------------------
class MySQLInterface
{
public:
DBInterface();
~DBInterface();
// bool createDB(const std::string dbname);
// bool dropDB(const std::string dbname);
MYSQL_RES * listFields(const std::string& table, const std::string& wild );
MySQLInterface();
~MySQLInterface();
// MySQLResult listFields( const std::string& table, const std::string& wild );
bool connect( const std::string& host, const std::string& user, const std::string& pswd,
const std::string& dbname);
bool close();
bool query(const std::string& q);
bool query_ok( const std::string& q );
// \param finalize - освободить буфер после запроса
MySQLResult query( const std::string& q );
const std::string lastQuery();
bool insert(const std::string& q);
bool insert( const std::string& q );
std::string addslashes(const std::string& str);
......@@ -61,32 +66,55 @@ class DBInterface
/*! связь с БД установлена (была) */
bool isConnection();
bool nextRecord();
void freeResult();
unsigned int numCols();
unsigned int numRows();
bool moveToRow(int ind);
int insert_id();
const MYSQL_ROW getRow();
const std::string error();
MYSQL_ROW Row;
// *******************
const char* gethostinfo();
protected:
private:
MYSQL_RES *result;
MYSQL *mysql;
std::string lastQ;
bool queryok; // успешность текущего запроса
bool connected;
};
// ----------------------------------------------------------------------------------
class MySQLResult
{
public:
MySQLResult(){}
MySQLResult( MYSQL_RES* r, bool finalize=true );
~MySQLResult();
typedef std::vector<std::string> COL;
typedef std::deque<COL> ROW;
typedef ROW::iterator iterator;
inline iterator begin(){ return res.begin(); }
inline iterator end(){ return res.end(); }
inline operator bool(){ return !res.empty(); }
inline size_t size(){ return res.size(); }
inline bool empty(){ return res.empty(); }
protected:
ROW res;
};
// ----------------------------------------------------------------------------------
int num_cols( MySQLResult::iterator& );
// ROW
int as_int( MySQLResult::iterator&, int col );
double as_double( MySQLResult::iterator&, int col );
std::string as_text( MySQLResult::iterator&, int col );
// ----------------------------------------------------------------------------
// COL
int as_int( MySQLResult::COL::iterator& );
double as_double( MySQLResult::COL::iterator& );
std::string as_string( MySQLResult::COL::iterator& );
// ----------------------------------------------------------------------------
#endif
#include <iostream>
#include <sstream>
#include "Exceptions.h"
#include "MySQLInterface.h"
// --------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
// --------------------------------------------------------------------------
int main(int argc, char** argv)
{
std::string dbname("test-db");
if( argc > 1 )
dbname = string(argv[1]);
try
{
MySQLInterface db;
if( !db.connect("localhost","dbadmin","dbadmin",dbname) )
{
cerr << "db connect error: " << db.error() << endl;
return 1;
}
stringstream q;
q << "SELECT * from main_history";
MySQLResult r = db.query(q.str());
if( !r )
{
cerr << "db connect error: " << db.error() << endl;
return 1;
}
for( MySQLResult::iterator it=r.begin(); it!=r.end(); it++ )
{
cout << "ROW: ";
MySQLResult::COL col(*it);
for( MySQLResult::COL::iterator cit = it->begin(); cit!=it->end(); cit++ )
cout << as_string(cit) << "(" << as_double(cit) << ") | ";
cout << endl;
}
db.close();
}
catch( Exception& ex )
{
cerr << "(test): " << ex << endl;
}
catch( std::exception& ex )
{
cerr << "(test): " << ex.what() << endl;
}
catch(...)
{
cerr << "(test): catch ..." << endl;
}
return 0;
}
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