mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Manual merge from mysql-trunk.
Conflicts: - client/mysqltest.cc - mysql-test/collections/default.experimental - mysql-test/suite/rpl/t/disabled.def - sql/mysqld.cc - sql/opt_range.cc - sql/sp.cc - sql/sql_acl.cc - sql/sql_partition.cc - sql/sql_table.cc
This commit is contained in:
@@ -223,6 +223,7 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
|
||||
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
|
||||
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 prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct);
|
||||
static bool init_sum_functions(Item_sum **func, Item_sum **end);
|
||||
static bool update_sum_func(Item_sum **func);
|
||||
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
|
||||
@@ -1026,13 +1027,13 @@ JOIN::optimize()
|
||||
}
|
||||
if (const_tables && !thd->locked_tables &&
|
||||
!(select_options & SELECT_NO_UNLOCK))
|
||||
mysql_unlock_some_tables(thd, table, const_tables);
|
||||
mysql_unlock_some_tables(thd, all_tables, const_tables);
|
||||
if (!conds && outer_join)
|
||||
{
|
||||
/* Handle the case where we have an OUTER JOIN without a WHERE */
|
||||
conds=new Item_int((longlong) 1,1); // Always true
|
||||
}
|
||||
select= make_select(*table, const_table_map,
|
||||
select= make_select(*all_tables, const_table_map,
|
||||
const_table_map, conds, 1, &error);
|
||||
if (error)
|
||||
{ /* purecov: inspected */
|
||||
@@ -1269,7 +1270,11 @@ JOIN::optimize()
|
||||
|
||||
if (test_if_subpart(group_list, order) ||
|
||||
(!group_list && tmp_table_param.sum_func_count))
|
||||
{
|
||||
order=0;
|
||||
if (is_indexed_agg_distinct(this, NULL))
|
||||
sort_and_group= 0;
|
||||
}
|
||||
|
||||
// Can't use sort on head table if using join buffering
|
||||
if (full_join)
|
||||
@@ -1459,8 +1464,16 @@ JOIN::optimize()
|
||||
single table queries, thus it is sufficient to test only the first
|
||||
join_tab element of the plan for its access method.
|
||||
*/
|
||||
bool need_distinct= TRUE;
|
||||
if (join_tab->is_using_loose_index_scan())
|
||||
{
|
||||
tmp_table_param.precomputed_group_by= TRUE;
|
||||
if (join_tab->is_using_agg_loose_index_scan())
|
||||
{
|
||||
need_distinct= FALSE;
|
||||
tmp_table_param.precomputed_group_by= FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a tmp table if distinct or if the sort is too complicated */
|
||||
if (need_tmp)
|
||||
@@ -1521,6 +1534,7 @@ JOIN::optimize()
|
||||
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
|
||||
alloc_group_fields(this, group_list) ||
|
||||
make_sum_func_list(all_fields, fields_list, 1) ||
|
||||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
|
||||
setup_sum_funcs(thd, sum_funcs))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
@@ -1530,6 +1544,7 @@ JOIN::optimize()
|
||||
else
|
||||
{
|
||||
if (make_sum_func_list(all_fields, fields_list, 0) ||
|
||||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
|
||||
setup_sum_funcs(thd, sum_funcs))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
@@ -1714,8 +1729,8 @@ JOIN::exec()
|
||||
(zero_result_cause?zero_result_cause:"No tables used"));
|
||||
else
|
||||
{
|
||||
if (result->send_fields(*columns_list,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||
if (result->send_result_set_metadata(*columns_list,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||
{
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@@ -2002,7 +2017,9 @@ JOIN::exec()
|
||||
}
|
||||
}
|
||||
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
|
||||
1, TRUE))
|
||||
1, TRUE) ||
|
||||
prepare_sum_aggregators(curr_join->sum_funcs,
|
||||
!curr_join->join_tab->is_using_agg_loose_index_scan()))
|
||||
DBUG_VOID_RETURN;
|
||||
curr_join->group_list= 0;
|
||||
if (!curr_join->sort_and_group &&
|
||||
@@ -2106,13 +2123,17 @@ JOIN::exec()
|
||||
|
||||
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
|
||||
1, TRUE) ||
|
||||
prepare_sum_aggregators(curr_join->sum_funcs,
|
||||
!curr_join->join_tab ||
|
||||
!curr_join->join_tab->
|
||||
is_using_agg_loose_index_scan()) ||
|
||||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
|
||||
thd->is_fatal_error)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
if (curr_join->group_list || curr_join->order)
|
||||
{
|
||||
DBUG_PRINT("info",("Sorting for send_fields"));
|
||||
DBUG_PRINT("info",("Sorting for send_result_set_metadata"));
|
||||
thd_proc_info(thd, "Sorting result");
|
||||
/* If we have already done the group, add HAVING to sorted table */
|
||||
if (curr_join->tmp_having && ! curr_join->group_list &&
|
||||
@@ -2248,7 +2269,7 @@ JOIN::exec()
|
||||
{
|
||||
thd_proc_info(thd, "Sending data");
|
||||
DBUG_PRINT("info", ("%s", thd->proc_info));
|
||||
result->send_fields((procedure ? curr_join->procedure_fields_list :
|
||||
result->send_result_set_metadata((procedure ? curr_join->procedure_fields_list :
|
||||
*curr_fields_list),
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||
error= do_select(curr_join, curr_fields_list, NULL, procedure);
|
||||
@@ -2695,7 +2716,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
goto error; // Fatal error
|
||||
}
|
||||
else
|
||||
{
|
||||
found_const_table_map|= s->table->map;
|
||||
s->table->pos_in_table_list->optimized_away= TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* loop until no more const tables are found */
|
||||
@@ -2932,7 +2956,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
|
||||
join->join_tab=stat;
|
||||
join->map2table=stat_ref;
|
||||
join->table= join->all_tables=table_vector;
|
||||
join->all_tables= table_vector;
|
||||
join->const_tables=const_count;
|
||||
join->found_const_table_map=found_const_table_map;
|
||||
|
||||
@@ -3637,16 +3661,16 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
|
||||
Item_func *arg0=(Item_func *)(func->arguments()[0]),
|
||||
*arg1=(Item_func *)(func->arguments()[1]);
|
||||
if (arg1->const_item() &&
|
||||
((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
|
||||
(functype == Item_func::GT_FUNC && arg1->val_real() >=0)) &&
|
||||
arg0->type() == Item::FUNC_ITEM &&
|
||||
arg0->functype() == Item_func::FT_FUNC)
|
||||
arg0->functype() == Item_func::FT_FUNC &&
|
||||
((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
|
||||
(functype == Item_func::GT_FUNC && arg1->val_real() >=0)))
|
||||
cond_func=(Item_func_match *) arg0;
|
||||
else if (arg0->const_item() &&
|
||||
((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
|
||||
(functype == Item_func::LT_FUNC && arg0->val_real() >=0)) &&
|
||||
arg1->type() == Item::FUNC_ITEM &&
|
||||
arg1->functype() == Item_func::FT_FUNC)
|
||||
arg1->functype() == Item_func::FT_FUNC &&
|
||||
((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
|
||||
(functype == Item_func::LT_FUNC && arg0->val_real() >=0)))
|
||||
cond_func=(Item_func_match *) arg1;
|
||||
}
|
||||
}
|
||||
@@ -3983,6 +4007,82 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check for the presence of AGGFN(DISTINCT a) queries that may be subject
|
||||
to loose index scan.
|
||||
|
||||
|
||||
Check if the query is a subject to AGGFN(DISTINCT) using loose index scan
|
||||
(QUICK_GROUP_MIN_MAX_SELECT).
|
||||
Optionally (if out_args is supplied) will push the arguments of
|
||||
AGGFN(DISTINCT) to the list
|
||||
|
||||
@param join the join to check
|
||||
@param[out] out_args list of aggregate function arguments
|
||||
@return does the query qualify for indexed AGGFN(DISTINCT)
|
||||
@retval true it does
|
||||
@retval false AGGFN(DISTINCT) must apply distinct in it.
|
||||
*/
|
||||
|
||||
bool
|
||||
is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
|
||||
{
|
||||
Item_sum **sum_item_ptr;
|
||||
bool result= false;
|
||||
|
||||
if (join->tables != 1 || /* reference more than 1 table */
|
||||
join->select_distinct || /* or a DISTINCT */
|
||||
join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */
|
||||
return false;
|
||||
|
||||
if (join->make_sum_func_list(join->all_fields, join->fields_list, true))
|
||||
return false;
|
||||
|
||||
for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
|
||||
{
|
||||
Item_sum *sum_item= *sum_item_ptr;
|
||||
Item *expr;
|
||||
/* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
|
||||
switch (sum_item->sum_func())
|
||||
{
|
||||
case Item_sum::MIN_FUNC:
|
||||
case Item_sum::MAX_FUNC:
|
||||
continue;
|
||||
case Item_sum::COUNT_DISTINCT_FUNC:
|
||||
break;
|
||||
case Item_sum::AVG_DISTINCT_FUNC:
|
||||
case Item_sum::SUM_DISTINCT_FUNC:
|
||||
if (sum_item->get_arg_count() == 1)
|
||||
break;
|
||||
/* fall through */
|
||||
default: return false;
|
||||
}
|
||||
/*
|
||||
We arrive here for every COUNT(DISTINCT),AVG(DISTINCT) or SUM(DISTINCT).
|
||||
Collect the arguments of the aggregate functions to a list.
|
||||
We don't worry about duplicates as these will be sorted out later in
|
||||
get_best_group_min_max
|
||||
*/
|
||||
for (uint i= 0; i < sum_item->get_arg_count(); i++)
|
||||
{
|
||||
expr= sum_item->get_arg(i);
|
||||
/* The AGGFN(DISTINCT) arg is not an attribute? */
|
||||
if (expr->real_item()->type() != Item::FIELD_ITEM)
|
||||
return false;
|
||||
|
||||
/*
|
||||
If we came to this point the AGGFN(DISTINCT) loose index scan
|
||||
optimization is applicable
|
||||
*/
|
||||
if (out_args)
|
||||
out_args->push_back((Item_field *) expr);
|
||||
result= true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Discover the indexes that can be used for GROUP BY or DISTINCT queries.
|
||||
|
||||
@@ -4025,6 +4125,10 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
|
||||
item->walk(&Item::collect_item_field_processor, 0,
|
||||
(uchar*) &indexed_fields);
|
||||
}
|
||||
else if (is_indexed_agg_distinct(join, &indexed_fields))
|
||||
{
|
||||
join->sort_and_group= 1;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
@@ -4272,7 +4376,8 @@ best_access_path(JOIN *join,
|
||||
in ReuseRangeEstimateForRef-3.
|
||||
*/
|
||||
if (table->quick_keys.is_set(key) &&
|
||||
const_part & (1 << table->quick_key_parts[key]) &&
|
||||
(const_part & ((1 << table->quick_key_parts[key])-1)) ==
|
||||
((1 << table->quick_key_parts[key])-1) &&
|
||||
table->quick_n_ranges[key] == 1 &&
|
||||
records > (double) table->quick_rows[key])
|
||||
{
|
||||
@@ -5005,8 +5110,8 @@ greedy_search(JOIN *join,
|
||||
the interleaving state to the one of the non-extended partial plan
|
||||
on exit.
|
||||
*/
|
||||
IF_DBUG(bool is_interleave_error= )
|
||||
check_interleaving_with_nj (best_table);
|
||||
bool is_interleave_error __attribute__((unused))=
|
||||
check_interleaving_with_nj (best_table);
|
||||
/* This has been already checked by best_extension_by_limited_search */
|
||||
DBUG_ASSERT(!is_interleave_error);
|
||||
|
||||
@@ -5542,7 +5647,7 @@ get_best_combination(JOIN *join)
|
||||
{
|
||||
TABLE *form;
|
||||
*j= *join->best_positions[tablenr].table;
|
||||
form=join->table[tablenr]=j->table;
|
||||
form=join->all_tables[tablenr]=j->table;
|
||||
used_tables|= form->map;
|
||||
form->reginfo.join_tab=j;
|
||||
if (!*j->on_expr_ref)
|
||||
@@ -5816,7 +5921,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
|
||||
join_tab= parent->join_tab_reexec;
|
||||
table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table;
|
||||
parent->table_reexec[0]= tmp_table;
|
||||
tables= 1;
|
||||
const_tables= 0;
|
||||
const_table_map= 0;
|
||||
@@ -6873,24 +6978,23 @@ void JOIN::cleanup(bool full)
|
||||
{
|
||||
DBUG_ENTER("JOIN::cleanup");
|
||||
|
||||
if (table)
|
||||
if (all_tables)
|
||||
{
|
||||
JOIN_TAB *tab,*end;
|
||||
/*
|
||||
Only a sorted table may be cached. This sorted table is always the
|
||||
first non const table in join->table
|
||||
first non const table in join->all_tables
|
||||
*/
|
||||
if (tables > const_tables) // Test for not-const tables
|
||||
{
|
||||
free_io_cache(table[const_tables]);
|
||||
filesort_free_buffers(table[const_tables],full);
|
||||
free_io_cache(all_tables[const_tables]);
|
||||
filesort_free_buffers(all_tables[const_tables],full);
|
||||
}
|
||||
|
||||
if (full)
|
||||
{
|
||||
for (tab= join_tab, end= tab+tables; tab != end; tab++)
|
||||
tab->cleanup();
|
||||
table= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7189,7 +7293,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
|
||||
if (having && having->val_int() == 0)
|
||||
send_row=0;
|
||||
}
|
||||
if (!(result->send_fields(fields,
|
||||
if (!(result->send_result_set_metadata(fields,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
|
||||
{
|
||||
bool send_error= FALSE;
|
||||
@@ -7219,7 +7323,7 @@ static void clear_tables(JOIN *join)
|
||||
are not re-calculated.
|
||||
*/
|
||||
for (uint i=join->const_tables ; i < join->tables ; i++)
|
||||
mark_as_null_row(join->table[i]); // All fields are NULL
|
||||
mark_as_null_row(join->all_tables[i]); // All fields are NULL
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -9164,7 +9268,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
thd->substitute_null_with_insert_id))
|
||||
{
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
query_cache_abort(&thd->net);
|
||||
query_cache_abort(&thd->query_cache_tls);
|
||||
#endif
|
||||
COND *new_cond;
|
||||
if ((new_cond= new Item_func_eq(args[0],
|
||||
@@ -9714,7 +9818,7 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
|
||||
Create a temp table according to a field list.
|
||||
|
||||
Given field pointers are changed to point at tmp_table for
|
||||
send_fields. The table object is self contained: it's
|
||||
send_result_set_metadata. The table object is self contained: it's
|
||||
allocated in its own memory root, as well as Field objects
|
||||
created for table columns.
|
||||
This function will replace Item_sum items in 'fields' list with
|
||||
@@ -9899,6 +10003,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
share->primary_key= MAX_KEY; // Indicate no primary key
|
||||
share->keys_for_keyread.init();
|
||||
share->keys_in_use.init();
|
||||
if (param->schema_table)
|
||||
share->db= INFORMATION_SCHEMA_NAME;
|
||||
|
||||
/* Calculate which type of fields we will store in the temporary table */
|
||||
|
||||
@@ -10454,6 +10560,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
|
||||
bzero(share, sizeof(*share));
|
||||
table->field= field;
|
||||
table->s= share;
|
||||
table->temp_pool_slot= MY_BIT_NONE;
|
||||
share->blob_field= blob_field;
|
||||
share->fields= field_count;
|
||||
share->blob_ptr_size= portable_sizeof_char_ptr;
|
||||
@@ -10957,7 +11064,6 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
||||
so we don't touch it here.
|
||||
*/
|
||||
join->examined_rows++;
|
||||
join->thd->row_count++;
|
||||
DBUG_ASSERT(join->examined_rows <= 1);
|
||||
}
|
||||
else if (join->send_row_on_empty_set())
|
||||
@@ -10979,26 +11085,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
||||
if (error == NESTED_LOOP_NO_MORE_ROWS)
|
||||
error= NESTED_LOOP_OK;
|
||||
|
||||
if (error == NESTED_LOOP_OK)
|
||||
{
|
||||
/*
|
||||
Sic: this branch works even if rc != 0, e.g. when
|
||||
send_data above returns an error.
|
||||
*/
|
||||
if (!table) // If sending data to client
|
||||
{
|
||||
/*
|
||||
The following will unlock all cursors if the command wasn't an
|
||||
update command
|
||||
*/
|
||||
join->join_free(); // Unlock all cursors
|
||||
if (join->result->send_eof())
|
||||
rc= 1; // Don't send error
|
||||
}
|
||||
DBUG_PRINT("info",("%ld records output", (long) join->send_records));
|
||||
}
|
||||
else
|
||||
rc= -1;
|
||||
|
||||
if (table)
|
||||
{
|
||||
int tmp, new_errno= 0;
|
||||
@@ -11015,6 +11102,29 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
||||
if (new_errno)
|
||||
table->file->print_error(new_errno,MYF(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
The following will unlock all cursors if the command wasn't an
|
||||
update command
|
||||
*/
|
||||
join->join_free(); // Unlock all cursors
|
||||
}
|
||||
if (error == NESTED_LOOP_OK)
|
||||
{
|
||||
/*
|
||||
Sic: this branch works even if rc != 0, e.g. when
|
||||
send_data above returns an error.
|
||||
*/
|
||||
if (!table) // If sending data to client
|
||||
{
|
||||
if (join->result->send_eof())
|
||||
rc= 1; // Don't send error
|
||||
}
|
||||
DBUG_PRINT("info",("%ld records output", (long) join->send_records));
|
||||
}
|
||||
else
|
||||
rc= -1;
|
||||
#ifndef DBUG_OFF
|
||||
if (rc)
|
||||
{
|
||||
@@ -11211,7 +11321,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
||||
/* Set first_unmatched for the last inner table of this group */
|
||||
join_tab->last_inner->first_unmatched= join_tab;
|
||||
}
|
||||
join->thd->row_count= 0;
|
||||
join->thd->warning_info->reset_current_row_for_warning();
|
||||
|
||||
error= (*join_tab->read_first_record)(join_tab);
|
||||
rc= evaluate_join_record(join, join_tab, error);
|
||||
@@ -11332,7 +11442,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
(See above join->return_tab= tab).
|
||||
*/
|
||||
join->examined_rows++;
|
||||
join->thd->row_count++;
|
||||
DBUG_PRINT("counts", ("join->examined_rows++: %lu",
|
||||
(ulong) join->examined_rows));
|
||||
|
||||
@@ -11341,6 +11450,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
enum enum_nested_loop_state rc;
|
||||
/* A match from join_tab is found for the current partial join. */
|
||||
rc= (*join_tab->next_select)(join, join_tab+1, 0);
|
||||
join->thd->warning_info->inc_current_row_for_warning();
|
||||
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
|
||||
return rc;
|
||||
if (join->return_tab < join_tab)
|
||||
@@ -11354,7 +11464,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
return NESTED_LOOP_NO_MORE_ROWS;
|
||||
}
|
||||
else
|
||||
{
|
||||
join->thd->warning_info->inc_current_row_for_warning();
|
||||
join_tab->read_record.unlock_row(join_tab);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -11363,7 +11476,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
with the beginning coinciding with the current partial join.
|
||||
*/
|
||||
join->examined_rows++;
|
||||
join->thd->row_count++;
|
||||
join->thd->warning_info->inc_current_row_for_warning();
|
||||
join_tab->read_record.unlock_row(join_tab);
|
||||
}
|
||||
return NESTED_LOOP_OK;
|
||||
@@ -11907,10 +12020,8 @@ join_init_quick_read_record(JOIN_TAB *tab)
|
||||
}
|
||||
|
||||
|
||||
int rr_sequential(READ_RECORD *info);
|
||||
int init_read_record_seq(JOIN_TAB *tab)
|
||||
int read_first_record_seq(JOIN_TAB *tab)
|
||||
{
|
||||
tab->read_record.read_record= rr_sequential;
|
||||
if (tab->read_record.file->ha_rnd_init(1))
|
||||
return 1;
|
||||
return (*tab->read_record.read_record)(&tab->read_record);
|
||||
@@ -13922,8 +14033,8 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
|
||||
extra_length= ALIGN_SIZE(key_length)-key_length;
|
||||
}
|
||||
|
||||
if (hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
|
||||
key_length, (hash_get_key) 0, 0, 0))
|
||||
if (my_hash_init(&hash, &my_charset_bin, (uint) file->stats.records, 0,
|
||||
key_length, (my_hash_get_key) 0, 0, 0))
|
||||
{
|
||||
my_free((char*) key_buffer,MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
@@ -13964,7 +14075,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
|
||||
key_pos+= *field_length++;
|
||||
}
|
||||
/* Check if it exists before */
|
||||
if (hash_search(&hash, org_key_pos, key_length))
|
||||
if (my_hash_search(&hash, org_key_pos, key_length))
|
||||
{
|
||||
/* Duplicated found ; Remove the row */
|
||||
if ((error=file->ha_delete_row(record)))
|
||||
@@ -13978,14 +14089,14 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
|
||||
key_pos+=extra_length;
|
||||
}
|
||||
my_free((char*) key_buffer,MYF(0));
|
||||
hash_free(&hash);
|
||||
my_hash_free(&hash);
|
||||
file->extra(HA_EXTRA_NO_CACHE);
|
||||
(void) file->ha_rnd_end();
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
my_free((char*) key_buffer,MYF(0));
|
||||
hash_free(&hash);
|
||||
my_hash_free(&hash);
|
||||
file->extra(HA_EXTRA_NO_CACHE);
|
||||
(void) file->ha_rnd_end();
|
||||
if (error)
|
||||
@@ -14666,7 +14777,7 @@ setup_new_fields(THD *thd, List<Item> &fields,
|
||||
optimize away 'order by'.
|
||||
*/
|
||||
|
||||
static ORDER *
|
||||
ORDER *
|
||||
create_distinct_group(THD *thd, Item **ref_pointer_array,
|
||||
ORDER *order_list, List<Item> &fields,
|
||||
List<Item> &all_fields,
|
||||
@@ -15021,7 +15132,7 @@ test_if_group_changed(List<Cached_item> &list)
|
||||
|
||||
Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
|
||||
Change old item_field to use a new field with points at saved fieldvalue
|
||||
This function is only called before use of send_fields.
|
||||
This function is only called before use of send_result_set_metadata.
|
||||
|
||||
@param thd THD pointer
|
||||
@param param temporary table parameters
|
||||
@@ -15052,7 +15163,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
||||
Item *pos;
|
||||
List_iterator_fast<Item> li(all_fields);
|
||||
Copy_field *copy= NULL;
|
||||
IF_DBUG(Copy_field *copy_start);
|
||||
Copy_field *copy_start __attribute__((unused));
|
||||
res_selected_fields.empty();
|
||||
res_all_fields.empty();
|
||||
List_iterator_fast<Item> itr(res_all_fields);
|
||||
@@ -15065,7 +15176,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
||||
goto err2;
|
||||
|
||||
param->copy_funcs.empty();
|
||||
IF_DBUG(copy_start= copy);
|
||||
copy_start= copy;
|
||||
for (i= 0; (pos= li++); i++)
|
||||
{
|
||||
Field *field;
|
||||
@@ -15261,7 +15372,7 @@ bool JOIN::alloc_func_list()
|
||||
Initialize 'sum_funcs' array with all Item_sum objects.
|
||||
|
||||
@param field_list All items
|
||||
@param send_fields Items in select list
|
||||
@param send_result_set_metadata Items in select list
|
||||
@param before_group_by Set to 1 if this is called before GROUP BY handling
|
||||
@param recompute Set to TRUE if sum_funcs must be recomputed
|
||||
|
||||
@@ -15271,7 +15382,7 @@ bool JOIN::alloc_func_list()
|
||||
1 error
|
||||
*/
|
||||
|
||||
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
|
||||
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_result_set_metadata,
|
||||
bool before_group_by, bool recompute)
|
||||
{
|
||||
List_iterator_fast<Item> it(field_list);
|
||||
@@ -15293,7 +15404,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
|
||||
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
|
||||
{
|
||||
rollup.state= ROLLUP::STATE_READY;
|
||||
if (rollup_make_fields(field_list, send_fields, &func))
|
||||
if (rollup_make_fields(field_list, send_result_set_metadata, &func))
|
||||
DBUG_RETURN(TRUE); // Should never happen
|
||||
}
|
||||
else if (rollup.state == ROLLUP::STATE_NONE)
|
||||
@@ -15468,7 +15579,22 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
|
||||
DBUG_ENTER("setup_sum_funcs");
|
||||
while ((func= *(func_ptr++)))
|
||||
{
|
||||
if (func->setup(thd))
|
||||
if (func->aggregator_setup(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct)
|
||||
{
|
||||
Item_sum *func;
|
||||
DBUG_ENTER("prepare_sum_aggregators");
|
||||
while ((func= *(func_ptr++)))
|
||||
{
|
||||
if (func->set_aggregator(need_distinct && func->has_with_distinct() ?
|
||||
Aggregator::DISTINCT_AGGREGATOR :
|
||||
Aggregator::SIMPLE_AGGREGATOR))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
DBUG_RETURN(FALSE);
|
||||
@@ -15518,7 +15644,7 @@ init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
|
||||
/* If rollup, calculate the upper sum levels */
|
||||
for ( ; *func_ptr ; func_ptr++)
|
||||
{
|
||||
if ((*func_ptr)->add())
|
||||
if ((*func_ptr)->aggregator_add())
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -15530,7 +15656,7 @@ update_sum_func(Item_sum **func_ptr)
|
||||
{
|
||||
Item_sum *func;
|
||||
for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
|
||||
if (func->add())
|
||||
if (func->aggregator_add())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -16475,7 +16601,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
if (key_read)
|
||||
{
|
||||
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
|
||||
{
|
||||
QUICK_GROUP_MIN_MAX_SELECT *qgs=
|
||||
(QUICK_GROUP_MIN_MAX_SELECT *) tab->select->quick;
|
||||
extra.append(STRING_WITH_LEN("; Using index for group-by"));
|
||||
qgs->append_loose_scan_type(&extra);
|
||||
}
|
||||
else
|
||||
extra.append(STRING_WITH_LEN("; Using index"));
|
||||
}
|
||||
@@ -16606,18 +16737,35 @@ static void print_join(THD *thd,
|
||||
{
|
||||
/* List is reversed => we should reverse it before using */
|
||||
List_iterator_fast<TABLE_LIST> ti(*tables);
|
||||
TABLE_LIST **table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
|
||||
tables->elements);
|
||||
if (table == 0)
|
||||
TABLE_LIST **table;
|
||||
uint non_const_tables= 0;
|
||||
|
||||
for (TABLE_LIST *t= ti++; t ; t= ti++)
|
||||
if (!t->optimized_away)
|
||||
non_const_tables++;
|
||||
if (!non_const_tables)
|
||||
{
|
||||
str->append(STRING_WITH_LEN("dual"));
|
||||
return; // all tables were optimized away
|
||||
}
|
||||
ti.rewind();
|
||||
|
||||
if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
|
||||
non_const_tables)))
|
||||
return; // out of memory
|
||||
|
||||
for (TABLE_LIST **t= table + (tables->elements - 1); t >= table; t--)
|
||||
*t= ti++;
|
||||
TABLE_LIST *tmp, **t= table + (non_const_tables - 1);
|
||||
while ((tmp= ti++))
|
||||
{
|
||||
if (tmp->optimized_away)
|
||||
continue;
|
||||
*t--= tmp;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(tables->elements >= 1);
|
||||
(*table)->print(thd, str, query_type);
|
||||
|
||||
TABLE_LIST **end= table + tables->elements;
|
||||
TABLE_LIST **end= table + non_const_tables;
|
||||
for (TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
|
||||
{
|
||||
TABLE_LIST *curr= *tbl;
|
||||
|
||||
Reference in New Issue
Block a user