Skip to content

fix: decode fixed-length CODEUNITS32 CHAR and GRAPHIC as length-prefixed - #43

Open
cevheri wants to merge 2 commits into
gurungabit:mainfrom
libredb:fix/codeunits32-fixed-strings
Open

cevheri wants to merge 2 commits into
gurungabit:mainfrom
libredb:fix/codeunits32-fixed-strings

Conversation

@cevheri

@cevheri cevheri commented Nov 2, 2026

Copy link
Copy Markdown

Fixes #42

On Db2 LUW 12.1, CHAR(n CODEUNITS32) and GRAPHIC(n CODEUNITS32) are fixed-length in SQLDARD (SQLTYPE 452/468), but QRYDSC declares them with LIDs 0xB0-0xB3 and QRYDTA sends a 2-byte count before each value.
Reading them as fixed-width shifted every later column and row.

Changes:

  • crates/db2-proto/src/fdoca.rs: new apply_qrydsc_string_layout copies the QRYDSC wire type onto the matching SQLDARD descriptor; decode_column_value reads 0xB2/0xB3 as a UTF-8 byte count and 0xB0/0xB1 as a UTF-16 code-unit count; compact_gda_descriptor_type maps the same LIDs.
  • crates/db2-client/src/connection.rs: process_query_frames applies the QRYDSC layout to the SQLDARD descriptors whichever of the two arrives first, and normalize_luw_descriptors treats 0xB0 like the other graphic types.

The layout is applied only when both descriptor lists have the same column count, so the LOB row envelope case keeps its current behaviour.

Tests use QRYDSC and QRYDTA bytes captured from Db2 12.1.0.0 for both types, with ASCII and non-ASCII values:

  • test_codeunits32_fixed_strings_are_length_prefixed_on_the_wire decodes the rows with the layout applied and fails without the fdoca.rs change.
  • query_frames_decode_codeunits32_fixed_strings_in_either_descriptor_order runs the reply frames through process_query_frames with SQLDARD before and after QRYDSC.
  • query_frames_decode_codeunits32_fixed_strings_from_qrydsc_alone covers a reply with no SQLDARD.

Verified live on Db2 12.1.0.0: 60 type, width and row-count combinations, all rows correct.
Locally: cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings and unit tests pass, plus integration and Node.js tests against the CI Db2 11.5.9 setup.
Not run: the release workflow and the docs build.

On Db2 LUW 12.1, SQLDARD describes a CHAR(n CODEUNITS32) or
GRAPHIC(n CODEUNITS32) column as fixed-length (SQLTYPE 452/468), but
QRYDSC declares it with LIDs 0xB2/0xB3 or 0xB0/0xB1 and QRYDTA sends a
2-byte count before each value. Decoding those values as fixed-width
shifted every later column and row, so a query failed with "query ended
with undecoded row data" or returned wrong values and fewer rows.

The QRYDSC layout is now applied to the SQLDARD descriptors, and the
decoder reads these columns as a UTF-8 byte count (0xB2/0xB3) or a
UTF-16 code-unit count (0xB0/0xB1) followed by the value. The compact
GDA path maps the same LIDs.

Fixes gurungabit#42
The QRYDSC layout was copied onto the SQLDARD descriptors only when
QRYDSC arrived second. A reply carrying SQLDARD after QRYDSC replaced
the descriptors without it, and the length-prefixed CODEUNITS32 values
were decoded as fixed-width again.

Add tests that run captured Db2 12.1 reply frames through
process_query_frames with SQLDARD before and after QRYDSC, and with
QRYDSC alone.

This branch has not been deployed

No deployments
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.

Fixed-length CHAR/GRAPHIC in CODEUNITS32 decoded as fixed-width: wrong values, lost rows

1 participant