You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SQL_ATTR_KEYSET_SIZE overwrites the rowset size; SQLGetDescField on an unprepared IRD answers HY091 instead of HY007 #307
Two small deviations noticed while working on block cursors (#303, #304, #305). Both verified on Windows x64 against master 35fae3e (+ #303), Firebird 5.0.3, Microsoft driver manager; the code involved is platform-independent.
1. SQL_ATTR_KEYSET_SIZE overwrites the rowset size
OdbcStatement::sqlSetStmtAttr handles SQL_ATTR_KEYSET_SIZE in the same case as the ODBC 2 SQL_ROWSET_SIZE and stores it in the ARD's array size:
SQL_ROWSET_SIZE (9) is the ODBC 2 name of the row array size, so that half is right. SQL_ATTR_KEYSET_SIZE (8) is a different attribute: the number of rows in the keyset of a keyset-driven cursor. An application that sets it (ODBC 2 applications and generic layers do, typically with values such as 100 or more) silently gets a rowset of that size, and the next SQLFetch writes that many rows into buffers bound for one row, with no rows-fetched counter or status array to warn it. That is a buffer overrun in the application's memory.
Expected: SQL_ATTR_KEYSET_SIZE does not touch SQL_ATTR_ROW_ARRAY_SIZE. A driver without keyset-driven cursors can store the value and return it from SQLGetStmtAttr (or answer 01S02 with the value it substituted); the getter case follows the shape of #304.
2. SQLGetDescField on an unprepared IRD answers HY091
OdbcDesc::sqlGetDescField starts with
if ( bDefined == false )
return sqlReturn (SQL_ERROR, "HY091", "Invalid descriptor field identifier");
and for the IRD bDefined stays false until the statement is prepared. So before SQLPrepare every IRD field reads back as "invalid field identifier", including the header fields the application itself just set through SQLSetStmtAttr:
before SQLPrepare:
SQLGetDescField(IRD, SQL_DESC_ROWS_PROCESSED_PTR) -> SQL_ERROR, HY091
SQLGetDescField(IRD, SQL_DESC_ARRAY_STATUS_PTR) -> SQL_ERROR, HY091
after SQLPrepare:
both return the pointers that were set
The SQLSTATE for that state is HY007 "Associated statement is not prepared" (the field identifiers are valid). Returning the header fields regardless of the prepared state would be friendlier still, since they do not depend on the result set; SQL_DESC_COUNT and the record fields are the ones that need a prepared statement.
Activity