Commit df403992 authored by Vadim Zeitlin's avatar Vadim Zeitlin

Fix bug with null strings in bull selections in ODBC and DB2

The changes of be4f26fe (ODBC) and
51c4c1e1 (DB2) didn't handle null
strings correctly, the indicator value for them is -1 and can't be used
as length.

Fix this now by adding a test for this particular case.

Closes #581.
parent 2d74f9aa
......@@ -196,11 +196,18 @@ void db2_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
const char *pos = buf;
std::size_t const vsize = v.size();
for (std::size_t i = 0; i != vsize; ++i)
for (std::size_t i = 0; i != vsize; ++i, pos += colSize)
{
// See ODBC backend for explanation, this code for determining
// the string length is exactly the same as there.
const char* end = pos + indVec[i];
SQLLEN const len = indVec[i];
if (len == -1)
{
v[i].clear();
continue;
}
const char* end = pos + len;
while (end != pos)
{
if (*--end != ' ')
......@@ -211,7 +218,6 @@ void db2_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
}
v[i].assign(pos, end - pos);
pos += colSize;
}
}
else if (type == x_stdtm)
......
......@@ -223,8 +223,16 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
const char *pos = buf_;
std::size_t const vsize = v.size();
for (std::size_t i = 0; i != vsize; ++i)
for (std::size_t i = 0; i != vsize; ++i, pos += colSize_)
{
SQLLEN const len = indHolderVec_[i];
if (len == -1)
{
// Value is null.
v[i].clear();
continue;
}
// Find the actual length of the string: for a VARCHAR(N)
// column, it may be right-padded with spaces up to the length
// of the longest string in the result set. This happens with
......@@ -235,7 +243,7 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
//
// So deal with this generically by just trimming all the
// spaces from the right hand-side.
const char* end = pos + indHolderVec_[i];
const char* end = pos + len;
while (end != pos)
{
// Pre-decrement as "end" is one past the end, as usual.
......@@ -248,7 +256,6 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
}
v[i].assign(pos, end - pos);
pos += colSize_;
}
}
else if (type_ == x_stdtm)
......
......@@ -1227,11 +1227,11 @@ TEST_CASE_METHOD(common_tests, "Indicators vector", "[core][indicator][vector]")
// create and populate the test table
auto_table_creator tableCreator(tc_.table_creator_1(sql));
{
sql << "insert into soci_test(id, val) values(1, 10)";
sql << "insert into soci_test(id, val) values(2, 11)";
sql << "insert into soci_test(id, val) values(3, NULL)";
sql << "insert into soci_test(id, val) values(4, NULL)";
sql << "insert into soci_test(id, val) values(5, 12)";
sql << "insert into soci_test(id, str, val) values(1, 'ten', 10)";
sql << "insert into soci_test(id, str, val) values(2, 'elf', 11)";
sql << "insert into soci_test(id, str, val) values(3, NULL, NULL)";
sql << "insert into soci_test(id, str, val) values(4, NULL, NULL)";
sql << "insert into soci_test(id, str, val) values(5, 'xii', 12)";
{
std::vector<int> vals(4);
......@@ -1248,6 +1248,15 @@ TEST_CASE_METHOD(common_tests, "Indicators vector", "[core][indicator][vector]")
st.fetch();
CHECK(vals.size() == 1);
CHECK(inds.size() == 1);
std::vector<std::string> strs(5);
sql << "select str from soci_test order by id", into(strs, inds);
REQUIRE(inds.size() == 5);
CHECK(inds[0] == i_ok);
CHECK(inds[1] == i_ok);
CHECK(inds[2] == i_null);
CHECK(inds[3] == i_null);
CHECK(inds[4] == i_ok);
}
}
......
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