Hi there,
I've run into an issue, and wondering whether anyone out there has tackled this before/any ideas?
- I am writing an app in C++ using the ODBC/CLI on solaris.
- I have a database connection that is using autocommit.
- I have a number of statements/cursors on the connection.
- Updates/Deletes occur on the cursors as per the positioned method (WHERE CURRENT OF)
- There is no natural commit point/synchronization (hence the autocommit)
- The app is dynamic in nature and can query a lot of tables in a lot of different ways (using select/where clauses etc)
- A number of cursors will be active at any given time
- There is no order to cursor usage (either which tables, or selects or updates)
- For performance reasons, I use SQLPrepare and cache the cursor, reusing it where possible.
- For scalability, I retire old cursors that aren't in use and not used very much every so often.
I have run into a problem. When closing a cursor (SQLCloseCursor) in autocommit mode, it causes all cursors to become unpositioned. If I then want to perform an "UPDATE ... WHERE CURRENT OF ..." on one of the cursors, I get the error "SQL0508N The cursor specificed in the UPDATE or DELETE statement is not positioned on a row. SQLSTATE=24504"
The SQLCloseCursor caused the commit, which caused all cursors to become unpositioned.
Is it possible to reposition/refresh the cursor so a positioned UPDATE can occur? I am using solaris and use the following statement settings (below). I have to use a forward only cursor, as the true dynamic cursor is only available on AIX (unfortunate that), which means I cant use SQLSetPos.
[cursor settings]
SQL_ATTR_CONCURRENCY=SQL_CONCUR_LOCK
SQL_ATTR_CURSOR_SCROLLABLE=SQL_SCROLLABLE
SQL_ATTR_CURSOR_TYPE=SQL_CURSOR_FORWARD_ONLY
Documentation refers to the use of SQLFetch(), but this reads in the next row, and it is no longer possible to perform the UPDATE on the previous row.
I could detect a SQL0508N error and reissue the SQLExecute(), followed by n SQLFetch() operations, but...
- this is costly (especially as it could happen many times)
- reissuing SQLExecute means that the result set may have changed (read consistency)
- this is manual, and error prone (ie previous result set was 5, now its 6 because a record had been inserted by another app)
PATCH1=4096 (
DB2 Database for Linux, UNIX, and Windows) allows the CLI to not send the COMMIT during the SQLFreeStmt() call, but I dont think this buys me anything as I have no idea when I'm safe to issue a commit otherwise.
Any help or thoughts would be much appreciated?
rgds,
Jason
------------
[OS = Solaris 10 Update 5]
> db2level
DB21085I Instance "dbdevar1" uses "64" bits and DB2 code release "SQL09015"
with level identifier "01060107".
Informational tokens are "DB2 v9.1.0.5", "s080512", "U815923", and Fix Pack
"5".
Product is installed at "/opt/IBM/db2/V9.1".
> db2licm -l
Product name: "DB2 Workgroup Server Edition"
License type: "CPU"
Expiry date: "Permanent"
Product identifier: "db2wse"
Version information: "9.1"
Max number of CPUs: "4"
Max amount of memory (GB): "16"
Annotation: "3;(_c)"
Features:
DB2 Performance Optimization WSE: "Not licensed"
DB2 High Availability WSE: "Not licensed"
DB2 Workload Management WSE: "Not licensed"
DB2 pureXML WSE: "Not licensed"
IBM Homogeneous Federation WSE: "Not licensed"