-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Optimization
-
Fully Compatible
-
ALL
-
-
None
-
None
-
None
-
None
-
None
-
None
-
None
The plan reconstruction logic in plan_stability_subjoin_cardinality_md.js mishandles IXSCAN bounds on indexes that contain dates when the index range is open ended, e.g. {a: {$gt: new Date("2020-01-01")}}. When the index range is open ended, the MongoDB server inserts new Date(INT64_MAX) (code) or new Date(INT64_MIN) (code)(depending on the side of the open bound). The reconstructed pipeline emits NaN for the open bound e.g. in the case of an open upper bound (note INT64_MAX = 9223372036854775807)
For the index bounds:
"indexBounds": { "o_orderdate": [ "(new Date(887932800000), new Date(9223372036854775807)]" ]}
We see the reconstructed plan emit:
{
"o_orderdate" : {
"$gt" : ISODate("1998-02-20T00:00:00Z"),
"$lte" : ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ")
}
}
The issue is in this logic where if we see a "Date" when parsing index bounds literal for reconstruction, we simply call the js parseInt(<date>).
This results in the following sequence of issues (based on a combination of my + Claude understanding):
1. parseInt("9223372036854775807") loses precision because parseInt() converts upto Number.MAX_SAFE_INTEGER which is 2^53 - 1, but INT64_MAX is 2^63 - 1. parseInt returns 9223372036854776000 (rounded to the nearest representable double).
2. new Date(9223372036854776000) exceeds JavaScript's Date clamp at 8.64e15, so the constructor returns Invalid Date.
A possible fix is:
In parseIndexBoundLiteral() we recognize the INT64_MAX/INT64_MIN sentinel values and return the existing "MaxKey"/"MinKey" strings, so later on the downstream predicate builder (which already handles that) correctly omits the bounds).
This surfaced because SERVER-125579 makes pipeline-form $lookup with an absorbed $match join-eligible and thus we choose an access path that produces an edge case that is not handled by the reconstruction code. This bug predates SERVER-125579 and the attached repro script shows a much simpler find() query triggering this issue. This particular issue surfaced on query idx 11:
{"aggregate":"lineitem","pipeline":[
{"$lookup":{"from":"orders","localField":"l_orderkey","foreignField":"o_orderkey","pipeline":[
{"$match":{"$and":[{"o_orderdate":{"$gt":"1998-02-20T00:00:00.000Z"}}]}},
{"$match":{"$and":[{"o_orderpriority":"3-MEDIUM"}]}}],"as":"orders"}},
{"$unwind":"$orders"},
{"$lookup":{"from":"customer","localField":"orders.o_custkey","foreignField":"c_custkey","pipeline":[
{"$match":{"$and":[{"c_acctbal":{"$gte":6089.13}}]}}],"as":"customer"}},
{"$unwind":"$customer"},
{"$lookup":{"from":"supplier","localField":"customer.c_nationkey","foreignField":"s_nationkey","pipeline":[
{"$match":{"$or":[{"s_acctbal":{"$eq":3580.35}},{"s_name":"Supplier#000000338"}]}},
{"$match":{"$nor":[{"s_nationkey":13},{"s_nationkey":6}]}},
{"$match":{"$nor":[{"s_acctbal":{"$eq":3839.44}},{"s_acctbal":{"$gt":9583.11}}]}}],"as":"supplier"}},
{"$unwind":"$supplier"},
{"$match":{"$and":[{"customer.c_mktsegment":"MACHINERY"}]}}],"cursor":{},"idx":11}
- is related to
-
SERVER-125579 Support absorbed single-table filters for let/sub-pipeline
-
- In Code Review
-
- related to
-
SERVER-127296 Use consistent JSON string serialization functions in plan_stability_subjoin_cardinality_md
-
- Backlog
-