Skip to content

fix(jdbc): wrap REAL to int like SQLite - #131

Merged
magnusp merged 1 commit into
mainfrom
fix/i101-real-int-wrap
Oct 22, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/i101-real-int-wrap

Conversation

@magnusp

@magnusp magnusp commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Fixes #101

Contract: Hrana 3 is the source of truth for transport and values (Value.Float is a 64-bit double, Value.Integer a 64-bit signed integer). java.sql is the source of truth for the ResultSet surface. xerial/sqlite-jdbc is a behavioral reference only.

Change

  • getInt on a REAL now uses (int) (long) f.value(), so conversion goes through int64 and keeps the low 32 bits like SQLite instead of clamping to the int range.
  • getFloat on an INTEGER now uses (float) (double) i.value(), matching SQLite's double-then-float rounding.
  • getObject(col, Integer.class) already routed through getInt, so it inherits the wrap. getByte and getShort still go through getLong and are unchanged.

Evidence

Red at trunk, source reverted, new cases only (/tmp/xerial-parity-i101/lane-1-regression.log): 3 failures, 3e9 returned 2147483647 instead of -1294967296, 4294967296.0 returned true, and the large INTEGER returned 1.1529216E18f instead of 1.1529215E18f.

Green at head (/tmp/xerial-parity-i101/green.log): Tests run: 21, Failures: 0, Errors: 0 for LibsqlResultSetTest.

Lanes, all at head bf58589444d954071e0ac168f0815ea3503c373b:

  • Lane 1 regression: red at trunk, green at head (lane-1-regression.log).
  • Lane 2 getObject Integer wrap: 40 tests, BUILD SUCCESS (lane-2-specific.log).
  • Lane 3 getByte/getShort untouched: 83 tests, BUILD SUCCESS (lane-3-specific.log).
  • Lane 4 module suite: 226 tests, BUILD SUCCESS (lane-4-module-suite.log).
  • Lane 5 conformance against libSQL: 115 tests, BUILD SUCCESS, no new divergence (lane-5-conformance.log).
  • Lane 6 xerial control probe: 100 tests, BUILD SUCCESS, no reference divergence (lane-6-control.log).
  • Lane 7 spotless:check: BUILD SUCCESS (lane-7-spotless.log).
  • Lane 8 full reactor: BUILD SUCCESS (lane-8-reactor.log).
  • Lane 9 boolean getter suite: 8 tests, BUILD SUCCESS (lane-9-specific.log).
  • Lane 10 jar assembly: BUILD SUCCESS (lane-10-package.log).

Perf: time ./mvnw -pl libsql-jdbc test, three interleaved runs per side (perf.log). Trunk median 2.301 s, head median 2.277 s, within the 10 percent rule.

Divergences

  • None from the plan. + in the plan's -Dtest examples is not a Surefire separator, so the combined lanes use commas; the single-class lanes run exactly as written.

SHAs

  • Base: 1faf4fca800e8ac4a7d418ad26a1054f5f4182b1
  • Head: bf58589444d954071e0ac168f0815ea3503c373b

getInt cast a REAL straight to int, which clamps. SQLite converts
through int64 and keeps the low 32 bits. Route REAL through long and
round INTEGER through double before narrowing to float, matching
SQLite's numeric conversion.

Fixes #101
@magnusp
magnusp merged commit ff84b2d into main Oct 22, 2026
5 checks passed
@magnusp
magnusp deleted the fix/i101-real-int-wrap branch October 22, 2026 21:56
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.

getInt on REAL clamps to the int range where SQLite wraps

1 participant