summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_derived.cc4
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_lex.h7
-rw-r--r--sql/sql_prepare.cc21
-rw-r--r--sql/sql_union.cc5
6 files changed, 30 insertions, 15 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index e990eba8e54..1709669d8a2 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -90,6 +90,7 @@ mysql_handle_derived(LEX *lex, uint phases)
sl= sl->next_select_in_list())
{
TABLE_LIST *cursor= sl->get_table_list();
+ sl->changed_elements|= TOUCHED_SEL_DERIVED;
/*
DT_MERGE_FOR_INSERT is not needed for views/derived tables inside
subqueries. Views and derived tables of subqueries should be
@@ -1002,8 +1003,7 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->get_unit()));
st_select_lex_unit *unit= derived->get_unit();
- if (derived->table)
- derived->merged_for_insert= FALSE;
+ derived->merged_for_insert= FALSE;
unit->unclean();
unit->types.empty();
/* for derived tables & PS (which can't be reset by Item_subquery) */
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ba8134bfaf1..cc040508842 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1510,7 +1510,6 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds);
- select_lex->first_execution= 0;
}
/*
Only call prepare_for_posistion() if we are not performing a DELAYED
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3c0d3049ae4..7d694f90aa2 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1904,7 +1904,7 @@ void st_select_lex::init_query()
n_child_sum_items= 0;
subquery_in_having= explicit_limit= 0;
is_item_list_lookup= 0;
- first_execution= 1;
+ changed_elements= 0;
first_natural_join_processing= 1;
first_cond_optimization= 1;
parsing_place= NO_MATTER;
@@ -3367,9 +3367,10 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
Item **having_conds)
{
DBUG_ENTER("st_select_lex::fix_prepare_information");
- if (!thd->stmt_arena->is_conventional() && first_execution)
+ if (!thd->stmt_arena->is_conventional() &&
+ !(changed_elements & TOUCHED_SEL_COND))
{
- first_execution= 0;
+ changed_elements|= TOUCHED_SEL_COND;
if (group_list.first)
{
if (!group_list_ptrs)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 8a31560d2bf..2bde94ee5c2 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -729,6 +729,10 @@ public:
typedef class st_select_lex_unit SELECT_LEX_UNIT;
+
+#define TOUCHED_SEL_COND 1/* WHERE/HAVING/ON should be reinited before use */
+#define TOUCHED_SEL_DERIVED 2/* derived should be reinited before use */
+
/*
SELECT_LEX - store information of parsed SELECT statment
*/
@@ -876,7 +880,8 @@ public:
subquery. Prepared statements work OK in that regard, as in
case of an error during prepare the PS is not created.
*/
- bool first_execution;
+ uint8 changed_elements; // see TOUCHED_SEL_*
+ /* TODO: add foloowing first_* to bitmap above */
bool first_natural_join_processing;
bool first_cond_optimization;
/* do not wrap view fields with Item_ref */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 6aa6aacc504..16923ee5a21 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2496,7 +2496,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
}
for (; sl; sl= sl->next_select_in_list())
{
- if (!sl->first_execution)
+ if (sl->changed_elements & TOUCHED_SEL_COND)
{
/* remove option which was put by mysql_explain_union() */
sl->options&= ~SELECT_DESCRIBE;
@@ -2543,19 +2543,28 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
order->next= sl->group_list_ptrs->at(ix+1);
}
}
+ }
+ { // no harm to do it (item_ptr set on parsing)
+ ORDER *order;
for (order= sl->group_list.first; order; order= order->next)
+ {
order->item= &order->item_ptr;
+ }
/* Fix ORDER list */
for (order= sl->order_list.first; order; order= order->next)
- order->item= &order->item_ptr;
{
+ order->item= &order->item_ptr;
+ }
+ }
+ if (sl->changed_elements & TOUCHED_SEL_DERIVED)
+ {
#ifndef DBUG_OFF
- bool res=
+ bool res=
#endif
- sl->handle_derived(lex, DT_REINIT);
- DBUG_ASSERT(res == 0);
- }
+ sl->handle_derived(lex, DT_REINIT);
+ DBUG_ASSERT(res == 0);
}
+
{
SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean();
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index bbb4133417e..e855b64e600 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -215,8 +215,9 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
called at the first execution of the statement, while first_execution
shows whether this is called at the first execution of the union that
may form just a subselect.
- */
- if (!fake_select_lex->first_execution && first_execution)
+ */
+ if ((fake_select_lex->changed_elements & TOUCHED_SEL_COND) &&
+ first_execution)
{
for (ORDER *order= global_parameters->order_list.first;
order;