Обсуждение: Bug report: x64 Row status Array uses wrong data type
Hi
Thank you for psq odbc driver!
I’ve found an issue with 64 bit driver.
The array returned from fetch for row statuses uses 16 bit values
instead of 64 bit values.
Tested on x64 Windows (7, 10, srv2012 and srv2016)
with 64 bit psqlodbc-09.06.0500 (Unicode and ANSI)
Client is set ODBC version 2
Changing SQLUSMALLINT to SQLSETPOSIROW in descriptor.h
for two structs and in the code handling these structs fixed the issue.
Code in psqlodbc-10.02.0000 is the same for these parts.
struct IRDFields_
{
StatementClass *stmt;
SQLULEN *rowsFetched;
-> SQLSETPOSIROW *rowStatusArray;
UInt4 nfields;
SQLSMALLINT allocated;
FIELD_INFO **fi;
};
struct IPDFields_
{
SQLULEN *param_processed_ptr;
-> SQLSETPOSIROW *param_status_ptr;
SQLSMALLINT allocated;
ParameterImplClass *parameters;
};
Below pseudo code reproduces the issue:
SQLUINTEGER rowsFetched=0;
SQLSETPOSIROW pRowStatus[1];
SQLRETURN retCode;
pRowStatus[0]=-1; // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &rowsFetched, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, pRowStatus, 0);
retCode=SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 1);
// pRowStatus
// after fetch 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
// exected to be 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Thank you,
Jari Siikarla
Hi
Thank you for psq odbc driver!
I’ve found an issue with 64 bit driver.
The array returned from fetch for row statuses uses 16 bit values
instead of 64 bit values.
Tested on x64 Windows (7, 10, srv2012 and srv2016)
with 64 bit psqlodbc-09.06.0500 (Unicode and ANSI)
Client is set ODBC version 2
Changing SQLUSMALLINT to SQLSETPOSIROW in descriptor.h
for two structs and in the code handling these structs fixed the issue.
Code in psqlodbc-10.02.0000 is the same for these parts.
Where can I find the description that SQL_ATTR_ROW_STATUS_PTR
(or SQL_ATTR_PARAM_STATUS_PTR) doesn't point to an array of
SQLUSMALLINT but SQLSETPOSIROW?
regards,
Hiroshi Inoue
struct IRDFields_
{
StatementClass *stmt;
SQLULEN *rowsFetched;
-> SQLSETPOSIROW *rowStatusArray;
UInt4 nfields;
SQLSMALLINT allocated;
FIELD_INFO **fi;
};
struct IPDFields_
{
SQLULEN *param_processed_ptr;
-> SQLSETPOSIROW *param_status_ptr;
SQLSMALLINT allocated;
ParameterImplClass *parameters;
};
Below pseudo code reproduces the issue:
SQLUINTEGER rowsFetched=0;
SQLSETPOSIROW pRowStatus[1];
SQLRETURN retCode;
pRowStatus[0]=-1; // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &rowsFetched, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, pRowStatus, 0);
retCode=SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 1);
// pRowStatus
// after fetch 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
// exected to be 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Thank you,
Jari Siikarla
Jari Siikarla wrote: > The array returned from fetch for row statuses uses 16 bit values > instead of 64 bit values. https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetstmtattr-function says: | SQL_ATTR_ROW_STATUS_PTR | An SQLUSMALLINT * value that points to an array of SQLUSMALLINT | values containing row status values after a call to SQLFetch or | SQLFetchScroll. > Client is set ODBC version 2 SQL_ATTR_ROW_STATUS_PTR was introduced in ODBC 3.0. Regards, Clemens
Hi Hiroshi
Hi Jari,
On 2018/05/11 18:33, Jari Siikarla wrote:
Hi
Thank you for psq odbc driver!
I’ve found an issue with 64 bit driver.
The array returned from fetch for row statuses uses 16 bit values
instead of 64 bit values.
Tested on x64 Windows (7, 10, srv2012 and srv2016)
with 64 bit psqlodbc-09.06.0500 (Unicode and ANSI)
Client is set ODBC version 2
Changing SQLUSMALLINT to SQLSETPOSIROW in descriptor.h
for two structs and in the code handling these structs fixed the issue.
Code in psqlodbc-10.02.0000 is the same for these parts.
Where can I find the description that SQL_ATTR_ROW_STATUS_PTR
(or SQL_ATTR_PARAM_STATUS_PTR) doesn't point to an array of
SQLUSMALLINT but SQLSETPOSIROW?
This is from observing workings of existing code. Not from ODBC specification.
Having a functionality on a platform with a provider really doesn’t mean that the functionality is by specks L
Oracle 11.1-12 64 bit ODBC driver on Windows returns 64 bit values for row statuses and 32 bit driver returns 16 bit values.
SQLSETPOSIROW follows this 16/64 bit definition nicely, so we used it in calling code when migrating the DB code to x64.
https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-64-bit-information?view=sql-server-2017
“ODBC 64-Bit Information”
“
SQLSetStmtAttr
When the Attribute parameter has one of the following values, a 64-bit value is passed in *ValuePtr:
…
SQL_ATTR_ROW_STATUS_PTR
…
”
We hit a related bug in Oracle 11.2 ODBC 32 bit driver on x64 windows. (This has been fixed):
https://support.oracle.com/knowledge/Oracle%20Database%20Products/1472987_1.html
“ODBC Row Status Array (SQL_ATTR_ROW_STATUS_PTR) Populated As SQLUINTEGER Rather Than SQLUSMALLINT”
“
This issue reproduces with all versions of the Oracle ODBC driver since 11.1.0.6. It is a 32-bit-only problem;
in 64-bit mode the status values are 64-bit and this has been correctly implemented
(the bug being due most likely to a simple oversight and some inconsistency between 32-bit and 64-bit Windows:
if a value is 64 bits in 64-bit mode then it would be expected to be 32 bits in 32-bit mode, but in fact it is 16 bits in 32-bit mode).
“
I’m adding the support for PG alongside Oracle and this disparity is causing some head scratching.
I hope I don’t have to resort to if (((char*) pRowStatus)[2])
Thank you,
Jari Siikarla
struct IRDFields_
{
StatementClass *stmt;
SQLULEN *rowsFetched;
-> SQLSETPOSIROW *rowStatusArray;
UInt4 nfields;
SQLSMALLINT allocated;
FIELD_INFO **fi;
};
struct IPDFields_
{
SQLULEN *param_processed_ptr;
-> SQLSETPOSIROW *param_status_ptr;
SQLSMALLINT allocated;
ParameterImplClass *parameters;
};
Below pseudo code reproduces the issue:
SQLUINTEGER rowsFetched=0;
SQLSETPOSIROW pRowStatus[1];
SQLRETURN retCode;
pRowStatus[0]=-1; // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &rowsFetched, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, pRowStatus, 0);
retCode=SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 1);
// pRowStatus
// after fetch 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
// exected to be 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Thank you,
Jari Siikarla
Jari Siikarla wrote: > https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-64-bit-information > “ > SQLSetStmtAttr > When the Attribute parameter has one of the following values, a 64-bit value is passed in *ValuePtr: > … > SQL_ATTR_ROW_STATUS_PTR > … > ” This is a typo on that web page, "*ValuePtr" should be "ValuePtr". (Most of these SQL_ATTR_xxx attribute values are not pointers, so it does not make sense to dereference ValuePtr.) Only the _pointer_ to the row status array is 64 bits. > https://support.oracle.com/knowledge/Oracle%20Database%20Products/1472987_1.html > “ > in 64-bit mode the status values are 64-bit Of the two possible interpretations of Microsoft's statement, Oracle chose the wrong one. Regards, Clemens
Hi Hiroshi
Hi Jari,
On 2018/05/11 18:33, Jari Siikarla wrote:
Hi
Thank you for psq odbc driver!
I’ve found an issue with 64 bit driver.
The array returned from fetch for row statuses uses 16 bit values
instead of 64 bit values.
Tested on x64 Windows (7, 10, srv2012 and srv2016)
with 64 bit psqlodbc-09.06.0500 (Unicode and ANSI)
Client is set ODBC version 2
Changing SQLUSMALLINT to SQLSETPOSIROW in descriptor.h
for two structs and in the code handling these structs fixed the issue.
Code in psqlodbc-10.02.0000 is the same for these parts.
Where can I find the description that SQL_ATTR_ROW_STATUS_PTR
(or SQL_ATTR_PARAM_STATUS_PTR) doesn't point to an array of
SQLUSMALLINT but SQLSETPOSIROW?
This is from observing workings of existing code. Not from ODBC specification.
Having a functionality on a platform with a provider really doesn’t mean that the functionality is by specks L
Oracle 11.1-12 64 bit ODBC driver on Windows returns 64 bit values for row statuses and 32 bit driver returns 16 bit values.
If it's true, it seems a bug to me.
regards,
Hiroshi Inoue
SQLSETPOSIROW follows this 16/64 bit definition nicely, so we used it in calling code when migrating the DB code to x64.
https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-64-bit-information?view=sql-server-2017
“ODBC 64-Bit Information”
“
SQLSetStmtAttr
When the Attribute parameter has one of the following values, a 64-bit value is passed in *ValuePtr:
…
SQL_ATTR_ROW_STATUS_PTR
…
”
We hit a related bug in Oracle 11.2 ODBC 32 bit driver on x64 windows. (This has been fixed):
https://support.oracle.com/knowledge/Oracle%20Database%20Products/1472987_1.html
“ODBC Row Status Array (SQL_ATTR_ROW_STATUS_PTR) Populated As SQLUINTEGER Rather Than SQLUSMALLINT”
“
This issue reproduces with all versions of the Oracle ODBC driver since 11.1.0.6. It is a 32-bit-only problem;
in 64-bit mode the status values are 64-bit and this has been correctly implemented
(the bug being due most likely to a simple oversight and some inconsistency between 32-bit and 64-bit Windows:
if a value is 64 bits in 64-bit mode then it would be expected to be 32 bits in 32-bit mode, but in fact it is 16 bits in 32-bit mode).
“
I’m adding the support for PG alongside Oracle and this disparity is causing some head scratching.
I hope I don’t have to resort to if (((char*) pRowStatus)[2])
Thank you,
Jari Siikarla
struct IRDFields_
{
StatementClass *stmt;
SQLULEN *rowsFetched;
-> SQLSETPOSIROW *rowStatusArray;
UInt4 nfields;
SQLSMALLINT allocated;
FIELD_INFO **fi;
};
struct IPDFields_
{
SQLULEN *param_processed_ptr;
-> SQLSETPOSIROW *param_status_ptr;
SQLSMALLINT allocated;
ParameterImplClass *parameters;
};
Below pseudo code reproduces the issue:
SQLUINTEGER rowsFetched=0;
SQLSETPOSIROW pRowStatus[1];
SQLRETURN retCode;
pRowStatus[0]=-1; // 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &rowsFetched, 0);
retCode=SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, pRowStatus, 0);
retCode=SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 1);
// pRowStatus
// after fetch 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
// exected to be 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Thank you,
Jari Siikarla
I consider this closed as “bug in implementation by Oracle”.
Thank you Clemens and Hiroshi for your time and effort!
Jari Siikarla