BLQL compares two Int64 values through double
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 82/100
調査の方向性
src/BLite.Core/Query/Blql/BsonValueComparer.cs、特に Compare と数値変換の経路を読む。issue の再現値を使って、2^53 および long.MaxValue 付近の整数比較を検証し、その後 tests/BLite.Tests/Oracles/DynamicDifferentialTests.cs の DynamicCollection oracle テストを実行する。これらのケースで整数が正確に比較され、oracle の行がパスすれば完了。
索引モデルが issue の本文から書いたものです。
説明
BLQL compares two Int64 (or Int32 and Int64) values by converting both to double, so it cannot tell apart integers above 2^53 that differ by less than their double spacing: {t: {$gt: long.MaxValue - 1}} does not match long.MaxValue, and {t: 2^53} matches 2^53 + 1. The comparer's own summary says integers are compared exactly.
Found by the DynamicCollection oracle tests (tests/BLite.Tests/Oracles/DynamicDifferentialTests.cs, PR to follow, stacked on #263), which carry the affected rows (4: indexed/blql and plain/blql, both oracles, total > long.MaxValue - 1: expected the one document with long.MaxValue, got none) as a known candidate until this is fixed.
Repro
// t: long.MaxValue ("max"), long.MaxValue - 1 ("max-1"), 2^53 + 1 ("2^53+1"), all stored as Int64
col.Query(BlqlFilter.Gt("t", long.MaxValue - 1)).ToList(); // expected [max], actual []
col.Query(BlqlFilter.Eq("t", long.MaxValue - 1)).ToList(); // expected [max-1], actual [max, max-1]
col.Query(BlqlFilter.Eq("t", 1L << 53)).ToList(); // expected [], actual [2^53+1]
Expected: exact comparison of integers, as BsonValueComparer's summary says: "Within the same numerical family, values are compared numerically: exactly (as decimal) when neither side is a Double, through double otherwise" (src/BLite.Core/Query/Blql/BsonValueComparer.cs:11-12). LINQ and the typed collection compare long exactly.
Actual: see above. The indexed collection is wrong too: its scan bounds are exact (IndexKey(long)), and the residual filter then drops the right document.
Mechanism (verified on 0450b97)
BsonValueComparer.Compare takes the exact path only when one side is a Decimal128 (BsonValueComparer.cs:29-33); Int32 and Int64 pairs fall through to ToDouble(a).CompareTo(ToDouble(b)) (:35), which rounds above 2^53.
Affected versions: since BLQL (a86d458, v1.9.0). Reproduced on v5.2.3 / 0450b97.
Fix considerations
- Compare as
decimal(orlong) whenever neither side is a Double, as the summary describes: the condition at:31drops theDecimal128requirement. - A Double against an Int64 still goes through
double; comparing those exactly (as MongoDB does) is a further step and not what the summary promises. - The evaluator's cross-type range matching (#267) is in
CompareFilter, a separate fix.
Related: #150 and #222 (closed, the typed decimal and cross-type bound fixes), and the other BLQL rows of the same tests: #264, #265, #266, #267.
- 主要言語
- C#
- スター
- 66
- フォーク
- 6
- 平均マージ
- 1日 2時間
- マージ済み PR(30日)
- 43
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
EntglDb/BLite のほかの issue
-
area/indexing bug package/core triage
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
area/indexing bug package/core triage
難易度 4/5 3〜5日 初心者へのやさしさ 57/100
メンテナーはふだん 1 日以内に返信
-
area/indexing bug package/core triage
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
-
area/linq bug package/core triage
難易度 4/5 1〜2日 初心者へのやさしさ 42/100
メンテナーはふだん 1 日以内に返信
-
area/linq bug package/core triage
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 76/100
pyrevitlabs/pyRevit#3792 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 60/100
メンテナーはふだん 1 日以内に返信
-
area: design documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
eyalgolan/statecraft-israel#883 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 3 日以内に返信
-
Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
nunit/nunit-console#1913 ·
メンテナーはふだん 1 日以内に返信