Commit bb2f6345 authored by Pavel Vainerman's avatar Pavel Vainerman

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

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