In non-SQL CLR environments, such as z/OS DB2, you can typically chain transactions from the calling application through SQL activity in a COBOL stored procedure. For example, consider the following sequence executed from a COBOL client application:
EXEC SQL Insert 1 END-EXEC EXEC SQL Call COBOL stored procedure A END-EXEC EXEC SQL Insert 2 END-EXEC Cobol call to COBOL routine B EXEC SQL Commit END-EXEC EXEC SQL Insert 3 END-EXEC EXEC SQL Rollback END-EXEC EXEC SQL Insert 4 END-EXEC EXEC SQL Insert 5 END-EXEC EXEC SQL Commit END-EXEC
The DBMS typically inserts records 1, 2, 4, and 5.
With SQL Server using SQL CLR, SQL Server forms a nested rather than a chained transaction when an application calls a stored procedure flow of any kind. The outermost transaction of this nested transaction ultimately determines whether to commit or roll back the work of all the transactions contained therein, regardless of what those transactions did. In the above example, because the COBOL client application starts the nested transaction and ends it with a COMMIT, all five records are inserted; if the COBOL client application ends with a ROLLBACK instead, as is often the case, none of the five records are inserted.
This behavior is not acceptable if you want your migrated SQL Server application to mimic serial transaction chaining.
Although OpenESQL cannot always commit or roll back chained transactions precisely like z/OS DB2, it does provide the SQLCLRTRANS compiler directive option to address this issue. SQLCLRTRANS emulates the z/OS DB2 behavior, and uses a specific SQL Server save point named MF__SAVEPOINT.
In this solution, when you compile your COBOL code using the SQLCLRTRANS compiler directive option, OpenESQL automatically makes the following code adjustments:
ON ENTRY1 | EXEC SQL COMMIT | EXEC SQL ROLLBACK | ON EXIT2 | |
---|---|---|---|---|
Client application (COBOL only) |
start transaction set savepoint, MF_SAVEPOINT |
commit set savepoint, MF_SAVEPOINT |
roll back set savepoint, MF_SAVEPOINT |
roll back disconnect |
Lead (called) stored procedure |
reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT |
||
Nested stored procedures |
reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT |
||
1 Or, the connection is opened by the client application | ||||
2 Return, or the connection is closed by the client application |
However, if you routinely compile your applications using the AUTOCOMMIT directive, or if explicitly turn autocommit on in your COBOL application, consider the following:
After you have made necessary code adjustments, if required, compile your COBOL application and all COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option.
For non-COBOL applications that call stored procedures, make the following checks/changes to your calling application code before compiling it:
Compile all non-COBOL calling applications as required. Then, compile all COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option.
EXEC SQL Call COBOL stored procedure A END-EXEC EXEC SQL Insert 1 END-EXEC EXEC SQL CALL COBOL stored procedure B END-EXEC EXEC SQL Commit END-EXEC EXEC SQL Insert 2 END-EXEC EXEC SQL Rollback END-EXEC EXEC SQL Insert 3 END-EXEC EXEC SQL Commit END-EXEC
Also consider that this solution is best suited for applications for which concurrency to SQL Server data is important, as is retaining nested stored procedures rather than converting them to COBOL routines.
In this solution, when you compile your COBOL code using the SQLCLRTRANS compiler directive option and optionally the SPCOMMITONRETURN directive as well, OpenESQL automatically makes the following code adjustments:
ON ENTRY | EXEC SQL COMMIT | EXEC SQL ROLLBACK | ON EXIT (return) | |
---|---|---|---|---|
Lead (called) Stored Procedure |
start transaction set savepoint, MF_SAVEPOINT |
commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT Or commit1 |
Nested Stored Procedures |
reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT |
||
Called COBOL Routines |
commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT commit reset MF_SAVEPOINT |
||
1 If you specified SQL(SPCOMMITONRETURN) when compiling, the commit is executed when the stored procedure returns to the calling program. If you did not specify SQL(SPCOMMITONRETURN), a rollback is performed to the last save point set by OpenESQL. |
After you have made all necessary code adjustments, compile your COBOL application and all COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option, and optionally also with the SPCOMMITONRETURN directive.
In this solution, non-COBOL applications that call SQL CLR COBOL stored procedures must be in autocommit mode before issuing the call to a SQL CLR COBOL stored procedure. You can do this by inserting the following TSQL statement before the call:
SET IMPLICIT_TRANSACTIONS ON
To optionally turn off autocommit mode after issuing the call, insert the following TSQL statement:
SET IMPLICIT_TRANSACTIONS OFF
If your code issues multiple calls to SQL CLR COBOL stored procedures, be sure that autocommit mode is turned on before each call is issued.
After you have made all necessary code adjustments, compile your application and also compile all COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option, and optionally also with the SPCOMMITONRETURN directive.
EXEC SQL Call COBOL stored procedure A END-EXEC EXEC SQL Insert 1 END-EXEC CALL COBOL routine B END-EXEC EXEC SQL Commit END-EXEC EXEC SQL Insert 2 END-EXEC EXEC SQL Rollback END-EXEC EXEC SQL Insert 3 END-EXEC EXEC SQL Commit END-EXEC
Also consider that this solution is best suited for applications for which concurrency to SQL Server data is most important, and your lead COBOL stored procedure can manage all serial transaction chaining for your application.
In this solution, when you compile your COBOL code using the SQLCLRTRANS compiler directive option and optionally the SPCOMMITONRETURN directive as well, OpenESQL automatically makes the following code adjustments:
ON ENTRY | EXEC SQL COMMIT | EXEC SQL ROLLBACK | ON EXIT (return) | |
---|---|---|---|---|
Lead (called) Stored Procedure |
start transaction set savepoint, MF_SAVEPOINT |
commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT Or commit1 |
Nested Stored Procedures |
reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT |
||
Called COBOL Routines |
commit reset MF_SAVEPOINT |
roll back to MF_SAVEPOINT commit reset MF_SAVEPOINT |
||
1 If you specified SQL(SPCOMMITONRETURN) when compiling, the commit is executed when the stored procedure returns to the calling program. If you did not specify SQL(SPCOMMITONRETURN), a rollback is performed to the last save point set by OpenESQL. |
After you have made all necessary code adjustments, compile your COBOL application and all COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option, and optionally also with the SPCOMMITONRETURN directive, which automatically commits the work done by a stored procedure when it returns to the calling application. If SPCOMMITONRETURN is not specified, OpenESQL rolls back to the last commit done on behalf of the stored procedure.
SET IMPLICIT_TRANSACTIONS ON
To optionally turn off autocommit mode after issuing a call, insert the following TSQL statement:
SET IMPLICIT_TRANSACTIONS OFF
If your code issues multiple calls to SQL CLR COBOL stored procedures, be sure that autocommit mode is turned on before each call is issued.
After you have made all necessary code adjustments, compile all of your COBOL stored procedure code with the OpenESQL SQLCLRTRANS compiler directive option, and optionally also with the SPCOMMITONRETURN directive. SPCOMMITONRETURN automatically commits the work done by a stored procedure when it returns to the calling application. If SPCOMMITONRETURN is not specified, OpenESQL rolls back to the last commit done on behalf of the stored procedure.
You can also optionally use the HCOSS SPCALLLOCAL directive, which takes an EXEC SQL CALL stored procedure A statement and converts it to a standard COBOL CALL A. This can help to ease the transition to Solution 3.