summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc89
1 files changed, 64 insertions, 25 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 450efb84e5d..b7eebf80313 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -136,7 +136,8 @@ static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static void init_sum_functions(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);
static void describe_info(const char *info);
/*****************************************************************************
@@ -171,6 +172,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
no_order=0;
bzero((char*) &keyuse,sizeof(keyuse));
thd->proc_info="init";
+ thd->used_tables=0; // Updated by setup_fields
if (setup_fields(thd,tables,fields,1,&all_fields) ||
setup_conds(thd,tables,&conds) ||
@@ -261,7 +263,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join.join_tab=0;
join.tmp_table_param.copy_field=0;
join.sum_funcs=0;
- join.send_records=0L;
+ join.send_records=join.found_records=0;
join.tmp_table_param.end_write_records= HA_POS_ERROR;
join.first_record=join.sort_and_group=0;
join.select_options=select_options;
@@ -506,7 +508,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=0;
select_describe(&join,need_tmp,
(order != 0 &&
- (!need_tmp || order != group || simple_group)));
+ (!need_tmp || order != group || simple_group)),
+ select_distinct);
error=0;
goto err;
}
@@ -557,6 +560,26 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=0;
}
}
+
+ /*
+ Optimize distinct when used on some of the tables
+ SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
+ In this case we can stop scanning t2 when we have found one t1.a
+ */
+
+ if (tmp_table->distinct)
+ {
+ table_map used_tables= thd->used_tables;
+ JOIN_TAB *join_tab=join.join_tab+join.tables-1;
+ do
+ {
+ if (used_tables & join_tab->table->map)
+ break;
+ join_tab->not_used_in_distinct=1;
+ } while (join_tab-- != join.join_tab);
+ }
+
+ /* Copy data to the temporary table */
thd->proc_info="Copying to tmp table";
if (do_select(&join,(List<Item> *) 0,tmp_table,0))
goto err; /* purecov: inspected */
@@ -2122,7 +2145,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tmp_table_param.copy_field=0;
join->first_record=join->sort_and_group=0;
join->sum_funcs=0;
- join->send_records=0L;
+ join->send_records=(ha_rows) 0;
join->group=0;
join_tab->cache.buff=0; /* No cacheing */
@@ -2130,15 +2153,16 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->select=0;
join_tab->select_cond=0;
join_tab->quick=0;
- bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
join_tab->type= JT_ALL; /* Map through all records */
join_tab->keys= (uint) ~0; /* test everything in quick */
join_tab->info=0;
join_tab->on_expr=0;
join_tab->ref.key = -1;
+ join_tab->not_used_in_distinct=0;
+ join_tab->read_first_record= join_init_read_record;
+ bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
tmp_table->null_row=0;
- join_tab->read_first_record= join_init_read_record;
return FALSE;
}
@@ -3256,7 +3280,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (item->with_sum_func && type != Item::SUM_FUNC_ITEM ||
item->const_item())
continue;
-
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */
((Item_sum*) item)->result_field=0;
@@ -3913,7 +3936,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if (!(error=(*join_tab->read_first_record)(join_tab)))
{
- bool not_exists_optimize=join_tab->table->reginfo.not_exists_optimize;
+ bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
+ bool not_used_in_distinct=join_tab->not_used_in_distinct;
+ ha_rows found_records=join->found_records;
READ_RECORD *info= &join_tab->read_record;
do
@@ -3932,6 +3957,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
if ((error=(*next_select)(join,join_tab+1,0)) < 0)
return error;
+ if (not_used_in_distinct && found_records != join->found_records)
+ return 0;
}
}
} while (!(error=info->read_record(info)));
@@ -4545,23 +4572,21 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
if (!join->having || join->having->val_int())
{
+ join->found_records++;
if ((error=table->file->write_row(table->record[0])))
{
- if (error != HA_ERR_FOUND_DUPP_KEY &&
- error != HA_ERR_FOUND_DUPP_UNIQUE)
- {
- if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
- DBUG_RETURN(1); // Not a table_is_full error
- table->uniques=0; // To ensure rows are the same
- }
- }
- else
- {
+ if (error == HA_ERR_FOUND_DUPP_KEY ||
+ error == HA_ERR_FOUND_DUPP_UNIQUE)
+ goto end;
+ if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
+ DBUG_RETURN(1); // Not a table_is_full error
+ table->uniques=0; // To ensure rows are the same
if (++join->send_records >= join->tmp_table_param.end_write_records)
DBUG_RETURN(-3);
}
}
}
+end:
DBUG_RETURN(0);
}
@@ -4585,6 +4610,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(-2); /* purecov: inspected */
}
+ join->found_records++;
copy_fields(&join->tmp_table_param); // Groups are copied twice.
/* Make a key of group index */
for (group=table->group ; group ; group=group->next)
@@ -6335,12 +6361,13 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
** Send a description about what how the select will be done to stdout
****************************************************************************/
-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)
{
- DBUG_ENTER("select_describe");
-
List<Item> field_list;
Item *item;
+ THD *thd=join->thd;
+ DBUG_ENTER("select_describe");
field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10));
@@ -6356,11 +6383,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order)
item->maybe_null=1;
field_list.push_back(new Item_real("rows",0.0,0,10));
field_list.push_back(new Item_empty_string("Extra",255));
- if (send_fields(join->thd,field_list,1))
+ if (send_fields(thd,field_list,1))
return; /* purecov: inspected */
char buff[512],*buff_ptr;
- String tmp(buff,sizeof(buff)),*packet= &join->thd->packet;
+ String tmp(buff,sizeof(buff)),*packet= &thd->packet;
+ table_map used_tables=0;
for (uint i=0 ; i < join->tables ; i++)
{
JOIN_TAB *tab=join->join_tab+i;
@@ -6473,11 +6501,22 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order)
}
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(&join->thd->net,(char*) packet->ptr(),packet->length()))
+ if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_VOID_RETURN; /* purecov: inspected */
+
+ // For next iteration
+ used_tables|=table->map;
}
- send_eof(&join->thd->net);
+ send_eof(&thd->net);
DBUG_VOID_RETURN;
}