@@ -1095,6 +1095,29 @@ TEST(IntermediateBlueprintsTest, require_that_replaced_blueprints_retain_source_
10951095 EXPECT_EQ (42u , top2_up->getSourceId ());
10961096}
10971097
1098+ TEST (IntermediateBlueprintsTest, equiv_flow_stats_reach_into_intermediate_term_subtrees) {
1099+ // Equiv terms are not part of the optimize tree, so EquivBlueprint must
1100+ // update flow stats on the full subtree of each term — not just the term
1101+ // itself. Otherwise an IntermediateBlueprint sitting between Equiv and
1102+ // its real leaves (e.g. a SourceBlender wrapped around a term in proton)
1103+ // sees zero-initialized child stats, propagates estimate=0/cost=0 up to
1104+ // Equiv, and zeroes out the planner cost for everything that follows
1105+ // Equiv in an AND.
1106+ FieldSpecBaseList fields;
1107+ fields.add (FieldSpecBase (1 , 1 ));
1108+ auto equiv = std::make_unique<EquivBlueprint>(fields, EquivBlueprint::allocate_outside_equiv_tag{});
1109+ for (uint32_t i = 0 ; i < 3 ; ++i) {
1110+ auto wrap = std::make_unique<OrBlueprint>();
1111+ wrap->addChild (ap (MyLeafSpec (40 ).addField (1 , 2 + i * 2 ).create ()));
1112+ wrap->addChild (ap (MyLeafSpec (40 ).addField (1 , 3 + i * 2 ).create ()));
1113+ equiv->addTerm (std::move (wrap), 1.0 );
1114+ }
1115+ equiv->basic_plan (false , 1000 );
1116+ EXPECT_GT (equiv->estimate (), 0.0 );
1117+ EXPECT_GT (equiv->cost (), 0.0 );
1118+ EXPECT_GT (equiv->strict_cost (), 0.0 );
1119+ }
1120+
10981121TEST (IntermediateBlueprintsTest, test_Equiv_Blueprint) {
10991122 FieldSpecBaseList fields;
11001123 search::fef::MatchDataLayout subLayout;
0 commit comments