Fixing some bugs in UNION's

parent 8eeaacc2
...@@ -144,7 +144,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); ...@@ -144,7 +144,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static void init_sum_functions(Item_sum **func); static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func); static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct); bool distinct, const char *message=NullS);
static void describe_info(THD *thd, const char *info); static void describe_info(THD *thd, const char *info);
/* /*
...@@ -195,6 +195,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -195,6 +195,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
Procedure *procedure; Procedure *procedure;
List<Item> all_fields(fields); List<Item> all_fields(fields);
bool select_distinct; bool select_distinct;
SELECT_LEX *select_lex = &(thd->lex.select_lex);
DBUG_ENTER("mysql_select"); DBUG_ENTER("mysql_select");
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
...@@ -350,10 +351,13 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -350,10 +351,13 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
} }
if (cond_value == Item::COND_FALSE || !thd->select_limit) if (cond_value == Item::COND_FALSE || !thd->select_limit)
{ /* Impossible cond */ { /* Impossible cond */
error=return_zero_rows(result, tables, fields, if (select_options & SELECT_DESCRIBE && select_lex->next)
join.tmp_table_param.sum_func_count != 0 && !group, select_describe(&join,false,false,false,"Impossible WHERE");
select_options,"Impossible WHERE",having, else
procedure); error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,"Impossible WHERE",having,
procedure);
delete procedure; delete procedure;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -366,17 +370,23 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -366,17 +370,23 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ {
if (res < 0) if (res < 0)
{ {
error=return_zero_rows(result, tables, fields, !group, if (select_options & SELECT_DESCRIBE && select_lex->next)
select_options,"No matching min/max row", select_describe(&join,false,false,false,"No matching min/max row");
having,procedure); else
error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row",
having,procedure);
delete procedure; delete procedure;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
{ {
describe_info(thd,"Select tables optimized away"); if (select_lex->next)
select_describe(&join,false,false,false,"Select tables optimized away");
else
describe_info(thd,"Select tables optimized away");
delete procedure; delete procedure;
DBUG_RETURN(0); DBUG_RETURN(error);
} }
tables=0; // All tables resolved tables=0; // All tables resolved
} }
...@@ -385,7 +395,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -385,7 +395,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ // Only test of functions { // Only test of functions
error=0; error=0;
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
describe_info(thd,"No tables used"); {
if (select_lex->next)
select_describe(&join,false,false,false,"No tables used");
else
describe_info(thd,"No tables used");
}
else else
{ {
result->send_fields(fields,1); result->send_fields(fields,1);
...@@ -463,11 +478,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -463,11 +478,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
} }
if (make_join_select(&join,select,conds)) if (make_join_select(&join,select,conds))
{ {
error=return_zero_rows(result,tables,fields, if (select_options & SELECT_DESCRIBE && select_lex->next)
join.tmp_table_param.sum_func_count != 0 && !group, select_describe(&join,false,false,false,"Impossible WHERE noticed after reading const tables");
select_options, else
"Impossible WHERE noticed after reading const tables", error=return_zero_rows(result,tables,fields,
having,procedure); join.tmp_table_param.sum_func_count != 0 && !group,
select_options,
"Impossible WHERE noticed after reading const tables",
having,procedure);
goto err; goto err;
} }
...@@ -535,7 +553,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -535,7 +553,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
make_join_readinfo(&join, make_join_readinfo(&join,
(select_options & (SELECT_DESCRIBE | (select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) | SELECT_NO_JOIN_CACHE)) |
(thd->lex.select_lex.ftfunc_list.elements ? SELECT_NO_JOIN_CACHE : 0)); (select_lex->ftfunc_list.elements ? SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all /* Need to tell Innobase that to play it safe, it should fetch all
columns of the tables: this is because MySQL columns of the tables: this is because MySQL
...@@ -2516,6 +2534,7 @@ static void ...@@ -2516,6 +2534,7 @@ static void
make_join_readinfo(JOIN *join,uint options) make_join_readinfo(JOIN *join,uint options)
{ {
uint i; uint i;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
DBUG_ENTER("make_join_readinfo"); DBUG_ENTER("make_join_readinfo");
for (i=join->const_tables ; i < join->tables ; i++) for (i=join->const_tables ; i < join->tables ; i++)
...@@ -2598,7 +2617,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2598,7 +2617,7 @@ make_join_readinfo(JOIN *join,uint options)
/* These init changes read_record */ /* These init changes read_record */
if (tab->use_quick == 2) if (tab->use_quick == 2)
{ {
join->thd->lex.select_lex.options|=QUERY_NO_GOOD_INDEX_USED; select_lex->options|=QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record; tab->read_first_record= join_init_quick_read_record;
statistic_increment(select_range_check_count, &LOCK_status); statistic_increment(select_range_check_count, &LOCK_status);
} }
...@@ -2613,7 +2632,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2613,7 +2632,7 @@ make_join_readinfo(JOIN *join,uint options)
} }
else else
{ {
join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED; select_lex->options|=QUERY_NO_INDEX_USED;
statistic_increment(select_scan_count, &LOCK_status); statistic_increment(select_scan_count, &LOCK_status);
} }
} }
...@@ -2625,7 +2644,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2625,7 +2644,7 @@ make_join_readinfo(JOIN *join,uint options)
} }
else else
{ {
join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED; select_lex->options|=QUERY_NO_INDEX_USED;
statistic_increment(select_full_join_count, &LOCK_status); statistic_increment(select_full_join_count, &LOCK_status);
} }
} }
...@@ -2913,7 +2932,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields, ...@@ -2913,7 +2932,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("return_zero_rows"); DBUG_ENTER("return_zero_rows");
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
{ {
describe_info(current_thd, info); describe_info(current_thd, info);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -6940,16 +6959,17 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) ...@@ -6940,16 +6959,17 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
****************************************************************************/ ****************************************************************************/
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct) bool distinct,const char *message)
{ {
List<Item> field_list; List<Item> field_list;
Item *item; Item *item;
THD *thd=join->thd; THD *thd=join->thd;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
DBUG_ENTER("select_describe"); DBUG_ENTER("select_describe");
/* Don't log this into the slow query log */ /* Don't log this into the slow query log */
join->thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED); select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
if (join->thd->lex.select == &join->thd->lex.select_lex) if (join->thd->lex.select == select_lex)
{ {
field_list.push_back(new Item_empty_string("table",NAME_LEN)); field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10)); field_list.push_back(new Item_empty_string("type",10));
...@@ -6970,133 +6990,150 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -6970,133 +6990,150 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
} }
char buff[512],*buff_ptr; char buff[512],*buff_ptr;
String tmp(buff,sizeof(buff)),*packet= &thd->packet; String tmp(buff,sizeof(buff)),*packet= &thd->packet;
table_map used_tables=0; if (message)
for (uint i=0 ; i < join->tables ; i++)
{ {
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
packet->length(0); packet->length(0);
net_store_data(packet,table->table_name); net_store_null(packet);
net_store_data(packet,join_type_str[tab->type]); net_store_null(packet);
tmp.length(0); net_store_null(packet);
key_map bits; net_store_null(packet);
uint j; net_store_null(packet);
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1) net_store_null(packet);
{ net_store_null(packet);
if (bits & 1) net_store_data(packet,message,strlen(message));
{ if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
if (tmp.length()) DBUG_VOID_RETURN;
tmp.append(','); }
tmp.append(table->key_info[j].name); else
} {
} table_map used_tables=0;
if (tmp.length()) for (uint i=0 ; i < join->tables ; i++)
net_store_data(packet,tmp.ptr(),tmp.length());
else
net_store_null(packet);
if (tab->ref.key_parts)
{ {
net_store_data(packet,table->key_info[tab->ref.key].name); JOIN_TAB *tab=join->join_tab+i;
net_store_data(packet,(uint32) tab->ref.key_length); TABLE *table=tab->table;
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
packet->length(0);
net_store_data(packet,table->table_name);
net_store_data(packet,join_type_str[tab->type]);
tmp.length(0); tmp.length(0);
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++) key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
{ {
if (tmp.length()) if (bits & 1)
tmp.append(','); {
tmp.append((*ref)->name()); if (tmp.length())
tmp.append(',');
tmp.append(table->key_info[j].name);
}
} }
net_store_data(packet,tmp.ptr(),tmp.length()); if (tmp.length())
} net_store_data(packet,tmp.ptr(),tmp.length());
else if (tab->type == JT_NEXT) else
{ net_store_null(packet);
net_store_data(packet,table->key_info[tab->index].name); if (tab->ref.key_parts)
net_store_data(packet,(uint32) table->key_info[tab->index].key_length);
net_store_null(packet);
}
else if (tab->select && tab->select->quick)
{
net_store_data(packet,table->key_info[tab->select->quick->index].name);;
net_store_data(packet,(uint32) tab->select->quick->max_used_key_length);
net_store_null(packet);
}
else
{
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
}
sprintf(buff,"%.0f",join->best_positions[i].records_read);
net_store_data(packet,buff);
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
buff_ptr=buff;
if (tab->info)
net_store_data(packet,tab->info);
else if (tab->select)
{
if (tab->use_quick == 2)
{ {
sprintf(buff_ptr,"range checked for each record (index map: %u)", net_store_data(packet,table->key_info[tab->ref.key].name);
tab->keys); net_store_data(packet,(uint32) tab->ref.key_length);
buff_ptr=strend(buff_ptr); tmp.length(0);
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
{
if (tmp.length())
tmp.append(',');
tmp.append((*ref)->name());
}
net_store_data(packet,tmp.ptr(),tmp.length());
}
else if (tab->type == JT_NEXT)
{
net_store_data(packet,table->key_info[tab->index].name);
net_store_data(packet,(uint32) table->key_info[tab->index].key_length);
net_store_null(packet);
}
else if (tab->select && tab->select->quick)
{
net_store_data(packet,table->key_info[tab->select->quick->index].name);;
net_store_data(packet,(uint32) tab->select->quick->max_used_key_length);
net_store_null(packet);
} }
else else
buff_ptr=strmov(buff_ptr,"where used");
}
if (key_read)
{
if (buff != buff_ptr)
{ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
} }
buff_ptr=strmov(buff_ptr,"Using index"); sprintf(buff,"%.0f",join->best_positions[i].records_read);
} net_store_data(packet,buff);
if (table->reginfo.not_exists_optimize) my_bool key_read=table->key_read;
{ if (tab->type == JT_NEXT &&
if (buff != buff_ptr) ((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
buff_ptr=buff;
if (tab->info)
net_store_data(packet,tab->info);
else if (tab->select)
{ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; if (tab->use_quick == 2)
{
sprintf(buff_ptr,"range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
}
else
buff_ptr=strmov(buff_ptr,"where used");
} }
buff_ptr=strmov(buff_ptr,"Not exists"); if (key_read)
}
if (need_tmp_table)
{
need_tmp_table=0;
if (buff != buff_ptr)
{ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using index");
} }
buff_ptr=strmov(buff_ptr,"Using temporary"); if (table->reginfo.not_exists_optimize)
}
if (need_order)
{
need_order=0;
if (buff != buff_ptr)
{ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Not exists");
} }
buff_ptr=strmov(buff_ptr,"Using filesort"); if (need_tmp_table)
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
{
if (buff != buff_ptr)
{ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2; need_tmp_table=0;
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using temporary");
} }
buff_ptr=strmov(buff_ptr,"Distinct"); if (need_order)
} {
net_store_data(packet,buff,(uint) (buff_ptr - buff)); need_order=0;
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) if (buff != buff_ptr)
DBUG_VOID_RETURN; /* purecov: inspected */ {
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
{
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Distinct");
}
net_store_data(packet,buff,(uint) (buff_ptr - buff));
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_VOID_RETURN; /* Purecov: Inspected */
// For next iteration // For next iteration
used_tables|=table->map; used_tables|=table->map;
}
} }
if (!join->thd->lex.select->next) if (!join->thd->lex.select->next)
send_eof(&thd->net); send_eof(&thd->net);
......
...@@ -76,6 +76,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -76,6 +76,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
for (sl= &lex->select_lex; sl; sl=sl->next) for (sl= &lex->select_lex; sl; sl=sl->next)
{ {
lex->select=sl; lex->select=sl;
thd->offset_limit=sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first, res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
sl->item_list, sl->item_list,
sl->where, sl->where,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment