summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc11
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_select.cc147
-rw-r--r--sql/sql_union.cc36
6 files changed, 139 insertions, 62 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 2dabb8e26ef..96b78b38fb7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -369,9 +369,14 @@ const char *Item_ident::full_name() const
}
else
{
- tmp=(char*) sql_alloc((uint) strlen(table_name)+
- (uint) strlen(field_name)+2);
- strxmov(tmp,table_name,".",field_name,NullS);
+ if (table_name[0])
+ {
+ tmp= (char*) sql_alloc((uint) strlen(table_name) +
+ (uint) strlen(field_name) + 2);
+ strxmov(tmp, table_name, ".", field_name, NullS);
+ }
+ else
+ tmp= (char*) field_name;
}
return tmp;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d5eb7a9fd0e..af0fff4435a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -768,7 +768,7 @@ public:
uint current_tablenr,tmp_table;
uint server_status,open_options,system_thread;
uint32 db_length;
- uint select_number; //number of select (used for EXPLAIN)
+ int select_number; //number of select (used for EXPLAIN)
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
enum_check_fields count_cuted_fields;
@@ -1147,7 +1147,6 @@ class select_union :public select_result {
TABLE *table;
COPY_INFO info;
TMP_TABLE_PARAM tmp_table_param;
- bool not_describe;
select_union(TABLE *table_par);
~select_union();
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5fa8b37285e..586706be6c1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1007,6 +1007,7 @@ void st_select_lex_unit::init_query()
fake_select_lex= 0;
cleaned= 0;
item_list.empty();
+ describe= 0;
}
void st_select_lex::init_query()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 50f13a0391c..fd6e9142275 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -336,6 +336,7 @@ public:
st_select_lex *fake_select_lex;
st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */
+ bool describe; /* union exec() called for EXPLAIN */
void init_query();
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
@@ -413,7 +414,7 @@ public:
ulong table_join_options;
uint in_sum_expr;
- uint select_number; /* number of select (used for EXPLAIN) */
+ int select_number; /* number of select (used for EXPLAIN) */
uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2cfeb171153..2b3de669618 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -991,7 +991,7 @@ JOIN::optimize()
}
}
- if (select_lex->master_unit()->uncacheable)
+ if (select_lex->master_unit()->uncacheable || thd->lex->describe)
{
if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
DBUG_RETURN(-1);
@@ -9132,7 +9132,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (message)
{
- item_list.push_back(new Item_int((int32) join->select_lex->select_number));
+ item_list.push_back(new Item_int((longlong)
+ join->select_lex->select_number));
item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type), cs));
for (uint i=0 ; i < 7; i++)
@@ -9141,6 +9142,49 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (result->send_data(item_list))
join->error= 1;
}
+ else if (join->select_lex == join->unit->fake_select_lex)
+ {
+ /*
+ Here is guessing about fake_select_lex to avoid union SELECT
+ execution to get accurate information
+ */
+ char table_name_buffer[64];
+ item_list.empty();
+ /* id */
+ item_list.push_back(new Item_int((int32)
+ join->select_lex->select_number));
+ /* select_type */
+ item_list.push_back(new Item_string(join->select_lex->type,
+ strlen(join->select_lex->type),
+ cs));
+ /* table */
+ int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
+ "<union%d>",
+ -join->select_lex->select_number);
+ item_list.push_back(new Item_string(table_name_buffer, len, cs));
+ item_list.push_back(new Item_string(join_type_str[JT_ALL],
+ strlen(join_type_str[JT_ALL]),
+ cs));
+ /* possible_keys */
+ item_list.push_back(item_null);
+ /* key*/
+ item_list.push_back(item_null);
+ /* key_len */
+ item_list.push_back(item_null);
+ /* ref */
+ item_list.push_back(item_null);
+ /* rows */
+ item_list.push_back(item_null);
+ /* extra */
+ if (join->unit->global_parameters->order_list.first)
+ item_list.push_back(new Item_string("Using filesort",
+ 14, cs));
+ else
+ item_list.push_back(new Item_string("", 0, cs));
+
+ if (result->send_data(item_list))
+ join->error= 1;
+ }
else
{
table_map used_tables=0;
@@ -9150,36 +9194,41 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
TABLE *table=tab->table;
char buff[512],*buff_ptr=buff;
char buff1[512], buff2[512];
- char derived_name[64];
+ char table_name_buffer[64];
String tmp1(buff1,sizeof(buff1),cs);
String tmp2(buff2,sizeof(buff2),cs);
tmp1.length(0);
tmp2.length(0);
item_list.empty();
+ /* id */
item_list.push_back(new Item_int((int32)
join->select_lex->select_number));
+ /* select_type */
item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type),
cs));
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
+ /* table */
if (table->derived_select_number)
{
/* Derived table name generation */
- int len= my_snprintf(derived_name, sizeof(derived_name)-1,
+ int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
"<derived%u>",
table->derived_select_number);
- item_list.push_back(new Item_string(derived_name, len, cs));
+ item_list.push_back(new Item_string(table_name_buffer, len, cs));
}
else
item_list.push_back(new Item_string(table->table_name,
strlen(table->table_name),
cs));
+ /* type */
item_list.push_back(new Item_string(join_type_str[tab->type],
strlen(join_type_str[tab->type]),
cs));
uint j;
+ /* possible_keys */
if (!tab->keys.is_clear_all())
{
for (j=0 ; j < table->keys ; j++)
@@ -9196,6 +9245,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
else
item_list.push_back(item_null);
+ /* key key_len ref */
if (tab->ref.key_parts)
{
KEY *key_info=table->key_info+ tab->ref.key;
@@ -9234,9 +9284,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null);
item_list.push_back(item_null);
}
+ /* rows */
item_list.push_back(new Item_int((longlong) (ulonglong)
join->best_positions[i]. records_read,
21));
+ /* extra */
my_bool key_read=table->key_read;
if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
table->used_keys.is_set(tab->index))
@@ -9301,32 +9353,53 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
DBUG_ENTER("mysql_explain_union");
int res= 0;
SELECT_LEX *first= unit->first_select();
+
for (SELECT_LEX *sl= first;
sl;
sl= sl->next_select())
{
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
-
- res= mysql_explain_select(thd, sl,
- (((&thd->lex->select_lex)==sl)?
- ((thd->lex->all_selects_list != sl) ?
- primary_key_name : "SIMPLE"):
- ((sl == first)?
- ((sl->linkage == DERIVED_TABLE_TYPE) ?
- "DERIVED":
- ((uncacheable & UNCACHEABLE_DEPENDENT) ?
- "DEPENDENT SUBQUERY":
- (uncacheable?"UNCACHEABLE SUBQUERY":
- "SUBQUERY"))):
- ((uncacheable & UNCACHEABLE_DEPENDENT) ?
- "DEPENDENT UNION":
- uncacheable?"UNCACHEABLE UNION":
- "UNION"))),
- result);
- if (res)
- break;
-
+ sl->type= (((&thd->lex->select_lex)==sl)?
+ ((thd->lex->all_selects_list != sl) ?
+ primary_key_name : "SIMPLE"):
+ ((sl == first)?
+ ((sl->linkage == DERIVED_TABLE_TYPE) ?
+ "DERIVED":
+ ((uncacheable & UNCACHEABLE_DEPENDENT) ?
+ "DEPENDENT SUBQUERY":
+ (uncacheable?"UNCACHEABLE SUBQUERY":
+ "SUBQUERY"))):
+ ((uncacheable & UNCACHEABLE_DEPENDENT) ?
+ "DEPENDENT UNION":
+ uncacheable?"UNCACHEABLE UNION":
+ "UNION")));
+ sl->options|= SELECT_DESCRIBE;
+ }
+ if (first->next_select())
+ {
+ unit->fake_select_lex->select_number= -first->select_number;
+ unit->fake_select_lex->type= "UNION RESULT";
+ unit->fake_select_lex->options|= SELECT_DESCRIBE;
+ if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
+ res= unit->exec();
+ res|= unit->cleanup();
+ }
+ else
+ {
+ thd->lex->current_select= first;
+ res= mysql_select(thd, &first->ref_pointer_array,
+ (TABLE_LIST*) first->table_list.first,
+ first->with_wild, first->item_list,
+ first->where,
+ first->order_list.elements +
+ first->group_list.elements,
+ (ORDER*) first->order_list.first,
+ (ORDER*) first->group_list.first,
+ first->having,
+ (ORDER*) thd->lex->proc_list.first,
+ first->options | thd->options | SELECT_DESCRIBE,
+ result, unit, first);
}
if (res > 0 || thd->net.report_error)
res= -1; // mysql_explain_select do not report error
@@ -9334,30 +9407,6 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
}
-int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
- select_result *result)
-{
- DBUG_ENTER("mysql_explain_select");
- DBUG_PRINT("info", ("Select 0x%lx, type %s", (ulong)select_lex, type))
- select_lex->type= type;
- thd->lex->current_select= select_lex;
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
- int res= mysql_select(thd, &select_lex->ref_pointer_array,
- (TABLE_LIST*) select_lex->table_list.first,
- select_lex->with_wild, select_lex->item_list,
- select_lex->where,
- select_lex->order_list.elements +
- select_lex->group_list.elements,
- (ORDER*) select_lex->order_list.first,
- (ORDER*) select_lex->group_list.first,
- select_lex->having,
- (ORDER*) thd->lex->proc_list.first,
- select_lex->options | thd->options | SELECT_DESCRIBE,
- result, unit, select_lex);
- DBUG_RETURN(res);
-}
-
-
void st_select_lex::print(THD *thd, String *str)
{
if (!thd)
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index e5649192fe5..b4f3e78e33a 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -41,7 +41,7 @@ int mysql_union(THD *thd, LEX *lex, select_result *result,
***************************************************************************/
select_union::select_union(TABLE *table_par)
- :table(table_par), not_describe(0)
+ :table(table_par)
{
bzero((char*) &info,sizeof(info));
/*
@@ -114,6 +114,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
select_result *tmp_result;
DBUG_ENTER("st_select_lex_unit::prepare");
+ describe= test(additional_options & SELECT_DESCRIBE);
+
/*
result object should be reassigned even if preparing already done for
max/min subquery (ALL/ANY optimization)
@@ -121,7 +123,26 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
result= sel_result;
if (prepared)
+ {
+ if (describe)
+ {
+ /* fast reinit for EXPLAIN */
+ for (sl= first_select_in_union(); sl; sl= sl->next_select())
+ {
+ sl->join->result= result;
+ select_limit_cnt= HA_POS_ERROR;
+ offset_limit_cnt= 0;
+ if (!sl->join->procedure &&
+ result->prepare(sl->join->fields_list, this))
+ {
+ DBUG_RETURN(1);
+ }
+ sl->join->select_options|= SELECT_DESCRIBE;
+ sl->join->reinit();
+ }
+ }
DBUG_RETURN(0);
+ }
prepared= 1;
res= 0;
@@ -134,8 +155,9 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
if (!(tmp_result= union_result= new select_union(0)))
goto err;
- union_result->not_describe= 1;
union_result->tmp_table_param.init();
+ if (describe)
+ tmp_result= sel_result;
}
else
{
@@ -269,11 +291,11 @@ int st_select_lex_unit::exec()
ulonglong add_rows=0;
DBUG_ENTER("st_select_lex_unit::exec");
- if (executed && !uncacheable)
+ if (executed && !uncacheable && !describe)
DBUG_RETURN(0);
executed= 1;
- if (uncacheable || !item || !item->assigned())
+ if (uncacheable || !item || !item->assigned() || describe)
{
if (optimized && item && item->assigned())
{
@@ -292,7 +314,7 @@ int st_select_lex_unit::exec()
res= sl->join->reinit();
else
{
- if (sl != global_parameters)
+ if (sl != global_parameters && !describe)
{
offset_limit_cnt= sl->offset_limit;
select_limit_cnt= sl->select_limit+sl->offset_limit;
@@ -304,7 +326,7 @@ int st_select_lex_unit::exec()
We can't use LIMIT at this stage if we are using ORDER BY for the
whole query
*/
- if (sl->order_list.first)
+ if (sl->order_list.first || describe)
select_limit_cnt= HA_POS_ERROR;
else
select_limit_cnt= sl->select_limit+sl->offset_limit;
@@ -373,7 +395,7 @@ int st_select_lex_unit::exec()
if (!thd->is_fatal_error) // Check if EOM
{
- ulong options_tmp= thd->options;
+ ulong options_tmp= thd->options | fake_select_lex->options;
thd->lex->current_select= fake_select_lex;
offset_limit_cnt= global_parameters->offset_limit;
select_limit_cnt= global_parameters->select_limit +