Transaction handling in PsqlODBC does not work

From: Zoltan Boszormenyi <zboszor(at)dunaweb(dot)hu>
To: pgsql-odbc(at)postgresql(dot)org
Subject: Transaction handling in PsqlODBC does not work
Date: 2005-05-19 23:28:11
Message-ID: 428D210B.7090508@dunaweb.hu
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-odbc

Hi,

I am experimenting with transactions using SELECT FOR UPDATE.

I created and populated a table:

CREATE mytable1 (id serial primary key, t varchar(10));
INSERT INTO mytable1 (t) values ('A');
INSERT INTO mytable1 (t) values ('B');
INSERT INTO mytable1 (t) values ('C');
INSERT INTO mytable1 (t) values ('D');

From two psql sessions, I can do

BEGIN WORK;
SELECT t FROM mytable1 WHERE id=2 FOR UPDATE;
ROLLBACK;

The second session correctly block on the SELECT FROM
statement until I issue a ROLLBACK or COMMIT in the
first session but I can also abort the statement
by pressing Ctrl-C in the second psql session.

I thought I try to do the same in ODBC using SQLCancel().

It would be useful e.g. to display a "please wait" dialog
before executing a SELECT FOR UPDATE and immediately closing it
when the statement executed normally but allow the user
to abort the operation when it blocks, e.g. when another user
is just modifying the same record and be able to return to
the previous state.

My test program doesn't work the way I expect although
it behaves the same with both built-in PostgreSQL drivers in
unixODBC and with the official 8.00.0101 psqlodbc.so.
At least it's consistent. :-)

The server is PostgreSQL-8.0.3 on FC3/AMD64.

I attached my program, someone may enlighten my why it doesn't work.
It may also be a bug in my program.

The program has three mandatory options: DSN, userid and password
and an optional fourth, a string that may contain these letters:
B = issue BEGIN WORK before the SELECT FOR UPDATE
R = issue ROLLBACK after the SELECT FOR UPDATE
O = issue ROLLBACK using SQLEndTran(), overrides R
C = try to cancel the second (blocked) connection
A = execute SELECTs asynchronously

The program works like this:

Allocate two ODBC environment handles and two connection handles
for both environments. Both connection is set to use ODBC 3.0+
functions and autocommit disabled. The three threads are created,
their start time is separated by 2 seconds. The first two thread
try to do the same sequence as above:

BEGIN WORK; (optional, option B)
SELECT t FROM mytable1 WHERE id=2 FOR UPDATE;
ROLLBACK; (optional, option R or O)

The third thread tries to abort the SELECT FOR UPDATE in the
second (blocked) thread using SQLCancel(). The long running time
(the blocked state) of the second thread ensures that global
variable hStmt2 is valid.

When the threads finish, the program cleans up. Problem is,
it finishes only when there is no transaction.

Bug #1:

Despite I set SQL_AUTOCOMMIT_OFF on both connection,
the SELECT FOR UPDATE doesn't block on my second connection,
e.g. the ODBC driver doesn't issue BEGIN WORK before executing
a statement outside of a transaction. I had the impression
it's implicitely included. It isn't the case. And it seems
neither SQLTransact() nor SQLEndTran() issues "BEGIN WORK",
only the COMMIT or ROLLBACK they were instructed.
So the letter B is required. With letter B given on the commandline,
my second connection blocks correctly on SELECT FOR UPDATE.

Bug #2:

With letters B and C given, SQLCancel() blocks in another thread
for the second connection, regardless of the presence or lack of
option 'A', e.g. both in sync or async mode.

Bug #3:

With letters B and R given, the first connection blocks in
SQLAllocHandle() that should allocate the statement handle
for the manual ROLLBACK.

Bug #4:

With letters B and O given, the first connection blocks in
SQLEndTran().

Bug #3 and #4 happens with either given or omitted 'C' option,
i.e. with or without SQLCancel() and with or without 'A', sync
or async mode.

It must be a problem in my program, I don't believe noone
uses transactions from ODBC on PostgreSQL servers.

BTW anyone can lookup page 303 in the ODBC 3.5 Developer's
Guide, where is says that ODBC API funtions should be executed
asynchronously only on single-threaded OSs, on multi-threaded
OSs ODBC API functions should be called in separate threads,
which I just did. For me, it means I don't have to set
statement attribute SQL_ASYNC_ENABLE to SQL_ASYNC_ENABLE_ON.

Best regards,
Zoltán Böszörményi

Attachment Content-Type Size
test-sqlcancel.c text/x-csrc 8.2 KB

Browse pgsql-odbc by date

  From Date Subject
Next Message Raul Carolus 2005-05-20 14:59:14 Note about ODBC drivers on a Windows Terminal Server Environment
Previous Message Jeff Eckermann 2005-05-18 20:10:28 Re: My MS-Access problem keeps getting weirder and