Commit 71c4cc4a authored by timour@mysql.com's avatar timour@mysql.com

WL#1972 - manual merge with latest bk source

parent 866abfdd
...@@ -91,7 +91,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, ...@@ -91,7 +91,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
uint select_options, const char *info, uint select_options, const char *info,
Item *having, Procedure *proc, Item *having, Procedure *proc,
SELECT_LEX_UNIT *unit); SELECT_LEX_UNIT *unit);
static COND *build_equal_items(COND *cond, static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited, COND_EQUAL *inherited,
List<TABLE_LIST> *join_list, List<TABLE_LIST> *join_list,
COND_EQUAL **cond_equal_ref); COND_EQUAL **cond_equal_ref);
...@@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond, ...@@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
COND *conds, bool top); COND *conds, bool top);
static COND *optimize_cond(JOIN *join, COND *conds, static COND *optimize_cond(JOIN *join, COND *conds,
List<TABLE_LIST> *join_list,
Item::cond_result *cond_value); Item::cond_result *cond_value);
static bool resolve_nested_join (TABLE_LIST *table); static bool resolve_nested_join (TABLE_LIST *table);
static COND *remove_eq_conds(THD *thd, COND *cond, static COND *remove_eq_conds(THD *thd, COND *cond,
...@@ -191,6 +192,7 @@ static void init_tmptable_sum_functions(Item_sum **func); ...@@ -191,6 +192,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr); static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func); static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
...@@ -228,15 +230,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -228,15 +230,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->options | thd->options, select_lex->options | thd->options,
result, unit, select_lex); result, unit, select_lex);
} }
/* Don't set res if it's -1 as we may want this later */
DBUG_PRINT("info",("res: %d report_error: %d", res, DBUG_PRINT("info",("res: %d report_error: %d", res,
thd->net.report_error)); thd->net.report_error));
if (thd->net.report_error) if (thd->net.report_error || res < 0)
res= 1;
if (unlikely(res))
{ {
if (res > 0)
result->send_error(0, NullS); result->send_error(0, NullS);
result->abort(); result->abort();
res= 1; // Error sent to client res= 1; // Error sent to client
...@@ -333,7 +330,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -333,7 +330,7 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having_fix_rc || thd->net.report_error) if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func) if (having->with_sum_func)
having->split_sum_func(ref_pointer_array, all_fields); having->split_sum_func(thd, ref_pointer_array, all_fields);
} }
if (!thd->lex->view_prepare_mode) if (!thd->lex->view_prepare_mode)
...@@ -558,17 +555,7 @@ JOIN::optimize() ...@@ -558,17 +555,7 @@ JOIN::optimize()
thd->restore_backup_item_arena(arena, &backup); thd->restore_backup_item_arena(arena, &backup);
} }
/* conds= optimize_cond(this, conds, join_list, &cond_value);
Build all multiple equality predicates and eliminate equality
predicates that can be inferred from these multiple equalities.
For each reference of a field included into a multiple equality
that occurs in a function set a pointer to the multiple equality
predicate. Substitute a constant instead of this field if the
multiple equality contains a constant.
*/
conds= build_equal_items(conds, NULL, join_list, &cond_equal);
conds= optimize_cond(this, conds,&cond_value);
if (thd->net.report_error) if (thd->net.report_error)
{ {
error= 1; error= 1;
...@@ -686,6 +673,7 @@ JOIN::optimize() ...@@ -686,6 +673,7 @@ JOIN::optimize()
{ {
conds= substitute_for_best_equal_field(conds, cond_equal, map2table); conds= substitute_for_best_equal_field(conds, cond_equal, map2table);
conds->update_used_tables(); conds->update_used_tables();
DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
} }
/* /*
Permorm the the optimization on fields evaluation mentioned above Permorm the the optimization on fields evaluation mentioned above
...@@ -1003,13 +991,15 @@ JOIN::optimize() ...@@ -1003,13 +991,15 @@ JOIN::optimize()
if (create_sort_index(thd, this, group_list, if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR) || HA_POS_ERROR, HA_POS_ERROR) ||
alloc_group_fields(this, group_list) || alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1)) make_sum_func_list(all_fields, fields_list, 1) ||
setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1); DBUG_RETURN(1);
group_list=0; group_list=0;
} }
else else
{ {
if (make_sum_func_list(all_fields, fields_list, 0)) if (make_sum_func_list(all_fields, fields_list, 0) ||
setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1); DBUG_RETURN(1);
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order) if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{ {
...@@ -1385,6 +1375,7 @@ JOIN::exec() ...@@ -1385,6 +1375,7 @@ JOIN::exec()
} }
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) || 1, TRUE) ||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0))) 0)))
{ {
...@@ -1472,7 +1463,9 @@ JOIN::exec() ...@@ -1472,7 +1463,9 @@ JOIN::exec()
set_items_ref_array(items3); set_items_ref_array(items3);
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) || thd->is_fatal_error) 1, TRUE) ||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
thd->is_fatal_error)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (curr_join->group_list || curr_join->order) if (curr_join->group_list || curr_join->order)
...@@ -1665,9 +1658,13 @@ Cursor::init_from_thd(THD *thd) ...@@ -1665,9 +1658,13 @@ Cursor::init_from_thd(THD *thd)
/* /*
We need to save and reset thd->mem_root, otherwise it'll be freed We need to save and reset thd->mem_root, otherwise it'll be freed
later in mysql_parse. later in mysql_parse.
We can't just change the thd->mem_root here as we want to keep the things
that is already allocated in thd->mem_root for Cursor::fetch()
*/ */
mem_root= thd->mem_root; main_mem_root= *thd->mem_root;
init_sql_alloc(&thd->mem_root, /* Allocate new memory root for thd */
init_sql_alloc(thd->mem_root,
thd->variables.query_alloc_block_size, thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size); thd->variables.query_prealloc_size);
...@@ -1696,8 +1693,6 @@ Cursor::init_from_thd(THD *thd) ...@@ -1696,8 +1693,6 @@ Cursor::init_from_thd(THD *thd)
void void
Cursor::init_thd(THD *thd) Cursor::init_thd(THD *thd)
{ {
thd->mem_root= mem_root;
DBUG_ASSERT(thd->derived_tables == 0); DBUG_ASSERT(thd->derived_tables == 0);
thd->derived_tables= derived_tables; thd->derived_tables= derived_tables;
...@@ -1707,7 +1702,6 @@ Cursor::init_thd(THD *thd) ...@@ -1707,7 +1702,6 @@ Cursor::init_thd(THD *thd)
DBUG_ASSERT(thd->lock== 0); DBUG_ASSERT(thd->lock== 0);
thd->lock= lock; thd->lock= lock;
thd->query_id= query_id; thd->query_id= query_id;
thd->free_list= free_list;
} }
...@@ -1725,11 +1719,10 @@ int ...@@ -1725,11 +1719,10 @@ int
Cursor::open(JOIN *join_arg) Cursor::open(JOIN *join_arg)
{ {
join= join_arg; join= join_arg;
THD *thd= join->thd; THD *thd= join->thd;
/* First non-constant table */ /* First non-constant table */
JOIN_TAB *join_tab= join->join_tab + join->const_tables; JOIN_TAB *join_tab= join->join_tab + join->const_tables;
DBUG_ENTER("Cursor::open");
/* /*
Send fields description to the client; server_status is sent Send fields description to the client; server_status is sent
...@@ -1751,7 +1744,9 @@ Cursor::open(JOIN *join_arg) ...@@ -1751,7 +1744,9 @@ Cursor::open(JOIN *join_arg)
join->fetch_limit= join->unit->offset_limit_cnt; join->fetch_limit= join->unit->offset_limit_cnt;
/* Disable JOIN CACHE as it is not working with cursors yet */ /* Disable JOIN CACHE as it is not working with cursors yet */
for (JOIN_TAB *tab= join_tab; tab != join->join_tab + join->tables - 1; ++tab) for (JOIN_TAB *tab= join_tab;
tab != join->join_tab + join->tables - 1;
tab++)
{ {
if (tab->next_select == sub_select_cache) if (tab->next_select == sub_select_cache)
tab->next_select= sub_select; tab->next_select= sub_select;
...@@ -1765,7 +1760,7 @@ Cursor::open(JOIN *join_arg) ...@@ -1765,7 +1760,7 @@ Cursor::open(JOIN *join_arg)
*/ */
DBUG_ASSERT(join_tab->table->null_row == 0); DBUG_ASSERT(join_tab->table->null_row == 0);
return join_tab->read_first_record(join_tab); DBUG_RETURN(join_tab->read_first_record(join_tab));
} }
...@@ -1784,13 +1779,15 @@ int ...@@ -1784,13 +1779,15 @@ int
Cursor::fetch(ulong num_rows) Cursor::fetch(ulong num_rows)
{ {
THD *thd= join->thd; THD *thd= join->thd;
JOIN_TAB *join_tab= join->join_tab + join->const_tables;; JOIN_TAB *join_tab= join->join_tab + join->const_tables;
COND *on_expr= *join_tab->on_expr_ref; COND *on_expr= *join_tab->on_expr_ref;
COND *select_cond= join_tab->select_cond; COND *select_cond= join_tab->select_cond;
READ_RECORD *info= &join_tab->read_record; READ_RECORD *info= &join_tab->read_record;
int error= 0; int error= 0;
/* save references to memory, allocated during fetch */
thd->set_n_backup_item_arena(this, &thd->stmt_backup);
join->fetch_limit+= num_rows; join->fetch_limit+= num_rows;
/* /*
...@@ -1855,53 +1852,37 @@ Cursor::fetch(ulong num_rows) ...@@ -1855,53 +1852,37 @@ Cursor::fetch(ulong num_rows)
if (thd->net.report_error) if (thd->net.report_error)
error= -1; error= -1;
switch (error) { if (error == -3) /* LIMIT clause worked */
/* Fetch limit worked, possibly more rows are there */ error= 0;
case -4:
#ifdef USING_TRANSACTIONS
if (thd->transaction.all.innobase_tid) if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd); ha_release_temporary_latches(thd);
#endif
thd->restore_backup_item_arena(this, &thd->stmt_backup);
if (error == -4)
{
/* Fetch limit worked, possibly more rows are there */
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
::send_eof(thd); ::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
/* save references to memory, allocated during fetch */ }
mem_root= thd->mem_root; else
free_list= thd->free_list; {
break;
/* Limit clause worked: this is the same as 'no more rows' */
case -3: /* LIMIT clause worked */
error= 0;
/* fallthrough */
case 0: /* No more rows */
if (thd->transaction.all.innobase_tid)
ha_release_temporary_latches(thd);
close(); close();
if (error == 0)
{
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT; thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
::send_eof(thd); ::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT; thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
join= 0; }
unit= 0; else
free_items(thd->free_list); send_error(thd, ER_OUT_OF_RESOURCES);
thd->free_list= free_list= 0; /* free cursor memory */
/* free_items(free_list);
Must be last, as some memory might be allocated for free purposes, free_list= 0;
like in free_tmp_table() (TODO: fix this issue) free_root(&main_mem_root, MYF(0));
*/
mem_root= thd->mem_root;
free_root(&mem_root, MYF(0));
break;
default:
close();
join= 0;
unit= 0;
free_items(thd->free_list);
thd->free_list= free_list= 0;
/*
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
*/
mem_root= thd->mem_root;
free_root(&mem_root, MYF(0));
break;
} }
return error; return error;
} }
...@@ -1939,6 +1920,8 @@ Cursor::close() ...@@ -1939,6 +1920,8 @@ Cursor::close()
thd->derived_tables= tmp_derived_tables; thd->derived_tables= tmp_derived_tables;
thd->lock= tmp_lock; thd->lock= tmp_lock;
} }
join= 0;
unit= 0;
} }
...@@ -1951,7 +1934,7 @@ Cursor::~Cursor() ...@@ -1951,7 +1934,7 @@ Cursor::~Cursor()
Must be last, as some memory might be allocated for free purposes, Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue) like in free_tmp_table() (TODO: fix this issue)
*/ */
free_root(&mem_root, MYF(0)); free_root(&main_mem_root, MYF(0));
} }
/*********************************************************************/ /*********************************************************************/
...@@ -5030,7 +5013,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) ...@@ -5030,7 +5013,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
{ {
tmp= new Item_func_trig_cond(tmp, &tab->found); tmp= new Item_func_trig_cond(tmp, &tab->found);
} }
if (!tmp) if (tmp)
tmp->quick_fix_field(); tmp->quick_fix_field();
return tmp; return tmp;
} }
...@@ -5304,8 +5287,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -5304,8 +5287,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/* Join with outer join condition */ /* Join with outer join condition */
COND *orig_cond=sel->cond; COND *orig_cond=sel->cond;
sel->cond= and_conds(sel->cond, *tab->on_expr_ref); sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
/*
We can't call sel->cond->fix_fields,
as it will break tab->on_expr if it's AND condition
(fix_fields currently removes extra AND/OR levels).
Yet attributes of the just built condition are not needed.
Thus we call sel->cond->quick_fix_field for safety.
*/
if (sel->cond && !sel->cond->fixed) if (sel->cond && !sel->cond->fixed)
sel->cond->fix_fields(join->thd, 0, &sel->cond); sel->cond->quick_fix_field();
if (sel->test_quick_select(join->thd, tab->keys, if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map, used_tables & ~ current_map,
(join->select_options & (join->select_options &
...@@ -6030,7 +6022,7 @@ template class List_iterator<Item_func_match>; ...@@ -6030,7 +6022,7 @@ template class List_iterator<Item_func_match>;
find_item_equal() find_item_equal()
cond_equal multiple equalities to search in cond_equal multiple equalities to search in
field field to look for field field to look for
inherited_fl :out set up to TRUE iff multiple equality is found inherited_fl :out set up to TRUE if multiple equality is found
on upper levels (not on current level of cond_equal) on upper levels (not on current level of cond_equal)
DESCRIPTION DESCRIPTION
...@@ -6448,12 +6440,14 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -6448,12 +6440,14 @@ static COND *build_equal_items_for_cond(COND *cond,
return cond; return cond;
} }
/* /*
Build multiple equalities for a condition and all on expressions that Build multiple equalities for a condition and all on expressions that
inherit these multiple equalities inherit these multiple equalities
SYNOPSIS SYNOPSIS
build_equal_items() build_equal_items()
thd Thread handler
cond condition to build the multiple equalities for cond condition to build the multiple equalities for
inherited path to all inherited multiple equality items inherited path to all inherited multiple equality items
join_list list of join tables to which the condition refers to join_list list of join tables to which the condition refers to
...@@ -6505,7 +6499,7 @@ static COND *build_equal_items_for_cond(COND *cond, ...@@ -6505,7 +6499,7 @@ static COND *build_equal_items_for_cond(COND *cond,
pointer to the transformed condition containing multiple equalities pointer to the transformed condition containing multiple equalities
*/ */
static COND *build_equal_items(COND *cond, static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited, COND_EQUAL *inherited,
List<TABLE_LIST> *join_list, List<TABLE_LIST> *join_list,
COND_EQUAL **cond_equal_ref) COND_EQUAL **cond_equal_ref)
...@@ -6542,12 +6536,13 @@ static COND *build_equal_items(COND *cond, ...@@ -6542,12 +6536,13 @@ static COND *build_equal_items(COND *cond,
{ {
if (table->on_expr) if (table->on_expr)
{ {
Item *expr;
List<TABLE_LIST> *join_list= table->nested_join ? List<TABLE_LIST> *join_list= table->nested_join ?
&table->nested_join->join_list : NULL; &table->nested_join->join_list : NULL;
table->on_expr= build_equal_items(table->on_expr, expr= build_equal_items(thd, table->on_expr, inherited, join_list,
inherited,
join_list,
&table->cond_equal); &table->cond_equal);
if (expr != table->on_expr)
thd->change_item_tree(&table->on_expr, expr);
} }
} }
} }
...@@ -6555,6 +6550,7 @@ static COND *build_equal_items(COND *cond, ...@@ -6555,6 +6550,7 @@ static COND *build_equal_items(COND *cond,
return cond; return cond;
} }
/* /*
Compare field items by table order in the execution plan Compare field items by table order in the execution plan
...@@ -6649,10 +6645,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, ...@@ -6649,10 +6645,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
List<Item> eq_list; List<Item> eq_list;
Item_func_eq *eq_item= 0; Item_func_eq *eq_item= 0;
if (((Item *) item_equal)->const_item() && !item_equal->val_int()) if (((Item *) item_equal)->const_item() && !item_equal->val_int())
{ return new Item_int((longlong) 0,1);
cond= new Item_int((char*) "FALSE",0,1);
return cond;
}
Item *item_const= item_equal->get_const(); Item *item_const= item_equal->get_const();
Item_equal_iterator it(*item_equal); Item_equal_iterator it(*item_equal);
Item *head; Item *head;
...@@ -6695,8 +6688,13 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, ...@@ -6695,8 +6688,13 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
} }
if (!cond && !eq_list.head()) if (!cond && !eq_list.head())
{
if (!eq_item)
return new Item_int((longlong) 1,1);
return eq_item; return eq_item;
}
if (eq_item)
eq_list.push_back(eq_item); eq_list.push_back(eq_item);
if (!cond) if (!cond)
cond= new Item_cond_and(eq_list); cond= new Item_cond_and(eq_list);
...@@ -6799,14 +6797,16 @@ static COND* substitute_for_best_equal_field(COND *cond, ...@@ -6799,14 +6797,16 @@ static COND* substitute_for_best_equal_field(COND *cond,
return cond; return cond;
} }
/* /*
change field = field to field = const for each found field = const in the change field = field to field = const for each found field = const in the
and_level and_level
*/ */
static void static void
change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
Item *cond, Item *field, Item *value) Item *and_father, Item *cond,
Item *field, Item *value)
{ {
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
{ {
...@@ -6815,7 +6815,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -6815,7 +6815,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
Item *item; Item *item;
while ((item=li++)) while ((item=li++))
change_cond_ref_to_const(save_list,and_level ? cond : item, item, change_cond_ref_to_const(thd, save_list,and_level ? cond : item, item,
field, value); field, value);
return; return;
} }
...@@ -6823,8 +6823,9 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -6823,8 +6823,9 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
return; // Not a boolean function return; // Not a boolean function
Item_bool_func2 *func= (Item_bool_func2*) cond; Item_bool_func2 *func= (Item_bool_func2*) cond;
Item *left_item= func->arguments()[0]; Item **args= func->arguments();
Item *right_item= func->arguments()[1]; Item *left_item= args[0];
Item *right_item= args[1];
Item_func::Functype functype= func->functype(); Item_func::Functype functype= func->functype();
if (right_item->eq(field,0) && left_item != value && if (right_item->eq(field,0) && left_item != value &&
...@@ -6835,7 +6836,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -6835,7 +6836,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
Item *tmp=value->new_item(); Item *tmp=value->new_item();
if (tmp) if (tmp)
{ {
func->arguments()[1] = tmp; thd->change_item_tree(args + 1, tmp);
func->update_used_tables(); func->update_used_tables();
if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC) if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
&& and_father != cond && !left_item->const_item()) && and_father != cond && !left_item->const_item())
...@@ -6856,13 +6857,14 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, ...@@ -6856,13 +6857,14 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
Item *tmp=value->new_item(); Item *tmp=value->new_item();
if (tmp) if (tmp)
{ {
func->arguments()[0] = value = tmp; thd->change_item_tree(args, tmp);
value= tmp;
func->update_used_tables(); func->update_used_tables();
if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC) if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
&& and_father != cond && !right_item->const_item()) && and_father != cond && !right_item->const_item())
{ {
func->arguments()[0] = func->arguments()[1]; // For easy check args[0]= args[1]; // For easy check
func->arguments()[1] = value; thd->change_item_tree(args + 1, value);
cond->marker=1; cond->marker=1;
COND_CMP *tmp2; COND_CMP *tmp2;
if ((tmp2=new COND_CMP(and_father,func))) if ((tmp2=new COND_CMP(and_father,func)))
...@@ -6908,8 +6910,8 @@ static Item *remove_additional_cond(Item* conds) ...@@ -6908,8 +6910,8 @@ static Item *remove_additional_cond(Item* conds)
} }
static void static void
propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father, propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
COND *cond) COND *and_father, COND *cond)
{ {
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
{ {
...@@ -6920,18 +6922,19 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father, ...@@ -6920,18 +6922,19 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
I_List<COND_CMP> save; I_List<COND_CMP> save;
while ((item=li++)) while ((item=li++))
{ {
propagate_cond_constants(&save,and_level ? cond : item, item); propagate_cond_constants(thd, &save,and_level ? cond : item, item);
} }
if (and_level) if (and_level)
{ // Handle other found items { // Handle other found items
I_List_iterator<COND_CMP> cond_itr(save); I_List_iterator<COND_CMP> cond_itr(save);
COND_CMP *cond_cmp; COND_CMP *cond_cmp;
while ((cond_cmp=cond_itr++)) while ((cond_cmp=cond_itr++))
if (!cond_cmp->cmp_func->arguments()[0]->const_item()) {
change_cond_ref_to_const(&save,cond_cmp->and_level, Item **args= cond_cmp->cmp_func->arguments();
cond_cmp->and_level, if (!args[0]->const_item())
cond_cmp->cmp_func->arguments()[0], change_cond_ref_to_const(thd, &save,cond_cmp->and_level,
cond_cmp->cmp_func->arguments()[1]); cond_cmp->and_level, args[0], args[1]);
}
} }
} }
else if (and_father != cond && !cond->marker) // In a AND group else if (and_father != cond && !cond->marker) // In a AND group
...@@ -6941,29 +6944,25 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father, ...@@ -6941,29 +6944,25 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_father,
((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)) ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC))
{ {
Item_func_eq *func=(Item_func_eq*) cond; Item_func_eq *func=(Item_func_eq*) cond;
bool left_const= func->arguments()[0]->const_item(); Item **args= func->arguments();
bool right_const=func->arguments()[1]->const_item(); bool left_const= args[0]->const_item();
bool right_const= args[1]->const_item();
if (!(left_const && right_const) && if (!(left_const && right_const) &&
(func->arguments()[0]->result_type() == args[0]->result_type() == args[1]->result_type())
(func->arguments()[1]->result_type())))
{ {
if (right_const) if (right_const)
{ {
func->arguments()[1]=resolve_const_item(func->arguments()[1], resolve_const_item(thd, &args[1], args[0]);
func->arguments()[0]);
func->update_used_tables(); func->update_used_tables();
change_cond_ref_to_const(save_list,and_father,and_father, change_cond_ref_to_const(thd, save_list, and_father, and_father,
func->arguments()[0], args[0], args[1]);
func->arguments()[1]);
} }
else if (left_const) else if (left_const)
{ {
func->arguments()[0]=resolve_const_item(func->arguments()[0], resolve_const_item(thd, &args[0], args[1]);
func->arguments()[1]);
func->update_used_tables(); func->update_used_tables();
change_cond_ref_to_const(save_list,and_father,and_father, change_cond_ref_to_const(thd, save_list, and_father, and_father,
func->arguments()[1], args[1], args[0]);
func->arguments()[0]);
} }
} }
} }
...@@ -7091,6 +7090,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) ...@@ -7091,6 +7090,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
*/ */
if (table->on_expr) if (table->on_expr)
{ {
Item *expr;
/* /*
If an on expression E is attached to the table, If an on expression E is attached to the table,
check all null rejected predicates in this expression. check all null rejected predicates in this expression.
...@@ -7099,8 +7099,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) ...@@ -7099,8 +7099,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
the outer join is converted to an inner join and the outer join is converted to an inner join and
the corresponding on expression is added to E. the corresponding on expression is added to E.
*/ */
table->on_expr= simplify_joins(join, &nested_join->join_list, expr= simplify_joins(join, &nested_join->join_list,
table->on_expr, FALSE); table->on_expr, FALSE);
table->on_expr= expr;
} }
nested_join->used_tables= (table_map) 0; nested_join->used_tables= (table_map) 0;
nested_join->not_null_tables=(table_map) 0; nested_join->not_null_tables=(table_map) 0;
...@@ -7209,8 +7210,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) ...@@ -7209,8 +7210,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
DBUG_RETURN(conds); DBUG_RETURN(conds);
} }
static COND * static COND *
optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value) optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
Item::cond_result *cond_value)
{ {
THD *thd= join->thd; THD *thd= join->thd;
SELECT_LEX *select= thd->lex->current_select; SELECT_LEX *select= thd->lex->current_select;
...@@ -7223,9 +7226,21 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value) ...@@ -7223,9 +7226,21 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
} }
else else
{ {
/*
Build all multiple equality predicates and eliminate equality
predicates that can be inferred from these multiple equalities.
For each reference of a field included into a multiple equality
that occurs in a function set a pointer to the multiple equality
predicate. Substitute a constant instead of this field if the
multiple equality contains a constant.
*/
DBUG_EXECUTE("where", print_where(conds, "original");); DBUG_EXECUTE("where", print_where(conds, "original"););
conds= build_equal_items(join->thd, conds, NULL, join_list,
&join->cond_equal);
DBUG_EXECUTE("where",print_where(conds,"after equal_items"););
/* change field = field to field = const for each found field = const */ /* change field = field to field = const for each found field = const */
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds); propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
/* /*
Remove all instances of item == item Remove all instances of item == item
Remove all and-levels where CONST item != CONST item Remove all and-levels where CONST item != CONST item
...@@ -7461,21 +7476,28 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ...@@ -7461,21 +7476,28 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
the record in the original table. the record in the original table.
If modify_item is 0 then fill_record() will update If modify_item is 0 then fill_record() will update
the temporary table the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN RETURN
0 on error 0 on error
new_created field new_created field
*/ */
static Field* create_tmp_field_from_field(THD *thd,
Field* org_field, static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
Item *item, Item *item, TABLE *table,
TABLE *table, bool modify_item,
bool modify_item) uint convert_blob_length)
{ {
Field *new_field; Field *new_field;
// The following should always be true if (convert_blob_length && org_field->flags & BLOB_FLAG)
if ((new_field= org_field->new_field(&thd->mem_root,table))) new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(),
org_field->field_name, table,
org_field->charset());
else
new_field= org_field->new_field(thd->mem_root, table);
if (new_field)
{ {
if (modify_item) if (modify_item)
((Item_field *)item)->result_field= new_field; ((Item_field *)item)->result_field= new_field;
...@@ -7506,16 +7528,16 @@ static Field* create_tmp_field_from_field(THD *thd, ...@@ -7506,16 +7528,16 @@ static Field* create_tmp_field_from_field(THD *thd,
the record in the original table. the record in the original table.
If modify_item is 0 then fill_record() will update If modify_item is 0 then fill_record() will update
the temporary table the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN RETURN
0 on error 0 on error
new_created field new_created field
*/ */
static Field* create_tmp_field_from_item(THD *thd, static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
Item *item, Item ***copy_func, bool modify_item,
TABLE *table, uint convert_blob_length)
Item ***copy_func,
bool modify_item)
{ {
bool maybe_null=item->maybe_null; bool maybe_null=item->maybe_null;
Field *new_field; Field *new_field;
...@@ -7532,13 +7554,18 @@ static Field* create_tmp_field_from_item(THD *thd, ...@@ -7532,13 +7554,18 @@ static Field* create_tmp_field_from_item(THD *thd,
break; break;
case STRING_RESULT: case STRING_RESULT:
if (item->max_length > 255) if (item->max_length > 255)
new_field= new Field_blob(item->max_length, maybe_null, {
if (convert_blob_length)
new_field= new Field_varstring(convert_blob_length, maybe_null,
item->name, table, item->name, table,
item->collation.collation); item->collation.collation);
else else
new_field= new Field_string(item->max_length, maybe_null, new_field= new Field_blob(item->max_length, maybe_null, item->name,
item->name, table, table, item->collation.collation);
item->collation.collation); }
else
new_field= new Field_string(item->max_length, maybe_null, item->name,
table, item->collation.collation);
break; break;
case ROW_RESULT: case ROW_RESULT:
default: default:
...@@ -7575,6 +7602,8 @@ static Field* create_tmp_field_from_item(THD *thd, ...@@ -7575,6 +7602,8 @@ static Field* create_tmp_field_from_item(THD *thd,
the record in the original table. the record in the original table.
If modify_item is 0 then fill_record() will update If modify_item is 0 then fill_record() will update
the temporary table the temporary table
convert_blob_length If >0 create a varstring(convert_blob_length) field
instead of blob.
RETURN RETURN
0 on error 0 on error
...@@ -7583,7 +7612,7 @@ static Field* create_tmp_field_from_item(THD *thd, ...@@ -7583,7 +7612,7 @@ static Field* create_tmp_field_from_item(THD *thd,
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
bool group, bool modify_item) bool group, bool modify_item, uint convert_blob_length)
{ {
switch (type) { switch (type) {
case Item::SUM_FUNC_ITEM: case Item::SUM_FUNC_ITEM:
...@@ -7618,8 +7647,15 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -7618,8 +7647,15 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
item->name,table,item->unsigned_flag); item->name,table,item->unsigned_flag);
case STRING_RESULT: case STRING_RESULT:
if (item_sum->max_length > 255) if (item_sum->max_length > 255)
return new Field_blob(item_sum->max_length,maybe_null, {
item->name,table,item->collation.collation); if (convert_blob_length)
return new Field_varstring(convert_blob_length, maybe_null,
item->name, table,
item->collation.collation);
else
return new Field_blob(item_sum->max_length, maybe_null, item->name,
table, item->collation.collation);
}
return new Field_string(item_sum->max_length,maybe_null, return new Field_string(item_sum->max_length,maybe_null,
item->name,table,item->collation.collation); item->name,table,item->collation.collation);
case ROW_RESULT: case ROW_RESULT:
...@@ -7636,8 +7672,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -7636,8 +7672,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::DEFAULT_VALUE_ITEM: case Item::DEFAULT_VALUE_ITEM:
{ {
Item_field *field= (Item_field*) item; Item_field *field= (Item_field*) item;
return create_tmp_field_from_field(thd, (*from_field= field->field), return create_tmp_field_from_field(thd, (*from_field= field->field), item,
item, table, modify_item); table, modify_item, convert_blob_length);
} }
case Item::FUNC_ITEM: case Item::FUNC_ITEM:
case Item::COND_ITEM: case Item::COND_ITEM:
...@@ -7652,14 +7688,16 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -7652,14 +7688,16 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::REF_ITEM: case Item::REF_ITEM:
case Item::NULL_ITEM: case Item::NULL_ITEM:
case Item::VARBIN_ITEM: case Item::VARBIN_ITEM:
return create_tmp_field_from_item(thd, item, table, return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
copy_func, modify_item); convert_blob_length);
case Item::TYPE_HOLDER: case Item::TYPE_HOLDER:
{ {
Field *example= ((Item_type_holder *)item)->example(); Field *example= ((Item_type_holder *)item)->example();
if (example) if (example)
return create_tmp_field_from_field(thd, example, item, table, 0); return create_tmp_field_from_field(thd, example, item, table, 0,
return create_tmp_field_from_item(thd, item, table, copy_func, 0); convert_blob_length);
return create_tmp_field_from_item(thd, item, table, copy_func, 0,
convert_blob_length);
} }
default: // Dosen't have to be stored default: // Dosen't have to be stored
return 0; return 0;
...@@ -7818,12 +7856,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -7818,12 +7856,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
((Item_sum*) item)->result_field=0; ((Item_sum*) item)->result_field=0;
for (i=0 ; i < ((Item_sum*) item)->arg_count ; i++) for (i=0 ; i < ((Item_sum*) item)->arg_count ; i++)
{ {
Item *arg= ((Item_sum*) item)->args[i]; Item **argp= ((Item_sum*) item)->args + i;
Item *arg= *argp;
if (!arg->const_item()) if (!arg->const_item())
{ {
Field *new_field= Field *new_field=
create_tmp_field(thd, table,arg,arg->type(),&copy_func, create_tmp_field(thd, table, arg, arg->type(), &copy_func,
tmp_from_field, group != 0,not_all_columns); tmp_from_field, group != 0,not_all_columns,
param->convert_blob_length);
if (!new_field) if (!new_field)
goto err; // Should be OOM goto err; // Should be OOM
tmp_from_field++; tmp_from_field++;
...@@ -7834,7 +7874,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -7834,7 +7874,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field++= new_field; *blob_field++= new_field;
blob_count++; blob_count++;
} }
((Item_sum*) item)->args[i]= new Item_field(new_field); thd->change_item_tree(argp, new Item_field(new_field));
if (!(new_field->flags & NOT_NULL_FLAG)) if (!(new_field->flags & NOT_NULL_FLAG))
{ {
null_count++; null_count++;
...@@ -7842,7 +7882,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -7842,7 +7882,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
new_field->maybe_null() is still false, it will be new_field->maybe_null() is still false, it will be
changed below. But we have to setup Item_field correctly changed below. But we have to setup Item_field correctly
*/ */
((Item_sum*) item)->args[i]->maybe_null=1; (*argp)->maybe_null=1;
} }
} }
} }
...@@ -7859,9 +7899,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -7859,9 +7899,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
We here distinguish between UNION and multi-table-updates by the fact We here distinguish between UNION and multi-table-updates by the fact
that in the later case group is set to the row pointer. that in the later case group is set to the row pointer.
*/ */
Field *new_field=create_tmp_field(thd, table, item,type, &copy_func, Field *new_field= create_tmp_field(thd, table, item, type, &copy_func,
tmp_from_field, group != 0, tmp_from_field, group != 0,
not_all_columns || group !=0); not_all_columns || group !=0,
param->convert_blob_length);
if (!new_field) if (!new_field)
{ {
if (thd->is_fatal_error) if (thd->is_fatal_error)
...@@ -8058,7 +8099,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -8058,7 +8099,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!using_unique_constraint) if (!using_unique_constraint)
{ {
group->buff=(char*) group_buff; group->buff=(char*) group_buff;
if (!(group->field=field->new_field(&thd->mem_root,table))) if (!(group->field=field->new_field(thd->mem_root,table)))
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
if (maybe_null) if (maybe_null)
{ {
...@@ -8569,7 +8610,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -8569,7 +8610,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
DBUG_PRINT("error",("Error: do_select() failed")); DBUG_PRINT("error",("Error: do_select() failed"));
} }
#endif #endif
DBUG_RETURN(error || join->thd->net.report_error); DBUG_RETURN(join->thd->net.report_error ? -1 : error);
} }
...@@ -9050,6 +9091,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) ...@@ -9050,6 +9091,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{ {
table->key_read=1; table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD); table->file->extra(HA_EXTRA_KEYREAD);
tab->index= tab->ref.key;
} }
if ((error=join_read_const(tab))) if ((error=join_read_const(tab)))
{ {
...@@ -10037,10 +10079,23 @@ part_of_refkey(TABLE *table,Field *field) ...@@ -10037,10 +10079,23 @@ part_of_refkey(TABLE *table,Field *field)
/***************************************************************************** /*****************************************************************************
Test if one can use the key to resolve ORDER BY Test if one can use the key to resolve ORDER BY
Returns: 1 if key is ok.
0 if key can't be used SYNOPSIS
-1 if reverse key can be used test_if_order_by_key()
used_key_parts is set to key parts used if length != 0 order Sort order
table Table to sort
idx Index to check
used_key_parts Return value for used key parts.
NOTES
used_key_parts is set to correct key parts used if return value != 0
(On other cases, used_key_part may be changed)
RETURN
1 key is ok.
0 Key can't be used
-1 Reverse key can be used
*****************************************************************************/ *****************************************************************************/
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
...@@ -10069,13 +10124,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, ...@@ -10069,13 +10124,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
DBUG_RETURN(0); DBUG_RETURN(0);
/* set flag to 1 if we can use read-next on key, else to -1 */ /* set flag to 1 if we can use read-next on key, else to -1 */
flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ? 1 : -1); flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
1 : -1);
if (reverse && flag != reverse) if (reverse && flag != reverse)
DBUG_RETURN(0); DBUG_RETURN(0);
reverse=flag; // Remember if reverse reverse=flag; // Remember if reverse
key_part++; key_part++;
} }
*used_key_parts= (uint) (key_part - table->key_info[idx].key_part); *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
HA_READ_PREV))
reverse= 0; // Index can't be used
DBUG_RETURN(reverse); DBUG_RETURN(reverse);
} }
...@@ -10288,10 +10347,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -10288,10 +10347,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (!select->quick->reverse_sorted()) if (!select->quick->reverse_sorted())
{ {
int quick_type= select->quick->get_type(); int quick_type= select->quick->get_type();
/* here used_key_parts >0 */ if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
if (!(table->file->index_flags(ref_key,used_key_parts-1, 1)
& HA_READ_PREV) ||
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
...@@ -10317,9 +10373,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -10317,9 +10373,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
Use a traversal function that starts by reading the last row Use a traversal function that starts by reading the last row
with key part (A) and then traverse the index backwards. with key part (A) and then traverse the index backwards.
*/ */
if (!(table->file->index_flags(ref_key,used_key_parts-1, 1)
& HA_READ_PREV))
DBUG_RETURN(0); // Use filesort
tab->read_first_record= join_read_last_key; tab->read_first_record= join_read_last_key;
tab->read_record.read_record= join_read_prev_same; tab->read_record.read_record= join_read_prev_same;
/* fall through */ /* fall through */
...@@ -10365,7 +10418,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -10365,7 +10418,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (keys.is_set(nr)) if (keys.is_set(nr))
{ {
int flag; int flag;
if ((flag=test_if_order_by_key(order, table, nr, &not_used))) if ((flag= test_if_order_by_key(order, table, nr, &not_used)))
{ {
if (!no_changes) if (!no_changes)
{ {
...@@ -11150,7 +11203,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11150,7 +11203,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
ORDER *order, List<Item> &fields, List<Item> &all_fields, ORDER *order, List<Item> &fields, List<Item> &all_fields,
bool is_group_field) bool is_group_field)
{ {
Item *order_item=*order->item; /* The item from the GROUP/ORDER caluse. */ Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
Item::Type order_item_type; Item::Type order_item_type;
Item **select_item; /* The corresponding item from the SELECT clause. */ Item **select_item; /* The corresponding item from the SELECT clause. */
Field *from_field; /* The corresponding field from the FROM clause. */ Field *from_field; /* The corresponding field from the FROM clause. */
...@@ -11161,8 +11214,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11161,8 +11214,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (!count || count > fields.elements) if (!count || count > fields.elements)
{ {
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR), my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
MYF(0),order_item->full_name(), MYF(0), order_item->full_name(), thd->where);
thd->where);
return 1; return 1;
} }
order->item= ref_pointer_array + count - 1; order->item= ref_pointer_array + count - 1;
...@@ -11173,8 +11225,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11173,8 +11225,9 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
} }
/* Lookup the current GROUP/ORDER field in the SELECT clause. */ /* Lookup the current GROUP/ORDER field in the SELECT clause. */
uint counter; uint counter;
bool unaliased;
select_item= find_item_in_list(order_item, fields, &counter, select_item= find_item_in_list(order_item, fields, &counter,
REPORT_EXCEPT_NOT_FOUND); REPORT_EXCEPT_NOT_FOUND, &unaliased);
if (!select_item) if (!select_item)
return 1; /* Some error occured. */ return 1; /* Some error occured. */
...@@ -11182,6 +11235,14 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11182,6 +11235,14 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
/* Check whether the resolved field is not ambiguos. */ /* Check whether the resolved field is not ambiguos. */
if (select_item != not_found_item) if (select_item != not_found_item)
{ {
/*
If we have found field not by its alias in select list but by its
original field name, we should additionaly check if we have conflict
for this name (in case if we would perform lookup in all tables).
*/
if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables, order->item))
return 1;
/* Lookup the current GROUP field in the FROM clause. */ /* Lookup the current GROUP field in the FROM clause. */
order_item_type= order_item->type(); order_item_type= order_item->type();
if (is_group_field && if (is_group_field &&
...@@ -11215,16 +11276,15 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11215,16 +11276,15 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
} }
order->in_field_list=0; order->in_field_list=0;
Item *it= *order->item;
/* /*
We check it->fixed because Item_func_group_concat can put We check order_item->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called. arguments for which fix_fields already was called.
'it' reassigned in if condition because fix_field can change it. 'it' reassigned in if condition because fix_field can change it.
*/ */
if (!it->fixed && if (!order_item->fixed &&
(it->fix_fields(thd, tables, order->item) || (order_item->fix_fields(thd, tables, order->item) ||
(it= *order->item)->check_cols(1) || (order_item= *order->item)->check_cols(1) ||
thd->is_fatal_error)) thd->is_fatal_error))
return 1; // Wrong field return 1; // Wrong field
uint el= all_fields.elements; uint el= all_fields.elements;
...@@ -11234,6 +11294,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -11234,6 +11294,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
return 0; return 0;
} }
/* /*
Change order to point at item in select list. If item isn't a number Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list. and doesn't exits in the select list, add it the the field list.
...@@ -11344,10 +11405,11 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -11344,10 +11405,11 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but... thd->set_query_id=1; // Not really needed, but...
uint counter; uint counter;
bool not_used;
for (; new_field ; new_field= new_field->next) for (; new_field ; new_field= new_field->next)
{ {
if ((item= find_item_in_list(*new_field->item, fields, &counter, if ((item= find_item_in_list(*new_field->item, fields, &counter,
IGNORE_ERRORS))) IGNORE_ERRORS, &not_used)))
new_field->item=item; /* Change to shared Item */ new_field->item=item; /* Change to shared Item */
else else
{ {
...@@ -11695,7 +11757,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, ...@@ -11695,7 +11757,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
saved value saved value
*/ */
Field *field= item->field; Field *field= item->field;
item->result_field=field->new_field(&thd->mem_root,field->table); item->result_field=field->new_field(thd->mem_root,field->table);
char *tmp=(char*) sql_alloc(field->pack_length()+1); char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp) if (!tmp)
goto err; goto err;
...@@ -11705,6 +11767,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, ...@@ -11705,6 +11767,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
} }
} }
else if ((pos->type() == Item::FUNC_ITEM || else if ((pos->type() == Item::FUNC_ITEM ||
pos->type() == Item::SUBSELECT_ITEM ||
pos->type() == Item::CACHE_ITEM ||
pos->type() == Item::COND_ITEM) && pos->type() == Item::COND_ITEM) &&
!pos->with_sum_func) !pos->with_sum_func)
{ // Save for send fields { // Save for send fields
...@@ -11812,9 +11876,6 @@ bool JOIN::alloc_func_list() ...@@ -11812,9 +11876,6 @@ bool JOIN::alloc_func_list()
before_group_by Set to 1 if this is called before GROUP BY handling before_group_by Set to 1 if this is called before GROUP BY handling
recompute Set to TRUE if sum_funcs must be recomputed recompute Set to TRUE if sum_funcs must be recomputed
NOTES
Calls ::setup() for all item_sum objects in field_list
RETURN RETURN
0 ok 0 ok
1 error 1 error
...@@ -11835,12 +11896,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields, ...@@ -11835,12 +11896,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
while ((item=it++)) while ((item=it++))
{ {
if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
{
*func++= (Item_sum*) item; *func++= (Item_sum*) item;
/* let COUNT(DISTINCT) create the temporary table */
if (((Item_sum*) item)->setup(thd))
DBUG_RETURN(TRUE);
}
} }
if (before_group_by && rollup.state == ROLLUP::STATE_INITED) if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
{ {
...@@ -11985,6 +12041,30 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, ...@@ -11985,6 +12041,30 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
Code for calculating functions Code for calculating functions
******************************************************************************/ ******************************************************************************/
/*
Call ::setup for all sum functions
SYNOPSIS
setup_sum_funcs()
thd thread handler
func_ptr sum function list
RETURN
FALSE ok
TRUE error
*/
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
{
Item_sum *func;
while ((func= *(func_ptr++)))
if (func->setup(thd))
return TRUE;
return FALSE;
}
static void static void
init_tmptable_sum_functions(Item_sum **func_ptr) init_tmptable_sum_functions(Item_sum **func_ptr)
{ {
...@@ -12140,7 +12220,7 @@ bool JOIN::rollup_init() ...@@ -12140,7 +12220,7 @@ bool JOIN::rollup_init()
return 1; return 1;
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts); rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts); ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
rollup.item_null= new (&thd->mem_root) Item_null(); rollup.item_null= new (thd->mem_root) Item_null();
/* /*
Prepare space for field list for the different levels Prepare space for field list for the different levels
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment