Skip to content

Commit

Permalink
playing with binding output parameter as string instead of double
Browse files Browse the repository at this point in the history
  • Loading branch information
vnaydionov authored and mloskot committed Feb 18, 2013
1 parent 8260247 commit a47965a
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 14 deletions.
15 changes: 14 additions & 1 deletion src/backends/firebird/common.cpp
Expand Up @@ -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<short>(var);
}
else if ((var->sqltype & ~1) == SQL_LONG)
{
return format_decimal<int>(var);
}
else if ((var->sqltype & ~1) == SQL_INT64)
{
return format_decimal<long long>(var);
}
else
throw soci_error("Unexpected string type");

return std::string(var->sqldata + offset, size);
}
Expand Down
15 changes: 15 additions & 0 deletions src/backends/firebird/common.h
Expand Up @@ -14,6 +14,7 @@
#include <ctime>
#include <limits>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>

Expand Down Expand Up @@ -151,6 +152,20 @@ void parse_decimal(void * val, XSQLVAR * var, const char * s)
to_isc<IntType>(val, var, scale);
}

template<typename IntType>
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<IntType *>(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<typename T1>
T1 from_isc(XSQLVAR * var)
{
Expand Down
8 changes: 5 additions & 3 deletions src/backends/firebird/statement.cpp
Expand Up @@ -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();

Expand Down Expand Up @@ -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
{
Expand All @@ -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
{
Expand Down
18 changes: 12 additions & 6 deletions src/backends/firebird/test/test-firebird.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -749,29 +750,34 @@ 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<int>(0) == 1);
assert(r.get<std::string>(1) == "Hello");
assert(r.get<std::string>(2) == d_str);
assert(r.get<double>(2) == d);

// get values by name
assert(r.get<int>("ID") == 1);
assert(r.get<std::string>("MSG") == "Hello");
assert(r.get<double>("NTEST") == d);
assert(r.get<std::string>("NTEST") == d_str);
//assert(r.get<double>("NTEST") == d);

st.fetch();
assert(r.get<int>(0) == 2);
assert(r.get<std::string>("MSG") == "Firebird");
assert(r.get_indicator(2) == i_null);

// verify default values
assert(r.get<double>("NTEST", 2) == 2);
//assert(r.get<double>("NTEST", 2) == 2);
assert(r.get<std::string>("NTEST", "2") == "2");
bool caught = false;
try
{
double d1 = r.get<double>("NTEST");
//double d1 = r.get<double>("NTEST");
std::string d1 = r.get<std::string>("NTEST");
std::cout << d1 << std::endl; // just for compiler
}
catch (soci_error&)
Expand Down
22 changes: 18 additions & 4 deletions src/core/row.h
Expand Up @@ -68,11 +68,25 @@ class SOCI_DECL row
assert(holders_.size() >= pos + 1);

typedef typename type_conversion<T>::base_type base_type;
base_type const& baseVal = holders_[pos]->get<base_type>();
#ifdef HAVE_BOOST
try
{
#endif
base_type const& baseVal = holders_[pos]->get<base_type>();
T ret;
type_conversion<T>::from_base(baseVal, *indicators_[pos], ret);
return ret;
#ifdef HAVE_BOOST
}
catch (std::bad_cast const& )
{
std::string const& baseVal = holders_[pos]->get<std::string>();
T ret;
string_conversion<T>::from_string(baseVal, *indicators_[pos], ret);
return ret;

T ret;
type_conversion<T>::from_base(baseVal, *indicators_[pos], ret);
return ret;
}
#endif
}

template <typename T>
Expand Down
32 changes: 32 additions & 0 deletions src/core/type-conversion-traits.h
Expand Up @@ -9,6 +9,10 @@
#define SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED

#include "soci-backend.h"
#ifdef HAVE_BOOST
#include <string>
#include <boost/lexical_cast.hpp>
#endif

namespace soci
{
Expand Down Expand Up @@ -36,6 +40,34 @@ struct type_conversion
}
};

#ifdef HAVE_BOOST
template <typename T>
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<double>
{
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<double>(in);
}
};
#endif

} // namespace soci

#endif // SOCI_TYPE_CONVERSION_TRAITS_H_INCLUDED

0 comments on commit a47965a

Please sign in to comment.