1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge bk-internal:/home/bk/mysql-5.1

into  dl145s.mysql.com:/data0/bk/team_tree_merge/MERGE/mysql-5.1-opt
This commit is contained in:
gkodinov@dl145s.mysql.com
2006-11-28 17:14:16 +01:00
73 changed files with 2155 additions and 322 deletions

View File

@ -158,8 +158,8 @@ static int join_read_prev_same(READ_RECORD *info);
static int join_read_prev(READ_RECORD *info);
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
static int join_read_always_key_or_null(JOIN_TAB *tab);
static int join_read_next_same_or_null(READ_RECORD *info);
int join_read_always_key_or_null(JOIN_TAB *tab);
int join_read_next_same_or_null(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table,
table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
@ -505,11 +505,12 @@ err:
DBUG_RETURN(-1); /* purecov: inspected */
}
/*
test if it is known for optimisation IN subquery
SYNOPSYS
JOIN::test_in_subselect
SYNOPSIS
JOIN::test_in_subselect()
where - pointer for variable in which conditions should be
stored if subquery is known
@ -543,6 +544,35 @@ bool JOIN::test_in_subselect(Item **where)
}
/*
Check if the passed HAVING clause is a clause added by subquery optimizer
SYNOPSIS
is_having_subq_predicates()
having Having clause
RETURN
TRUE The passed HAVING clause was added by the subquery optimizer
FALSE Otherwise
*/
bool is_having_subq_predicates(Item *having)
{
if (having->type() == Item::FUNC_ITEM)
{
if (((Item_func *) having)->functype() == Item_func::ISNOTNULLTEST_FUNC)
return TRUE;
if (((Item_func *) having)->functype() == Item_func::TRIG_COND_FUNC)
{
having= ((Item_func*)having)->arguments()[0];
if (((Item_func *) having)->functype() == Item_func::ISNOTNULLTEST_FUNC)
return TRUE;
}
return TRUE;
}
return FALSE;
}
/*
global select optimisation.
return 0 - success
@ -1028,9 +1058,7 @@ JOIN::optimize()
}
} else if (join_tab[0].type == JT_REF_OR_NULL &&
join_tab[0].ref.items[0]->name == in_left_expr_name &&
having->type() == Item::FUNC_ITEM &&
((Item_func *) having)->functype() ==
Item_func::ISNOTNULLTEST_FUNC)
is_having_subq_predicates(having))
{
join_tab[0].type= JT_INDEX_SUBQUERY;
error= 0;
@ -1276,14 +1304,14 @@ JOIN::reinit()
exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
exec_tmp_table1->file->delete_all_rows();
free_io_cache(exec_tmp_table1);
filesort_free_buffers(exec_tmp_table1);
filesort_free_buffers(exec_tmp_table1,0);
}
if (exec_tmp_table2)
{
exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
exec_tmp_table2->file->delete_all_rows();
free_io_cache(exec_tmp_table2);
filesort_free_buffers(exec_tmp_table2);
filesort_free_buffers(exec_tmp_table2,0);
}
if (items0)
set_items_ref_array(items0);
@ -1446,6 +1474,7 @@ JOIN::exec()
curr_join->examined_rows= 0;
if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
!thd->lex->describe &&
get_schema_tables_result(curr_join))
{
DBUG_VOID_RETURN;
@ -2547,6 +2576,9 @@ typedef struct key_field_t { // Used when finding key fields
when val IS NULL.
*/
bool null_rejecting;
/* TRUE<=> This ref access is an outer subquery reference access */
bool outer_ref;
} KEY_FIELD;
/* Values in optimize */
@ -2848,6 +2880,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
((*value)->type() == Item::FIELD_ITEM) &&
((Item_field*)*value)->field->maybe_null());
(*key_fields)->outer_ref= FALSE;
(*key_fields)++;
}
@ -2906,7 +2939,7 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
}
static void
add_key_fields(KEY_FIELD **key_fields,uint *and_level,
add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
COND *cond, table_map usable_tables,
SARGABLE_PARAM **sargables)
{
@ -2919,28 +2952,56 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
{
Item *item;
while ((item=li++))
add_key_fields(key_fields,and_level,item,usable_tables,sargables);
add_key_fields(join, key_fields, and_level, item, usable_tables,
sargables);
for (; org_key_fields != *key_fields ; org_key_fields++)
org_key_fields->level= *and_level;
}
else
{
(*and_level)++;
add_key_fields(key_fields,and_level,li++,usable_tables,sargables);
add_key_fields(join, key_fields, and_level, li++, usable_tables,
sargables);
Item *item;
while ((item=li++))
{
KEY_FIELD *start_key_fields= *key_fields;
(*and_level)++;
add_key_fields(key_fields,and_level,item,usable_tables,sargables);
add_key_fields(join, key_fields, and_level, item, usable_tables,
sargables);
*key_fields=merge_key_fields(org_key_fields,start_key_fields,
*key_fields,++(*and_level));
}
}
return;
}
/* If item is of type 'field op field/constant' add it to key_fields */
/*
Subquery optimization: check if the encountered condition is one
added by condition push down into subquery.
*/
{
if (cond->type() == Item::FUNC_ITEM &&
((Item_func*)cond)->functype() == Item_func::TRIG_COND_FUNC)
{
cond= ((Item_func*)cond)->arguments()[0];
if (!join->group_list && !join->order &&
join->unit->item &&
join->unit->item->substype() == Item_subselect::IN_SUBS &&
!join->unit->first_select()->next_select())
{
KEY_FIELD *save= *key_fields;
add_key_fields(join, key_fields, and_level, cond, usable_tables,
sargables);
// Indicate that this ref access candidate is for subquery lookup:
for (; save != *key_fields; save++)
save->outer_ref= TRUE;
}
return;
}
}
/* If item is of type 'field op field/constant' add it to key_fields */
if (cond->type() != Item::FUNC_ITEM)
return;
Item_func *cond_func= (Item_func*) cond;
@ -3114,6 +3175,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
keyuse.used_tables=key_field->val->used_tables();
keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
keyuse.null_rejecting= key_field->null_rejecting;
keyuse.outer_ref= key_field->outer_ref;
VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}
}
@ -3236,7 +3298,7 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
Here we can add 'ref' access candidates for t1 and t2, but not for t3.
*/
static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
static void add_key_fields_for_nj(JOIN *join, TABLE_LIST *nested_join_table,
KEY_FIELD **end, uint *and_level,
SARGABLE_PARAM **sargables)
{
@ -3248,12 +3310,13 @@ static void add_key_fields_for_nj(TABLE_LIST *nested_join_table,
while ((table= li++))
{
if (table->nested_join)
add_key_fields_for_nj(table, end, and_level, sargables);
add_key_fields_for_nj(join, table, end, and_level, sargables);
else
if (!table->on_expr)
tables |= table->table->map;
}
add_key_fields(end, and_level, nested_join_table->on_expr, tables, sargables);
add_key_fields(join, end, and_level, nested_join_table->on_expr, tables,
sargables);
}
@ -3328,7 +3391,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
return TRUE;
if (cond)
{
add_key_fields(&end,&and_level,cond,normal_tables,sargables);
add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables,
sargables);
for (; field != end ; field++)
{
add_key_part(keyuse,field);
@ -3350,8 +3414,9 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
into account as well.
*/
if (*join_tab[i].on_expr_ref)
add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
join_tab[i].table->map,sargables);
add_key_fields(join_tab->join, &end, &and_level,
*join_tab[i].on_expr_ref,
join_tab[i].table->map, sargables);
}
/* Process ON conditions for the nested joins */
@ -3361,7 +3426,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
while ((table= li++))
{
if (table->nested_join)
add_key_fields_for_nj(table, &end, &and_level, sargables);
add_key_fields_for_nj(join_tab->join, table, &end, &and_level,
sargables);
}
}
@ -6257,7 +6323,7 @@ void JOIN::cleanup(bool full)
if (tables > const_tables) // Test for not-const tables
{
free_io_cache(table[const_tables]);
filesort_free_buffers(table[const_tables]);
filesort_free_buffers(table[const_tables],full);
}
if (full)
@ -11012,6 +11078,13 @@ join_init_quick_read_record(JOIN_TAB *tab)
}
int rr_sequential(READ_RECORD *info);
int init_read_record_seq(JOIN_TAB *tab)
{
tab->read_record.read_record= rr_sequential;
return tab->read_record.file->ha_rnd_init(1);
}
static int
test_if_quick_select(JOIN_TAB *tab)
{
@ -11141,7 +11214,7 @@ join_ft_read_next(READ_RECORD *info)
Reading of key with key reference and one part that may be NULL
*/
static int
int
join_read_always_key_or_null(JOIN_TAB *tab)
{
int res;
@ -11157,7 +11230,7 @@ join_read_always_key_or_null(JOIN_TAB *tab)
}
static int
int
join_read_next_same_or_null(READ_RECORD *info)
{
int error;
@ -12427,6 +12500,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
/* Fill schema tables with data before filesort if it's necessary */
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
!thd->lex->describe &&
get_schema_tables_result(join))
goto err;
@ -13762,9 +13836,16 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
if (real_pos->type() == Item::FIELD_ITEM)
{
Item_field *item;
pos= real_pos;
if (!(item= new Item_field(thd, ((Item_field*) pos))))
if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
goto err;
if (pos->type() == Item::REF_ITEM)
{
/* preserve the names of the ref when dereferncing */
Item_ref *ref= (Item_ref *) pos;
item->db_name= ref->db_name;
item->table_name= ref->table_name;
item->name= ref->name;
}
pos= item;
if (item->field->flags & BLOB_FLAG)
{