diff options
| -rw-r--r-- | libdbpp/command.cpp | 19 | ||||
| -rw-r--r-- | libdbpp/command.h | 16 | ||||
| -rw-r--r-- | libdbpp/unittests/Jamfile.jam | 2 | ||||
| -rw-r--r-- | libdbpp/unittests/testUtils.cpp | 102 | 
4 files changed, 139 insertions, 0 deletions
| diff --git a/libdbpp/command.cpp b/libdbpp/command.cpp index abbb53f..97a6518 100644 --- a/libdbpp/command.cpp +++ b/libdbpp/command.cpp @@ -17,3 +17,22 @@ DB::ParameterOutOfRange::ParameterOutOfRange()  {  } +void +DB::Command::bindParamS(unsigned int i, const char * const o) +{ +	if (o) +		bindParamS(i, Glib::ustring(o)); +	else +		bindNull(i); +} + + +void +DB::Command::bindParamS(unsigned int i, char * const o) +{ +	if (o) +		bindParamS(i, Glib::ustring(o)); +	else +		bindNull(i); +} + diff --git a/libdbpp/command.h b/libdbpp/command.h index 3305342..ae18158 100644 --- a/libdbpp/command.h +++ b/libdbpp/command.h @@ -61,6 +61,22 @@ namespace DB {  			/// The SQL statement.  			const std::string sql; + +#define OPTWRAPPER(func) \ +			template<typename O> \ +			inline void func(unsigned int i, const O & o) { \ +				if (o) \ +					func(i, *o); \ +				else \ +					bindNull(i); \ +			} +			OPTWRAPPER(bindParamI); +			OPTWRAPPER(bindParamF); +			OPTWRAPPER(bindParamS); +			OPTWRAPPER(bindParamB); +			OPTWRAPPER(bindParamT); +			void bindParamS(unsigned int, const char * const); +			void bindParamS(unsigned int, char * const);  	};  	typedef boost::shared_ptr<Command> CommandPtr;  } diff --git a/libdbpp/unittests/Jamfile.jam b/libdbpp/unittests/Jamfile.jam index 08bd027..93b26b3 100644 --- a/libdbpp/unittests/Jamfile.jam +++ b/libdbpp/unittests/Jamfile.jam @@ -3,6 +3,7 @@ import testing ;  path-constant me : . ;  lib boost_utf : : <name>boost_unit_test_framework ; +lib IceUtil ;  run  	testConnection.cpp @@ -62,6 +63,7 @@ run  	<library>..//adhocutil  	<library>../../libpqpp//dbpp-postgresql  	<library>boost_utf +	<library>IceUtil  	<dependency>util.sql  	:  	testUtils diff --git a/libdbpp/unittests/testUtils.cpp b/libdbpp/unittests/testUtils.cpp index ac9b7c1..cb660cc 100644 --- a/libdbpp/unittests/testUtils.cpp +++ b/libdbpp/unittests/testUtils.cpp @@ -3,11 +3,14 @@  #include <connection.h>  #include <selectcommand.h> +#include <modifycommand.h>  #include <selectcommandUtil.impl.h>  #include <definedDirs.h>  #include <fstream>  #include <pq-mock.h>  #include <boost/date_time/posix_time/posix_time_io.hpp> +#include <IceUtil/Exception.h> +#include <IceUtil/Optional.h>  class StandardMockDatabase : public PQ::Mock {  	public: @@ -148,3 +151,102 @@ BOOST_AUTO_TEST_CASE( bulkLoadFile )  		});  } +BOOST_AUTO_TEST_CASE( nullBind ) +{ +	auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); +	auto ins = db->modify("INSERT INTO forEachRow VALUES(?, ?, ?, ?, ?, ?)"); +	ins->bindParamI(0, boost::optional<int>()); +	ins->bindParamF(1, boost::optional<double>()); +	ins->bindParamS(2, boost::optional<Glib::ustring>()); +	ins->bindParamT(3, boost::optional<boost::posix_time::ptime>()); +	ins->bindParamT(4, boost::optional<boost::posix_time::time_duration>()); +	ins->bindParamB(5, boost::optional<bool>()); +	ins->execute(); +	auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, b, c, d, e, f FROM forEachRow WHERE a IS NULL AND b IS NULL AND c IS NULL AND d IS NULL AND e IS NULL AND f IS NULL")); +	unsigned int count = 0; +	for (const auto & row : sel->as<>()) { +		(void)row; +		count += 1; +	} +	BOOST_REQUIRE_EQUAL(1, count); +} + +BOOST_AUTO_TEST_CASE( iceNullBind ) +{ +	auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); +	auto ins = db->modify("INSERT INTO forEachRow VALUES(?, ?, ?, ?, ?, ?)"); +	ins->bindParamI(0, IceUtil::Optional<int>()); +	ins->bindParamF(1, IceUtil::Optional<double>()); +	ins->bindParamS(2, IceUtil::Optional<Glib::ustring>()); +	ins->bindParamT(3, IceUtil::Optional<boost::posix_time::ptime>()); +	ins->bindParamT(4, IceUtil::Optional<boost::posix_time::time_duration>()); +	ins->bindParamB(5, IceUtil::Optional<bool>()); +	ins->execute(); +	auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, b, c, d, e, f FROM forEachRow WHERE a IS NULL AND b IS NULL AND c IS NULL AND d IS NULL AND e IS NULL AND f IS NULL")); +	unsigned int count = 0; +	for (const auto & row : sel->as<>()) { +		(void)row; +		count += 1; +	} +	BOOST_REQUIRE_EQUAL(2, count); +} + +BOOST_AUTO_TEST_CASE( charStarBindNull ) +{ +	auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); +	db->modify("DELETE FROM forEachRow")->execute(); +	auto ins = db->modify("INSERT INTO forEachRow(a, c) VALUES(?, ?)"); +	char * cs = NULL; +	char * cs2 = strdup("a thing"); +	ins->bindParamS(0, cs); +	ins->bindParamS(1, cs2); +	ins->execute(); +	const char * ccs = cs; +	const char * ccs2 = cs2; +	ins->bindParamS(0, ccs); +	ins->bindParamS(1, ccs2); +	ins->execute(); +	const char * const ccsc = ccs; +	const char * const ccsc2 = ccs2; +	ins->bindParamS(0, ccsc); +	ins->bindParamS(1, ccsc2); +	ins->execute(); +	free(cs2); +	auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, c FROM forEachRow")); +	for (const auto & row : sel->as<boost::optional<int64_t>, boost::optional<std::string>>()) { +		BOOST_REQUIRE(row[0].isNull()); +		BOOST_REQUIRE(!row[1].isNull()); +	} +} + +BOOST_AUTO_TEST_CASE( bindIntPtr ) +{ +	auto db = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("pqmock")); +	db->modify("DELETE FROM forEachRow")->execute(); +	auto ins = db->modify("INSERT INTO forEachRow(a, b) VALUES(?, ?)"); +	int * is = NULL; +	int * is2 = new int(53); +	ins->bindParamI(0, is); +	ins->bindParamI(1, is2); +	ins->execute(); +	const int * cis = is; +	const int * cis2 = is2; +	ins->bindParamI(0, cis); +	ins->bindParamI(1, cis2); +	ins->execute(); +	const int * const cisc = cis; +	const int * const cisc2 = cis2; +	ins->bindParamI(0, cisc); +	ins->bindParamI(1, cisc2); +	ins->execute(); +	delete is2; +	auto sel = DB::SelectCommandPtr(db->newSelectCommand("SELECT a, b FROM forEachRow")); +	unsigned int total = 0; +	for (const auto & row : sel->as<boost::optional<int64_t>, boost::optional<double>>()) { +		BOOST_REQUIRE(row[0].isNull()); +		BOOST_REQUIRE(!row[1].isNull()); +		total += *row.value<1>(); +	} +	BOOST_REQUIRE_EQUAL(159, total); +} + | 
