summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc13
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_select.cc23
-rw-r--r--sql/sql_select.h1
6 files changed, 45 insertions, 5 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 8461de9cd36..429d2ad4dc7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -318,7 +318,18 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
field_item->field_type() != MYSQL_TYPE_YEAR)
return 1;
- if ((*item)->const_item() && !(*item)->is_expensive())
+ /*
+ Replace (*item) with its value if the item can be computed.
+
+ Do not replace items that contain aggregate functions:
+ There can be such items that are constants, e.g. COLLATION(AVG(123)),
+ but this function is called at Name Resolution phase.
+ Removing aggregate functions may confuse query plan generation code, e.g.
+ the optimizer might conclude that the query doesn't need to do grouping
+ at all.
+ */
+ if ((*item)->const_item() && !(*item)->is_expensive() &&
+ !(*item)->with_sum_func())
{
TABLE *table= field->table;
Sql_mode_save sql_mode(thd);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 659df67adaf..1da220d7276 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6209,6 +6209,8 @@ bool Item_func_match::init_search(THD *thd, bool no_order)
ft_handler= table->file->ft_init_ext(flags, key, ft_tmp);
+ if (!ft_handler)
+ DBUG_RETURN(1);
if (join_key)
table->file->ft_handler=ft_handler;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0fe6037e88b..4c359955dbe 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1292,7 +1292,9 @@ multi_delete::initialize_tables(JOIN *join)
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
- init_ftfuncs(thd, thd->lex->current_select, 1);
+ if (init_ftfuncs(thd, thd->lex->current_select, 1))
+ DBUG_RETURN(true);
+
DBUG_RETURN(thd->is_fatal_error);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 7088a9c447b..1d160bd9a65 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3154,6 +3154,7 @@ void st_select_lex_node::fast_exclude()
for (; slave; slave= slave->next)
slave->fast_exclude();
+ prev= NULL; // to ensure correct behavior of st_select_lex_unit::is_excluded()
}
@@ -3228,9 +3229,7 @@ void st_select_lex_node::exclude_from_tree()
*/
void st_select_lex_node::exclude()
{
- /* exclude from global list */
- fast_exclude();
- /* exclude from other structures */
+ /* exclude the node from the tree */
exclude_from_tree();
/*
We do not need following statements, because prev pointer of first
@@ -3238,6 +3237,8 @@ void st_select_lex_node::exclude()
if (master->slave == this)
master->slave= next;
*/
+ /* exclude all nodes under this excluded node */
+ fast_exclude();
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1f32c784248..81c4991e801 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1851,6 +1851,9 @@ JOIN::optimize_inner()
DEBUG_SYNC(thd, "before_join_optimize");
THD_STAGE_INFO(thd, stage_optimizing);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= 0;
+#endif
set_allowed_join_cache_types();
need_distinct= TRUE;
@@ -3100,6 +3103,9 @@ setup_subq_exit:
{
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
DBUG_RETURN(1);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= 1;
+#endif
need_tmp= 1;
}
if (make_aggr_tables_info())
@@ -3414,6 +3420,7 @@ bool JOIN::make_aggr_tables_info()
{
aggr_tables++;
curr_tab= join_tab + exec_join_tab_cnt();
+ DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
bzero((void*)curr_tab, sizeof(JOIN_TAB));
curr_tab->ref.key= -1;
if (only_const_tables())
@@ -3542,6 +3549,7 @@ bool JOIN::make_aggr_tables_info()
curr_tab++;
aggr_tables++;
+ DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
bzero((void*)curr_tab, sizeof(JOIN_TAB));
curr_tab->ref.key= -1;
@@ -10539,6 +10547,21 @@ bool JOIN::get_best_combination()
fix_semijoin_strategies_for_picked_join_order(this);
top_join_tab_count= get_number_of_tables_at_top_level(this);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= top_join_tab_count + aggr_tables;
+#endif
+ /*
+ NOTE: The above computation of aggr_tables can produce wrong result because some
+ of the variables it uses may change their values after we leave this function.
+ Known examples:
+ - Dangerous: using_outer_summary_function=false at this point. Added
+ DBUG_ASSERT below to demonstrate. Can this cause us to allocate less
+ space than we would need?
+ - Not dangerous: select_distinct can be true here but be assigned false
+ afterwards.
+ */
+ aggr_tables= 2;
+ DBUG_ASSERT(!tmp_table_param.using_outer_summary_function);
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*
(top_join_tab_count + aggr_tables))))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index d43737fbd40..4ada816692e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1301,6 +1301,7 @@ public:
#ifndef DBUG_OFF
void dbug_verify_sj_inner_tables(uint n_positions) const;
+ uint dbug_join_tab_array_size;
#endif
/* We also maintain a stack of join optimization states in * join->positions[] */