Task: Write floating point values to the database without rounding
Table of Contents
This page documents a task in the Model the ORE report configuration as entities story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
A double written through sqlgen reads back as the same double, so no value the system stores is silently rounded.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Model the ORE report configuration as entities |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-03 |
3. Acceptance
- A double such as 1e-12 or 0.0123456789 written through a generated repository reads back unchanged, proven by a test.
- The fix is a patch on the sqlgen overlay port at its pinned commit, with the upstream code named so it can be offered upstream.
- The curve configuration database round trip passes once this lands.
4. Plan
Found by the curve configuration database round trip: a yield curve tolerance
of 1e-12 was written to the database and read back as 0.
The cause is upstream. sqlgen's Parser<T>::write in
include/sqlgen/parsing/Parser_default.hpp turns every value with no
reflection method and no enum type into text with std::to_string. For a
float or a double that is printf("%f"): six decimal places, so 1e-12 is
written as 0.000000 and 0.0123456789 as 0.012346. The read side,
std::stod, is exact; only the write loses digits. The latest upstream commit
that touches the file, 816ca6adec, still does this.
The fix is a patch on the overlay port, which pins sqlgen at 47e5711: floats
are written with std::to_chars, the shortest text that reads back as the same
value. The port version is bumped so a cached build of the old port is not
reused.
Proof: a repository test writes three doubles through a generated repository and reads them back. Run against the unpatched port it fails all three cases; with the patch it passes them.
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit | |
|---|---|---|---|---|
| Double fields in generated repository entities | 29 fields in 20 entities: trading 13, refdata 4, dq 1, reporting 1, synthetic 1 | =grep -rlE "std::optional<double>\ | double [a-z_]+;" projects/*/core/include/*/repository/*_entity.hpp= | 4b5499c45d |
| Values read back before the patch | 1e-12 as 0.0; 0.0123456789 as 0.012346; 123456789.123456789 as 123456789.123457 | compass test run -- -R ores.refdata.core.tests, cases in repository_floating_point_precision_tests.cpp |
4b5499c45d |
6. Notes
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
8. PRs
| PR | Title |
|---|---|
| #2540 | [build] Write floating point values to the database without rounding |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | Scientific notation in numeric or text columns; nan and inf | patch | No change | PostgreSQL reads 1e-12 into double precision, real and numeric; nan and inf were written the same way before. |
| 2 | Floating to_chars needs a recent standard library | patch | No change | The macOS build uses Xcode 16 on macos-14; Apple's libc++ provides floating to_chars from macOS 13.3. The scheduled macOS build confirms it. |
| 3 | Add float, negative and zero cases | repository_floating_point_precision_tests.cpp | Decline | No entity holds a float; sign and zero do not depend on the digit count the defect was about. |
| 4 | Offer the fix upstream | portfile.cmake | Deferred to the operator | Opening an issue on getml/sqlgen is an outward action; proposed to the operator. |
| 5 | Existing rows keep their rounded values | PR | No change | Stated in the PR's limitations; release notes are built from the PR. |
10. Result
- The sqlgen overlay port carries
fix-floating-point-precision.patch, which writes floats withstd::to_charsinstead ofstd::to_string. The port version is bumped to 1 so a cached build is not reused. repository_floating_point_precision_tests.cppwrites1e-12,0.0123456789and123456789.123456789through a generated repository. It failed all three against the unpatched port and passes all three with the patch.- Build clean after a reconfigure; ctest 89/89 with services up.
- The same defect exists in upstream sqlgen at
816ca6adec; the patch is written against the upstream file so it can be offered there.