Skip to content

fix: binding of COMP numeric host variables - #209

Open
david-marconis wants to merge 1 commit into
mridoni:mainfrom
david-marconis:fix-comp-numeric-binding
Open

fix: binding of COMP numeric host variables#209
david-marconis wants to merge 1 commit into
mridoni:mainfrom
david-marconis:fix-comp-numeric-binding

Conversation

@david-marconis

Copy link
Copy Markdown

Problem

A numeric host variable is always rendered to a decimal display string by SqlVar::createRealData (and parsed back by createCobolData), regardless of its COBOL USAGE. gixpp, however, sets CBL_FIELD_FLAG_BINARY for any USAGE BINARY item, including COMP integers, and every backend keys its parameter transmission on that flag:

Backend binary branch
ODBC SQL_C_BINARY
SQLite sqlite3_bind_blob
PostgreSQL binary format / OID_BYTEA
MySQL MYSQL_TYPE_BLOB
Oracle DPI_ORACLE_TYPE_BLOB

So a COMP host variable had its rendered ASCII digits ("42") transmitted as raw binary. Db2/ODBC rejects this with SQLSTATE 22003 ("numeric value out of range"); SQLite and the others silently bind a blob that never matches, so a lookup keyed on a COMP column returns no rows (SQLCODE 100). COMP-3 was unaffected only because gixpp does not flag it binary.

Fix

A single, backend-agnostic change in SqlVar:

  • In the constructor, clear the binary flag for numeric types so every backend stays on the text path.
  • Trim db_data_len for the COBOL_TYPE_*_BINARY cases so the trailing NULs left by snprintf in the length-sized buffer are not sent to the database.

Test

Adds TSQL044A (a COMP host variable used as a WHERE parameter and a FETCH target). It fails on the unfixed runtime and passes with the fix, across all configured backends.

old runtime:   SELECT SQLCODE: +0000000100   FLD2: 0000   -> fails
fixed runtime: SELECT SQLCODE: +0000000000   FLD2: 1234   -> passes

Verification

Checked against SQLite and Db2 (LUW, via unixODBC + the IBM clidriver): COMP, COMP-3, signed, V99 decimal, negative and 8-byte values all round-trip correctly as both WHERE-clause parameters and FETCH ... INTO targets.

@david-marconis
david-marconis force-pushed the fix-comp-numeric-binding branch from c9622bb to 43c9e01 Compare June 15, 2026 12:09
A numeric host variable is always rendered to a decimal display string by
SqlVar::createRealData (and parsed back by createCobolData), regardless of
its COBOL USAGE. gixpp, however, sets CBL_FIELD_FLAG_BINARY for any USAGE
BINARY item, including COMP integers. Every backend keys its parameter
transmission on that flag:

  - ODBC   : SQL_C_BINARY      (DbInterfaceODBC.cpp)
  - SQLite : sqlite3_bind_blob (DbInterfaceSQLite.cpp)
  - PgSQL  : binary format / OID_BYTEA (DbInterfacePGSQL.cpp)
  - MySQL  : MYSQL_TYPE_BLOB   (DbInterfaceMySQL.cpp)
  - Oracle : DPI_ORACLE_TYPE_BLOB (DbInterfaceOracle.cpp)

So a COMP host variable had its rendered ASCII digits ("42") transmitted as
raw binary. Db2/ODBC rejects this with SQLSTATE 22003 "numeric value out of
range"; SQLite/others silently bind a blob that never matches, so a lookup
keyed on a COMP column returns no rows (SQLCODE 100). COMP-3 was unaffected
only because gixpp does not flag it binary.

Fix: In the SqlVar constructor clear the binary flag for numeric types, so
every backend stays on the text path. Also trim db_data_len for the
COMP_TYPE_*_BINARY cases so the trailing NULs left by snprintf in the
length-sized buffer are not sent to the database.

Add regression test TSQL044A (COMP host var as WHERE parameter and FETCH
target); fails on the unfixed runtime, passes with the fix, across all
configured backends.
@david-marconis
david-marconis force-pushed the fix-comp-numeric-binding branch from 43c9e01 to 405d2e3 Compare June 15, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant