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.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.056 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
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.