Cursors WITH HOLD

Informix®

Informix closes opened cursors automatically when a transaction ends, unless the WITH HOLD option is used in the DECLARE instruction:
DECLARE c1 CURSOR WITH HOLD FOR SELECT ...
OPEN c1
BEGIN WORK
FETCH c1 ...
COMMIT WORK
FETCH c1 ...
CLOSE c1

PostgreSQL

With PostgreSQL, opened cursors using SELECT statements without a FOR UPDATE clause are not closed when a transaction ends. All PostgreSQL cursors are WITH HOLD cursors, unless the FOR UPDATE clause issued in the SELECT statement.
Note: Native PostgreSQL WITH HOLD cursors are automatically closed, if the cursor is opened inside a transaction block, and the transaction is canceled with a rollback.
BDL WITH HOLD cursors declared with a SELECT ... FOR UPDATE cannot be supported with PostgreSQL: Native holdable cursors declared for update produce the following SQL error:
DECLARE CURSOR WITH HOLD ... FOR UPDATE is not supported
DETAIL:  Holdable cursors must be READ ONLY.

Solution

For consistency with other database brands, database cursors that are not declared WITH HOLD are automatically closed, when a COMMIT WORK or ROLLBACK WORK is performed.

Important: Opening a WITH HOLD cursor declared with a SELECT FOR UPDATE results in an SQL error; in the same conditions, this does not normally appear with Informix. Review the program logic in order to find another way to set locks.
Cursors declared WITH HOLD and using a SELECT without the FOR UPDATE clause can be used, as long as the cursor is opened outside a transaction block.
Important: Since PostgreSQL automatically closes all WITH HOLD cursors opened in a transaction which is canceled by a rollback, do not open such cursor after a BEGIN WORK, that can potentially be terminated by a ROLLBACK WORK.
The following code can be used with PostgreSQL:
MAIN
    DEFINE rec RECORD
               pkey INT,
               name VARCHAR(50)
           END RECORD

    CONNECT TO "test1+driver='dbmpgs'" USER "pgsuser" USING "fourjs"

    WHENEVER ERROR CONTINUE
    DROP TABLE tab1
    WHENEVER ERROR STOP
    CREATE TABLE tab1 ( pkey INT, name VARCHAR(50) )
    FOR rec.pkey=1 TO 10
        LET rec.name = SFMT("Item %1", rec.pkey)
        INSERT INTO tab1 VALUES ( rec.pkey, rec.name )
    END FOR

    DECLARE c1 CURSOR WITH HOLD FOR SELECT * FROM tab1 ORDER BY pkey

    OPEN c1 -- Outside TX block!
    FETCH c1 INTO rec.*     DISPLAY rec.*
    BEGIN WORK
    FETCH c1 INTO rec.*     DISPLAY rec.*
    ROLLBACK WORK
    BEGIN WORK
    FETCH c1 INTO rec.*     DISPLAY rec.*
    COMMIT WORK
    FETCH c1 INTO rec.*     DISPLAY rec.*
    BEGIN WORK
    FETCH c1 INTO rec.*     DISPLAY rec.*
    ROLLBACK WORK
    FETCH c1 INTO rec.*     DISPLAY rec.*
    CLOSE c1

    FOREACH c1 INTO rec.*
        BEGIN WORK
        DISPLAY rec.* -- Do some real SQL here...
        IF rec.pkey MOD 2 == 0 THEN
            COMMIT WORK
        ELSE
            ROLLBACK WORK
        END IF
    END FOREACH

END MAIN

Since PostgreSQL automatically closes FOR UPDATE cursors when the transaction ends, opening cursors declared FOR UPDATE and the WITH HOLD option results in an SQL error that does not normally appear with Informix under the same conditions.

Review the program logic in order to find another way to set locks.