Skip to content

Commit

Permalink
Fix int and long mismatch for vector in ODBC
Browse files Browse the repository at this point in the history
This is attempt to investigate and solve problems with failing ODBC tests after Travis CI switched to Linux VMs from 32-bit to  64-bit.
Apparently, there is mismatch of C++ types vector<int> and vector<long> int with use() and into(). ODBC backend relies on C++ sizeof and casting, so mixing 4-byte int with 8-byte long on Linxu 64-bit is asking for troubles.

This commit may be incomplete and serves purpose of illustration of the problem, needs to be reviewed and improved if needed. As the common-tests.h have been changed, it is necessary to verify those changes against other backends as well.
(Problems of this sort prove that sorting out strong requirements regarding C++ integer type support is a must.)
  • Loading branch information
mloskot committed Mar 15, 2013
1 parent 4d5e76a commit 54cf844
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/backends/odbc/standard-into-type.cpp
Expand Up @@ -53,7 +53,7 @@ void odbc_standard_into_type_backend::define_by_pos(
break;
case x_integer:
odbcType_ = SQL_C_SLONG;
size = sizeof(long);
size = sizeof(int);
break;
case x_long_long:
if (use_string_for_bigint())
Expand Down
3 changes: 2 additions & 1 deletion src/backends/odbc/statement.cpp
Expand Up @@ -181,9 +181,10 @@ statement_backend::exec_fetch_result
odbc_statement_backend::fetch(int number)
{
numRowsFetched_ = 0;
SQLULEN const row_array_size = static_cast<SQLULEN>(number);

SQLSetStmtAttr(hstmt_, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
SQLSetStmtAttr(hstmt_, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)number, 0);
SQLSetStmtAttr(hstmt_, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)row_array_size, 0);
SQLSetStmtAttr(hstmt_, SQL_ATTR_ROWS_FETCHED_PTR, &numRowsFetched_, 0);

SQLRETURN rc = SQLFetch(hstmt_);
Expand Down
19 changes: 11 additions & 8 deletions src/backends/odbc/vector-into-type.cpp
Expand Up @@ -7,6 +7,7 @@

#define SOCI_ODBC_SOURCE
#include "soci-odbc.h"
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstring>
Expand All @@ -33,7 +34,7 @@ void odbc_vector_into_type_backend::define_by_pos(
data_ = data; // for future reference
type_ = type; // for future reference

SQLINTEGER size = 0; // also dummy
SQLLEN size = 0; // also dummy

switch (type)
{
Expand All @@ -51,9 +52,10 @@ void odbc_vector_into_type_backend::define_by_pos(
case x_integer:
{
odbcType_ = SQL_C_SLONG;
size = sizeof(long);
std::vector<long> *vp = static_cast<std::vector<long> *>(data);
std::vector<long> &v(*vp);
size = sizeof(SQLINTEGER);
assert(sizeof(SQLINTEGER) == sizeof(int));
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
std::vector<int> &v(*vp);
prepare_indicators(v.size());
data = &v[0];
}
Expand Down Expand Up @@ -129,8 +131,9 @@ void odbc_vector_into_type_backend::define_by_pos(
case x_unsigned_long_long: break; // TODO: verify if can be supported
}

SQLRETURN rc = SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
odbcType_, data, size, indHolders_);
SQLRETURN rc
= SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
odbcType_, static_cast<SQLPOINTER>(data), size, indHolders_);
if (is_odbc_error(rc))
{
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
Expand Down Expand Up @@ -267,7 +270,7 @@ void odbc_vector_into_type_backend::resize(std::size_t sz)
break;
case x_integer:
{
std::vector<long> *v = static_cast<std::vector<long> *>(data_);
std::vector<int> *v = static_cast<std::vector<int> *>(data_);
v->resize(sz);
}
break;
Expand Down Expand Up @@ -321,7 +324,7 @@ std::size_t odbc_vector_into_type_backend::size()
break;
case x_integer:
{
std::vector<long> *v = static_cast<std::vector<long> *>(data_);
std::vector<int> *v = static_cast<std::vector<int> *>(data_);
sz = v->size();
}
break;
Expand Down
6 changes: 4 additions & 2 deletions src/backends/odbc/vector-use-type.cpp
Expand Up @@ -7,6 +7,7 @@

#define SOCI_ODBC_SOURCE
#include "soci-odbc.h"
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstring>
Expand Down Expand Up @@ -55,7 +56,8 @@ void odbc_vector_use_type_backend::prepare_for_bind(void *&data, SQLUINTEGER &si
{
sqlType = SQL_INTEGER;
cType = SQL_C_SLONG;
size = sizeof(int);
size = sizeof(SQLINTEGER);
assert(sizeof(SQLINTEGER) == sizeof(int));
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
std::vector<int> &v(*vp);
prepare_indicators(v.size());
Expand Down Expand Up @@ -171,7 +173,7 @@ void odbc_vector_use_type_backend::bind_helper(int &position, void *data, exchan

prepare_for_bind(data, size, sqlType, cType);

SQLINTEGER arraySize = (SQLINTEGER)indHolderVec_.size();
SQLULEN const arraySize = static_cast<SQLULEN>(indHolderVec_.size());
SQLSetStmtAttr(statement_.hstmt_, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);

SQLRETURN rc = SQLBindParameter(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
Expand Down
21 changes: 10 additions & 11 deletions src/core/test/common-tests.h
Expand Up @@ -741,7 +741,7 @@ void test3()
}
}

// repeated fetch and bulk fetch of int
// repeated fetch and bulk fetch of int (4-bytes)
{
// create and populate the test table
auto_table_creator tableCreator(tc_.table_creator_1(sql));
Expand Down Expand Up @@ -800,7 +800,6 @@ void test3()
{
for (std::size_t i = 0; i != vec.size(); ++i)
{
std::clog << i2 << " -> " << vec[i] << std::endl;
assert(i2 == vec[i]);
++i2;
}
Expand All @@ -811,13 +810,13 @@ void test3()
}
}

// repeated fetch and bulk fetch of unsigned long
// repeated fetch and bulk fetch of unsigned int (4-bytes)
{
// create and populate the test table
auto_table_creator tableCreator(tc_.table_creator_1(sql));

unsigned long const rowsToTest = 100;
unsigned long ul;
unsigned int const rowsToTest = 100;
unsigned int ul;
for (ul = 0; ul != rowsToTest; ++ul)
{
sql << "insert into soci_test(ul) values(" << ul << ")";
Expand All @@ -828,7 +827,7 @@ void test3()
assert(count == static_cast<int>(rowsToTest));

{
unsigned long ul2 = 0;
unsigned int ul2 = 0;

statement st = (sql.prepare <<
"select ul from soci_test order by ul", into(ul));
Expand All @@ -842,9 +841,9 @@ void test3()
assert(ul2 == rowsToTest);
}
{
unsigned long ul2 = 0;
unsigned int ul2 = 0;

std::vector<unsigned long> vec(8);
std::vector<unsigned int> vec(8);
statement st = (sql.prepare <<
"select ul from soci_test order by ul", into(vec));
st.execute();
Expand Down Expand Up @@ -1573,19 +1572,19 @@ void test8()
assert(v2[3] == 2000000000);
}

// test for unsigned long
// test for unsigned int
{
auto_table_creator tableCreator(tc_.table_creator_1(sql));

std::vector<unsigned long> v;
std::vector<unsigned int> v;
v.push_back(0);
v.push_back(1);
v.push_back(123);
v.push_back(1000);

sql << "insert into soci_test(ul) values(:ul)", use(v);

std::vector<unsigned long> v2(4);
std::vector<unsigned int> v2(4);

sql << "select ul from soci_test order by ul", into(v2);
assert(v2.size() == 4);
Expand Down

0 comments on commit 54cf844

Please sign in to comment.