=== modified file 'sql/sql_select.cc' --- sql/sql_select.cc 2009-11-05 12:13:00 +0000 +++ sql/sql_select.cc 2009-11-15 20:17:24 +0000 @@ -192,7 +192,7 @@ static COND *make_cond_for_table_from_pr table_map tables, table_map used_table, bool exclude_expensive_cond); -static Item* part_of_refkey(TABLE *form,Field *field); +static Item* part_of_refkey(TABLE *form,Field *field,uint *part_no); uint find_shortest_key(TABLE *table, const key_map *usable_keys); static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, ha_rows select_limit, bool no_changes, @@ -246,8 +246,9 @@ void select_describe(JOIN *join, bool ne bool distinct, const char *message=NullS); static Item *remove_additional_cond(Item* conds); static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab); -static bool test_if_ref(Item *root_cond, - Item_field *left_item,Item *right_item); +static bool test_if_ref(COND *root_cond, + Item_field *left_item,Item *right_item, + COND *ref_cond); static bool replace_where_subcondition(JOIN *join, Item **expr, Item *old_cond, Item *new_cond, bool do_fix_fields); @@ -997,7 +998,7 @@ void JOIN::remove_subq_pushed_predicates ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM && test_if_ref (this->conds, (Item_field *)((Item_func *)conds)->arguments()[1], - ((Item_func *)conds)->arguments()[0])) + ((Item_func *)conds)->arguments()[0],NULL)) { *where= 0; return; @@ -8210,6 +8211,7 @@ static bool create_ref_for_key(JOIN *joi !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) * (keyparts+1)))) || !(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)) || + !(j->ref.conds= (COND**) thd->alloc(sizeof(COND*)*keyparts)) || !(j->ref.cond_guards= (bool**) thd->alloc(sizeof(uint*)*keyparts))) { DBUG_RETURN(TRUE); @@ -8244,6 +8246,7 @@ static bool create_ref_for_key(JOIN *joi uint maybe_null= test(keyinfo->key_part[i].null_bit); j->ref.items[i]=keyuse->val; // Save for cond removal + j->ref.conds[i]=0; j->ref.cond_guards[i]= keyuse->cond_guard; if (keyuse->null_rejecting) j->ref.null_rejecting |= 1 << i; @@ -17758,8 +17761,10 @@ end_write_group(JOIN *join, JOIN_TAB *jo */ static bool test_if_ref(COND *root_cond, - Item_field *left_item,Item *right_item) + Item_field *left_item,Item *right_item, + COND *ref_cond) { + bool res= FALSE; Field *field=left_item->field; JOIN_TAB *join_tab= field->table->reginfo.join_tab; // No need to change const test @@ -17767,16 +17772,17 @@ static bool test_if_ref(COND *root_cond, (!join_tab->first_inner || *join_tab->first_inner->on_expr_ref == root_cond)) { - Item *ref_item=part_of_refkey(field->table,field); + uint part_no; + Item *ref_item=part_of_refkey(field->table,field,&part_no); if (ref_item && ref_item->eq(right_item,1)) { right_item= right_item->real_item(); if (right_item->type() == Item::FIELD_ITEM) - return (field->eq_def(((Item_field *) right_item)->field)); + res= (field->eq_def(((Item_field *) right_item)->field)); /* remove equalities injected by IN->EXISTS transformation */ else if (right_item->type() == Item::CACHE_ITEM) - return ((Item_cache *)right_item)->eq_def (field); - if (right_item->const_item() && !(right_item->is_null())) + res= ((Item_cache *)right_item)->eq_def (field); + else if (right_item->const_item() && !(right_item->is_null())) { /* We can remove binary fields and numerical fields except float, @@ -17796,12 +17802,14 @@ static bool test_if_ref(COND *root_cond, field->real_type() != MYSQL_TYPE_VARCHAR && (field->type() != MYSQL_TYPE_FLOAT || field->decimals() == 0)) { - return !store_val_in_field(field, right_item, CHECK_FIELD_WARN); + res= !store_val_in_field(field, right_item, CHECK_FIELD_WARN); } } + if (res) + field->table->reginfo.join_tab->ref.conds[part_no]= ref_cond; } } - return 0; // keep test + return res; // keep test } /** @@ -18004,13 +18012,13 @@ make_cond_for_table_from_pred(COND *root Item *left_item= ((Item_func*) cond)->arguments()[0]->real_item(); Item *right_item= ((Item_func*) cond)->arguments()[1]->real_item(); if (left_item->type() == Item::FIELD_ITEM && - test_if_ref(root_cond, (Item_field*) left_item,right_item)) + test_if_ref(root_cond, (Item_field*) left_item,right_item,cond)) { cond->marker=3; // Checked when read return (COND*) 0; } if (right_item->type() == Item::FIELD_ITEM && - test_if_ref(root_cond, (Item_field*) right_item,left_item)) + test_if_ref(root_cond, (Item_field*) right_item,left_item,cond)) { cond->marker=3; // Checked when read return (COND*) 0; @@ -18106,13 +18114,13 @@ make_cond_after_sjm(Item *root_cond, Ite Item *left_item= ((Item_func*) cond)->arguments()[0]->real_item(); Item *right_item= ((Item_func*) cond)->arguments()[1]->real_item(); if (left_item->type() == Item::FIELD_ITEM && - test_if_ref(root_cond, (Item_field*) left_item,right_item)) + test_if_ref(root_cond, (Item_field*) left_item,right_item,NULL)) { cond->marker=3; // Checked when read return (COND*) 0; } if (right_item->type() == Item::FIELD_ITEM && - test_if_ref(root_cond, (Item_field*) right_item,left_item)) + test_if_ref(root_cond, (Item_field*) right_item,left_item,NULL)) { cond->marker=3; // Checked when read return (COND*) 0; @@ -18124,7 +18132,7 @@ make_cond_after_sjm(Item *root_cond, Ite static Item * -part_of_refkey(TABLE *table,Field *field) +part_of_refkey(TABLE *table,Field *field,uint *part_no) { if (!table->reginfo.join_tab) return (Item*) 0; // field from outer non-select (UPDATE,...) @@ -18145,7 +18153,10 @@ part_of_refkey(TABLE *table,Field *field for (part=0 ; part < ref_parts ; part++,key_part++) if (field->eq(key_part->field) && !(key_part->key_part_flag & HA_PART_KEY_SEG)) + { + *part_no= part; return table->reginfo.join_tab->ref.items[part]; + } } return (Item*) 0; } @@ -20872,23 +20883,26 @@ static bool add_ref_to_table_cond(THD *t DBUG_RETURN(FALSE); Item_cond_and *cond=new Item_cond_and(); - TABLE *table=join_tab->table; int error; if (!cond) DBUG_RETURN(TRUE); for (uint i=0 ; i < join_tab->ref.key_parts ; i++) - { - Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i]. - fieldnr-1]; - Item *value=join_tab->ref.items[i]; - cond->add(new Item_func_equal(new Item_field(field), value)); + { + COND *ref_cond= join_tab->ref.conds[i]; + if(ref_cond && cond->add(ref_cond)) + DBUG_RETURN(TRUE); } if (thd->is_fatal_error) DBUG_RETURN(TRUE); +#if 0 if (!cond->fixed) cond->fix_fields(thd, (Item**)&cond); +#else + cond->quick_fix_field(); +#endif + if (join_tab->select) { error=(int) cond->add(join_tab->select->cond); === modified file 'sql/sql_select.h' --- sql/sql_select.h 2009-11-02 15:16:58 +0000 +++ sql/sql_select.h 2009-11-15 05:55:19 +0000 @@ -77,6 +77,7 @@ typedef struct st_table_ref uchar *key_buff2; ///< key_buff+key_length store_key **key_copy; // Item **items; ///< val()'s for each keypart + COND **conds; // conditions used /* Array of pointers to trigger variables. Some/all of the pointers may be NULL. The ref access can be used iff