diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-11-09 18:24:23 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-11-09 18:24:23 +0000 |
commit | d45b1219e9aa832c48a3c4503709dbde32434815 (patch) | |
tree | 4e1042ea9d1637a8cd58df7a62ac3da7e33eb537 | |
parent | Support extracting nullable fields into boost::optional<T>s (diff) | |
download | libdbpp-d45b1219e9aa832c48a3c4503709dbde32434815.tar.bz2 libdbpp-d45b1219e9aa832c48a3c4503709dbde32434815.tar.xz libdbpp-d45b1219e9aa832c48a3c4503709dbde32434815.zip |
Add specific exception for invalid conversions during extract and tests over extract
-rw-r--r-- | libdbpp/column.cpp | 19 | ||||
-rw-r--r-- | libdbpp/column.h | 13 | ||||
-rw-r--r-- | libdbpp/unittests/testUtils.cpp | 32 | ||||
-rw-r--r-- | libdbpp/unittests/util.sql | 4 |
4 files changed, 60 insertions, 8 deletions
diff --git a/libdbpp/column.cpp b/libdbpp/column.cpp index 81150a5..a29b80e 100644 --- a/libdbpp/column.cpp +++ b/libdbpp/column.cpp @@ -1,17 +1,27 @@ #include "column.h" #include <boost/utility/enable_if.hpp> #include <exception> +#include <buffer.h> -DB::Column::Column(const Glib::ustring & n, unsigned int i) : +namespace DB { +Column::Column(const Glib::ustring & n, unsigned int i) : colNo(i), name(n) { } -DB::Column::~Column() +Column::~Column() { } +InvalidConversion::InvalidConversion(const char * const f, const char * const t) : from(f), to(t) { } + +std::string +InvalidConversion::message() const throw() +{ + return stringf("Invalid conversion from column type (%s) to value type (%s)", from, to); +} + template<typename T> class Extract : public DB::HandleField { public: @@ -28,7 +38,7 @@ class Extract : public DB::HandleField { template <typename D, typename dummy = int> void operator()(const D &, typename boost::disable_if<std::is_convertible<D, T>, dummy>::type = 0) { - throw std::runtime_error("Invalid type conversion"); + throw InvalidConversion(typeid(D).name(), typeid(T).name()); } template <typename D, typename dummy = int> @@ -42,7 +52,7 @@ class Extract : public DB::HandleField { #define COLUMNINTO(Type) \ void \ -DB::Column::operator>>(Type & v) const \ +Column::operator>>(Type & v) const \ { \ Extract<Type> e(v); \ apply(e); \ @@ -54,4 +64,5 @@ COLUMNINTO(double); COLUMNINTO(std::string); COLUMNINTO(boost::posix_time::ptime); COLUMNINTO(boost::posix_time::time_duration); +} diff --git a/libdbpp/column.h b/libdbpp/column.h index 43d2687..d3475a3 100644 --- a/libdbpp/column.h +++ b/libdbpp/column.h @@ -6,8 +6,21 @@ #include <boost/shared_ptr.hpp> #include <boost/optional.hpp> #include <visibility.h> +#include <exception.h> +#include "error.h" namespace DB { + /// Exception thrown on an attempt to convert betweem incompatible types. + class DLL_PUBLIC InvalidConversion : public AdHoc::Exception<Error> { + public: + InvalidConversion(const char * const, const char * const); + + private: + std::string message() const throw() override; + const char * from; + const char * to; + }; + /// Abstract class for something that can handle field data. See Column::apply. class DLL_PUBLIC HandleField { public: diff --git a/libdbpp/unittests/testUtils.cpp b/libdbpp/unittests/testUtils.cpp index b7947c7..e86d851 100644 --- a/libdbpp/unittests/testUtils.cpp +++ b/libdbpp/unittests/testUtils.cpp @@ -25,7 +25,7 @@ BOOST_AUTO_TEST_CASE( forEachRow ) sel->forEachRow<int64_t, double, std::string, boost::posix_time::ptime, boost::posix_time::time_duration, bool>( [](auto a, auto b, auto c, auto d, auto e, auto f) { BOOST_REQUIRE_EQUAL(1, a); - BOOST_REQUIRE_EQUAL(2.3, b); + BOOST_REQUIRE_CLOSE(4.3, b, 0.001); 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); @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE( forEachRowNulls ) [](auto a, auto b, auto c, auto d, auto e, auto f) { BOOST_REQUIRE_EQUAL(2, a); BOOST_REQUIRE(b); - BOOST_REQUIRE_EQUAL(2.3, *b); + BOOST_REQUIRE_CLOSE(4.3, *b, 0.001); BOOST_REQUIRE_EQUAL("Some text", c); BOOST_REQUIRE(!d); BOOST_REQUIRE(!e); @@ -74,3 +74,31 @@ BOOST_AUTO_TEST_CASE( columns ) BOOST_REQUIRE_THROW((*sel)[""], DB::ColumnDoesNotExist); } +BOOST_AUTO_TEST_CASE( extract ) +{ + auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); + auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, b, c FROM forEachRow WHERE f")); + BOOST_REQUIRE(sel->fetch()); + int64_t lint; + double ldouble; + std::string lstring; + // Plain + (*sel)[0] >> lint; + (*sel)[1] >> ldouble; + (*sel)[2] >> lstring; + BOOST_REQUIRE_EQUAL(2, lint); + BOOST_REQUIRE_CLOSE(4.3, ldouble, 0.001); + BOOST_REQUIRE_EQUAL("Some text", lstring); + // Converted + (*sel)[1] >> lint; + (*sel)[0] >> ldouble; + BOOST_REQUIRE_EQUAL(4, lint); + BOOST_REQUIRE_CLOSE(2, ldouble, 0.001); + // Bad conversions + BOOST_REQUIRE_THROW((*sel)[2] >> lint, DB::InvalidConversion); + BOOST_REQUIRE_THROW((*sel)[2] >> ldouble, DB::InvalidConversion); + BOOST_REQUIRE_THROW((*sel)[1] >> lstring, DB::InvalidConversion); + BOOST_REQUIRE_THROW((*sel)[0] >> lstring, DB::InvalidConversion); + BOOST_REQUIRE(!sel->fetch()); +} + diff --git a/libdbpp/unittests/util.sql b/libdbpp/unittests/util.sql index 04c6bf6..13391ea 100644 --- a/libdbpp/unittests/util.sql +++ b/libdbpp/unittests/util.sql @@ -5,6 +5,6 @@ CREATE TABLE foreachrow ( d timestamp without time zone, e interval, f boolean); -INSERT INTO foreachrow(a, b, c, d, e, f) VALUES(1, 2.3, 'Some text', '2015-11-07 13:39:17', '04:03:02', true); -INSERT INTO foreachrow(a, b, c, f) VALUES(2, 2.3, 'Some text', false); +INSERT INTO foreachrow(a, b, c, d, e, f) VALUES(1, 4.3, 'Some text', '2015-11-07 13:39:17', '04:03:02', true); +INSERT INTO foreachrow(a, b, c, f) VALUES(2, 4.3, 'Some text', false); |