Commit 12279f7c authored by unknown's avatar unknown
Browse files

Merge rurik.mysql.com:/home/igor/mysql-5.0-opt

into  rurik.mysql.com:/home/igor/dev-opt/mysql-5.0-opt-bug16081

parents a0e95927 a53f3d0f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1126,7 +1126,7 @@ a b a b
7	8	7	5
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	ALL	PRIMARY	NULL	NULL	NULL	4	Using where
1	SIMPLE	t2	ALL	PRIMARY	NULL	NULL	NULL	4	
1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.a	1	
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+125 −0
Original line number Diff line number Diff line
@@ -181,3 +181,128 @@ SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NUL
select row(NULL,1)=(2,0);
row(NULL,1)=(2,0)
0
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b));
INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3);
EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	const	PRIMARY	PRIMARY	8	const,const	1	Using index
EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	const	PRIMARY	PRIMARY	8	const,const	1	Using index
SELECT * FROM t1 WHERE a=3 and b=2;
a	b
3	2
SELECT * FROM t1 WHERE (a,b)=(3,2);
a	b
3	2
CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c));
INSERT INTO t2 VALUES
(1,1,2), (3,1,3), (1,2,2), (4,4,2),
(1,1,1), (3,1,1), (1,2,1);
EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	Using index
EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	Using index
SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b;
a	b	a	b	c
1	1	1	1	1
1	1	1	1	2
1	2	1	2	1
1	2	1	2	2
3	1	3	1	1
3	1	3	1	3
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b);
a	b	a	b	c
1	1	1	1	1
1	1	1	1	2
1	2	1	2	1
1	2	1	2	2
3	1	3	1	1
3	1	3	1	3
EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	5	Using where; Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	4	test.t1.a	1	Using index
EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	5	Using where; Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	4	test.t1.a	1	Using index
SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b;
a	b	a	b	c
1	1	1	1	2
1	1	3	1	3
1	2	1	2	2
1	1	1	1	1
1	1	3	1	1
1	2	1	2	1
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2);
a	b	a	b	c
1	2	1	1	1
1	2	1	1	2
1	2	1	2	1
1	2	1	2	2
3	2	3	1	1
3	2	3	1	3
EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	4	test.t1.a	1	Using where; Using index
Warnings:
Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1)))
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1);
a	b	a	b	c
1	2	1	1	1
1	2	1	1	2
3	2	3	1	1
3	2	3	1	3
EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	index	NULL	PRIMARY	12	NULL	7	Using where; Using index
Warnings:
Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t1`.`a` - 1) = (`test`.`t2`.`a` - 1)) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1)))
SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1);
a	b	a	b	c
1	2	1	1	2
3	2	3	1	3
1	2	1	1	1
3	2	3	1	1
EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	8	const,const	1	Using index
EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	8	const,const	1	Using index
SELECT * FROM t2 WHERE a=3 and b=2;
a	b	c
SELECT * FROM t2 WHERE (a,b)=(3,2);
a	b	c
EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	12	test.t1.a,const,const	1	Using index
EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1));
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	12	test.t1.a,const,const	1	Using index
Warnings:
Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`))
SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1));
a	b	a	b	c
1	1	1	2	1
1	2	1	2	1
EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	index	PRIMARY	PRIMARY	8	NULL	6	Using index
1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	12	test.t1.a,const,const	1	Using index
Warnings:
Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`))
SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
a	b	a	b	c
1	1	1	2	1
1	2	1	2	1
DROP TABLE t1,t2;
+47 −0
Original line number Diff line number Diff line
@@ -92,3 +92,50 @@ SELECT ROW(NULL,10) <=> ROW(3,NULL);
#
SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
select row(NULL,1)=(2,0);

#
# Bug #16081: row equalities are to be used for query optimizations  
#

CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b));
INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3);

EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2;
EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2);
SELECT * FROM t1 WHERE a=3 and b=2;
SELECT * FROM t1 WHERE (a,b)=(3,2);

CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c));
INSERT INTO t2 VALUES
  (1,1,2), (3,1,3), (1,2,2), (4,4,2),
  (1,1,1), (3,1,1), (1,2,1);

EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b;
EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b);
SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b;
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b);

EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2;
EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2);
SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b;
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2);

EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1);
SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1);

EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1);
SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1);

EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2;
EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2);
SELECT * FROM t2 WHERE a=3 and b=2;
SELECT * FROM t2 WHERE (a,b)=(3,2);

EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1;
EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1));
SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1));

EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);
SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1);

DROP TABLE t1,t2;
+3 −3
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ class base_list :public Sql_alloc
  {
    elements= tmp.elements;
    first= tmp.first;
    last=tmp.last;
    last= elements ? tmp.last : &first;
  }
  inline base_list(bool error) { }
  inline bool push_back(void *info)
+303 −151
Original line number Diff line number Diff line
@@ -6351,29 +6351,30 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,

  
/* 
  Check whether an item is a simple equality predicate and if so
  create/find a multiple equality for this predicate
  Check whether an equality can be used to build multiple equalities

  SYNOPSIS
    check_equality()
    item       item to check
    cond_equal multiple equalities that must hold together with the predicate
    check_simple_equality()
      left_item   left term of the quality to be checked
      right_item  right term of the equality to be checked
      item        equality item if the equality originates from a condition
                  predicate, 0 if the equality is the result of row elimination
      cond_equal  multiple equalities that must hold together with the equality

  DESCRIPTION
    This function first checks whether an item is a simple equality i.e.
    the one that equates a field with another field or a constant
    (item=constant_item or item=field_item).
    If this is the case the function looks a for a multiple equality
    This function first checks whether the equality (left_item=right_item)
    is a simple equality i.e. the one that equates a field with another field
    or a constant (field=field_item or field=const_item).
    If this is the case the function looks for a multiple equality
    in the lists referenced directly or indirectly by cond_equal inferring
    the given simple equality. If it doesn't find any, it builds a multiple
    equality that covers the predicate, i.e. the predicate can be inferred
    from it.
    from this multiple equality.
    The built multiple equality could be obtained in such a way:
    create a binary  multiple equality equivalent to the predicate, then
    merge it, if possible, with one of old multiple equalities.
    This guarantees that the set of multiple equalities covering equality
    predicates will
    be minimal.
    predicates will be minimal.

  EXAMPLE
    For the where condition
@@ -6391,7 +6392,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
    and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).

  NOTES
    Now only fields that have the same type defintions (verified by
    Now only fields that have the same type definitions (verified by
    the Field::eq_def method) are placed to the same multiple equalities.
    Because of this some equality predicates are not eliminated and
    can be used in the constant propagation procedure.
@@ -6424,18 +6425,14 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
    copying would be much more complicated.

  RETURN
    TRUE  - if the predicate is a simple equality predicate
    FALSE - otherwise
    TRUE    if the predicate is a simple equality predicate to be used
            for building multiple equalities
    FALSE   otherwise
*/

static bool check_equality(Item *item, COND_EQUAL *cond_equal)
{
  if (item->type() == Item::FUNC_ITEM &&
         ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
static bool check_simple_equality(Item *left_item, Item *right_item,
                                  Item *item, COND_EQUAL *cond_equal)
{
    Item *left_item= ((Item_func*) item)->arguments()[0];
    Item *right_item= ((Item_func*) item)->arguments()[1];

  if (left_item->type() == Item::REF_ITEM &&
      ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
  {
@@ -6463,9 +6460,6 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
    if (!left_field->eq_def(right_field))
      return FALSE;

      if (left_field->eq(right_field))  /* f = f */
        return TRUE;
      
    /* Search for multiple equalities containing field1 and/or field2 */
    bool left_copyfl, right_copyfl;
    Item_equal *left_item_equal=
@@ -6473,6 +6467,10 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
    Item_equal *right_item_equal= 
               find_item_equal(cond_equal, right_field, &right_copyfl);

    /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */
    if (left_field->eq(right_field)) /* f = f */
      return (!(left_field->maybe_null() && !left_item_equal)); 

    if (left_item_equal && left_item_equal == right_item_equal)
    {
      /* 
@@ -6555,7 +6553,16 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
      if (field_item->result_type() == STRING_RESULT)
      {
        CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset();
          if ((cs != ((Item_cond *) item)->compare_collation()) ||
        if (!item)
        {
          Item_func_eq *eq_item;
          if ((eq_item= new Item_func_eq(left_item, right_item)))
            return FALSE;
          eq_item->set_cmp_func();
          eq_item->quick_fix_field();
          item= eq_item;
        }  
        if ((cs != ((Item_func *) item)->compare_collation()) ||
            !cs->coll->propagate(cs, 0, 0))
          return FALSE;
      }
@@ -6584,10 +6591,116 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal)
      return TRUE;
    }
  }
  return FALSE;
}


/* 
  Convert row equalities into a conjunction of regular equalities

  SYNOPSIS
    check_row_equality()
      left_row   left term of the row equality to be processed     
      right_row  right term of the row equality to be processed
      cond_equal multiple equalities that must hold together with the predicate
      eq_list    results of conversions of row equalities that are not simple
                 enough to form multiple equalities

  DESCRIPTION
    The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n)
    into a list of equalities E1=E'1,...,En=E'n. For each of these equalities
    Ei=E'i the function checks whether it is a simple equality or a row equality.
    If it is a simple equality it is used to expand multiple equalities of
    cond_equal. If it is a row equality it converted to a sequence of equalities
    between row elements. If Ei=E'i is neither a simple equality nor a row
    equality the item for this predicate is added to eq_list.

  RETURN
    TRUE    if conversion has succeeded (no fatal error) 
    FALSE   otherwise  
*/
 
static bool check_row_equality(Item *left_row, Item_row *right_row,
                               COND_EQUAL *cond_equal, List<Item>* eq_list)
{ 
  uint n= left_row->cols();
  for (uint i= 0 ; i < n; i++)
  {
    bool is_converted;
    Item *left_item= left_row->el(i);
    Item *right_item= right_row->el(i);
    if (left_item->type() == Item::ROW_ITEM &&
        right_item->type() == Item::ROW_ITEM)
      is_converted= check_row_equality((Item_row *) left_item,
	                               (Item_row *) right_item,
				       cond_equal, eq_list);
    else 
      is_converted= check_simple_equality(left_item, right_item, 0, cond_equal);

    if (!is_converted)  
    {
      Item_func_eq *eq_item;
      if (!(eq_item= new Item_func_eq(left_item, right_item)))
        return FALSE;
      eq_item->set_cmp_func();
      eq_item->quick_fix_field();
      eq_list->push_back(eq_item);
    }
  }
  return TRUE;
}


/* 
  Eliminate row equalities and form multiple equalities predicates 

  SYNOPSIS
    check_equality()
      item       predicate to process     
      cond_equal multiple equalities that must hold together with the predicate
      eq_list    results of conversions of row equalities that are not simple
                 enough to form multiple equalities

  DESCRIPTION
    This function checks whether the item is a simple equality
    i.e. the one that equates a field with another field or a constant
    (field=field_item or field=constant_item), or, a row equality.
    For a simple equality the function looks for a multiple equality
    in the lists referenced directly or indirectly by cond_equal inferring
    the given simple equality. If it doesn't find any, it builds/expands
    multiple equality that covers the predicate.
    Row equalities are eliminated substituted for conjunctive regular equalities
    which are treated in the same way as original equality predicates.

  RETURN
    TRUE   if re-writing rules have been applied
    FALSE  otherwise, i.e.
           if the predicate is not an equality,
           or, if the equality is neither a simple one nor a row equality,
           or, if the procedure fails by a fatal error.
*/

static bool check_equality(Item *item, COND_EQUAL *cond_equal,
                           List<Item> *eq_list)
{
  if (item->type() == Item::FUNC_ITEM &&
         ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
  {
    Item *left_item= ((Item_func*) item)->arguments()[0];
    Item *right_item= ((Item_func*) item)->arguments()[1];

    if (left_item->type() == Item::ROW_ITEM &&
        right_item->type() == Item::ROW_ITEM)
      return check_row_equality((Item_row *) left_item,
                                (Item_row *) right_item,
                                cond_equal, eq_list);
    else 
      return check_simple_equality(left_item, right_item, item, cond_equal);
  } 
  return FALSE;
}

                          
/* 
  Replace all equality predicates in a condition by multiple equality items

@@ -6659,10 +6772,12 @@ static COND *build_equal_items_for_cond(COND *cond,
  Item_equal *item_equal;
  uint members;
  COND_EQUAL cond_equal;
  COND *new_cond;
  cond_equal.upper_levels= inherited;

  if (cond->type() == Item::COND_ITEM)
  {
    List<Item> eq_list;
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
    List<Item> *args= ((Item_cond*) cond)->argument_list();
@@ -6685,7 +6800,7 @@ static COND *build_equal_items_for_cond(COND *cond,
          structure here because it's restored before each
          re-execution of any prepared statement/stored procedure.
        */
        if (check_equality(item, &cond_equal))
        if (check_equality(item, &cond_equal, &eq_list))
          li.remove();
      }

@@ -6732,10 +6847,14 @@ static COND *build_equal_items_for_cond(COND *cond,
      }
    }
    if (and_level)
    {
      args->concat(&eq_list);
      args->concat((List<Item> *)&cond_equal.current_level);
    }
  }
  else if (cond->type() == Item::FUNC_ITEM)
  {
    List<Item> eq_list;
    /*
      If an equality predicate forms the whole and level,
      we call it standalone equality and it's processed here.
@@ -6746,13 +6865,46 @@ static COND *build_equal_items_for_cond(COND *cond,
      for WHERE a=b AND c=d AND (b=c OR d=5)
      b=c is replaced by =(a,b,c,d).  
     */
    if (check_equality(cond, &cond_equal) &&
        (item_equal= cond_equal.current_level.pop()))
    if (check_equality(cond, &cond_equal, &eq_list))
    {
      int n= cond_equal.current_level.elements + eq_list.elements;
      if (n == 0)
        return new Item_int((longlong) 1,1);
      else if (n == 1)
      {
        if ((item_equal= cond_equal.current_level.pop()))
        {
          item_equal->fix_length_and_dec();
          item_equal->update_used_tables();
          return item_equal;
	}
        else
          return eq_list.pop();
      }
      else
      {
        /* 
          Here a new AND level must be created. It can happen only
          when a row equality is processed as a standalone predicate.
	*/
        Item_cond_and *and_cond= new Item_cond_and(eq_list);
        and_cond->quick_fix_field();
        List<Item> *args= and_cond->argument_list();
        List_iterator_fast<Item_equal> it(cond_equal.current_level);
        while ((item_equal= it++))
        {
          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; 
        }
        and_cond->cond_equal= cond_equal;
        args->concat((List<Item> *)&cond_equal.current_level);
        
        return and_cond;
      }
    }
    /* 
      For each field reference in cond, not from equal item predicates,
      set a pointer to the multiple equality it belongs to (if there is any)
@@ -7038,7 +7190,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,

/* 
  Substitute every field reference in a condition by the best equal field 
  and eliminate all multiplle equality predicates
  and eliminate all multiple equality predicates
 
  SYNOPSIS
    substitute_for_best_equal_field()