Embedded SQL Host Variable Mapping: GnuCOBOL versus Micro Focus Divergence
0 reputation · 19 Mar 2021, 22:01 UTC
0 reputation · 19 Mar 2021, 22:01 UTC
In a repeatable COBOL development pipeline, consistent mapping of EXEC SQL host variables between COBOL data structures and relational schema is required across compiler vendors. The goal is to determine whether a given COBOL record binding to a database column produces identical runtime values when compiled with GnuCOBOL and Micro Focus.
Both compilers support the ANSI EXEC SQL syntax, but their preprocessors generate divergent boilerplate for host variable allocation, cursor management, and error handling. Copybook picture clauses such as PIC 9(5)V or PIC A(20) are translated using compiler-specific rules, often resulting in silent truncation or type mismatches when COBOL records bind to SQL tables. Runtime cursor FETCH behavior also differs, with some compilers targeting predefined working-storage fields while others require explicit LOCK/RELEASE statements, impacting transactional consistency.
Do GnuCOBOL and Micro Focus emit equivalent host variable declarations for the same EXEC SQL SELECT statement when targeting an identical PostgreSQL table? How do picture clause translations for edited numeric fields affect data rounding or truncation during host variable assignment? Can a unified copybook-to-schema mapping strategy be defined that preserves semantic equivalence across both compiler runtimes?
34775 reputation · 20 Mar 2021, 07:23 UTC
No. GnuCOBOL and Micro Focus do not emit equivalent host variable declarations for the same EXEC SQL SELECT against an identical PostgreSQL table. The ANSI EXEC SQL syntax is shared, but everything below the syntax layer — host variable allocation, SQLCA wiring, cursor control, and type coercion — is generated by each vendor's precompiler, and those generators are different programs with different rules.
GnuCOBOL has no built-in embedded SQL processor; the usual path is a third-party precompiler such as esqlOC/ocesql, which translates EXEC SQL into calls against PostgreSQL's libpq C client. Micro Focus ships its own precompiler stack (COBSQL / OpenESQL) with its own runtime cursor and locking model. Identical COBOL source therefore produces different call sequences, different buffer layouts, and different conversion routines on each side.
PIC 9(5)V is a fixed-point field with an implied decimal and no SQL-native counterpart. One precompiler may bind it as zoned character data and convert in its own runtime; another may pass it through a packed or binary intermediate. Whether assignment rounds or truncates is a property of that vendor's conversion routine, not of ANSI EXEC SQL. A value like 12345.67 landing in 9(5)V can silently lose the fraction on one runtime and raise a condition on the other — or lose it on both, differently.
Edited pictures such as PIC ZZ,ZZ9.99 are display strings. Binding one directly to a numeric column forces a character-to-numeric conversion at runtime, where blank handling, sign representation, and locale-sensitive separators diverge silently between vendors. The safe rule: never bind an edited field to SQL. Move the value through an unedited intermediate (9(5)V99 or COMP-3) and bind that.
PIC A(20) / PIC X(20) are fixed-length and space-filled; PostgreSQL VARCHAR is variable-length. Each precompiler draws the trim/pad boundary differently, so a fetched 'SMITH' may arrive with 15 trailing spaces on one runtime and trimmed on the other, breaking downstream comparisons.
Micro Focus OpenESQL integrates cursor and lock management into its own runtime; GnuCOBOL-based precompilers delegate cursor control to libpq. Expectations about predefined working-storage fetch targets or LOCK/RELEASE-style demarcation do not transfer between the two.
Semantic equivalence is achievable, but only by constraining the copybooks to a portable subset and enforcing it mechanically:
PIC X(n) only, sized to the column, and standardize on one trim/pad convention applied in application code rather than trusting the precompiler.9(5)V99 COMP-3 → NUMERIC(7,2), X(20) → VARCHAR(20)) and enforce it in code review or with a lint step over the copybooks.Silent truncation frequently raises no SQLCODE on either runtime, so equivalence must be tested:
EXEC SQL SELECT with both toolchains and diff the precompiler-generated intermediate source for host variable declarations.99999.9, negatives, zero — INSERT from COBOL, SELECT back, compare byte-for-byte.9(5)) and record each runtime's behavior.X(20) and inspect trailing bytes; fetch a NULL and compare SQLCA indicator contents on both sides.One caveat: exact behavior is version-sensitive, especially on the GnuCOBOL side where the precompiler is an external project with its own release cycle. Treat any specific conversion rule as confirmed only for the versions you actually test, and re-run the round-trip suite on every toolchain upgrade.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.