Commit 99d54f78 authored by msobczak's avatar msobczak

Added conversion validity checks.

parent 4b24b5be
......@@ -19,6 +19,27 @@ namespace details
namespace postgresql
{
// helper function for integer conversions
template <typename T>
void check_integer_conversion(char * buf, char * end, T & val)
{
if (end == buf)
{
if (std::tolower(*buf) == 't')
{
val = static_cast<T>(1);
}
else if (std::tolower(*buf) == 'f')
{
val = static_cast<T>(0);
}
else
{
throw soci_error("Cannot convert data.");
}
}
}
// helper function for parsing datetime values
void parse_std_tm(char const *buf, std::tm &t);
......
......@@ -69,6 +69,8 @@ void postgresql_standard_into_type_backend::post_fetch(
}
*ind = i_null;
// no need to convert data if it is null
return;
}
else
......@@ -114,38 +116,49 @@ void postgresql_standard_into_type_backend::post_fetch(
case x_short:
{
short *dest = static_cast<short*>(data_);
long val = strtol(buf, NULL, 10);
char * end;
long val = strtol(buf, &end, 10);
check_integer_conversion(buf, end, val);
*dest = static_cast<short>(val);
}
break;
case x_integer:
{
int *dest = static_cast<int*>(data_);
long val = strtol(buf, NULL, 10);
if (std::tolower(*buf) == 't')
{
val = 1;
}
char * end;
long val = strtol(buf, &end, 10);
check_integer_conversion(buf, end, val);
*dest = static_cast<int>(val);
}
break;
case x_unsigned_long:
{
unsigned long *dest = static_cast<unsigned long *>(data_);
long long val = strtoll(buf, NULL, 10);
char * end;
long long val = strtoll(buf, &end, 10);
check_integer_conversion(buf, end, val);
*dest = static_cast<unsigned long>(val);
}
break;
case x_long_long:
{
long long *dest = static_cast<long long *>(data_);
*dest = strtoll(buf, NULL, 10);
char * end;
long long val = strtoll(buf, &end, 10);
check_integer_conversion(buf, end, val);
*dest = val;
}
break;
case x_double:
{
double *dest = static_cast<double*>(data_);
*dest = strtod(buf, NULL);
char * end;
double val = strtod(buf, &end);
if (end == buf)
{
throw soci_error("Cannot convert data.");
}
*dest = val;
}
break;
case x_stdtm:
......@@ -164,13 +177,23 @@ void postgresql_standard_into_type_backend::post_fetch(
= static_cast<postgresql_rowid_backend *>(
rid->get_backend());
long long val = strtoll(buf, NULL, 10);
char * end;
long long val = strtoll(buf, &end, 10);
if (end == buf)
{
throw soci_error("Cannot convert data.");
}
rbe->value_ = static_cast<unsigned long>(val);
}
break;
case x_blob:
{
long long llval = strtoll(buf, NULL, 10);
char * end;
long long llval = strtoll(buf, &end, 10);
if (end == buf)
{
throw soci_error("Cannot convert data.");
}
unsigned long oid = static_cast<unsigned long>(llval);
int fd = lo_open(statement_.session_.conn_, oid,
......
......@@ -360,6 +360,29 @@ void test6()
std::cout << "test 6 passed" << std::endl;
}
void test7()
{
{
session sql(backEnd, connectString);
int i;
sql << "select 123", into(i);
assert(i == 123);
try
{
sql << "select 'ABC'", into (i);
assert(false);
}
catch (soci_error const & e)
{
assert(e.what() == std::string("Cannot convert data."));
}
}
std::cout << "test 7 passed" << std::endl;
}
// DDL Creation objects for common tests
struct table_creator_one : public table_creator_base
{
......@@ -465,7 +488,11 @@ int main(int argc, char** argv)
test3();
test4();
test5();
// test6();
std::cout << "test 6 skipped (dynamic backend)\n";
test7();
std::cout << "\nOK, all tests passed.\n\n";
return EXIT_SUCCESS;
......
......@@ -82,6 +82,9 @@ void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator *in
}
ind[i] = i_null;
// no need to convert data if it is null, go to next row
continue;
}
else
{
......@@ -104,35 +107,44 @@ void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator *in
break;
case x_short:
{
long val = strtol(buf, NULL, 10);
char * end;
long val = strtol(buf, &end, 10);
check_integer_conversion(buf, end, val);
set_invector_(data_, i, static_cast<short>(val));
}
break;
case x_integer:
{
long val = strtol(buf, NULL, 10);
if (std::tolower(*buf) == 't')
{
val = 1;
}
char * end;
long val = strtol(buf, &end, 10);
check_integer_conversion(buf, end, val);
set_invector_(data_, i, static_cast<int>(val));
}
break;
case x_unsigned_long:
{
long long val = strtoll(buf, NULL, 10);
char * end;
long long val = strtoll(buf, &end, 10);
check_integer_conversion(buf, end, val);
set_invector_(data_, i, static_cast<unsigned long>(val));
}
break;
case x_long_long:
{
long long val = strtoll(buf, NULL, 10);
char * end;
long long val = strtoll(buf, &end, 10);
check_integer_conversion(buf, end, val);
set_invector_(data_, i, val);
}
break;
case x_double:
{
double val = strtod(buf, NULL);
char * end;
double val = strtod(buf, &end);
if (end == buf)
{
throw soci_error("Cannot convert data.");
}
set_invector_(data_, i, val);
}
break;
......@@ -174,14 +186,14 @@ void postgresql_vector_into_type_backend::resize(std::size_t sz)
switch (type_)
{
// simple cases
case x_char: resizevector_<char> (data_, sz); break;
case x_short: resizevector_<short> (data_, sz); break;
case x_integer: resizevector_<int> (data_, sz); break;
case x_char: resizevector_<char> (data_, sz); break;
case x_short: resizevector_<short> (data_, sz); break;
case x_integer: resizevector_<int> (data_, sz); break;
case x_unsigned_long: resizevector_<unsigned long>(data_, sz); break;
case x_long_long: resizevector_<long long> (data_, sz); break;
case x_double: resizevector_<double> (data_, sz); break;
case x_stdstring: resizevector_<std::string> (data_, sz); break;
case x_stdtm: resizevector_<std::tm> (data_, sz); break;
case x_double: resizevector_<double> (data_, sz); break;
case x_stdstring: resizevector_<std::string> (data_, sz); break;
case x_stdtm: resizevector_<std::tm> (data_, sz); break;
default:
throw soci_error("Into vector element used with non-supported type.");
......@@ -194,14 +206,14 @@ std::size_t postgresql_vector_into_type_backend::size()
switch (type_)
{
// simple cases
case x_char: sz = get_vector_size<char> (data_); break;
case x_short: sz = get_vector_size<short> (data_); break;
case x_integer: sz = get_vector_size<int> (data_); break;
case x_char: sz = get_vector_size<char> (data_); break;
case x_short: sz = get_vector_size<short> (data_); break;
case x_integer: sz = get_vector_size<int> (data_); break;
case x_unsigned_long: sz = get_vector_size<unsigned long>(data_); break;
case x_long_long: sz = get_vector_size<long long> (data_); break;
case x_double: sz = get_vector_size<double> (data_); break;
case x_stdstring: sz = get_vector_size<std::string> (data_); break;
case x_stdtm: sz = get_vector_size<std::tm> (data_); break;
case x_double: sz = get_vector_size<double> (data_); break;
case x_stdstring: sz = get_vector_size<std::string> (data_); break;
case x_stdtm: sz = get_vector_size<std::tm> (data_); break;
default:
throw soci_error("Into vector element used with non-supported type.");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment