SlimeCOBOL-ESQL — COBOL Embedded SQL (EXEC SQL) Conversion
A capability that moves the embedded SQL (EXEC SQL) that legacy COBOL writes directly inside the program to a modern form (Java = JDBC / Rust = sqlx) without changing the answer. A bit-exact approach. It is currently in development / verification; final confirmation on real IBM DB2 is the next stage.
What we can prove right now (honestly)
- Against an independent reference implementation (Open-COBOL-ESQL / ocesql), 47 cases match the translation result exactly (both the observed values and the stored table state).
- Identical results from both the Java (JDBC) and Rust (sqlx, typed bind) emitters — confirming the Slot IR's language-independence even at the DB I/O boundary.
- Covered syntax: SELECT / SELECT INTO / INSERT・UPDATE・DELETE / cursors (single and multiple) / numeric (sign, digits) / JOIN / GROUP BY & aggregation / dynamic SQL (EXECUTE) / NULL indicator.
- Faithfully reproduces COBOL fixed-length (PIC X space padding), explicit transactions (COMMIT/ROLLBACK), and packed/numeric digit layout.
Thorough audit on real code (2026-06-10)
Beyond the 47 synthetic cases, we ran the extractor (S1.5) across 146 real public EXEC SQL programs (IBM db2-samples, GnuCOBOL contrib, Rocket BankDemo, IBM CBSA, AWS carddemo, Portfolio Mgmt, Open-COBOL-ESQL, and others).
| Metric | Value |
|---|---|
| Programs audited | 146 (from public corpora) |
| Clean exit | 146 / 146 (0 crashes, 0 timeouts) |
| EXEC SQL statements → extracted | 1,038 → 1,008 (97.1% extraction) |
| Statements recognized / handled by type | 95.1% (DML, cursors, TX, INCLUDE + DECLARE SECTION, CONNECT, etc.) |
| Advanced SQL not yet covered | 4.9% (DDL, dynamic PREPARE, LOB / stored proc, IMS attach) |
What this number means (no exaggeration): the above is the coverage of extraction + classification on real code, not bit-exact equivalence of the conversion result. Final equivalence is still bounded by the 47 cases (independent oracle, ocesql); executing the real corpus end-to-end requires each program's real DB2 catalog/schema (DSN8C10 / CORPDATA, etc.) = real IBM DB2 (next stage). It does not mean "95% of real code is converted".
Real programs, end-to-end (2026-06-10)
Beyond extraction/classification, we ran real public programs end-to-end, matching the independent oracle's result (ocesql compiled and run on the spot, or psql-direct) against the SQL (JDBC) this feature emits.
- INSERTTBL.cbl (write path) — CONNECT → DROP / CREATE TABLE → INSERT (literal + host variables) → COMMIT, with Shift-JIS Japanese data. Both EMP tables are byte-identical (all 12 rows, ordered md5 match).
- FETCHTBL.cbl (read path) — SELECT COUNT(*) + a cursor (DECLARE / OPEN / FETCH / CLOSE). Count 12 = 12, and the 12 cursor rows match the oracle exactly.
- PGMOD2 / PGMOD3 (book table, rich types) — a 10-column SELECT INTO and INSERT over numeric(13) / character(40, 60) / date / timestamp. All 10 SELECT columns match the oracle (down to timestamp microseconds); INSERT's deterministic columns match (
CURRENT_TIMESTAMPis server-clock, out of scope). - Dynamic SQL (IBM Db2
dynamic.sqb/trigsql.sqbpatterns) — SQL assembled as a string at run time, handled via PREPARE → dynamic cursor (DECLARE / OPEN USING / FETCH) and PREPARE → EXECUTE … USING (dynamic UPDATE/DML). The 34 fetched rows and 5 updated rows both match the oracle exactly (md5 match). - VALUES INTO (DB2 scalar assignment
VALUES (expr) INTO :var) — the DB2 idiom that evaluates an expression into host variables, converted to reading the evaluated result. Matches the oracle while preserving COBOL fixed-length (space-padded) semantics. - Stored procedures (
EXEC SQL CALL proc(:p)) — DB2 stored-procedure calls converted to a JDBC CallableStatement. Against a real PostgreSQL procedure the update result matches the oracle exactly (md5 match). The dynamic-descriptor form (CALL … USING DESCRIPTOR= SQLDA) is a real-DB2-stage item. - LOB (
SQL TYPE IS CLOB/BLOB/CLOB-LOCATOR,FREE LOCATOR) — recognized (no longer unclassified). But LOB locators are a DB2 server-side concept with no PostgreSQL equivalent, so faithful LOB needs real IBM DB2 (next stage). We do not write "supported" here.
- These required implementing DDL conversion (CREATE / DROP TABLE), now done.
- The real code surfaced two fidelity bugs, both fixed on the spot: (1) numeric host variables declared under a group item were bound as strings; (2) date / timestamp columns were bound with a mismatched type. Running real code is exactly how we find and kill such bugs, by the numbers.
- All regressions stay green after the fixes (including 47-case runtime equivalence against the independent ocesql oracle).
* Converting the COBOL procedural logic (PERFORM loops, etc.) is out of this feature's scope (that is the separate full transpile); here the loop's input values are supplied. What is verified is that the embedded-SQL conversion reproduces the identical result (DB state / fetched rows).
How it is verified
Extract (S1.5) → emit (Java / Rust) → execute on real PostgreSQL → full observed-value diff against an independent oracle (ocesql). Areas one oracle cannot handle (NULL indicator, dynamic SQL) are covered by a second psql-direct oracle — a multi-layer verification. At every stage the existing numeric-core regression (501/501) is kept green.
What we have not yet confirmed (no exaggeration)
- Final validation on real IBM DB2 — everything is currently on PostgreSQL. DB2-specific SQLCODE, dialects, and locking will be checked in real-machine validation (next stage).
- Coverage is confirmed through individual PoCs on the customer's own code, not by a "large-scale sweep" over a synthetic corpus (we do not claim comprehensive coverage of large-scale production code that cannot realistically be obtained).
- Finalization of the service offering.
* "501/501" is the figure for SlimeCOBOL's structural acceptance via Slot IR, and is distinct from the actual EXEC SQL conversion (emit). The EXEC SQL conversion is in development as this feature (SlimeCOBOL-ESQL), and the 47 cases above are the current verification scope. This is not "supported / done" — it is a stage where we build while confirming, by the numbers, that the answer does not change.
