Bug #43921 SQL_DESC_AUTO_UNIQUE_VALUE invalid value returned
Submitted: 27 Mar 2009 18:39 Modified: 21 Dec 2012 8:16
Reporter: Farid Zidan (Candidate Quality Contributor) Email Updates:
Status: Won't fix Impact on me:
Category:Connector / ODBC Severity:S2 (Serious)
Version:3.51.27 (x64) OS:Microsoft Windows
Assigned to: Bogdan Degtyariov CPU Architecture:Any
Tags: qc

[27 Mar 2009 18:39] Farid Zidan
64-bit driver does not set correct 64-bit value for SQLColAttribute SQL_DESC_AUTO_UNIQUE_VALUE

How to repeat:
        SQLLEN nDescAutoUniqueValue = -1; // 64-bit integer

        rc = SQLColAttribute( hstmt,
                              &nDescAutoUniqueValue );

        if ( !RC_SUCCESS(rc) ) {

          // error;
        else if ( nDescAutoUniqueValue != SQL_FALSE &&
                  nDescAutoUniqueValue != SQL_TRUE ) {

Suggested fix:
Assign SQL_FALSE or SQL_TRUE to reference variable not just low 32-bit
[30 Mar 2009 17:28] Jess Balint
Where do you see that this should fill a 64-bit value?
[30 Mar 2009 17:52] Farid Zidan

Per function declaration of SQLColAttribute for _WIN64 where the last parameter datatype is pointer to SQLLEN (SQLLEN in _WIN64 is 64-bit):

SQLColAttribute (SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber,
    SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr, 
   SQLSMALLINT BufferLength, SQLSMALLINT * StringLengthPtr, 
   SQLLEN* NumericAttributePtr)

So the address of a 64-bit variable (which may or may not be properly initialized) is passed to the driver and I the driver needs to assign the requested value to the the passed variable as per the function declaration and not just lower byte, word or DWORD.
[30 Mar 2009 18:22] Jess Balint

As per documentation here:
(SQLSetDescField) http://msdn.microsoft.com/en-us/library/ms713560.aspx

SQL_DESC_AUTO_UNIQUE_VALUE has the type SQLINTEGER, which is not a 64-bit value.

And according to the SQLColAttribute documentation:

"SQLColAttribute returns information either in *NumericAttributePtr or in *CharacterAttributePtr. Integer information is returned in *NumericAttributePtr as a 32-bit, signed value; all other formats of information are returned in *CharacterAttributePtr. When information is returned in *NumericAttributePtr, the driver ignores CharacterAttributePtr, BufferLength, and StringLengthPtr. When information is returned in *CharacterAttributePtr, the driver ignores NumericAttributePtr."
[30 Mar 2009 19:25] Farid Zidan

Integer information is returned in *NumericAttributePtr as a
32-bit, signed value;

This MS doc needs to be updated to account for 64-bit drivers. Here is the updated MS doc for SQLColAttribute for 64-bit drivers:
"When the FieldIdentifier parameter has one of the following values, a 64-bit value is returned in *NumericAttribute:




SQL_DESC_AUTO_UNIQUE_VALUE is not listed as a 64-bit value because the returned value is either 0 or 1 and its value range has not changed. But the function prototype has changed from 32-bit pointer to 64-bit pointer.

As per my testing, all the following 64-bit drivers dereference the 64-bit passed pointer for SQLColAttribute SQL_DESC_AUTO_UNIQUE_VALUE:
MS SQL Server Native Client, Oracle ODBC driver, DB2 ODBC driver, Sybase SQL Anywhere 64-bit.
[31 Mar 2009 15:07] Jess Balint
Farid, I see no justification for this. Additional comments on that page include:

"Some of the descriptor fields that can be set through the various SQLSet and SQLGet functions have been changed to accommodate 64-bit values while others are still 32-bit values. Make sure that you use the appropriate sized variable when setting and retrieving these fields. Specifics of which descriptor fields have changed are listed under Function Declaration Changes."

Have you found documentation for one of the other drivers to verify that they will fill a 64-bit buffer for SQL_DESC_AUTO_UNIQUE_VALUE?
[31 Mar 2009 16:07] Farid Zidan

MS doc can be conflicting as we all know. It boils down to the function prototype. For 32-bit driver, the pointer is to 32-bit memory location, for 64-bit the pointer is to 64-bit memory location. Instead of hardcoding *(SQLINTEGER*)<var> = <result> the driver needs to do *(SQLLEN*)<var> = <result> which will work and has the same behavior of the function call for both 32-bit and 64-bit versions of the driver and client. So the client and the driver can use the same code base for both 32-bit and 64-bit versions and get the same behavior (please see my sample code at the start of this issue)

As per my testing all the other 64-bit ODBC drivers (except both MySQL 3.51.27 and 5.1.5) dereference the pointer being passed when setting the requested value. One justification is that the 64-bit memory location being passed may or may not be initialized by the client because the client is assuming the driver will deposit the requested into the 64-bit memory location being passed. 

Another justification is that if for 64-bit the driver will dereference only the low DWORD depending of the field, the client will have to, per field, cast an already good 64-bit memory location to 32-bit depending on the field being passed which will add unnecessary logic to the function call without any advantage to the driver or client.
[25 Aug 2010 10:41] Lawrenty Novitsky
As we fixed that in 5.1.7, I think that will be natural to deem this a bug and fix it in 3.51 as well
[21 Dec 2012 8:15] Hemant Dangi
Patch for correct data type for last parameter of SQLColAttribute, according to http://msdn.microsoft.com/en-us/library/ms716287(VS.85).aspx, has been pushed in rev#908 for BUG#55024. And issue is not there in 5.2.