On Fri, Mar 20, 2009 at 3:01 PM, Steven Watanabe wrote:
In this case, I think Boost.Fusion can help (warning untested).
#include
#include
struct get_t {
ResultSet& r;
int& n;
template<class T>
void operator()(T& t) const {
t = r.get<T>(n++);
}
};
template<Row>
void get_rows(const char* query, std::vector<Row>& out) {
ResultSet rset = sql_exec(query);
while(rset.hasMoreRows()) {
Row row;
int n = 0;
get_t getter = { rset, n };
boost::fusion::for_each(row, getter);
out.push_back(row);
}
}
Simply amazing Steven :) Thanks a lot!
Here's the code I ended up with, which reveals more context.
Many thanks. I can't believe the quality and speed of your answer frankly.
You made me day. Sincerely, --DD
#include
#include
#include
...
// Courtesy Steven Watanabe, Mar 20, 2009, boost-users mailing list.
struct get_rows_binder {
sqlite3pp::query& qry;
int& bind_idx;
template <class T> void operator()(const T& t) const {
qry.bind(bind_idx++, t);
}
};
struct get_rows_getter {
sqlite3pp::query::iterator& i;
int& col_idx;
template <class T> void operator()(T& t) const {
t = i->get<T>(col_idx++);
}
};
template void get_rows(
const char* query, const BIND& binds, std::vector<ROW>& out
) {
sqlite3pp::database& conn = DBConnection::instance()->db();
sqlite3pp::query qry(conn);
checkerr(conn, qry.prepare(query));
if (boost::tuples::length<BIND>::value > 0) {
int bind_idx = 1; // 1-based for binds
get_rows_binder binder = { qry, bind_idx };
boost::fusion::for_each(binds, binder);
}
for (sqlite3pp::query::iterator i = qry.begin(); i != qry.end(); ++i) {
ROW row;
int col_idx = 0; // 0-based for result-set columns
get_rows_getter getter = { i, col_idx };
boost::fusion::for_each(row, getter);
out.push_back(row);
}
}
template <class ROW> void get_rows(const char* query, std::vector<ROW>& out) {
get_rows(query, boost::make_tuple(), out);
}
void TypeIdTests::test_rtti_vtable() {
...
{
typedef boost::tuple Row;
std::vector<Row> rset;
get_rows("select count(*) from rtti", rset);
CPPUNIT_ASSERT_EQUAL(1, (int)rset.size());
CPPUNIT_ASSERT_EQUAL(expected_count, boost::get<0>(rset[0]));
}
{
typedef boost::tuple Row;
std::vector<Row> rset;
get_rows(
"select type, is_a, distance from rtti where type = :1 and
is_a = :2",
boost::make_tuple(ts.transient_id(), ag.transient_id()), rset
);
CPPUNIT_ASSERT_EQUAL(1, (int)rset.size());
CPPUNIT_ASSERT_EQUAL(ts.transient_id(), boost::get<0>(rset[0]));
CPPUNIT_ASSERT_EQUAL(ag.transient_id(), boost::get<1>(rset[0]));
CPPUNIT_ASSERT_EQUAL(unsigned short(1), boost::get<2>(rset[0]));
}
}