summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-11-09 18:24:23 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2015-11-09 18:24:23 +0000
commitd45b1219e9aa832c48a3c4503709dbde32434815 (patch)
tree4e1042ea9d1637a8cd58df7a62ac3da7e33eb537
parentSupport extracting nullable fields into boost::optional<T>s (diff)
downloadlibdbpp-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.cpp19
-rw-r--r--libdbpp/column.h13
-rw-r--r--libdbpp/unittests/testUtils.cpp32
-rw-r--r--libdbpp/unittests/util.sql4
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);