Bug #30520 | MyODBC > 3.51.12 Returns null value for multiple references | ||
---|---|---|---|
Submitted: | 20 Aug 2007 20:14 | Modified: | 2 Nov 2007 21:50 |
Reporter: | James Cahill | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | Connector / ODBC | Severity: | S2 (Serious) |
Version: | 3.51.20 | OS: | Windows (2003 Server (IIS6/ASP Classic)) |
Assigned to: | Bogdan Degtyariov | CPU Architecture: | Any |
Tags: | MyODBC, null return, text |
[20 Aug 2007 20:14]
James Cahill
[25 Aug 2007 14:00]
Kent Boortz
I wrote an ADO regression test case that show this problem. The test case and manager trace is attached. Might not be the problem, but ADODB mixes use of SQLBindCol() and SQLGetData(), something the IBM ODBC documentation says is not allowed, and Microsoft documentation mentions as allowed but with restrictions. https://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=/com.ibm.db2.luw.apd... http://msdn2.microsoft.com/en-us/library/ms715441.aspx Reading the log, the flow is simplified SQLBindCol() - Binds column 1, the integer data SQLFetch() - Get the recordset SQLGetData() - With length 0, to find real length => SQL_SUCCESS_WITH_INFO The manager reports DIAG [01004] [MySQL][ODBC 3.51 Driver] [mysqld-5.0.46-enterprise-gpl-nt-log] String data, right truncated (501) SQLGetData() - Same as the previous SQLGetData() - With length returned above + 1, returns all data SQLGetData() - With length 0, to find real length => SQL_SUCCESS_WITH_INFO. Now gets the answer 0, gets same DIAG. SQLGetData() - Same as the previous SQLGetData() - With length 0 + 1 ?! => SQL_NO_DATA_FOUND SQLFreeStmt() - SQL_UNBIND SQLFreeStmt() - SQL_CLOSE SQLFreeStmt() - SQL_DROP SQLDisconnect() SQLFreeConnect()
[25 Aug 2007 14:02]
Kent Boortz
Test case for ADO regression suite
Attachment: bug30520.vbs (application/octet-stream, text), 3.12 KiB.
[25 Aug 2007 14:03]
Kent Boortz
Manager trace from running the ADO regression suite test case
Attachment: SQL.LOG (application/octet-stream, text), 105.66 KiB.
[25 Aug 2007 14:24]
Kent Boortz
Further investigation shows that an application can ask if SQLGetData() is supported on bound columns. This is done with a call to SQLGetInfo() with the option SQL_GETDATA_EXTENSIONS, and the MySQL driver will answer it can support SQL_GD_ANY_COLUMN SQL_GD_ANY_ORDER SQL_GD_BOUND Just as a note, the IBM DB2 database currently doesn't support SQL_GD_BOUND. http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.apdv.c... The ADODB driver does ask about what the driver support, could be the reason for the mix of calls. Another track to investigate is if SQLGetData() really should return success when there is no more data, even if the caller give length 0.
[25 Aug 2007 14:33]
Kent Boortz
The problem could also be that ADODB gets confused because our driver doesn't follow the Microsoft documentation. http://msdn2.microsoft.com/en-us/library/ms715441.aspx The SQLGetData() call returning the last part of data is to return SQL_SUCCESS. Then Microsoft writes If SQLGetData is called after this, it returns SQL_NO_DATA. This is not done in the MySQL driver according to the trace, instead a call by the ADODB driver to SQLGetData() with length 0, will return SQL_SUCCESS_WITH_INFO and the length 0.
[25 Aug 2007 16:17]
Kent Boortz
With the following change, the test case passes =================================================================== --- driver/utility.c (revision 697) +++ driver/utility.c (working copy) @@ -256,9 +256,26 @@ fill_length= src_length; } if ( *offset == (ulong) ~0L ) - *offset= 0; /* First call */ - else if ( arg_length && *offset >= (ulong) fill_length ) + { + /* + This is first call, even if data has zero size, we don't + return SQL_NO_DATA_FOUND. + + FIXME this is one interpretation of the ODBC standard, could + be wrong. + */ + *offset= 0; + } + else if ( *offset >= (ulong) fill_length ) + { + /* + If not the first call, and we have no data left, + must be a call after we gave the last data. + We always return SQL_NO_DATA_FOUND in this case, + even if size is 0. + */ return SQL_NO_DATA_FOUND; + } src+= *offset; src_length-= (long) *offset; Would also require a change of line 601 in "my_result.c", the test case, as the test case assumes SQL_SUCCESS_WITH_INFO when all data is read. But the test case didn't fail (as it should if not updated) on Windows. Might be caused by how the test case is compiled (it the macro "assert"), will be investigated.
[31 Aug 2007 7:58]
Kent Boortz
SQLGetData() will now always return SQL_NO_DATA_FOUND on second call when no data left, even if requested size is 0 (bug#30520). Will be in 3.51.20
[11 Sep 2007 15:01]
James Cahill
This bug was not fixed in 3.51.20. I installed it today and it is still returning empty values for a field referenced more than once.
[13 Sep 2007 11:35]
MC Brown
A note has been added to the 3.51.20 changelog: SQLGetData() will now always return SQL_NO_DATA_FOUND on second call when no data left, even if requested size is 0
[23 Oct 2007 17:02]
Bogdan Degtyariov
This bug never occurs if use adClientSideCursor like in the test case below. This fix contradicts MSDN... I don't think it is needed because there is a workaround. NOTE: See how bug#30958 is affected by this fix
[23 Oct 2007 17:03]
Bogdan Degtyariov
Test case (see the comment above)
Attachment: bug30520.asp (application/octet-stream, text), 1.33 KiB.
[24 Oct 2007 17:36]
Bogdan Degtyariov
I have made the research related to behavior of Microsoft SQL 2005 and ADO application (VB6). Here are my findings: - Microsoft ODBC driver for SQL 2005 and MyODBC work IDENTICALLY with the test script I uploaded earlier. Some specific moments about SQLGetData was not clarified in MSDN, so we should make MyODBC to work similar to Microsoft ODBC driver - ADODB.CursorLocation = adUseClient affects both MS ODBC and MyODBC in the same way: they return the data every time ADODB.Recordset("test_text") is referenced - In case CursorLocation is not specified, both the drivers return values only for the first reference CONCLUSION: MyODBC and MS SQL ODBC drivers return SQL_SUCCESS_WITH_INFO every time SQLGetData is called with 0 buffer length. SQL_NO_DATA_FOUND is returned only when the previous call finished writing data in the buffer (returned SQL_SUCCESS) or there is an empty string result for the buffer with size bigger than 0. Patch for this bug must be rolled back in order to provide maximum compatibility with ADO and other Microsoft software.
[2 Nov 2007 21:50]
Jim Winstead
I am re-closing this bug. The originally-reported issue is fixed. That the fix caused a regression is call for opening a new bug, not re-opening this one and forcing people to make sense of the confusing history.