Repository navigation
EXEC SQL COMMIT / ROLLBACK / SAVEPOINT: a real Db2 unit of work in batch det ports (Part of #4269) - #4729
Merged
Conversation
…orts (Part of #4269) A batch step is one Db2 unit of work, as Db2 for z/OS runs a DSN / CAF program: committed at its normal end, backed out by an abend. EXEC SQL COMMIT / ROLLBACK [WORK] end it in between (DetSql.commit / rollback over the runner's DetSql.unitOfWork); COMMIT closes cursors not declared WITH HOLD, ROLLBACK every cursor -- on both sides (ggsql.c closes the CLI handles itself; the precompiler marks a held cursor's OPEN). ggabend.c backs the unit out before an abend exits; the Java harness runs a Db2 batch step in one transaction and gives DetSql its connection; Db2 tables are compared after a matching abend. ROLLBACK TO SAVEPOINT and a CICS program's ROLLBACK (-926 on z/OS) are refused by name. The det translator also finds a hyphenated program's generated Db2 methods (NEND-DAY): the census's other SQL gap in the same programs. Proven end to end on Db2 with a synthetic, hand-traced estate (tests/equivalence/db2/uow; EQUIVALENCE_E2E=1): no burned program issues ROLLBACK. Register Q3 MATCHED for batch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
Contributor
…it of work (Part of #4269) The census's last gap in NINT-CALC. Each runs as written on the unit of work's connection on both sides (DetSql.savepoint; the precompiler makes it an EXEC), so Db2 answers it (-880 for a savepoint that does not exist or was released). Refused with a host variable, or in a CICS program. Oracle quirks measured and neutralised: IBM's CLI runs `ROLLBACK WORK TO SAVEPOINT x` as a ROLLBACK of the whole unit (answering 0 where Db2 answers -880), so the precompiler drops the noise word WORK; CLI's row count -1 for a statement with none no longer reaches SQLERRD(3). UOWDEMO gains a hand-traced savepoint section; register Q3 updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
squid-protocol
marked this pull request as ready for review
October 9, 2026 00:48
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4269.
Slice chosen by demand
Census (
cics_census.py blockers --baseline --all-programs, origin/main d3b7440, 179 programs over burned + non-burned corpora): of all #4269 forms, only ROLLBACK reaches a translatable program -- WHENEVER, dynamic SQL, CALL, CONNECT, rowset FETCH: 0 programs; SCROLL: 1 (GenApp, not a gap). The only EXEC SQL gaps wereROLLBACK: the generated repositories commit each statement(3 programs, 2 one gap-class from whole) andno generated Db2 repository method(the same 3; 2 one-away) -- nexusbank NEND-DAY, NINT-CALC (batch) and NBLK-ACCT (CICS), all non-burned. The second turned out to be a det translator bug: the generated Javadoc's program nameNEND-DAYdid not match\w+. Once those were fixed, NINT-CALC's last gap wasROLLBACK TO SAVEPOINT, so savepoints are in this slice too.Census before -> after (programs translated whole): 95 -> 96 / 179 (non-burned 9 -> 10). NINT-CALC is now whole (89 -> 97/97 statements). NEND-DAY goes 86 -> 100/101: its one gap left is a host variable the translator does not find, not SQL. NBLK-ACCT goes 118 -> 128/166, and its ROLLBACKs are now refused by name (CICS). EXEC SQL gap classes over all programs: 2 classes in 3 programs -> 1 (CICS ROLLBACK, 1 program).
What changed
det/sql.py)COMMIT [WORK]->DetSql.commit,ROLLBACK [WORK]->DetSql.rollback.SAVEPOINT ... ON ROLLBACK RETAIN CURSORS,ROLLBACK [WORK] TO SAVEPOINT [x]andRELEASE [TO] SAVEPOINT x->DetSql.savepoint(run as written).hold. A hyphenated program name now finds its generated methods.DetSql)UnitOfWork, given by the runner, holds a batch step's Db2 transaction. COMMIT closes the cursors not declared WITH HOLD. A held cursor keeps no current row, so a positioned statement before the next FETCH gets -508.ggsql.c,equivalence_sql.py,ggabend.c)H.ROLLBACK WORK TO SAVEPOINTas a full ROLLBACK (0 where Db2 answers -880), so the precompiler drops the noise word WORK. CLI's row count of -1 no longer reaches SQLERRD(3).equivalence.py run --corpus-dir, never with--record, for a synthetic estate.IBM references (register Q3 / Q4,
docs/language_status/oracle_assumptions.md)Db2 for z/OS SQL Reference: COMMIT (closes cursors not WITH HOLD), ROLLBACK (backs out, closes all cursors), SAVEPOINT / ROLLBACK TO SAVEPOINT / RELEASE SAVEPOINT (-880, -881). Codes: -501, -508, -803, -925 / -926 (2D521, COMMIT / ROLLBACK invalid in CICS). Application Programming and SQL Guide: unit of work in TSO / CAF (commit at a normal end, backout at an abnormal one). Q3 goes from DIFFERS (batch) to MATCHED.
Oracle / z/OS differences, declared:
Proof
tests/equivalence/db2/uow(synthetic UOWDEMO estate) +test_sql_unit_of_work.py::test_uowdemo_det_port_proves_on_db2_against_the_hand_trace, gated on EQUIVALENCE_E2E=1 and passing locally in normal and abend modes.det_port.py checkvs origin/main: 29 ports changed. Every Db2 port carriesDetSql.java, and LGUPDB01 also gains the WITH HOLD flag. Re-proven withproof_sweep.py --det-only --cases <29> --faults all: 29/29 proven, "sweep: as expected".pr_gates.py --fast5/5 pass;pr_gates.py --ratchets7/7 pass, none skipped.Next slices (#4269)
EXEC ... HV-SO-IM: no such item, line 408). Probably not SQL; it makes the program whole.🤖 Generated with Claude Code
https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D