diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index b2f59ba2a5ad2eb1d5d40d68967521235c2cc206..95ac45f40c43b1a4782c918538e7aa2e0ac282ad 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -4673,9 +4673,17 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
   MYSQL      *mysql= stmt->mysql;
   MYSQL_DATA *result= &stmt->result;
   MYSQL_ROWS *cur, **prev_ptr= &result->data;
-  NET        *net = &mysql->net;
+  NET        *net;
+
+  if (!mysql)
+  {
+    set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
+    return 1;
+  }
+
   DBUG_ENTER("cli_read_binary_rows");
 
+  net = &mysql->net;
   mysql= mysql->last_used_con;
 
   while ((pkt_len= cli_safe_read(mysql)) != packet_error)
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 1ebed6d17d5b737344ec6a4c6354c6d8c137cb4a..f1bfbec1555feeff91ec37bf79833ba1eb1ee760 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3990,4 +3990,61 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) > 0;
 ERROR HY000: Too high level of nesting for select
 DROP TABLE t1;
+CREATE TABLE t1 (
+c1 int(11) NOT NULL AUTO_INCREMENT,
+c2 varchar(1000) DEFAULT NULL,
+c3 bigint(20) DEFAULT NULL,
+c4 bigint(20) DEFAULT NULL,
+PRIMARY KEY (c1)
+);
+EXPLAIN EXTENDED 
+SELECT  join_2.c1  
+FROM 
+t1 AS join_0, 
+t1 AS join_1, 
+t1 AS join_2, 
+t1 AS join_3, 
+t1 AS join_4, 
+t1 AS join_5, 
+t1 AS join_6, 
+t1 AS join_7
+WHERE 
+join_0.c1=join_1.c1  AND 
+join_1.c1=join_2.c1  AND 
+join_2.c1=join_3.c1  AND 
+join_3.c1=join_4.c1  AND 
+join_4.c1=join_5.c1  AND 
+join_5.c1=join_6.c1  AND 
+join_6.c1=join_7.c1 
+OR 
+join_0.c2 < '?'  AND 
+join_1.c2 < '?'  AND
+join_2.c2 > '?'  AND
+join_2.c2 < '!'  AND
+join_3.c2 > '?'  AND 
+join_4.c2 = '?'  AND 
+join_5.c2 <> '?' AND
+join_6.c2 <> '?' AND 
+join_7.c2 >= '?' AND
+join_0.c1=join_1.c1  AND 
+join_1.c1=join_2.c1  AND 
+join_2.c1=join_3.c1  AND
+join_3.c1=join_4.c1  AND 
+join_4.c1=join_5.c1  AND 
+join_5.c1=join_6.c1  AND 
+join_6.c1=join_7.c1
+GROUP BY 
+join_3.c1,
+join_2.c1,
+join_7.c1,
+join_1.c1,
+join_0.c1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+Warnings:
+Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+SHOW WARNINGS;
+Level	Code	Message
+Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index b513d17bfa02006efe5c79a644ed085202338b99..3f17eb92d40d4024b766d69c0aab19a01d76405b 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -3389,4 +3389,64 @@ eval EXPLAIN SELECT c1 FROM t1 WHERE $q > 0;
 
 DROP TABLE t1;
 
+#
+# Bug #30396: crash for a join with equalities and sargable predicates
+#             in disjunctive parts of the WHERE condition 
+#
+
+CREATE TABLE t1 (
+  c1 int(11) NOT NULL AUTO_INCREMENT,
+  c2 varchar(1000) DEFAULT NULL,
+  c3 bigint(20) DEFAULT NULL,
+  c4 bigint(20) DEFAULT NULL,
+  PRIMARY KEY (c1)
+);
+
+EXPLAIN EXTENDED 
+SELECT  join_2.c1  
+FROM 
+	t1 AS join_0, 
+	t1 AS join_1, 
+	t1 AS join_2, 
+	t1 AS join_3, 
+	t1 AS join_4, 
+	t1 AS join_5, 
+	t1 AS join_6, 
+	t1 AS join_7
+WHERE 
+	join_0.c1=join_1.c1  AND 
+	join_1.c1=join_2.c1  AND 
+	join_2.c1=join_3.c1  AND 
+	join_3.c1=join_4.c1  AND 
+	join_4.c1=join_5.c1  AND 
+	join_5.c1=join_6.c1  AND 
+	join_6.c1=join_7.c1 
+         OR 
+	join_0.c2 < '?'  AND 
+	join_1.c2 < '?'  AND
+	join_2.c2 > '?'  AND
+	join_2.c2 < '!'  AND
+	join_3.c2 > '?'  AND 
+	join_4.c2 = '?'  AND 
+	join_5.c2 <> '?' AND
+	join_6.c2 <> '?' AND 
+	join_7.c2 >= '?' AND
+        join_0.c1=join_1.c1  AND 
+	join_1.c1=join_2.c1  AND 
+        join_2.c1=join_3.c1  AND
+	join_3.c1=join_4.c1  AND 
+	join_4.c1=join_5.c1  AND 
+	join_5.c1=join_6.c1  AND 
+	join_6.c1=join_7.c1
+GROUP BY 
+	join_3.c1,
+	join_2.c1,
+	join_7.c1,
+	join_1.c1,
+	join_0.c1;
+	
+SHOW WARNINGS;
+
+DROP TABLE t1;
+
 --echo End of 5.0 tests
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 47914c59b4c0618bd5deb513a3afb3e523b554a4..7e5d30a92f9c9a74b1abb848a1aa34b746dad89b 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1570,7 +1570,6 @@ class COND_EQUAL: public Sql_alloc
                                      the current and level           */
   COND_EQUAL()
   { 
-    max_members= 0;
     upper_levels= 0;
   }
 };
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 24c6979c0f66d491e99b8ebe25d10e2a9e8b2aed..737ad39745adec6ed760bd05dd23fbfb156877e4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6738,6 +6738,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
   DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
   select_lex->cond_count= 0;
   select_lex->between_count= 0;
+  select_lex->max_equal_elems= 0;
 
   for (table= tables; table; table= table->next_local)
   {
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index c83c7a1c8940bd5a735d830b1174fcf298abf841..cb314362b5cfe1d002d18cfc6971d26b6707d84a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1517,6 +1517,7 @@ void st_select_lex::init_query()
   */
   parent_lex->push_context(&context);
   cond_count= between_count= with_wild= 0;
+  max_equal_elems= 0;
   conds_processed_with_permanent_arena= 0;
   ref_pointer_array= 0;
   select_n_where_fields= 0;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 11273bba31424b7c8f2126b284685b21837b8409..3969d75f64d752886f676cf4a676e7d0e725f999 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -606,7 +606,8 @@ class st_select_lex: public st_select_lex_node
   */
   uint select_n_having_items;
   uint cond_count;    /* number of arguments of and/or/xor in where/having/on */
-  uint between_count; /* number of between predicates in where/having/on      */   
+  uint between_count; /* number of between predicates in where/having/on      */
+  uint max_equal_elems; /* maximal number of elements in multiple equalities  */   
   /*
     Number of fields used in select list or where clause of current select
     and all inner subselects.
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6f3851b66a14a5840561a9e8403140e234e56fb3..a7d0bd30346bb04464265770482700a53303e1be 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3562,10 +3562,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
   uint	and_level,i,found_eq_constant;
   KEY_FIELD *key_fields, *end, *field;
   uint sz;
-  uint m= 1;
-  
-  if (cond_equal && cond_equal->max_members)
-    m= cond_equal->max_members;
+  uint m= max(select_lex->max_equal_elems,1);
   
   /* 
     We use the same piece of memory to store both  KEY_FIELD 
@@ -3585,7 +3582,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
     it is considered as sargable only for its first argument.
     Multiple equality can add  elements that are filled after
     substitution of field arguments by equal fields. There
-    can be not more than cond_equal->max_members such substitutions.
+    can be not more than select_lex->max_equal_elems such 
+    substitutions.
   */ 
   sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
       (((thd->lex->current_select->cond_count+1)*2 +
@@ -7388,8 +7386,7 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
     just an argument of a comparison predicate.
     The function also determines the maximum number of members in 
     equality lists of each Item_cond_and object assigning it to
-    cond_equal->max_members of this object and updating accordingly
-    the upper levels COND_EQUAL structures.  
+    thd->lex->current_select->max_equal_elems.
 
   NOTES
     Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
@@ -7434,7 +7431,6 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
                                         COND_EQUAL *inherited)
 {
   Item_equal *item_equal;
-  uint members;
   COND_EQUAL cond_equal;
   cond_equal.upper_levels= inherited;
 
@@ -7472,19 +7468,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
       {
         item_equal->fix_length_and_dec();
         item_equal->update_used_tables();
-        members= item_equal->members();
-        if (cond_equal.max_members < members)
-          cond_equal.max_members= members; 
-      }
-      members= cond_equal.max_members;
-      if (inherited && inherited->max_members < members)
-      {
-        do
-        {
-	  inherited->max_members= members;
-          inherited= inherited->upper_levels;
-        }
-        while (inherited);
+        set_if_bigger(thd->lex->current_select->max_equal_elems,
+                      item_equal->members());  
       }
 
       ((Item_cond_and*)cond)->cond_equal= cond_equal;
@@ -7539,10 +7524,12 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
         {
           item_equal->fix_length_and_dec();
           item_equal->update_used_tables();
-          return item_equal;
 	}
         else
-          return eq_list.pop();
+          item_equal= (Item_equal *) eq_list.pop();
+        set_if_bigger(thd->lex->current_select->max_equal_elems,
+                      item_equal->members());  
+        return item_equal;
       }
       else
       {
@@ -7558,9 +7545,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
         {
           item_equal->fix_length_and_dec();
           item_equal->update_used_tables();
-          members= item_equal->members();
-          if (cond_equal.max_members < members)
-            cond_equal.max_members= members; 
+          set_if_bigger(thd->lex->current_select->max_equal_elems,
+                        item_equal->members());  
         }
         and_cond->cond_equal= cond_equal;
         args->concat((List<Item> *)&cond_equal.current_level);