Question

I've got a customer ODBC application that sanity-checks the rows affected after most operations. All of a sudden, those checks are failing. In this case, after an Insert the rows affected is expected to be 1. After reviewing logs, that value is coming back unknown (-1).

Does anyone have any idea why the behavior would change?

Additional information:

  • Application is running on a Windows server
  • The database is Oracle.
  • The driver is the Microsoft Oracle Driver
  • The customer states that no upgrades to the database or drivers has happened recently.
  • The customer claims the problem started after the changed/deleted a couple of rows in the table.

Additional details:

The driver is the "Microsoft ODBC for Oracle", version is 2.576.3959.00, file name is MSORCL32.dll, date is 2/17/2007. The Oracle database level is 10.2.

Any ideas?

Here is the ODBC log I had them capture:

dpxag35         a5c-cac   ENTER SQLExecDirect 
      HSTMT               015A2270
      UCHAR *             0x00177D9C [     364] "begin \  a <single simple insert statement here>; \ aend;"
      SDWORD                   364

dpxag35         a5c-cac   EXIT  SQLExecDirect  with return code 0 (SQL_SUCCESS)
      HSTMT               015A2270
      UCHAR *             0x00177D9C [     364] "begin \  a <single simple insert statement here>; \ aend;"
      SDWORD                   364

dpxag35         a5c-cac   ENTER SQLNumResultCols 
      HSTMT               015A2270
      SWORD *             0x0012F9B0

dpxag35         a5c-cac   EXIT  SQLNumResultCols  with return code 0 (SQL_SUCCESS)
      HSTMT               015A2270
      SWORD *             0x0012F9B0 (0)

dpxag35         a5c-cac   ENTER SQLRowCount 
      HSTMT               015A2270
      SQLLEN *            0x00163B88

dpxag35         a5c-cac   EXIT  SQLRowCount  with return code 0 (SQL_SUCCESS)
      HSTMT               015A2270
      SQLLEN *            0x00163B88 (-1)

dpxag35         a5c-cac   ENTER SQLFreeStmt 
      HSTMT               015A2270
      UWORD                        0 <SQL_CLOSE>

dpxag35         a5c-cac   EXIT  SQLFreeStmt  with return code 0 (SQL_SUCCESS)
      HSTMT               015A2270
      UWORD                        0 <SQL_CLOSE>

For reference, this is from the ODBC docos on the MSDN:

RowCountPtr [Output] Points to a buffer in which to return a row count. For UPDATE, INSERT, and DELETE statements, for the SQL_ADD, SQL_UPDATE_BY_BOOKMARK, and SQL_DELETE_BY_BOOKMARK operations in SQLBulkOperations, and for the SQL_UPDATE or SQL_DELETE operations in SQLSetPos, the value returned in *RowCountPtr is either the number of rows affected by the request or –1 if the number of affected rows is not available. When SQLExecute, SQLExecDirect, SQLBulkOperations, SQLSetPos, or SQLMoreResults is called, the SQL_DIAG_ROW_COUNT field of the diagnostic data structure is set to the row count, and the row count is cached in an implementation-dependent way. SQLRowCount returns the cached row count value. The cached row count value is valid until the statement handle is set back to the prepared or allocated state, the statement is reexecuted, or SQLCloseCursor is called. Note that if a function has been called since the SQL_DIAG_ROW_COUNT field was set, the value returned by SQLRowCount might be different from the value in the SQL_DIAG_ROW_COUNT field because the SQL_DIAG_ROW_COUNT field is reset to 0 by any function call. For other statements and functions, the driver may define the value returned in *RowCountPtr. For example, some data sources may be able to return the number of rows returned by a SELECT statement or a catalog function before fetching the rows. Note Many data sources cannot return the number of rows in a result set before fetching them; for maximum interoperability, applications should not rely on this behavior.

And at the very end of the doco page, we get this:

If the last SQL statement executed on the statement handle was not an UPDATE, INSERT, or DELETE statement or if the Operation argument in the previous call to SQLBulkOperations was not SQL_ADD, SQL_UPDATE_BY_BOOKMARK, or SQL_DELETE_BY_BOOKMARK, or if the Operation argument in the previous call to SQLSetPos was not SQL_UPDATE or SQL_DELETE, the value of *RowCountPtr is driver-defined. For more information, see Determining the Number of Affected Rows.

I guess it is plauable that because it was wrapped in a batch, it is yielding unknown.

But I cannot get past that this app has been running for two years and never had this problem. The customer states they changed / deleted some table data and then the app failed. I find it unlikely, experience tells me they did something else and aren't saying what.

Was it helpful?

Solution

As described in MSDN documentation, behavior of SQLRowCount after execution of batch operation (I suppose it's to be a batch, because it enclosed in begin ... end; ) is driver-defined, it's a good reason to check ODBC driver version.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top