Skip to content

ODBC Bug: Unicode text(NVARCHAT) read from DB is truncated to half. #1436

@JiekeZhu

Description

@JiekeZhu

Situation
If the filed is type NVARCHAT, and we use RecordSet to visit the selected result, we can only get half of what we want.

Root cause
There is a bug in the prepareVariableLen method, which we use to bind the column buffer.

Solution

  1. Wrong DataType specified.
    Modify the following method from
    inline void Preparator::prepare(std::size_t pos, const UTF16String&)
    {
    prepareVariableLenUTF16String::value_type(pos, SQL_C_WCHAR, maxDataSize(pos), DT_CHAR);
    }
    to
    inline void Preparator::prepare(std::size_t pos, const UTF16String&)
    {
    prepareVariableLenUTF16String::value_type(pos, SQL_C_WCHAR, maxDataSize(pos), DT_WCHAR);
    }

2. Wrong size specified for column binding buffer. Modify following method from template void prepareVariableLen(std::size_t pos, SQLSMALLINT valueType, std::size_t size, DataType dt) /// Utility function for preparation of variable length columns. { poco_assert (DE_BOUND == _dataExtraction); poco_assert (pos < _values.size());

T* pCache = new T[size]; 
std::memset(pCache, 0, size);

_values[pos] = Any(pCache);
_lengths[pos] = (SQLLEN) size;
_varLengthArrays.insert(IndexMap::value_type(pos, dt));

if (Utility::isError(SQLBindCol(_rStmt, 
    (SQLUSMALLINT) pos + 1, 
    valueType, 
    (SQLPOINTER) pCache, 
    (SQLINTEGER) size, 
    &_lengths[pos])))
{
    throw StatementException(_rStmt, "SQLBindCol()");
}

}
to
template
void prepareVariableLen(std::size_t pos, SQLSMALLINT valueType, std::size_t size, DataType dt)
/// Utility function for preparation of variable length columns.
{
poco_assert (DE_BOUND == _dataExtraction);
poco_assert (pos < _values.size());

T* pCache = new T[size]; 
std::memset(pCache, 0, size);

_values[pos] = Any(pCache);
_lengths[pos] = (SQLLEN) size;
_varLengthArrays.insert(IndexMap::value_type(pos, dt));

if (Utility::isError(SQLBindCol(_rStmt, 
    (SQLUSMALLINT) pos + 1, 
    valueType, 
    (SQLPOINTER) pCache, 
    (SQLINTEGER) size * sizeof(T), // Here is the difference. Please help check if this is enough to work correctly.
    &_lengths[pos])))
{
    throw StatementException(_rStmt, "SQLBindCol()");
}

}

Personally, I need to save Unicode text in my database. And I'd like to use RecordSet to get whatever I want casually. So these functions are very much needed.
Since I have not got the whole view for this problem, maybe I even can't, so please help check this.
Thanks a lot.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions