diff options
-rw-r--r-- | libdbpp/selectcommand.h | 4 | ||||
-rw-r--r-- | libdbpp/selectcommandUtil.impl.h | 35 | ||||
-rw-r--r-- | libdbpp/unittests/Jamfile.jam | 14 | ||||
-rw-r--r-- | libdbpp/unittests/testUtils.cpp | 37 | ||||
-rw-r--r-- | libdbpp/unittests/util.sql | 8 |
5 files changed, 98 insertions, 0 deletions
diff --git a/libdbpp/selectcommand.h b/libdbpp/selectcommand.h index 31ef9ca..1586357 100644 --- a/libdbpp/selectcommand.h +++ b/libdbpp/selectcommand.h @@ -7,6 +7,7 @@ #include <boost/multi_index/indexed_by.hpp> #include <boost/multi_index/ordered_index_fwd.hpp> #include <boost/multi_index/member.hpp> +#include <boost/function/function_fwd.hpp> #include <boost/shared_ptr.hpp> #include <visibility.h> @@ -31,6 +32,9 @@ namespace DB { unsigned int columnCount() const; /// Get the index of a column by name. unsigned int getOrdinal(const Glib::ustring &) const; + /// Push each row through a function accepting one value per column + template<typename ... Fn, typename Func = boost::function<void(Fn...)>> + void forEachRow(const Func & func); protected: /// Helper function so clients need not know about boost::multi_index_container. diff --git a/libdbpp/selectcommandUtil.impl.h b/libdbpp/selectcommandUtil.impl.h new file mode 100644 index 0000000..26ff1b7 --- /dev/null +++ b/libdbpp/selectcommandUtil.impl.h @@ -0,0 +1,35 @@ +#ifndef DB_SELECTCOMMANDUTIL_IMPL_H +#define DB_SELECTCOMMANDUTIL_IMPL_H + +#include "selectcommand.h" +#include <boost/function.hpp> +#include <boost/utility/enable_if.hpp> + +namespace DB { + template<typename Fields, typename Func, unsigned int field, typename ... Fn> + inline typename boost::disable_if_c<field < std::tuple_size<Fields>::value>::type + forEachField(DB::SelectCommand *, const Func & func, const Fn & ... args) + { + func(args...); + } + + template<typename Fields, typename Func, unsigned int field, typename ... Fn, typename ... Args> + inline typename boost::enable_if_c<field < std::tuple_size<Fields>::value>::type + forEachField(DB::SelectCommand * sel, const Func & func, const Args & ... args) + { + typename std::tuple_element<field, Fields>::type a; + (*sel)[field] >> a; + forEachField<Fields, Func, field + 1, Fn...>(sel, func, args..., a); + } + + template<typename ... Fn, typename Func> + inline void SelectCommand::forEachRow(const Func & func) + { + while (fetch()) { + forEachField<std::tuple<Fn...>, Func, 0>(this, func); + } + } +} + +#endif + diff --git a/libdbpp/unittests/Jamfile.jam b/libdbpp/unittests/Jamfile.jam index 0739af1..ad90ec6 100644 --- a/libdbpp/unittests/Jamfile.jam +++ b/libdbpp/unittests/Jamfile.jam @@ -17,3 +17,17 @@ run testConnection ; +run + testUtils.cpp + : : : + <define>ROOT=\"$(me)\" + <define>BOOST_TEST_DYN_LINK + <library>..//dbppcore + <library>..//adhocutil + <library>../../libpqpp//dbpp-postgresql + <library>boost_utf + <dependency>util.sql + : + testUtils + ; + diff --git a/libdbpp/unittests/testUtils.cpp b/libdbpp/unittests/testUtils.cpp new file mode 100644 index 0000000..79506cf --- /dev/null +++ b/libdbpp/unittests/testUtils.cpp @@ -0,0 +1,37 @@ +#define BOOST_TEST_MODULE DbUtil +#include <boost/test/unit_test.hpp> + +#include <factory.h> +#include <connection.h> +#include <selectcommand.h> +#include <selectcommandUtil.impl.h> +#include <definedDirs.h> +#include <fstream> +#include <vector> +#include <mock.h> +#include <boost/date_time/posix_time/posix_time_io.hpp> + +class StandardMockDatabase : public PQ::Mock { + public: + StandardMockDatabase() : PQ::Mock("user=postgres dbname=postgres", "pqmock", { + rootDir / "util.sql" }) + { + } +}; + +BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); + +BOOST_AUTO_TEST_CASE( forEachRow ) +{ + auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); + auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, b, c, d, e FROM forEachRow ORDER BY a LIMIT 1")); + sel->forEachRow<int64_t, double, std::string, boost::posix_time::ptime, boost::posix_time::time_duration>( + [](auto a, auto b, auto c, auto d, auto e) { + BOOST_REQUIRE_EQUAL(1, a); + BOOST_REQUIRE_EQUAL(2.3, b); + BOOST_REQUIRE_EQUAL("Some text", c); + BOOST_REQUIRE_EQUAL(boost::posix_time::ptime_from_tm({ 17, 39, 13, 7, 10, 115, 0, 0, 0, 0, 0}), d); + BOOST_REQUIRE_EQUAL(boost::posix_time::time_duration(4, 3, 2), e); + }); +} + diff --git a/libdbpp/unittests/util.sql b/libdbpp/unittests/util.sql new file mode 100644 index 0000000..a3c5ac8 --- /dev/null +++ b/libdbpp/unittests/util.sql @@ -0,0 +1,8 @@ +CREATE TABLE foreachrow ( + a int, + b numeric(4,2), + c text, + d timestamp without time zone, + e interval); +INSERT INTO foreachrow(a, b, c, d, e) VALUES(1, 2.3, 'Some text', '2015-11-07 13:39:17', '04:03:02'); + |