@@ -2692,7 +2692,8 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
26922692 LooseScan detector in best_access_path)
26932693 */
26942694 remaining_tables &= ~new_join_tab->table ->map ;
2695- table_map dups_producing_tables;
2695+ table_map dups_producing_tables, prev_dups_producing_tables,
2696+ prev_sjm_lookup_tables;
26962697
26972698 if (idx == join->const_tables )
26982699 dups_producing_tables= 0 ;
@@ -2703,7 +2704,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
27032704 if ((emb_sj_nest= new_join_tab->emb_sj_nest ))
27042705 dups_producing_tables |= emb_sj_nest->sj_inner_tables ;
27052706
2706- Semi_join_strategy_picker **strategy;
2707+ Semi_join_strategy_picker **strategy, **prev_strategy ;
27072708 if (idx == join->const_tables )
27082709 {
27092710 /* First table, initialize pickers */
@@ -2755,23 +2756,54 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
27552756 3. We have no clue what to do about fanount of semi-join Y.
27562757 */
27572758 if ((dups_producing_tables & handled_fanout) ||
2758- (read_time < *current_read_time &&
2759+ (read_time < *current_read_time &&
27592760 !(handled_fanout & pos->inner_tables_handled_with_other_sjs )))
27602761 {
2761- /* Mark strategy as used */
2762- (*strategy)->mark_used ();
2763- pos->sj_strategy = sj_strategy;
2764- if (sj_strategy == SJ_OPT_MATERIALIZE)
2765- join->sjm_lookup_tables |= handled_fanout;
2762+ DBUG_ASSERT (pos->sj_strategy != sj_strategy);
2763+ /*
2764+ If the strategy choosen first time or
2765+ the strategy replace strategy which was used to exectly the same
2766+ tables
2767+ */
2768+ if (pos->sj_strategy == SJ_OPT_NONE ||
2769+ handled_fanout ==
2770+ (prev_dups_producing_tables ^ dups_producing_tables))
2771+ {
2772+ prev_strategy= strategy;
2773+ if (pos->sj_strategy == SJ_OPT_NONE)
2774+ {
2775+ prev_dups_producing_tables= dups_producing_tables;
2776+ prev_sjm_lookup_tables= join->sjm_lookup_tables ;
2777+ }
2778+ /* Mark strategy as used */
2779+ (*strategy)->mark_used ();
2780+ pos->sj_strategy = sj_strategy;
2781+ if (sj_strategy == SJ_OPT_MATERIALIZE)
2782+ join->sjm_lookup_tables |= handled_fanout;
2783+ else
2784+ join->sjm_lookup_tables &= ~handled_fanout;
2785+ *current_read_time= read_time;
2786+ *current_record_count= rec_count;
2787+ dups_producing_tables &= ~handled_fanout;
2788+ // TODO: update bitmap of semi-joins that were handled together with
2789+ // others.
2790+ if (is_multiple_semi_joins (join, join->positions , idx,
2791+ handled_fanout))
2792+ pos->inner_tables_handled_with_other_sjs |= handled_fanout;
2793+ }
27662794 else
2767- join->sjm_lookup_tables &= ~handled_fanout;
2768- *current_read_time= read_time;
2769- *current_record_count= rec_count;
2770- dups_producing_tables &= ~handled_fanout;
2771- // TODO: update bitmap of semi-joins that were handled together with
2772- // others.
2773- if (is_multiple_semi_joins (join, join->positions , idx, handled_fanout))
2774- pos->inner_tables_handled_with_other_sjs |= handled_fanout;
2795+ {
2796+ /* Conflict fall to most general variant */
2797+ (*prev_strategy)->set_empty ();
2798+ dups_producing_tables= prev_dups_producing_tables;
2799+ join->sjm_lookup_tables = prev_sjm_lookup_tables;
2800+ // mark it 'none' to avpoid loops
2801+ pos->sj_strategy = SJ_OPT_NONE;
2802+ // next skip to last;
2803+ strategy= pickers +
2804+ (sizeof (pickers)/sizeof (Semi_join_strategy_picker*) - 3 );
2805+ continue ;
2806+ }
27752807 }
27762808 else
27772809 {
0 commit comments