Search code examples
databaseclassopenedgeprogress-4glundo

UNDO statement releases available buffer within class instance


I've added the test codes down below.

TestClass has BUFFER variable inside itself which is available after the execution of it's CONSTRUCTOR. Everything works fine until the code executes any UNDO or (UNDO, THROW...). After this the class instance is otherwise intact, except that the BUFFER variable is now NOT AVAILABLE.

Is there any way to prevent Progress from doing this RELEASE?

In the below test codes, the second iValue = oTestClass:Value. will throw error because the BUFFER is UNAVAILABLE.

I'm using Progress 11.7.5.

test.p:

DEF VAR oTestClass AS CLASS TestClass NO-UNDO.
DEF VAR iValue     AS INT NO-UNDO.

DO TRANSACTION:
    oTestClass = TestService:Singleton:Find().
    iValue= oTestClass:Value.
    UNDO.
END.

DO TRANSACTION:
    oTestClass = TestService:Singleton:Find().
    iValue = oTestClass:Value.
    UNDO.
END.

TestClassService.cls:

BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS TestService:
    
    DEF PUBLIC STATIC PROPERTY Singleton AS CLASS TestService NO-UNDO
        GET:
            IF TestService:Singleton = ? THEN TestService:Singleton = NEW TestService().
            RETURN TestService:Singleton.
        END.
        PROTECTED SET.
    
    DEF PRIVATE VAR oTestClass AS CLASS TestClass NO-UNDO.
    
    CONSTRUCTOR PROTECTED TestService(): END.
    
    METHOD PUBLIC CLASS TestClass Find():
        IF oTestClass = ? THEN DO:
            oTestClass = NEW TestClass(TO-ROWID("0x000000000017c201")).
        END.
        RETURN oTestClass.
    END.
END.

TestClass.cls:

BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS TestClass:
    DEF PRIVATE BUFFER MyTable_This FOR MyTable.
    DEF PUBLIC PROPERTY Value AS INT NO-UNDO
        GET:
            RETURN MyTable_This.Value.
        END.
    
    CONSTRUCTOR PUBLIC TestClass(i_rROWID AS ROWID):
        FIND FIRST MyTable_This WHERE ROWID(MyTable_This) = i_rROWID NO-LOCK.
    END.
END.

Solution

  • You can execute your example on ABL Dojo.

    Since a database table is not no-undo, any undo statement will undo anything done with it, including the find that brought the buffer into scope.

    A buffer on a no-undo temp-table does not have this "problem".