SlimeCOBOL-ESQL ― COBOL 埋め込み SQL(EXEC SQL)変換
古い COBOL がプログラム内に直接書く埋め込み SQL(EXEC SQL)を、答えを変えずに現代の形(Java=JDBC / Rust=sqlx)へ移すための機能。bit-exact 路線。現在は開発・検証段階で、実 IBM DB2 での最終確認は次段階です。
1960 年代から動く COBOL の基幹システムを、Java など現代の言語へ「意味を変えずに引っ越し」。1 円も狂わない計算(bit-exact)で、止められない勘定系を安全に近代化します。
COBOL の COMP-3(10 進数)や桁・符号は安易に変換すると 1 円ズレます。数値核を bit-exact に再現し、米連邦の COBOL 検証 CCVS85 501/501・FIPS 3,910/3,910 一致を実証。14 方言を自動検出。
COBOL を Slot IR へ射影し Java/Rust/Go/C#/Kotlin へ転写。数値核・制御フローは構造保存で bit-exact、EXEC SQL は SlimeCOBOL-ESQL として独立参照 ocesql で検証中。FILE/VSAM・CICS/IMS は段階的に。できない部分は隠さず分離。
COBOL の固定小数・編集 picture・COMP-3 を二の補数/10 進で厳密モデル化し、独立参照(本物の COBOL コンパイラ)と byte 突合。EXEC SQL は ocesql/実 DB2 をオラクルに N/N 等価検証。証明できた単位だけを主張する規律。
いま証明できていること(正直に)
- 独立した参照実装(Open-COBOL-ESQL / ocesql)に対し、47 ケースで翻訳結果が完全一致(観測値・格納テーブル状態とも)。
- Java(JDBC)と Rust(sqlx, typed bind)の両 emitter で同一結果 ── Slot IR の言語非依存を DB I/O 境界でも確認。
- カバー構文:SELECT / SELECT INTO / INSERT・UPDATE・DELETE / カーソル(単一・複数)/ numeric(符号・桁)/ JOIN / GROUP BY・集計 / 動的 SQL(EXECUTE)/ NULL indicator。
- COBOL 固定長(PIC X 空白詰め)・明示トランザクション(COMMIT/ROLLBACK)・packed/numeric の桁を忠実に再現。
実コードでの徹底監査(2026-06-10)
合成 47 ケースに留めず、巷に公開されている実 EXEC SQL コーパス 146 プログラム(IBM db2-samples・GnuCOBOL contrib・Rocket BankDemo・IBM CBSA・AWS carddemo・Portfolio Mgmt・Open-COBOL-ESQL 他)を抽出器(S1.5)に全数通しました。
| 指標 | 値 |
|---|---|
| 対象プログラム | 146(公開コーパス由来) |
| 正常終了 | 146 / 146(クラッシュ 0・タイムアウト 0) |
| EXEC SQL 文 → 抽出 | 1,038 → 1,008(抽出率 97.1%) |
| 型として認識・処理できる文 | 95.1%(DML・カーソル・TX・INCLUDE + DECLARE SECTION・CONNECT 等) |
| 未対応の高度 SQL | 4.9%(DDL・PREPARE 動的・LOB/ストアド・IMS attach) |
この数字の意味(誇張しない):上記は実コードに対する「抽出 + 種別分類」の網羅性であって、変換結果の bit-exact 等価ではありません。等価の最終確認は前述の 47 ケース(独立オラクル ocesql)が現時点の範囲で、実コーパスを丸ごと実行するには各プログラムが前提とする実 DB2 のカタログ・スキーマ(DSN8C10 / CORPDATA 等)が必要=実 DB2(次段階)です。「実コードの 95% を変換済み」という意味ではありません。
実コードを end-to-end で確認(2026-06-10)
抽出・分類だけでなく、巷の実公開プログラムを end-to-end で検証しました。独立オラクル(ocesql でその場コンパイル実行、または psql-direct)の結果と、当機能が変換した SQL(JDBC)の結果を突き合わせます。
- INSERTTBL.cbl(書き込み系) ― CONNECT → DROP / CREATE TABLE → INSERT(リテラル + ホスト変数)→ COMMIT、SJIS 日本語データ。両者の EMP テーブルが byte 一致(全 12 行、順序付き md5 一致)。
- FETCHTBL.cbl(読み取り系) ― SELECT COUNT(*) + カーソル(DECLARE / OPEN / FETCH / CLOSE)。件数 12 = 12、取得 12 行がオラクル出力と完全一致。
- PGMOD2 / PGMOD3(book テーブル、豊富な型) ― numeric(13) / character(40・60) / date / timestamp を含む 10 列の SELECT INTO と INSERT。SELECT の 10 列すべてがオラクルと一致(日付・タイムスタンプのマイクロ秒まで)、INSERT も決定的な列が一致(
CURRENT_TIMESTAMPはサーバ時刻のため対象外)。 - 動的 SQL(IBM Db2
dynamic.sqb/trigsql.sqbパターン) ― 実行時に文字列で組み立てる SQL を PREPARE → 動的カーソル(DECLARE / OPEN USING / FETCH)、および PREPARE → EXECUTE … USING(動的 UPDATE 等の DML)で処理。取得 34 行・更新 5 行とも オラクルと完全一致(md5 一致)。 - VALUES INTO(DB2 のスカラ代入
VALUES (式) INTO :変数) ― 式を評価してホスト変数へ代入する DB2 構文を、評価結果の読み取りに変換。COBOL 固定長(空白詰め)を忠実に保ったままオラクルと一致。 - ストアドプロシージャ(
EXEC SQL CALL proc(:p)) ― DB2 のストアド呼び出しを JDBC の CallableStatement に変換。PostgreSQL の実手続きに対し更新結果が オラクルと完全一致(md5 一致)。動的記述子版(CALL … USING DESCRIPTOR=SQLDA)は実 DB2 段階。 - LOB(
SQL TYPE IS CLOB/BLOB/CLOB-LOCATOR・FREE LOCATOR) ― 構文を認識(未分類にしない)。ただし LOB ロケータは DB2 サーバ側の概念で PostgreSQL に等価がなく、忠実再現は実 IBM DB2(次段階)。ここで「対応済」とは書きません。
- これらに必要な DDL(CREATE / DROP TABLE)の変換を実装。
- 実コードが 忠実性バグを 2 件あぶり出し、その場で修正:(1) 群項目配下の数値ホスト変数を文字列バインドしていた、(2) 日付・タイムスタンプ列のバインドが型不一致だった。実コードを通すからこそ出るバグを、数で潰しています。
- 修正後も全回帰グリーン(独立オラクル ocesql に対する 47 ケース runtime 一致を含む)。
※ COBOL の手続き(PERFORM ループ等)の変換は本機能の範囲外(別途の全文変換)で、本検証ではループの入力値を与えています。確認しているのは埋め込み SQL の変換が同一の結果(DB 状態・取得行)を再現することです。
検証のしくみ
抽出(S1.5)→ emit(Java / Rust)→ 実 PostgreSQL 実行 → 独立オラクル(ocesql)と観測値を全数差分。1 つのオラクルが扱えない領域(NULL indicator・動的 SQL)は psql-direct の別オラクルで補完する多層検証。各段で既存の数値核回帰(501/501)を緑のまま維持しています。
まだ確認していないこと(誇張しない)
- 実 IBM DB2 での最終検証 ── 現状はすべて PostgreSQL 上。DB2 固有の SQLCODE・方言・ロックは実機検証(次段階)で確かめます。
- 網羅性は、合成 corpus での「大規模一括」ではなく、お客様の実コードでの個別 PoC で確かめます(現実に得られない大規模本番コードの網羅は主張しません)。
- 提供形態(サービス)の確定。
※「501/501」は SlimeCOBOL の Slot IR による構造受理の数字であり、EXEC SQL の実変換(emit)とは別です。EXEC SQL の変換は本機能(SlimeCOBOL-ESQL)として開発中で、上記 47 ケースが現時点の検証範囲です。「対応済み」ではなく、答えが変わらないことを数で確かめながら作っている段階です。
