| Bug #61991 | SQLGetData return shorter than expected string when multiple rows are fetched | ||
|---|---|---|---|
| Submitted: | 26 Jul 2011 21:14 | Modified: | 21 Feb 2024 23:43 |
| Reporter: | Yan Dai | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / ODBC | Severity: | S2 (Serious) |
| Version: | 5.1.8 | OS: | Windows (Windows 7 Enterprise) |
| Assigned to: | Bogdan Degtyariov | CPU Architecture: | Any |
[5 Aug 2011 11:35]
Bogdan Degtyariov
Yan, Thank you for the very detailed bug description. I was able to repeat the problem locally. Setting the bug status to verified and checking the solution kindly offered by you.
[5 Aug 2011 12:20]
Bogdan Degtyariov
We cannot just use your patch as it is because it would break handling empty result sets. It seems that the irrec->row.datalen is set to the last result length, which is 12 in this particular case because the length of the table name `Transactions` is 12.
[5 Aug 2011 16:43]
Yan Dai
I found another issue in SQLGetData that using strlen for column value length did not work for blob or unicode data. I would suggest to add current_lengths corresponding to current_values in STMT struct and set current_lengths via mysql_fetch_lengths() call when mysql_fetch_row is called. I made a patch to solve the original issue and incorrect blob length issue. Please see the attachment.
[5 Aug 2011 16:44]
Yan Dai
bug fix for length setup in SQLGetData
Attachment: bug61991.patch (application/octet-stream, text), 3.04 KiB.
[15 Sep 2011 18:49]
Yan Dai
Hi Bogdan, Thanks for reviewing the previous patch. Did you get a chance to review the patch I submitted on Aug, 5th? Thanks, Yan
[15 Dec 2023 6:16]
Bogdan Degtyariov
Posted by developer: The driver is now updating the lengths when the position in the rowset is changed using SQLSetPos() function. The patch has been pushed into the source tree.
[21 Feb 2024 23:43]
Philip Olson
Posted by developer: Fixed as of the upcoming MySQL Connector/ODBC 8.4.0 release, and here's the proposed changelog entry from the documentation team: Changing position in the row set with SQLSetPos() would not update the lengths, which could cause SQLGetData() to retrieve less data than expected. Thank you for the bug report.

Description: I am running MySQL connector installed from version 5.1.8 on a 64 bit machine. The table names from select table query are truncated on some test scenarios. Please see "How to repeat" section. With SQLGetData calls, the returned table name are "object_equip" and "Transactions". It appeared last record's length is used for return data when doing multiple row fetch. How to repeat: First create two tables: object_equipment Transactions Then call following functions. To show the code cleanly, I omitted the return error checking. SQLExecDirect(handle, SqlString("SELECT table_name from information_schema.TABLES where table_schema=(select database())"), SQL_NTS); SQLULEN nRowsFetched = 0; SetStatementAttrPtr(SQL_ATTR_ROWS_FETCHED_PTR, &nRowsFetched); SetStatementAttr(SQL_ATTR_ROW_ARRAY_SIZE, 100); SQLFetchScroll(handle, SQL_FETCH_NEXT, 0); SQLSetPos(handle, 1, SQL_POSITION, SQL_LOCK_NO_CHANGE); SQLLEN len; SQLCHAR pBuffer[65536]; SQLGetData(handle, 1, SQL_C_CHAR, pBuffer, 65536, &len); The len returned will be 12 instead of real length of "object_equipment". Suggested fix: In results.c sql_get_data() function, the length should not use the length in last row, it should use the corresponding column current_values. The following code /* catalog functions with "fake" results won't have lengths */ length= irrec->row.datalen; if (!length && stmt->current_values[ColumnNumber]) length= strlen(stmt->current_values[ColumnNumber]); changed to: /* catalog functions with "fake" results won't have lengths */ length= irrec->row.datalen; if (stmt->current_values[ColumnNumber]) length= strlen(stmt->current_values[ColumnNumber]); These changes would fix the issue.