summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc133
1 files changed, 112 insertions, 21 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3b655bac5af..f1640bf71ed 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1684,6 +1684,31 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
slave= 0;
}
+
+void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
+{
+ for (; slave; slave= slave->next)
+ if (slave == slave_arg)
+ return;
+
+ if (slave)
+ {
+ st_select_lex_node *slave_arg_slave= slave_arg->slave;
+ /* Insert in the front of list of slaves if any. */
+ slave_arg->include_neighbour(slave);
+ /* include_neighbour() sets slave_arg->slave=0, restore it. */
+ slave_arg->slave= slave_arg_slave;
+ /* Count on include_neighbour() setting the master. */
+ DBUG_ASSERT(slave_arg->master == this);
+ }
+ else
+ {
+ slave= slave_arg;
+ slave_arg->master= this;
+ }
+}
+
+
/*
include on level down (but do not link)
@@ -1735,17 +1760,29 @@ void st_select_lex_node::fast_exclude()
}
+
+/*
+ Exclude a node from the tree lex structure, but leave it in the global
+ list of nodes.
+*/
+
+void st_select_lex_node::exclude_from_tree()
+{
+ if ((*prev= next))
+ next->prev= prev;
+}
+
+
/*
- excluding select_lex structure (except first (first select can't be
+ Exclude select_lex structure (except first (first select can't be
deleted, because it is most upper select))
*/
void st_select_lex_node::exclude()
{
- //exclude from global list
+ /* exclude from global list */
fast_exclude();
- //exclude from other structures
- if ((*prev= next))
- next->prev= prev;
+ /* exclude from other structures */
+ exclude_from_tree();
/*
We do not need following statements, because prev pointer of first
list element point to master->slave
@@ -1905,18 +1942,19 @@ bool st_select_lex::mark_as_dependent(THD *thd, st_select_lex *last, Item *depen
SELECT_LEX *s= this;
do
{
- if (!(s->uncacheable & UNCACHEABLE_DEPENDENT))
+ if (!(s->uncacheable & UNCACHEABLE_DEPENDENT_GENERATED))
{
// Select is dependent of outer select
s->uncacheable= (s->uncacheable & ~UNCACHEABLE_UNITED) |
- UNCACHEABLE_DEPENDENT;
+ UNCACHEABLE_DEPENDENT_GENERATED;
SELECT_LEX_UNIT *munit= s->master_unit();
munit->uncacheable= (munit->uncacheable & ~UNCACHEABLE_UNITED) |
- UNCACHEABLE_DEPENDENT;
+ UNCACHEABLE_DEPENDENT_GENERATED;
for (SELECT_LEX *sl= munit->first_select(); sl ; sl= sl->next_select())
{
if (sl != s &&
- !(sl->uncacheable & (UNCACHEABLE_DEPENDENT | UNCACHEABLE_UNITED)))
+ !(sl->uncacheable & (UNCACHEABLE_DEPENDENT_GENERATED |
+ UNCACHEABLE_UNITED)))
sl->uncacheable|= UNCACHEABLE_UNITED;
}
}
@@ -2141,17 +2179,6 @@ void st_select_lex::print_limit(THD *thd,
subs_type == Item_subselect::IN_SUBS ||
subs_type == Item_subselect::ALL_SUBS)
{
- DBUG_ASSERT(!item->fixed ||
- /*
- If not using materialization both:
- select_limit == 1, and there should be no offset_limit.
- */
- (((subs_type == Item_subselect::IN_SUBS) &&
- ((Item_in_subselect*)item)->exec_method ==
- Item_in_subselect::MATERIALIZATION) ?
- TRUE :
- (select_limit->val_int() == 1LL) &&
- offset_limit == 0));
return;
}
}
@@ -3078,6 +3105,71 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
str, length));
}
+
+bool st_select_lex::optimize_unflattened_subqueries()
+{
+ for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit())
+ {
+ Item_subselect *subquery_predicate= un->item;
+ if (subquery_predicate)
+ {
+ for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select())
+ {
+ JOIN *inner_join= sl->join;
+ SELECT_LEX *save_select= un->thd->lex->current_select;
+ ulonglong save_options;
+ int res;
+ /* We need only 1 row to determine existence */
+ un->set_limit(un->global_parameters);
+ un->thd->lex->current_select= sl;
+ save_options= inner_join->select_options;
+ if (un->outer_select()->options & SELECT_DESCRIBE)
+ {
+ /* Optimize the subquery in the context of EXPLAIN. */
+ sl->set_explain_type();
+ sl->options|= SELECT_DESCRIBE;
+ inner_join->select_options|= SELECT_DESCRIBE;
+ }
+ res= inner_join->optimize();
+ inner_join->select_options= save_options;
+ un->thd->lex->current_select= save_select;
+ if (res)
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ Set the EXPLAIN type for this subquery.
+*/
+
+void st_select_lex::set_explain_type()
+{
+ SELECT_LEX *first= master_unit()->first_select();
+ /* drop UNCACHEABLE_EXPLAIN, because it is for internal usage only */
+ uint8 is_uncacheable= (uncacheable & ~UNCACHEABLE_EXPLAIN);
+
+ type= ((&master_unit()->thd->lex->select_lex == this) ?
+ (first_inner_unit() || next_select() ?
+ "PRIMARY" : "SIMPLE") :
+ ((this == first) ?
+ ((linkage == DERIVED_TABLE_TYPE) ?
+ "DERIVED" :
+ ((is_uncacheable & UNCACHEABLE_DEPENDENT) ?
+ "DEPENDENT SUBQUERY" :
+ (is_uncacheable ? "UNCACHEABLE SUBQUERY" :
+ "SUBQUERY"))) :
+ ((is_uncacheable & UNCACHEABLE_DEPENDENT) ?
+ "DEPENDENT UNION":
+ is_uncacheable ? "UNCACHEABLE UNION":
+ "UNION")));
+ options|= SELECT_DESCRIBE;
+}
+
+
/**
A routine used by the parser to decide whether we are specifying a full
partitioning or if only partitions to add or to split.
@@ -3095,4 +3187,3 @@ bool st_lex::is_partition_management() const
(alter_info.flags == ALTER_ADD_PARTITION ||
alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
-