On Fri, Mar 20, 2009 at 3:01 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
In this case, I think Boost.Fusion can help (warning untested).
#include <boost/fusion/include/for_each.hpp> #include <boost/fusion/include/boost_tuple.hpp>
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 <sqlite3pp.h> #include <boost/fusion/include/for_each.hpp> #include <boost/fusion/include/boost_tuple.hpp> ... // 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 <class ROW, class BIND> 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<sqlite_int64> 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<unsigned short, unsigned short, unsigned short> 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])); } }