From: Date: October 3 2005 4:23pm Subject: bk commit into 5.0 tree (evgen:1.2005) BUG#13327 List-Archive: http://lists.mysql.com/internals/30638 X-Bug: 13327 Message-Id: <20051003142318.9968113E8C6@localhost.moonbone.local> Below is the list of changes that have just been committed into a local 5.0 repository of evgen. When evgen does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2005 05/10/03 18:23:14 evgen@stripped +7 -0 Fix bug#13327 check_equality() wasn't checking view's fields check_equality() finds equalities among field items. It checks input items to be Item_fields thus skipping view's fields, which are represented by Item_direct_view_ref. Because of this index wasn't applied in all cases it can be. To fix this problem check_equality() now make all checks on item->real_item(). if it founds an equality it stores in Item_equal original item - Item_field or Item_direct_view_ref. Item_equal now stores list of Item_idents instead of Item_fields to be able to store refs. mysql-test/r/view.result 1.122 05/10/03 18:22:48 evgen@stripped +22 -0 Test case for bug #13327 view wasn't using index for const condition mysql-test/t/view.test 1.114 05/10/03 18:22:32 evgen@stripped +20 -0 Test case for bug #13327 view wasn't using index for const condition sql/item.cc 1.185 05/10/03 18:21:00 evgen@stripped +2 -2 Fix bug#13327 check_equality() wasn't checking view's fields sql/item_cmpfunc.cc 1.181 05/10/03 18:20:35 evgen@stripped +27 -26 Fix bug#13327 check_equality() wasn't checking view's fields sql/item_cmpfunc.h 1.116 05/10/03 18:19:41 evgen@stripped +10 -10 Fix bug#13327 check_equality() wasn't checking view's fields Make Item_equal to store list of Item_idents instead of Item_fields. sql/opt_range.cc 1.191 05/10/03 18:18:42 evgen@stripped +5 -4 Fix bug#13327 check_equality() wasn't checking view's fields sql/sql_select.cc 1.377 05/10/03 18:04:14 evgen@stripped +37 -22 Fix bug#13327 check_equality() wasn't checking view's fields check_equality() now make all checks on item->real_item(). if it founds an equality it stores in Item_equal original item - Item_field or Item_direct_view_ref. Item_equal now stores list of Item_idents instead of Item_fields to be able to store refs. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: evgen # Host: moonbone.local # Root: /work/13327-bug-5.0-mysql --- 1.184/sql/item.cc 2005-09-29 13:23:44 +04:00 +++ 1.185/sql/item.cc 2005-10-03 18:21:00 +04:00 @@ -3607,8 +3607,8 @@ { if (item_equal) { - Item_field *subst= item_equal->get_first(); - if (!field->eq(subst->field)) + Item *subst= item_equal->get_first(); + if (!field->eq(((Item_field*)subst->real_item())->field)) return subst; } return this; --- 1.180/sql/item_cmpfunc.cc 2005-09-29 05:20:26 +04:00 +++ 1.181/sql/item_cmpfunc.cc 2005-10-03 18:20:35 +04:00 @@ -3533,7 +3533,7 @@ return 0; } -Item_equal::Item_equal(Item_field *f1, Item_field *f2) +Item_equal::Item_equal(Item_ident *f1, Item_ident *f2) : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) { const_item_cache= 0; @@ -3541,7 +3541,7 @@ fields.push_back(f2); } -Item_equal::Item_equal(Item *c, Item_field *f) +Item_equal::Item_equal(Item *c, Item_ident *f) : Item_bool_func(), eval_item(0), cond_false(0) { const_item_cache= 0; @@ -3554,8 +3554,8 @@ : Item_bool_func(), eval_item(0), cond_false(0) { const_item_cache= 0; - List_iterator_fast li(item_equal->fields); - Item_field *item; + List_iterator_fast li(item_equal->fields); + Item_ident *item; while ((item= li++)) { fields.push_back(item); @@ -3579,7 +3579,7 @@ cond_false = !(func->val_int()); } -void Item_equal::add(Item_field *f) +void Item_equal::add(Item_ident *f) { fields.push_back(f); } @@ -3607,11 +3607,11 @@ bool Item_equal::contains(Field *field) { - List_iterator_fast it(fields); - Item_field *item; + List_iterator_fast it(fields); + Item_ident *item; while ((item= it++)) { - if (field->eq(item->field)) + if (field->eq(((Item_field*)item->real_item())->field)) return 1; } return 0; @@ -3680,20 +3680,21 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) { bool swap; - List_iterator it(fields); + List_iterator it(fields); do { - Item_field *item1= it++; - Item_field **ref1= it.ref(); - Item_field *item2; + Item_ident *item1= it++; + Item_ident **ref1= it.ref(); + Item_ident *item2; swap= FALSE; while ((item2= it++)) { - Item_field **ref2= it.ref(); - if (cmp(item1, item2, arg) < 0) + Item_ident **ref2= it.ref(); + if (cmp((Item_field*)item1->real_item(), + (Item_field*)item2->real_item(), arg) < 0) { - Item_field *item= *ref1; + Item_ident *item= *ref1; *ref1= *ref2; *ref2= item; swap= TRUE; @@ -3710,8 +3711,8 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) { - List_iterator_fast li(fields); - Item *item; + List_iterator_fast li(fields); + Item_ident *item; not_null_tables_cache= used_tables_cache= 0; const_item_cache= 0; while ((item=li++)) @@ -3730,8 +3731,8 @@ void Item_equal::update_used_tables() { - List_iterator_fast li(fields); - Item *item; + List_iterator_fast li(fields); + Item_ident *item; not_null_tables_cache= used_tables_cache= 0; if ((const_item_cache= cond_false)) return; @@ -3747,7 +3748,7 @@ { if (cond_false) return 0; - List_iterator_fast it(fields); + List_iterator_fast it(fields); Item *item= const_item ? const_item : it++; if ((null_value= item->null_value)) return 0; @@ -3771,8 +3772,8 @@ bool Item_equal::walk(Item_processor processor, byte *arg) { - List_iterator_fast it(fields); - Item *item; + List_iterator_fast it(fields); + Item_ident *item; while ((item= it++)) if (item->walk(processor, arg)) return 1; @@ -3781,8 +3782,8 @@ Item *Item_equal::transform(Item_transformer transformer, byte *arg) { - List_iterator it(fields); - Item *item; + List_iterator it(fields); + Item_ident *item; while ((item= it++)) { Item *new_item= item->transform(transformer, arg); @@ -3798,8 +3799,8 @@ { str->append(func_name()); str->append('('); - List_iterator_fast it(fields); - Item *item; + List_iterator_fast it(fields); + Item_ident *item; if (const_item) const_item->print(str); else --- 1.115/sql/item_cmpfunc.h 2005-09-29 05:05:43 +04:00 +++ 1.116/sql/item_cmpfunc.h 2005-10-03 18:19:41 +04:00 @@ -1151,7 +1151,7 @@ class Item_equal: public Item_bool_func { - List fields; /* list of equal field items */ + List fields; /* list of equal field items */ Item *const_item; /* optional constant item equal to fields items */ cmp_item *eval_item; bool cond_false; @@ -1160,15 +1160,15 @@ inline Item_equal() : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) { const_item_cache=0 ;} - Item_equal(Item_field *f1, Item_field *f2); - Item_equal(Item *c, Item_field *f); + Item_equal(Item_ident *f1, Item_ident *f2); + Item_equal(Item *c, Item_ident *f); Item_equal(Item_equal *item_equal); inline Item* get_const() { return const_item; } void add(Item *c); - void add(Item_field *f); + void add(Item_ident *f); uint members(); bool contains(Field *field); - Item_field* get_first() { return fields.head(); } + Item_ident* get_first() { return fields.head(); } void merge(Item_equal *item); enum Functype functype() const { return MULT_EQUAL_FUNC; } longlong val_int(); @@ -1202,20 +1202,20 @@ }; -class Item_equal_iterator : public List_iterator_fast +class Item_equal_iterator : public List_iterator_fast { public: inline Item_equal_iterator(Item_equal &item_equal) - :List_iterator_fast (item_equal.fields) + :List_iterator_fast (item_equal.fields) {} - inline Item_field* operator++(int) + inline Item* operator++(int) { - Item_field *item= (*(List_iterator_fast *) this)++; + Item_ident *item= (*(List_iterator_fast *) this)++; return item; } inline void rewind(void) { - List_iterator_fast::rewind(); + List_iterator_fast::rewind(); } }; --- 1.190/sql/opt_range.cc 2005-09-30 14:20:11 +04:00 +++ 1.191/sql/opt_range.cc 2005-10-03 18:18:42 +04:00 @@ -3554,9 +3554,10 @@ DBUG_RETURN(0); Item_equal_iterator it(*item_equal); ref_tables= value->used_tables(); - while ((field_item= it++)) + Item* item; + while ((item= it++)) { - Field *field= field_item->field; + Field *field= ((Item_field*)item->real_item())->field; Item_result cmp_type= field->cmp_type(); if (!((ref_tables | field->table->map) & param_comp)) { @@ -3611,10 +3612,10 @@ if (item_equal) { Item_equal_iterator it(*item_equal); - Item_field *item; + Item *item; while ((item= it++)) { - Field *f= item->field; + Field *f= ((Item_field*)item->real_item())->field; if (field->eq(f)) continue; if (!((ref_tables | f->table->map) & param_comp)) --- 1.376/sql/sql_select.cc 2005-09-30 01:34:15 +04:00 +++ 1.377/sql/sql_select.cc 2005-10-03 18:04:14 +04:00 @@ -2570,12 +2570,13 @@ the field for an equal field included into item_equal */ Item_equal_iterator it(*item_equal); - Item_field *item; + Item *item; while ((item= it++)) { - if (!field->eq(item->field)) + if (!field->eq(((Item_field*)item->real_item())->field)) { - add_key_field(key_fields, and_level, cond, item->field, + add_key_field(key_fields, and_level, cond, + ((Item_field*)item->real_item())->field, eq_func, val, num_values, usable_tables); } } @@ -2686,7 +2687,7 @@ Item_equal *item_equal= (Item_equal *) cond; Item *const_item= item_equal->get_const(); Item_equal_iterator it(*item_equal); - Item_field *item; + Item *item; if (const_item) { /* @@ -2696,7 +2697,8 @@ */ while ((item= it++)) { - add_key_field(key_fields, *and_level, cond_func, item->field, + add_key_field(key_fields, *and_level, cond_func, + ((Item_field*)item->real_item())->field, TRUE, &const_item, 1, usable_tables); } } @@ -2711,10 +2713,10 @@ Item_equal_iterator fi(*item_equal); while ((item= fi++)) { - Field *field= item->field; + Field *field= ((Item_field*)item->real_item())->field; while ((item= it++)) { - if (!field->eq(item->field)) + if (!field->eq(((Item_field*)item->real_item())->field)) { add_key_field(key_fields, *and_level, cond_func, field, TRUE, (Item **) &item, 1, usable_tables); @@ -6252,12 +6254,20 @@ 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]; + Item* orig_left_item, *orig_right_item; + Item *left_item= orig_left_item= ((Item_func*) item)->arguments()[0]; + Item *right_item= orig_right_item= ((Item_func*) item)->arguments()[1]; + if (left_item->type() == Item::REF_ITEM && + ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) + left_item= left_item->real_item(); + if (right_item->type() == Item::REF_ITEM && + ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) + right_item= right_item->real_item(); + if (left_item->type() == Item::FIELD_ITEM && right_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - !((Item_field*)right_item)->depended_from) + !((Item_ident*)orig_left_item)->depended_from && + !((Item_ident*)orig_right_item)->depended_from) { /* The predicate the form field1=field2 is processed */ @@ -6305,7 +6315,7 @@ { /* left item was found in the current or one of the upper levels */ if (! right_item_equal) - left_item_equal->add((Item_field *) right_item); + left_item_equal->add((Item_ident*)orig_right_item); else { /* Merge two multiple equalities forming a new one */ @@ -6320,12 +6330,12 @@ { /* left item was not found neither the current nor in upper levels */ if (right_item_equal) - right_item_equal->add((Item_field *) left_item); + right_item_equal->add((Item_ident*)orig_left_item); else { /* None of the fields was found in multiple equalities */ - Item_equal *item= new Item_equal((Item_field *) left_item, - (Item_field *) right_item); + Item_equal *item= new Item_equal((Item_ident *) orig_left_item, + (Item_ident *) orig_right_item); cond_equal->current_level.push_back(item); } } @@ -6336,18 +6346,21 @@ /* The predicate of the form field=const/const=field is processed */ Item *const_item= 0; Item_field *field_item= 0; + Item_ident* orig_field_item= 0; if (left_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && + !((Item_ident*)orig_left_item)->depended_from && right_item->const_item()) { field_item= (Item_field*) left_item; + orig_field_item= (Item_ident*) orig_left_item; const_item= right_item; } else if (right_item->type() == Item::FIELD_ITEM && - !((Item_field*)right_item)->depended_from && + !((Item_ident*)orig_right_item)->depended_from && left_item->const_item()) { field_item= (Item_field*) right_item; + orig_field_item= (Item_ident*)orig_right_item; const_item= left_item; } if (const_item && @@ -6381,7 +6394,7 @@ } else { - item_equal= new Item_equal(const_item, field_item); + item_equal= new Item_equal(const_item, (Item_ident*)orig_field_item); cond_equal->current_level.push_back(item_equal); } return TRUE; @@ -6784,11 +6797,12 @@ head= item_equal->get_first(); it++; } - Item_field *item_field; + Item *item_field; while ((item_field= it++)) { - Item_equal *upper= item_field->find_item_equal(upper_levels); - Item_field *item= item_field; + Item_equal *upper= + ((Item_field*)item_field->real_item())->find_item_equal(upper_levels); + Item *item= item_field; if (upper) { if (item_const && upper->get_const()) @@ -6798,7 +6812,8 @@ Item_equal_iterator li(*item_equal); while ((item= li++) != item_field) { - if (item->find_item_equal(upper_levels) == upper) + if (((Item_field*)item->real_item())->find_item_equal(upper_levels) == + upper) break; } } --- 1.121/mysql-test/r/view.result 2005-09-27 10:26:57 +04:00 +++ 1.122/mysql-test/r/view.result 2005-10-03 18:22:48 +04:00 @@ -2288,3 +2288,25 @@ 3 DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT, INDEX(a,b)); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 (a INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +INSERT INTO t3 VALUES (1),(2),(3); +CREATE VIEW v1 AS SELECT t1.* FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +CREATE VIEW v2 AS SELECT t3.* FROM t1,t3 WHERE t1.a=t3.a; +EXPLAIN SELECT t1.* FROM t1 JOIN t2 WHERE t1.a=t2.a AND t1.b=t2.b AND t1.a=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index +EXPLAIN SELECT * FROM v1 WHERE a=1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref a a 5 const 1 Using where; Using index +1 PRIMARY t2 ref a a 10 const,test.t1.b 2 Using where; Using index +EXPLAIN SELECT * FROM v2 WHERE a=1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ref a a 5 const 1 Using where; Using index +1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where +DROP VIEW v1,v2; +DROP TABLE t1,t2,t3; --- 1.113/mysql-test/t/view.test 2005-09-27 10:26:29 +04:00 +++ 1.114/mysql-test/t/view.test 2005-10-03 18:22:32 +04:00 @@ -2165,3 +2165,23 @@ DROP VIEW v1; DROP TABLE t1; + +# +# Bug #13327 view wasn't using index for const condition +# + +CREATE TABLE t1 (a INT, b INT, INDEX(a,b)); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 (a INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +INSERT INTO t2 VALUES (1,1),(2,2),(3,3); +INSERT INTO t3 VALUES (1),(2),(3); +CREATE VIEW v1 AS SELECT t1.* FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +CREATE VIEW v2 AS SELECT t3.* FROM t1,t3 WHERE t1.a=t3.a; +EXPLAIN SELECT t1.* FROM t1 JOIN t2 WHERE t1.a=t2.a AND t1.b=t2.b AND t1.a=1; +EXPLAIN SELECT * FROM v1 WHERE a=1; +EXPLAIN SELECT * FROM v2 WHERE a=1; +DROP VIEW v1,v2; +DROP TABLE t1,t2,t3; + +