=== modified file 'sql/item.cc'
--- sql/item.cc	2013-09-25 18:07:06 +0000
+++ sql/item.cc	2013-10-14 11:32:47 +0000
@@ -6524,6 +6524,15 @@ bool Item::find_item_processor(uchar *ar
   return (this == ((Item *) arg));
 }
 
+bool Item::flip_marker_processor(uchar *arg)
+{
+  if (marker == 2)
+    marker= 5;
+  else if (marker == 5)
+    marker= 2;
+  return false;
+}
+
 bool Item_field::send(Protocol *protocol, String *buffer)
 {
   return protocol->store(result_field);

=== modified file 'sql/item.h'
--- sql/item.h	2013-09-25 18:07:06 +0000
+++ sql/item.h	2013-10-14 11:12:57 +0000
@@ -1181,6 +1181,7 @@ class Item {
   virtual bool find_item_processor(uchar *arg);
   virtual bool change_context_processor(uchar *context) { return 0; }
   virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
+  virtual bool flip_marker_processor(uchar *arg);
   virtual bool is_expensive_processor(uchar *arg) { return 0; }
   virtual bool register_field_in_read_map(uchar *arg) { return 0; }
   virtual bool register_field_in_write_map(uchar *arg) { return 0; }

=== modified file 'sql/sql_select.cc'
--- sql/sql_select.cc	2013-09-25 18:07:06 +0000
+++ sql/sql_select.cc	2013-10-14 11:38:37 +0000
@@ -7648,16 +7648,17 @@ void JOIN_TAB::calc_used_field_length(bo
 
 int JOIN_TAB::make_scan_filter()
 {
-  COND *tmp;
+  Item *tmp;
   DBUG_ENTER("make_scan_filter");
 
-  Item *cond= is_inner_table_of_outer_join() ?
-                *get_first_inner_table()->on_expr_ref : join->conds;
-  
-  if (cond &&
-      (tmp= make_cond_for_table(join->thd, cond,
-                               join->const_table_map | table->map,
-			       table->map, -1, FALSE, TRUE)))
+  if (is_inner_table_of_outer_join())
+    tmp= make_cond_for_table(join->thd, *get_first_inner_table()->on_expr_ref,
+                              join->const_table_map | table->map,
+                              table->map, -1, FALSE, TRUE);
+  else
+    tmp= single_table_select_cond;
+
+  if (tmp)
   {
      DBUG_EXECUTE("where",print_where(tmp,"cache", QT_ORDINARY););
      if (!(cache_select=
@@ -9153,8 +9154,61 @@ make_join_select(JOIN *join,SQL_SELECT *
         }
         else
          {
-	  tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
-                                   FALSE, FALSE);
+           int dummy= 0;
+           tab->single_table_select_cond= make_cond_for_table(
+                                            join->thd, cond,
+                                            join->const_table_map | tab->table->map,
+                                            tab->table->map, i, FALSE, FALSE);
+
+           if (tab->single_table_select_cond)
+             tab->single_table_select_cond->walk(&Item::flip_marker_processor,
+                                                 FALSE,
+                                                 (uchar*)&dummy);
+
+           tab->multi_table_select_cond= make_cond_for_table(thd, cond,
+                                                             used_tables,
+                                                             current_map, i,
+                                                             FALSE, FALSE);
+           if (tab->single_table_select_cond)
+             tab->single_table_select_cond->walk(&Item::flip_marker_processor,
+                                                 FALSE,
+                                                 (uchar*)&dummy);
+
+           DBUG_EXECUTE("where",
+                        char buff[256];
+                        String str(buff,sizeof(buff),system_charset_info);
+                        str.length(0);
+                        str.append(tab->table? tab->table->alias.c_ptr() :"<no_table>");
+                        str.append(" single_table_select_cond");
+                        print_where(tab->single_table_select_cond, str.c_ptr_safe(), QT_ORDINARY);
+                        str.length(0);
+                        str.append(tab->table? tab->table->alias.c_ptr() :"<no_table>");
+                        str.append(" multi_table_select_cond");
+                        print_where(tab->multi_table_select_cond,
+                                    tab->table? tab->table->alias.c_ptr() :"<no_table>",
+                                    QT_ORDINARY);
+                        );
+
+           if (tab->single_table_select_cond)
+           {
+             tmp= and_items(tab->multi_table_select_cond,
+                            tab->single_table_select_cond);
+             if (!tmp->fixed)
+               tmp->fix_fields(thd, 0);
+             tmp->update_used_tables();
+           }
+           else
+             tmp= tab->multi_table_select_cond;
+
+           DBUG_EXECUTE("where",
+                        char buff[256];
+                        String str(buff,sizeof(buff),system_charset_info);
+                        str.length(0);
+                        str.append(tab->table? tab->table->alias.c_ptr() :"<no_table>");
+                        str.append(" candidate_pushdown_cond");
+                        print_where(tmp,
+                                    str.c_ptr_safe(),
+                                    QT_ORDINARY););
          }
         /* Add conditions added by add_not_null_conds(). */
         if (tab->select_cond)
@@ -10680,6 +10734,25 @@ make_join_readinfo(JOIN *join, ulonglong
       abort();
       /* purecov: end */
     }
+    /*
+      If the single-table condition for this table will be used by a
+      blocked join to pre-filter this table's rows, there is no need
+      to use this condition during execution.
+    */
+    if (tab->select_cond && tab->cache_select &&
+        tab->single_table_select_cond == tab->cache_select->cond &&
+        tab->cache &&
+        (tab->cache->get_join_alg() == JOIN_CACHE::BNL_JOIN_ALG ||
+         tab->cache->get_join_alg() == JOIN_CACHE::BNLH_JOIN_ALG))
+      tab->select_cond= tab->multi_table_select_cond;
+
+    DBUG_EXECUTE("where",
+                 char buff[256];
+                 String str(buff,sizeof(buff),system_charset_info);
+                 str.length(0);
+                 str.append(tab->table? tab->table->alias.c_ptr() :"<no_table>");
+                 str.append(" final_pushdown_cond");
+                 print_where(tab->select_cond, str.c_ptr_safe(), QT_ORDINARY););
   }
   uint n_top_tables= join->join_tab_ranges.head()->end -  
                      join->join_tab_ranges.head()->start;
@@ -18948,7 +19021,8 @@ make_cond_for_table_from_pred(THD *thd,
     of the test
   */
   if ((cond->marker == 3 && !retain_ref_cond) ||
-      (cond->used_tables() & ~tables))
+      (cond->used_tables() & ~tables) ||
+      cond->marker == 5)
     return (COND*) 0;				// Can't check this yet
 
   if (cond->marker == 2 || cond->eq_cmp_result() == Item::COND_OK)

=== modified file 'sql/sql_select.h'
--- sql/sql_select.h	2013-09-18 11:07:31 +0000
+++ sql/sql_select.h	2013-10-10 14:41:08 +0000
@@ -222,6 +222,12 @@ typedef struct st_join_table {
   */
   Item          *pre_idx_push_select_cond;
   /*
+    Conditions that depend only on the table of this operator.
+    Used to pre-filter records during the scan phase of BNL and BNLH joins.
+  */
+  Item          *single_table_select_cond;
+  Item          *multi_table_select_cond;
+  /*
     Pointer to the associated ON expression. on_expr_ref=!NULL except for
     degenerate joins. 
     *on_expr_ref!=NULL for tables that are first inner tables within an outer

