Quantcast
Channel: FileMaker Forum > Report an issue
Viewing all articles
Browse latest Browse all 3510

SQLGetData ODBC call sometimes misses setting the terminating null

$
0
0

Issue report by Ranja

Product

FileMaker Server

Version

13

Operating system version

Windows 7 32bit, Windows Server 2008R2 SP1 64bit

Description of the issue

When SQLGetData function returns data, it must set the terminating null character in the buffer.
However, in some cases SQLGetData forgets doing this and fills the whole buffer with non-zero values.

Steps to reproduce the problem

I tested with the following C++ code.(a Win32 console application with MFC enabled)

{
CDatabase db;
if (db.OpenEx(_T("DSN=TestODBC;UID=admin;PWD=;"), CDatabase::noOdbcDialog))
{
_tprintf(_T("Opened\n"));

//実行
CRecordset rs(&db);
try{
rs.Open(CRecordset::forwardOnly, _T("SELECT Field2 FROM TestODBC WHERE Field1 = 7"));

//値を表示
if (!rs.IsEOF())
{
SQLLEN nActualSize;
DWORD nLen = 2047;

wchar_t pvData[2048];//one byte larger

RETCODE retCode = ::SQLGetData(rs.m_hstmt, 1, SQL_C_WCHAR, pvData, (nLen)*sizeof(wchar_t), &nActualSize);

for (int i = 0; i < nLen+1; i++){
_tprintf(_T("%ld: %5c\n"), i, pvData[i]);
}
_tprintf(_T("nActualSize=%ld\n"), nActualSize);

retCode = ::SQLGetData(rs.m_hstmt, 1, SQL_C_WCHAR, pvData, (nLen)*sizeof(wchar_t), &nActualSize);

for (int i = 0; i < nLen+1; i++){
_tprintf(_T("%ld: %5c\n"), i, pvData[i]);
}
_tprintf(_T("nActualSize=%ld\n"), nActualSize);

}
}
catch (...){
_tprintf(_T("Exception thrown\n"));
}

rs.Close();
db.Close();
}
}


I have set the buffer size to 2047*sizeof(wchar_t) bytes because Microsoft .NET Framework's OdbcDataReader class uses this value.

The FileMaker field 'Field2' contains a text "01234567890123456789...67Last1", whose length is 4093 (Length(Field2) = 4093).

After the second call of SQLGetData, the buffer pvData is filled with

...
pvData [2040] = '6'
pvData [2041] = '7'
pvData [2042] = 'L'
pvData [2043] = 'a'
pvData [2044] = 's'
pvData [2045] = 't'
pvData [2046] = '1'


However, pvData [2046] ought to be 0 (the terminating null).
(SQLGetData seems to set the pvData[2047] to 0, but this is beyond the buffer boundary.)

When I used DataDirect 32-BIT SequeLink 5.5 ODBC driver with a FileMaker 9 database, the content of pvData was:
...
pvData [2040] = '6'
pvData [2041] = '7'
pvData [2042] = 'L'
pvData [2043] = 'a'
pvData [2044] = 's'
pvData [2045] = 't'
pvData [2046] = '\0'

The final character '1' is not included here. This is natural. You just need to call SQLGetData one more time. As for FileMaker ODBC driver, one more SQLGetData call returns with a sign of NO DATA.

Because of this irregular behavior, Microsoft .NET Framework's OdbcDataReader GetString method goes into an infinite loop and the program gets stuck.
Both 32bit and 64bit driver have this issue.

Above, I used so-called '1-byte' characters as a text data. If I use 2-byte (Japanese) characters, only the first 1364 elements of pvData are filled with data.

e.g.
...
pvData [1362] = '2'
pvData [1363] = '3'
pvData [1364] = '\0'
...

Expected result

SQLGetData function is supposed to set the terminating null within the given buffer area.

Actual result

In some cases, the whole buffer is filled with non-null values.
When Japanese characters are used, only 1/3 of the data is returned.

Workaround

None

Viewing all articles
Browse latest Browse all 3510

Trending Articles