From a47965a1d892502c83243c7367bdb5893b23a75b Mon Sep 17 00:00:00 2001 From: Viacheslav Naydenov Date: Fri, 15 Feb 2013 12:41:58 +0400 Subject: [PATCH] playing with binding output parameter as string instead of double --- src/backends/firebird/common.cpp | 15 ++++++++- src/backends/firebird/common.h | 15 +++++++++ src/backends/firebird/statement.cpp | 8 +++-- src/backends/firebird/test/test-firebird.cpp | 18 +++++++---- src/core/row.h | 22 +++++++++++--- src/core/type-conversion-traits.h | 32 ++++++++++++++++++++ 6 files changed, 96 insertions(+), 14 deletions(-) diff --git a/src/backends/firebird/common.cpp b/src/backends/firebird/common.cpp index 63c7345c3..e7408d7a3 100644 --- a/src/backends/firebird/common.cpp +++ b/src/backends/firebird/common.cpp @@ -190,7 +190,20 @@ std::string getTextParam(XSQLVAR const *var) { size = var->sqllen; } - else throw soci_error("Unexpected string type"); + else if ((var->sqltype & ~1) == SQL_SHORT) + { + return format_decimal(var); + } + else if ((var->sqltype & ~1) == SQL_LONG) + { + return format_decimal(var); + } + else if ((var->sqltype & ~1) == SQL_INT64) + { + return format_decimal(var); + } + else + throw soci_error("Unexpected string type"); return std::string(var->sqldata + offset, size); } diff --git a/src/backends/firebird/common.h b/src/backends/firebird/common.h index e600b7651..b4975188e 100644 --- a/src/backends/firebird/common.h +++ b/src/backends/firebird/common.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -151,6 +152,20 @@ void parse_decimal(void * val, XSQLVAR * var, const char * s) to_isc(val, var, scale); } +template +std::string format_decimal(const XSQLVAR * var) +{ + std::stringstream out; + if (var->sqlscale < 0) + out << std::setw(-var->sqlscale + 1) << std::setfill('0'); + out << *reinterpret_cast(var->sqldata); + std::string r = out.str(); + if (var->sqlscale < 0) + return r.substr(0, r.size() + var->sqlscale) + '.' + + r.substr(r.size() + var->sqlscale, std::string::npos); + return r; +} + template T1 from_isc(XSQLVAR * var) { diff --git a/src/backends/firebird/statement.cpp b/src/backends/firebird/statement.cpp index c9d8703de..625cdcd79 100644 --- a/src/backends/firebird/statement.cpp +++ b/src/backends/firebird/statement.cpp @@ -287,7 +287,7 @@ void firebird_statement_backend::rewriteQuery( void firebird_statement_backend::prepare(std::string const & query, statement_type /* eType */) { - //std::cerr << "prepare: query=" << query << std::endl; + std::cerr << "prepare: query=" << query << std::endl; // clear named parametes names_.clear(); @@ -650,7 +650,8 @@ void firebird_statement_backend::describe_column(int colNum, case SQL_LONG: if (var->sqlscale < 0) { - type = dt_double; + //type = dt_double; + type = dt_string; } else { @@ -660,7 +661,8 @@ void firebird_statement_backend::describe_column(int colNum, case SQL_INT64: if (var->sqlscale < 0) { - type = dt_double; + //type = dt_double; + type = dt_string; } else { diff --git a/src/backends/firebird/test/test-firebird.cpp b/src/backends/firebird/test/test-firebird.cpp index 5662706f2..60811808b 100644 --- a/src/backends/firebird/test/test-firebird.cpp +++ b/src/backends/firebird/test/test-firebird.cpp @@ -708,7 +708,7 @@ void test9() assert(sql.got_data() == false); } - std::string msg("Hello"); + std::string msg("Hello"), d_str("3.14"); int i(1); double d(3.14); indicator ind(i_ok); @@ -740,7 +740,8 @@ void test9() assert(r.get_properties(0).get_data_type() == dt_integer); assert(r.get_properties(1).get_data_type() == dt_string); - assert(r.get_properties(2).get_data_type() == dt_double); + //assert(r.get_properties(2).get_data_type() == dt_double); + assert(r.get_properties(2).get_data_type() == dt_string); // get properties by name assert(r.get_properties("ID").get_name() == "ID"); @@ -749,17 +750,20 @@ void test9() assert(r.get_properties("ID").get_data_type() == dt_integer); assert(r.get_properties("MSG").get_data_type() == dt_string); - assert(r.get_properties("NTEST").get_data_type() == dt_double); + //assert(r.get_properties("NTEST").get_data_type() == dt_double); + assert(r.get_properties("NTEST").get_data_type() == dt_string); // get values by position assert(r.get(0) == 1); assert(r.get(1) == "Hello"); + assert(r.get(2) == d_str); assert(r.get(2) == d); // get values by name assert(r.get("ID") == 1); assert(r.get("MSG") == "Hello"); - assert(r.get("NTEST") == d); + assert(r.get("NTEST") == d_str); + //assert(r.get("NTEST") == d); st.fetch(); assert(r.get(0) == 2); @@ -767,11 +771,13 @@ void test9() assert(r.get_indicator(2) == i_null); // verify default values - assert(r.get("NTEST", 2) == 2); + //assert(r.get("NTEST", 2) == 2); + assert(r.get("NTEST", "2") == "2"); bool caught = false; try { - double d1 = r.get("NTEST"); + //double d1 = r.get("NTEST"); + std::string d1 = r.get("NTEST"); std::cout << d1 << std::endl; // just for compiler } catch (soci_error&) diff --git a/src/core/row.h b/src/core/row.h index f1aa90525..27ee86d2a 100644 --- a/src/core/row.h +++ b/src/core/row.h @@ -68,11 +68,25 @@ class SOCI_DECL row assert(holders_.size() >= pos + 1); typedef typename type_conversion::base_type base_type; - base_type const& baseVal = holders_[pos]->get(); +#ifdef HAVE_BOOST + try + { +#endif + base_type const& baseVal = holders_[pos]->get(); + T ret; + type_conversion::from_base(baseVal, *indicators_[pos], ret); + return ret; +#ifdef HAVE_BOOST + } + catch (std::bad_cast const& ) + { + std::string const& baseVal = holders_[pos]->get(); + T ret; + string_conversion::from_string(baseVal, *indicators_[pos], ret); + return ret; - T ret; - type_conversion::from_base(baseVal, *indicators_[pos], ret); - return ret; + } +#endif } template diff --git a/src/core/type-conversion-traits.h b/src/core/type-conversion-traits.h index 8ebbb3bf7..7ac36ca2a 100644 --- a/src/core/type-conversion-traits.h +++ b/src/core/type-conversion-traits.h @@ -9,6 +9,10 @@ #define SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED #include "soci-backend.h" +#ifdef HAVE_BOOST +#include +#include +#endif namespace soci { @@ -36,6 +40,34 @@ struct type_conversion } }; +#ifdef HAVE_BOOST +template +struct string_conversion +{ + static void from_string(std::string const & in, indicator ind, T & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for string type"); + } + throw std::bad_cast(); + } +}; + +template <> +struct string_conversion +{ + static void from_string(std::string const & in, indicator ind, double & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for string type"); + } + out = boost::lexical_cast(in); + } +}; +#endif + } // namespace soci #endif // SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED