Repository navigation
fix(sqlengine): keep the exact FLOAT and DOUBLE bound in a forward filter - #818
Merged
Merged
Conversation
…lter When the optimizer moves a range on an indexed field to a forward filter, data_buf_2_text() turns the bound back into text. For FLOAT and DOUBLE it used std::to_string(), which keeps six decimals, so "price > 1.0000001" became "price > 1.000000" on that segment and returned the documents at 1.0000001. It now prints max_digits10 significant digits (9 for FLOAT, 17 for DOUBLE), which read back as the same value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
egolearner
approved these changes
Oct 16, 2026
egolearner
left a comment
Collaborator
There was a problem hiding this comment.
LGTM
Thx for the fix.
Contributor
Author
|
The CI fail doesn't look like coming from me is it? |
Collaborator
Merged. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Keeps FLOAT and DOUBLE range bounds exact when the optimizer moves an inverted-index condition to a forward filter. An exclusive comparison then continues to exclude documents equal to its bound. Closes #817.
Problem on main
On
d7b478df9843ddfda23a0021ec09f16c105835a5,price > 1.0000001andweight > 1.0000000001each return 1,001 documents in the reproduction instead of 951. The collection contains 50 documents at the bounds and 951 above them, split into a sealed segment of 1,000 and a writing segment of one.The optimizer converts the binary bound back to text before the forward filter parses it again:
zvec/src/db/sqlengine/planner/optimizer.cc
Lines 130 to 135 in d7b478d
data_buf_2_text()usesStringHelper::ToString()for FLOAT and DOUBLE:zvec/src/db/sqlengine/analyzer/query_info_helper.cc
Lines 106 to 114 in d7b478d
Those overloads use
std::to_string(), which prints both reproduction bounds as1.000000in this build:zvec/src/include/zvec/ailego/utility/string_helper.h
Lines 164 to 172 in d7b478d
Changes
%.*gandstd::numeric_limits<T>::max_digits10significant digits: 9 for float and 17 for double. For example,1.0000001fprints as1.00000012, which parses back to the same float.FloatRangeFilter.ForwardScanKeepsExactBound, the collection-level reproduction from the issue. Both filters must return 951 documents.Tests
Local Release verification on macOS 27.0.1 arm64, Apple clang 21.0.0, CMake 4.3.2. Base production sources matched
d7b478df9843ddfda23a0021ec09f16c105835a5; fixed production sources included only this PR's helper change. The regression test was added to both builds.The regression fails on the base because each query returns 1,001. With the fix each returns 951.
Commands (binaries under
build/bin):Both builds use the compiler cache and six jobs. Tests run serially. Changed-line formatting passes Apple clang-format 21.0.0 with the repository configuration;
git diff --checkpasses.Compatibility and cost
From code reading: the integer branches and public
StringHelper::ToString()overloads keep their behavior. The conversion is shared by the optimizer and the constant-node conversion helper. A source search found no caller of that constant-node helper.Each converted FLOAT or DOUBLE bound replaces one decimal conversion with
snprintfinto a 32-byte stack buffer. The optimizer's choice of scan and engine operations are unchanged. This adds no persistent state, on-disk format, dependency, or public API.Not covered
delete_by_filter("price > 1.0000001")on this data fails earlier, on both base and fixed sources, withExecBatch::ToRecordBatch mismatching schema size. That is a separate defect; this PR does not change it.