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.cc86
1 files changed, 80 insertions, 6 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 608eccbaff6..cc6e33263b8 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4413,7 +4413,7 @@ void st_select_lex::set_explain_type(bool on_the_fly)
{
type= is_uncacheable ? "UNCACHEABLE UNION": "UNION";
if (this == master_unit()->fake_select_lex)
- type= "UNION RESULT";
+ type= unit_operation_text[master_unit()->common_op()];
/*
join below may be =NULL when this functions is called at an early
stage. It will be later called again and we will set the correct
@@ -4484,6 +4484,7 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
// in worse case none of record will be removed
break;
default:
+ // usual UNION
result->records+= records;
break;
}
@@ -4740,6 +4741,42 @@ void LEX::restore_set_statement_var()
DBUG_VOID_RETURN;
}
+unit_common_op st_select_lex_unit::common_op()
+{
+ SELECT_LEX *first= first_select();
+ bool first_op= TRUE;
+ unit_common_op operation= OP_MIX; // if no op
+ for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
+ {
+ if (sl != first)
+ {
+ unit_common_op op;
+ switch (sl->linkage)
+ {
+ case INTERSECT_TYPE:
+ op= OP_INTERSECT;
+ break;
+ case EXCEPT_TYPE:
+ op= OP_EXCEPT;
+ break;
+ default:
+ op= OP_UNION;
+ break;
+ }
+ if (first_op)
+ {
+ operation= op;
+ first_op= TRUE;
+ }
+ else
+ {
+ if (operation != op)
+ operation= OP_MIX;
+ }
+ }
+ }
+ return operation;
+}
/*
Save explain structures of a UNION. The only variable member is whether the
union has "Using filesort".
@@ -4776,11 +4813,10 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
Note: Non-merged semi-joins cannot be made out of UNIONs currently, so we
dont ever set EXPLAIN_NODE_NON_MERGED_SJ.
*/
-
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
eu->add_select(sl->select_number);
- eu->fake_select_type= "UNION RESULT";
+ eu->fake_select_type= unit_operation_text[eu->operation= common_op()];
eu->using_filesort= MY_TEST(global_parameters()->order_list.first);
eu->using_tmp= union_needs_tmp_table();
@@ -4836,6 +4872,12 @@ bool LEX::is_partition_management() const
}
+/**
+ Exclude last added SELECT_LEX (current) in the UNIT and return pointer in it
+ (previous become currect)
+
+ @return detached SELECT_LEX or NULL in case of error
+*/
SELECT_LEX *LEX::exclude_last_select()
{
@@ -4857,6 +4899,26 @@ SELECT_LEX *LEX::exclude_last_select()
DBUG_RETURN(exclude);
}
+
+/**
+ Put given (new) SELECT_LEX level below after currect (last) SELECT
+
+ LAST SELECT -> DUMMY SELECT
+ |
+ V
+ NEW UNIT
+ |
+ V
+ NEW SELECT
+
+ SELECT (*LAST*) ... FROM (SELECT (*NEW*) ... )
+
+ @param nselect Select to put one level below
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
{
DBUG_ENTER("LEX::add_unit_in_brackets");
@@ -4872,7 +4934,7 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
Name_resolution_context *context= &dummy_select->context;
context->init();
- /* add SELECT list*/
+ /* add SELECT list*/
Item *item= new (thd->mem_root)
Item_field(thd, context, NULL, NULL, "*");
if (item == NULL)
@@ -4895,8 +4957,11 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
char buff[10];
LEX_STRING alias;
alias.length= my_snprintf(buff, sizeof(buff),
- "__%d", dummy_select->select_number);
- alias.str= thd->strdup(buff);
+ "__%u", dummy_select->select_number);
+ alias.str= thd->strmake(buff, alias.length);
+ if (!alias.str)
+ DBUG_RETURN(TRUE);
+
TABLE_LIST *table_list;
if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias,
0, TL_READ,
@@ -4912,6 +4977,15 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
DBUG_RETURN(rc);
}
+
+/**
+ Checks if we need finish "automatic brackets" mode
+
+ INTERSECT has higher priority then UNION and EXCEPT, so when it is need we
+ automatically create lower layer for INTERSECT (automatic brackets) and
+ here we check if we should return back one level up during parsing procedure.
+*/
+
void LEX::check_automatic_up(enum sub_select_type type)
{
if (type != INTERSECT_TYPE &&