Repository navigation
#3834 (part 3): the Cultural Gauntlet's DB collation, input data and remaining runtime locales - #3947
Merged
Merged
Conversation
…remaining runtime locales D (target DB collation): a PIC X(8) KSDS that CICS browses and a batch step reads sequentially, generated for H2 / PostgreSQL / MySQL. collation-static checks #3822's contract; the opt-in --db layer creates the generated table in the databases this machine has (H2 from ~/.m2, a throwaway PostgreSQL cluster with C and en_US.UTF-8 databases; MySQL skipped, never faked) and reads the keys back through the generated finders' SQL against the keys' EBCDIC byte order. Found #3945 (batch sequential READ is findAll(): no key order). E (input data): DATUM / FECHA typed by PICTURE and SQL type, DB2 EUR / USA / ISO forms through Db2Dates, ROUNDED ties and NUMVAL / zoned over full-width, Arabic-Indic, Thai and Devanagari digits, pinned from GnuCOBOL 3 -std=ibm. Found #3946 (Db2Dates.parseTimestamp takes Arabic-Indic digits). C (rest): tr-TR, ar-EG, th-TH-u-nu-thai, de-DE x UTC / Asia/Kolkata / Europe/Berlin join --run's JVM environments (-Duser.extensions keeps -u-nu-thai); runtime-static traps locale-bound date formatters, SimpleDateFormat, Collator and Character.isDigit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment on lines
+381
to
+382
| "CustbatService.readAllCustFile: `return custRecRepository.findAll();` has no ORDER BY -- a sequential READ " | ||
| "of the KSDS returns its records in key order (cp277 bytes, CUST_KEY_SORT)", |
Contributor
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 #3834 (epic #3819). Parts 1 (#3907) and 2 (#3936) are merged. This part adds dimension D (target DB collation), dimension E (input data) and the rest of dimension C (runtime locales). Only the gauntlet changes:
tests/tools/cultural_gauntlet.py,tests/cultural_gauntlet/. No engine code.D: target database collation
Why: VSAM returns records in the order of the key's bytes in the data page: lower case before upper case, letters before digits. Target databases order differently. MySQL's
utf8mb4_0900_ai_cieven treatsa,Aandáas equal.The estate (rows
collation_*) is aPIC X(8)KSDS. A CICS program browses it (STARTBR / READNEXT / READPREV) and a batch step reads it sequentially. It is generated for H2, PostgreSQL and MySQL, in every column.collation-static(always, in CI) checks #3822's contract:COLLATE "C"on PostgreSQL,utf8mb4_binon MySQL, H2's own code-point default.@PrePersistsort key uses the declared page.sortKey(from, page).collation-db(opt-in,--db) runs against real databases, but only the ones this machine has:@Columnmappings.CobolRecords, withsortKeyfilling the sort column as@PrePersistwould. The keys cover mixed case,ÆØÅ,Ä,Ñ,é, digits and letters, punctuation, andABCnext toABC.findAll().The oracle is computed here, independently of the converter: each key space-padded and encoded in the page, sorted by bytes.
ABCis a duplicate WRITE. A canary checks that the database's ownORDER BY CUST_KEYdiffers from the mainframe's order, so the keys can actually catch a wrong collation.What really ran:
~/.m2.LOCALE 'C'and oneLOCALE 'en_US.UTF-8'. Each cell reports the collation the database names itself.utf8mb4_binis checked statically only.Result:
Cand PostgreSQLen_US.UTF-8, in all 8 columns: from LOW-VALUES, from a key, backwards, and the duplicate.findAll()with noORDER BY. PostgreSQL returns heap order and H2 returns primary-key code-point order, not the mainframe's order. Ledgered: 32collation-staticcells and 24collation-dbcells.E: input data
The estate (rows
input_eur,input_usa,input_iso, one per DB2 DATE format) has:DATUM PIC 9(8)andFECHA PIC X(10)next toACCT-DATE PIC 9(8);DATUMandFECHA, TIMEZEIT, andACCT_DATE CHAR(10);COMPUTE ... ROUNDEDandROUNDED MODE NEAREST-EVENon the same product;FUNCTION NUMVAL.input-staticchecks:LocalDate datum/fecha,String acctDate), and the repository's Db2Dates note.Db2Dates.FORMATis the declared format.HALF_UP/HALF_EVEN, and the ticket carries the NUMVAL rule (Java runtime accepts non-ASCII digits as numbers (Arabic-Indic, Devanagari, full-width) where COBOL NUMERIC/NUMVAL would not #3831).runtime-run(--run) checks the generatedDb2DatesandCobolRecordsin all 15 JVM environments against literals:26.09.2026 14.30.05,09/26/2026 02:30 PM,2026-09-26 14.30.05), and parsing all three.0.025 -> 0.03 / 0.02,-0.025 -> -0.03 / -0.02,2.5 / -2.5 / 3.5 -> 3 -3 4 / 2 -2 4.decimal()and zoned reads of full-width, Arabic-Indic, Thai and Devanagari digits must be invalid. This includes numbers printed by ath-TH-u-nu-thai/ar-EGformatter and a UTF-8 record's full-widthDATUM.The COBOL answers were decided by running GnuCOBOL 3
-std=ibm(the harness image) and are pinned in the tool:TEST-NUMVAL('123')andTEST-NUMVAL('١٢٣')return 1.-debug(IBM S0C7).Result:
Db2Dates.parseTimestamp("2026-09-26-١٤.٣٠.٠٥...")parses, becauseInteger.parseInttakes Arabic-Indic digits; DB2 rejects that string. Ledgered: 24runtime-runcells.C: the remaining runtime locales
--runenvironments: tr-TR, ar-EG, th-TH-u-nu-thai and de-DE, each with the JVM zone set to UTC, Asia/Kolkata and Europe/Berlin (12 new, 15 in all).PINNED_CLOCKis Berlin's spring-forward day, so a clock that used the JVM zone would read 03:30+0200.jvm_flagsnow passes-Duser.extensions=u-nu-thai. Before, the Thai environment silently ran as plain th-TH with ASCII digits. The canary now checks that Thai digits appear, and prints the Calendar year (2569 under Thai).runtime-statictraps:DateTimeFormatter.ofPatternwithout a Locale, when the pattern has a text or week field. A numeric-only pattern is locale-proof in java.time, and--runconfirms that under th/ar forMainframeClock'syyyyMMddHHmmssSSZ.ofLocalized*SimpleDateFormatwithout a LocaleCollator.getInstance()Character.isDigit/digit/getNumericValueCells (after #3940)
--ci(sampled)--full --ci--full --run --ci--full --db --ci--full --run --db --cicollation-dbcells are the MySQL ones.Gates
pr_gates.py --fast: 5/5 pass (lint, audits, secrets, xray, gauntlet 186 s).pytest tests/cultural_gauntlet/: 123 passed in 21.3 s (main: 103 in 11.5 s). The added time is mostly the real H2 and PostgreSQL runs and the 15-environment E run; each skips cleanly where its database or JDK is missing.Not done / limits
ai_ciis not executed, because there is no server here. Its cells say so.@Columns, not Hibernate itself.fromRecordreads them).sortKeyitself does not pad, so a port that passes a trimmed key to READPREV would miss the equal record. That is a porting-contract question, not ledgered.🤖 Generated with Claude Code