Commit bb2f6345 authored by Pavel Vainerman's avatar Pavel Vainerman

(DBInterface): реализация DBRowIterator

parent e825963b
...@@ -9,23 +9,30 @@ using namespace std; ...@@ -9,23 +9,30 @@ using namespace std;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
std::string dbname("test-db"); std::string dbname("test-db");
std::string host("localhost");
std::string table("main_history");
if( argc > 1 ) if( argc > 1 )
dbname = string(argv[1]); dbname = string(argv[1]);
if( argc > 2 )
host = string(argv[2]);
if( argc > 3 )
table = string(argv[3]);
try try
{ {
MySQLInterface db; MySQLInterface db;
if( !db.nconnect("localhost", "dbadmin", "dbadmin", dbname) ) if( !db.nconnect(host, "dbadmin", "dbadmin", dbname) )
{ {
cerr << "db connect error: " << db.error() << endl; cerr << "db connect error: " << db.error() << endl;
return 1; return 1;
} }
stringstream q; stringstream q;
q << "SELECT * from main_history"; q << "SELECT * from " << table;
DBResult r = db.query(q.str()); DBResult r = db.query(q.str());
...@@ -38,13 +45,17 @@ int main(int argc, char** argv) ...@@ -38,13 +45,17 @@ int main(int argc, char** argv)
for( DBResult::iterator it = r.begin(); it != r.end(); it++ ) for( DBResult::iterator it = r.begin(); it != r.end(); it++ )
{ {
cout << "ROW: "; cout << "ROW: ";
DBResult::COL col(*it); // DBResult::COL col(*it);
// for( DBResult::COL::iterator cit = col.begin(); cit != col.end(); cit++ )
// cout << DBResult::as_string(cit) << "(" << DBResult::as_double(cit) << ") | ";
// cout << endl;
for( DBResult::COL::iterator cit = it->begin(); cit != it->end(); cit++ ) for( DBResult::COL::iterator cit = it->begin(); cit != it->end(); cit++ )
cout << DBResult::as_string(cit) << "(" << DBResult::as_double(cit) << ") | "; cout << DBResult::as_string(cit) << "(" << DBResult::as_double(cit) << ") | ";
cout << endl; cout << endl;
cout << "ID: " << r.as_string(it,"id") << endl; cout << "ID: " << r.as_string(it,"id") << endl;
cout << "ID: " << it.as_string("id") << endl;
} }
db.close(); db.close();
......
...@@ -226,10 +226,13 @@ void PostgreSQLInterface::makeResult( DBResult& dbres, const pqxx::result& res ) ...@@ -226,10 +226,13 @@ void PostgreSQLInterface::makeResult( DBResult& dbres, const pqxx::result& res )
for( pqxx::result::tuple::const_iterator i = c.begin(); i != c.end(); i++ ) for( pqxx::result::tuple::const_iterator i = c.begin(); i != c.end(); i++ )
{ {
if( !i.is_null() ) if( i.is_null() )
col.push_back("");
else
{
dbres.setColName(i.num(),i.name()); dbres.setColName(i.num(),i.name());
col.push_back( i.as<string>() );
col.push_back( (i.is_null() ? "" : i.as<string>()) ); }
} }
dbres.row().push_back( std::move(col) ); dbres.row().push_back( std::move(col) );
......
...@@ -250,13 +250,14 @@ void SQLiteInterface::makeResult(DBResult& dbres, sqlite3_stmt* s, bool finalize ...@@ -250,13 +250,14 @@ void SQLiteInterface::makeResult(DBResult& dbres, sqlite3_stmt* s, bool finalize
for( int i = 0; i < n; i++ ) for( int i = 0; i < n; i++ )
{ {
char* p = (char*)sqlite3_column_text(s, i); const char* p = (const char*)sqlite3_column_text(s, i);
if( p ) if( p )
{ {
const char* cname = (const char*)sqlite3_column_name(s,i); const char* cname = (const char*)sqlite3_column_name(s,i);
if( cname ) if( cname )
dbres.setColName(i,cname); dbres.setColName(i,cname);
c.emplace_back(p); c.emplace_back(p);
} }
else else
......
...@@ -20,14 +20,14 @@ CREATE TABLE main_history ( ...@@ -20,14 +20,14 @@ CREATE TABLE main_history (
confirm INTEGER DEFAULT NULL confirm INTEGER DEFAULT NULL
); );
INSERT INTO main_history VALUES(NULL,0,0,0,100,20.3,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,100,20.3,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,101,20.65,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,101,20.65,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,102,20.7,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,102,20.7,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,103,20.1,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,103,20.1,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,105,20.3,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,105,20.3,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,106,20.65,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,106,20.65,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,107,20233.7,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,107,20233.7,1,0);
INSERT INTO main_history VALUES(NULL,0,0,0,108,245560.67671,1,0); INSERT INTO main_history VALUES(NULL,date('now'),time('now'),0,108,245560.67671,1,0);
DROP TABLE IF EXISTS `main_emergencylog`; DROP TABLE IF EXISTS `main_emergencylog`;
CREATE TABLE `main_emergencylog` ( CREATE TABLE `main_emergencylog` (
......
...@@ -39,7 +39,11 @@ int main(int argc, char** argv) ...@@ -39,7 +39,11 @@ int main(int argc, char** argv)
cout << endl; cout << endl;
// for( int i=0; i<col.size(); i++ )
// cerr << "[" << i << "]: " << r.getColName(i) << endl;
cout << "ID: " << r.as_string(it,"id") << endl; cout << "ID: " << r.as_string(it,"id") << endl;
cout << "date: " << it.as_string("date") << endl;
} }
db.close(); db.close();
......
...@@ -16,8 +16,8 @@ namespace uniset ...@@ -16,8 +16,8 @@ namespace uniset
{ {
public: public:
DBInterface() {}; DBInterface() {}
virtual ~DBInterface() {}; virtual ~DBInterface() {}
// Функция подключения к БД, параметры подключения зависят от типа БД // Функция подключения к БД, параметры подключения зависят от типа БД
virtual bool connect( const std::string& param ) = 0; virtual bool connect( const std::string& param ) = 0;
...@@ -36,8 +36,8 @@ namespace uniset ...@@ -36,8 +36,8 @@ namespace uniset
{ {
public: public:
DBNetInterface() {}; DBNetInterface() {}
virtual ~DBNetInterface() {}; virtual ~DBNetInterface() {}
// Для сетевых БД параметры должны быть в формате user@host:pswd:dbname:port // Для сетевых БД параметры должны быть в формате user@host:pswd:dbname:port
virtual bool connect( const std::string& param ); virtual bool connect( const std::string& param );
...@@ -45,16 +45,18 @@ namespace uniset ...@@ -45,16 +45,18 @@ namespace uniset
const std::string& dbname, unsigned int port ) = 0; const std::string& dbname, unsigned int port ) = 0;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
class DBRowIterator;
class DBResult class DBResult
{ {
public: public:
DBResult() {} DBResult() {}
virtual ~DBResult() {}; virtual ~DBResult() {}
typedef std::vector<std::string> COL; typedef std::vector<std::string> COL;
typedef std::deque<COL> ROW; typedef std::deque<COL> ROW;
typedef ROW::iterator iterator; typedef DBRowIterator iterator;
ROW& row(); ROW& row();
iterator begin(); iterator begin();
...@@ -63,7 +65,17 @@ namespace uniset ...@@ -63,7 +65,17 @@ namespace uniset
size_t size() const; size_t size() const;
bool empty() const; bool empty() const;
// ---------------------------------------------------------------------------- /*! установить соответствие индекса и имени поля */
void setColName( int index, const std::string& name );
/*! throw std::runtime_error if name not found */
int getColIndex( const std::string& name );
// slow function
std::string getColName( int index );
// ======================= DEPRECATED FUNCTIONS ===============================
// ROW // ROW
static int as_int( const DBResult::iterator& it, int col ); static int as_int( const DBResult::iterator& it, int col );
static double as_double( const DBResult::iterator& it, int col ); static double as_double( const DBResult::iterator& it, int col );
...@@ -79,11 +91,17 @@ namespace uniset ...@@ -79,11 +91,17 @@ namespace uniset
static std::string as_string( const DBResult::COL::iterator& it ); static std::string as_string( const DBResult::COL::iterator& it );
static size_t num_cols( const DBResult::iterator& it ); static size_t num_cols( const DBResult::iterator& it );
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ===== END OF DEPRECATED FUNCTIONS =====
// установить соответсвие индекса и имени поля // ----------------------------------------------------------------------------
void setColName( int index, const std::string& name ); // USE NEW INTERFACE:
// ------------------
std::string getColName( int index ); // slow function // for( auto it = dbres.begin(); it!= dbres.end(); ++it )
// cout << it.as_string("field_name") << endl;
// OR
// cout << it.as_string(index) << endl;
//
// available functions: as_string(), as_int(), as_double()
// ----------------------------------------------------------------------------
protected: protected:
...@@ -92,6 +110,52 @@ namespace uniset ...@@ -92,6 +110,52 @@ namespace uniset
std::unordered_map<std::string, int> colname; std::unordered_map<std::string, int> colname;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
class DBRowIterator:
public std::iterator<std::bidirectional_iterator_tag,
DBResult::ROW::value_type,
DBResult::ROW::difference_type,
DBResult::ROW::pointer,
DBResult::ROW::reference>
{
public:
std::string as_string( const char* name ) const;
std::string as_string( const std::string& name ) const;
int as_int( const std::string& name ) const;
double as_double( const std::string& name ) const;
std::string as_string( int col ) const;
int as_int( int col ) const;
double as_double( int col ) const;
size_t num_cols() const;
typename DBRowIterator::pointer operator->();
typename DBRowIterator::reference operator*() const;
DBRowIterator( const DBRowIterator& it );
bool operator!=(DBRowIterator const& ) const;
bool operator==(DBRowIterator const& ) const;
DBRowIterator& operator+(int) noexcept;
DBRowIterator& operator+=(int) noexcept;
DBRowIterator& operator++() noexcept; // ++x
DBRowIterator operator++(int) noexcept; // x++
DBRowIterator& operator-(int) noexcept;
DBRowIterator operator--(int) noexcept; // x--
DBRowIterator& operator--() noexcept; // --x
DBRowIterator& operator-=(int) noexcept;
private:
friend class DBResult;
DBRowIterator( DBResult& dbres, const DBResult::ROW::iterator& );
DBResult& dbres;
DBResult::ROW::iterator it;
};
// ----------------------------------------------------------------------------------
struct DBInterfaceDeleter struct DBInterfaceDeleter
{ {
void operator()(DBInterface* p) const void operator()(DBInterface* p) const
......
...@@ -56,12 +56,12 @@ namespace uniset ...@@ -56,12 +56,12 @@ namespace uniset
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
DBResult::iterator DBResult::begin() DBResult::iterator DBResult::begin()
{ {
return row_.begin(); return DBRowIterator(*this, row_.begin());
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
DBResult::iterator DBResult::end() DBResult::iterator DBResult::end()
{ {
return row_.end(); return DBRowIterator(*this, row_.end());
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
DBResult::operator bool() const DBResult::operator bool() const
...@@ -81,55 +81,52 @@ namespace uniset ...@@ -81,55 +81,52 @@ namespace uniset
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
int DBResult::as_int( const DBResult::iterator& it, int col ) int DBResult::as_int( const DBResult::iterator& it, int col )
{ {
return uniset::uni_atoi( (*it)[col] ); return it.as_int(col);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
double DBResult::as_double( const DBResult::iterator& it, int col ) double DBResult::as_double( const DBResult::iterator& it, int col )
{ {
return atof( ((*it)[col]).c_str() ); return it.as_double(col);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
std::string DBResult::as_string( const DBResult::iterator& it, int col ) std::string DBResult::as_string( const DBResult::iterator& it, int col )
{ {
return ((*it)[col]); return it.as_string(col);
} }
int DBResult::as_int( const DBResult::iterator& it, const std::string& cname ) int DBResult::as_int( const DBResult::iterator& it, const std::string& cname )
{ {
auto i = colname.find(cname); return it.as_int(cname);
if( i == colname.end() )
throw std::runtime_error("(DBInterface): Unknown field ='" + cname + "'");
return as_int(it,i->second);
} }
double DBResult::as_double(const DBResult::iterator& it, const std::string& cname) double DBResult::as_double(const DBResult::iterator& it, const std::string& cname)
{ {
auto i = colname.find(cname); return it.as_double(cname);
if( i == colname.end() )
throw std::runtime_error("(DBInterface): Unknown field ='" + cname + "'");
return as_double(it, i->second);
} }
std::string DBResult::as_string(const DBResult::iterator& it, const std::string& cname ) std::string DBResult::as_string( const DBResult::iterator& it, const std::string& cname )
{ {
auto i = colname.find(cname); return it.as_string(cname);
if( i == colname.end() )
throw std::runtime_error("(DBInterface): Unknown field ='" + cname + "'");
return as_string(it, i->second);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
size_t DBResult::num_cols( const DBResult::iterator& it ) size_t DBResult::num_cols( const DBResult::iterator& it )
{ {
return it->size(); return it.num_cols();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void DBResult::setColName( int index, const std::string& name ) void DBResult::setColName( int index, const std::string& name )
{ {
colname[name] = index; colname[name] = index;
} }
int DBResult::getColIndex( const std::string& name )
{
auto i = colname.find(name);
if( i == colname.end() )
throw std::runtime_error("(DBInterface): Unknown field ='" + name + "'");
return i->second;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
std::string DBResult::getColName( int index ) std::string DBResult::getColName( int index )
{ {
...@@ -157,11 +154,126 @@ namespace uniset ...@@ -157,11 +154,126 @@ namespace uniset
return (*it); return (*it);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if 0 DBRowIterator::DBRowIterator( DBResult& _dbres, const DBResult::ROW::iterator& _it ):
DBResult::COL DBResult::get_col( DBResult::iterator& it ) dbres(_dbres),it(_it)
{
}
DBRowIterator::DBRowIterator( const DBRowIterator& i ):
dbres(i.dbres),it(i.it)
{
}
bool DBRowIterator::operator!=( const DBRowIterator& i ) const
{
return (it != i.it);
}
bool DBRowIterator::operator==( const DBRowIterator& i) const
{
return (it == i.it);
}
DBRowIterator& DBRowIterator::operator+(int i) noexcept
{
it += i;
return (*this);
}
DBRowIterator& DBRowIterator::operator-(int i) noexcept
{
it -= i;
return (*this);
}
DBRowIterator DBRowIterator::operator--(int) noexcept
{
DBRowIterator tmp(*this);
it--;
return tmp;
}
DBRowIterator& DBRowIterator::operator--() noexcept
{
it--;
return (*this);
}
DBRowIterator& DBRowIterator::operator-=(int i) noexcept
{
return (*this) - i;
}
DBRowIterator& DBRowIterator::operator+=(int i) noexcept
{
return (*this) + i;
}
DBRowIterator& DBRowIterator::operator++() noexcept
{
++it;
return (*this);
}
DBRowIterator DBRowIterator::operator++(int) noexcept
{
DBRowIterator tmp(*this);
it++;
return tmp;
}
// ----------------------------------------------------------------------------
std::string DBRowIterator::as_string( const char* name ) const
{
return as_string( dbres.getColIndex(name) );
}
std::string DBRowIterator::as_string( const std::string& name ) const
{
return as_string( dbres.getColIndex(name) );
}
int DBRowIterator::as_int(const std::string& name ) const
{
return as_int(dbres.getColIndex(name));
}
double DBRowIterator::as_double( const std::string& name ) const
{
return as_double(dbres.getColIndex(name));
}
std::string DBRowIterator::as_string( int col ) const
{
return ((*it)[col]);
}
int DBRowIterator::as_int( int col ) const
{
return uniset::uni_atoi( (*it)[col] );
}
double DBRowIterator::as_double( int col ) const
{
return atof( ((*it)[col]).c_str() );
}
size_t DBRowIterator::num_cols() const
{
return it->size();
}
DBRowIterator::pointer DBRowIterator::operator->()
{
return it.operator->();
}
DBRowIterator::reference DBRowIterator::operator*() const
{ {
return (*it); return (*it);
} }
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
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