-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Optimization
-
ALL
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Problem
SERVER-132033 (commit 586c5a35cd5, PR 10gen/mongo#61467, merged to the explain-v3 branch on 2026-09-16) made qsnToBson() in src/mongo/db/query/plan_explainer_sbe.cpp serialize a QuerySolution tree in both the legacy and the V3 explain shape, and deliberately put an SBE plan node's stage-specific fields first in both shapes, followed by the filter and then the cost-based ranker estimates (cardinalityEstimate, costEstimate; flat in the legacy shape, inside the statistics subobject in V3). This is the order statsToBsonV3Impl emits for classic plans, so SBE and classic nodes read alike. Before that change the legacy shape emitted the estimates and the filter before the stage-specific fields.
The new order is intentional, but the golden tests that print SBE plans still record the old one. On the explain-v3 branch (Evergreen patches 6aac37666440ad0007abb4bf, 6aae76e268d57100079a2c98) six golden tests fail on mainline content the branch did not touch:
- jstests/query_golden/cached_partial_index_plan_not_reused_for_ineligible_query_md.js (query_golden_classic on the sbe-full variant, expected output under featureFlagSbeFull/): the FETCH node prints nss before filter. The same test also changes under internalQueryFrameworkControl: trySbeEngine (expected output under sbeFull/), a configuration neither the required nor the query alias runs golden tasks on.
- {{jstests/query_golden/join_opt/
{explain,projections,null_semantics,basic_joins,base_coll_reorder}
_md.js}} (query_golden_join_optimization on the join-optimization variant): all five print the winning plan through prettyPrintWinningPlan (jstests/query_golden/libs/pretty_plan.js), whose printPlanNode omits empty filters but emits the field separator before every field except the last. Once an empty filter: {} is a COLLSCAN node's last field, each such node gains a trailing blank line in the printed tree. Only base_coll_reorder.md and basic_joins.md contain non-empty filters whose position genuinely moves.
Fix
Test-only changes:
- printPlanNode drops empty filters before joining the fields, so a trailing empty filter leaves no blank line. Output is unchanged for every existing golden, since empty filters were already omitted.
- Re-record the four expected outputs whose content changes: featureFlagSbeFull/ and sbeFull/ cached_partial_index_plan_not_reused_for_ineligible_query.md, and internalEnableJoinOptimization/ base_coll_reorder.md and basic_joins.md. With the printer fix, explain.md, projections.md and null_semantics.md need no change.
- A unit test, PlanExplainerTest::StatsToBSONEstimateAndFilterPositionPerShape, pins the field order of a {{FETCH
{filter}
-> COLLSCAN}} node with estimates in both shapes, so the order is checked on every variant rather than only by the goldens on the sbe-full, trySbeEngine and join-optimization variants.
An earlier version of this ticket restored the old legacy order in the serializer; that approach was dropped once the reorder was confirmed to be intentional.
Scope
- This ticket: the golden and printer updates and the unit test above, as its own PR against explain-v3.
- Not this ticket: jstests/core/query/command_let_variables.js failing in core_explain_v3_passthrough on the sbe-full variant. That is a separate gap from the same commit (v3PlanToLegacyShape in jstests/libs/query/analyze_plan.js returns the ranked planStages tree, so planHasStage misses stages that exist only in executedPlanStages, e.g. the pushed-down UNWIND).
- No golden test runs V3 explain today, so none needs a second recording; if a golden V3 configuration is added later, begin_golden_test.js will need an explain-shape key for choosing the expected-output directory.
- is related to
-
SERVER-132033 Extend V3 explain with output from the SBE explainer
-
- Needs Merge
-
-
SERVER-133123 Split multiPlanStats into trial and finalize sections
-
- Needs Merge
-