Commit 207548a8 authored by monty@tramp.mysql.fi's avatar monty@tramp.mysql.fi

DISTINCT optimization

Fixes when using column privileges
Manual updates
parent a434c8d2
bk@work.mysql.com monty@tramp.mysql.fi
davida@work.mysql.com
jamppa@work.mysql.com
jcole@ham.spaceapes.com
jcole@jcole.burghcom.com
jcole@nslinux.bedford.progress.com
jcole@tetra.bedford.progress.com
jcole@tetra.spaceapes.com
matt@work.mysql.com
monty@donna.mysql.com
monty@work.mysql.com
mwagner@evoq.home.mwagner.org
nusphere@main.burghcom.com
paul@central.snake.net
paul@work.mysql.com
sasha@mysql.sashanet.com
sasha@work.mysql.com
serg@infomag.ape.relarn.ru
serg@work.mysql.com
sinisa@work.mysql.com
spurr@nslinux.bedford.progress.com
tim@localhost.polyesthetic.msg
tim@threads.polyesthetic.msg
tim@work.mysql.com
tonu@work.mysql.com
This diff is collapsed.
...@@ -32,6 +32,8 @@ static struct option long_options[] = ...@@ -32,6 +32,8 @@ static struct option long_options[] =
{ {
{"config-file", required_argument, 0, 'c'}, {"config-file", required_argument, 0, 'c'},
{"defaults-file", required_argument, 0, 'c'}, {"defaults-file", required_argument, 0, 'c'},
{"defaults-extra-file", required_argument, 0, 'e'},
{"extra-file", required_argument, 0, 'e'},
{"no-defaults", no_argument, 0, 'd'}, {"no-defaults", no_argument, 0, 'd'},
{"help", no_argument, 0, '?'}, {"help", no_argument, 0, '?'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
...@@ -40,7 +42,7 @@ static struct option long_options[] = ...@@ -40,7 +42,7 @@ static struct option long_options[] =
static void usage(my_bool version) static void usage(my_bool version)
{ {
printf("%s Ver 1.1 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 1.2 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
if (version) if (version)
return; return;
...@@ -50,6 +52,9 @@ static void usage(my_bool version) ...@@ -50,6 +52,9 @@ static void usage(my_bool version)
printf("\n\ printf("\n\
-c, --config-file=#, --defaults-file=#\n\ -c, --config-file=#, --defaults-file=#\n\
The config file to use (default '%s')\n\ The config file to use (default '%s')\n\
-e, --extra-file=#, --defaults-extra-file=#\n\
Read this file after the global /etc config file and\n\
before the config file in the users home directory.\n\
--no-defaults Return an empty string (useful for scripts)\n\ --no-defaults Return an empty string (useful for scripts)\n\
-?, --help Display this help message and exit.\n\ -?, --help Display this help message and exit.\n\
-V, --version Output version information and exit.\n", -V, --version Output version information and exit.\n",
...@@ -61,13 +66,16 @@ static int get_options(int *argc,char ***argv) ...@@ -61,13 +66,16 @@ static int get_options(int *argc,char ***argv)
{ {
int c,option_index; int c,option_index;
while ((c=getopt_long(*argc,*argv,"c:V?I", while ((c=getopt_long(*argc,*argv,"c:e:V?I",
long_options, &option_index)) != EOF) long_options, &option_index)) != EOF)
{ {
switch (c) { switch (c) {
case 'c': case 'c':
config_file=optarg; config_file=optarg;
break; break;
case 'e':
defaults_extra_file=optarg; /* Used by the load_defaults */
break;
case 'n': case 'n':
exit(0); exit(0);
case 'I': case 'I':
...@@ -102,7 +110,7 @@ int main(int argc, char **argv) ...@@ -102,7 +110,7 @@ int main(int argc, char **argv)
if (get_options(&argc,&argv)) if (get_options(&argc,&argv))
exit(1); exit(1);
if (!(load_default_groups=(char**) my_malloc((argc+2)*sizeof(char*), if (!(load_default_groups=(char**) my_malloc((argc+2)*sizeof(char*),
MYF(MY_WME)))) MYF(MY_WME))))
exit(1); exit(1);
for (count=0; *argv ; argv++,count++) for (count=0; *argv ; argv++,count++)
......
...@@ -206,6 +206,7 @@ extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io, ...@@ -206,6 +206,7 @@ extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io,
NEAR my_disable_flush_key_blocks; NEAR my_disable_flush_key_blocks;
extern char wild_many,wild_one,wild_prefix; extern char wild_many,wild_one,wild_prefix;
extern const char *charsets_dir; extern const char *charsets_dir;
extern char *defaults_extra_file;
typedef struct wild_file_pack /* Struct to hold info when selecting files */ typedef struct wild_file_pack /* Struct to hold info when selecting files */
{ {
......
...@@ -29,8 +29,9 @@ ...@@ -29,8 +29,9 @@
** The following arguments are handled automaticly; If used, they must be ** The following arguments are handled automaticly; If used, they must be
** first argument on the command line! ** first argument on the command line!
** --no-defaults ; no options are read. ** --no-defaults ; no options are read.
** --print-defaults ; Print the modified command line and exit
** --defaults-file=full-path-to-default-file ; Only this file will be read. ** --defaults-file=full-path-to-default-file ; Only this file will be read.
** --defaults-extra-file=full-path-to-default-file ; Read this file before ~/
** --print-defaults ; Print the modified command line and exit
****************************************************************************/ ****************************************************************************/
#undef SAFEMALLOC /* safe_malloc is not yet initailized */ #undef SAFEMALLOC /* safe_malloc is not yet initailized */
...@@ -39,6 +40,8 @@ ...@@ -39,6 +40,8 @@
#include "m_string.h" #include "m_string.h"
#include "m_ctype.h" #include "m_ctype.h"
char *defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */ /* Which directories are searched for options (and in which order) */
const char *default_directories[]= { const char *default_directories[]= {
...@@ -50,6 +53,7 @@ const char *default_directories[]= { ...@@ -50,6 +53,7 @@ const char *default_directories[]= {
#ifdef DATADIR #ifdef DATADIR
DATADIR, DATADIR,
#endif #endif
"", /* Place for defaults_extra_dir */
#ifndef __WIN__ #ifndef __WIN__
"~/", "~/",
#endif #endif
...@@ -71,9 +75,10 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -71,9 +75,10 @@ void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv) int *argc, char ***argv)
{ {
DYNAMIC_ARRAY args; DYNAMIC_ARRAY args;
const char **dirs, *extra_default_file; const char **dirs, *forced_default_file;
TYPELIB group; TYPELIB group;
my_bool found_print_defaults=0; my_bool found_print_defaults=0;
uint args_used=0;
MEM_ROOT alloc; MEM_ROOT alloc;
char *ptr,**res; char *ptr,**res;
DBUG_ENTER("load_defaults"); DBUG_ENTER("load_defaults");
...@@ -97,9 +102,20 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -97,9 +102,20 @@ void load_defaults(const char *conf_file, const char **groups,
} }
/* Check if we want to force the use a specific default file */ /* Check if we want to force the use a specific default file */
extra_default_file=0; forced_default_file=0;
if (*argc >= 2 && is_prefix(argv[0][1],"--defaults-file=")) if (*argc >= 2)
extra_default_file=strchr(argv[0][1],'=')+1; {
if (is_prefix(argv[0][1],"--defaults-file="))
{
forced_default_file=strchr(argv[0][1],'=')+1;
args_used++;
}
else if (is_prefix(argv[0][1],"--defaults-extra-file="))
{
defaults_extra_file=strchr(argv[0][1],'=')+1;
args_used++;
}
}
group.count=0; group.count=0;
group.name= "defaults"; group.name= "defaults";
...@@ -109,9 +125,9 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -109,9 +125,9 @@ void load_defaults(const char *conf_file, const char **groups,
if (init_dynamic_array(&args, sizeof(char*),*argc, 32)) if (init_dynamic_array(&args, sizeof(char*),*argc, 32))
goto err; goto err;
if (extra_default_file) if (forced_default_file)
{ {
if (search_default_file(&args, &alloc, "", extra_default_file, "", if (search_default_file(&args, &alloc, "", forced_default_file, "",
&group)) &group))
goto err; goto err;
} }
...@@ -132,8 +148,14 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -132,8 +148,14 @@ void load_defaults(const char *conf_file, const char **groups,
#endif #endif
for (dirs=default_directories ; *dirs; dirs++) for (dirs=default_directories ; *dirs; dirs++)
{ {
if (search_default_file(&args, &alloc, *dirs, conf_file, default_ext, int error;
&group)) if (**dirs)
error=search_default_file(&args, &alloc, *dirs, conf_file,
default_ext, &group);
else if (defaults_extra_file)
error=search_default_file(&args, &alloc, NullS, defaults_extra_file,
default_ext, &group);
if (error)
goto err; goto err;
} }
} }
...@@ -145,11 +167,9 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -145,11 +167,9 @@ void load_defaults(const char *conf_file, const char **groups,
/* copy name + found arguments + command line arguments to new array */ /* copy name + found arguments + command line arguments to new array */
res[0]=argv[0][0]; res[0]=argv[0][0];
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
if (extra_default_file) /* Skipp --defaults-file and --defaults-extra-file */
{ (*argc)-= args_used;
--*argc; /* Skipp --defaults-file */ (*argv)+= args_used;
++*argv;
}
/* Check if we wan't to see the new argument list */ /* Check if we wan't to see the new argument list */
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults")) if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
......
...@@ -2004,6 +2004,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables, ...@@ -2004,6 +2004,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
want_access &= ~table->grant.privilege; want_access &= ~table->grant.privilege;
goto err; // No grants goto err; // No grants
} }
if (show_table)
continue; // We have some priv on this
table->grant.grant_table=grant_table; // Remember for column test table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version; table->grant.version=grant_version;
...@@ -2013,8 +2015,6 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables, ...@@ -2013,8 +2015,6 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
if (!(~table->grant.privilege & want_access)) if (!(~table->grant.privilege & want_access))
continue; continue;
if (show_table && table->grant.privilege)
continue; // Test from show tables
if (want_access & ~(grant_table->cols | table->grant.privilege)) if (want_access & ~(grant_table->cols | table->grant.privilege))
{ {
...@@ -2457,18 +2457,18 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) ...@@ -2457,18 +2457,18 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!strcmp(lex_user->host.str,host)) !strcmp(lex_user->host.str,host))
{ {
want_access=grant_table->privs; want_access=grant_table->privs;
if (want_access) if ((want_access | grant_table->cols) != 0)
{ {
String global(buff,sizeof(buff)); String global(buff,sizeof(buff));
global.length(0); global.length(0);
global.append("GRANT ",6); global.append("GRANT ",6);
if (test_all_bits(want_access,(TABLE_ACLS & ~GRANT_ACL))) if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL)))
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else else
{ {
int found=0; int found=0;
uint j,test_access= want_access & ~GRANT_ACL; uint j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1) for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1)
{ {
......
...@@ -136,7 +136,8 @@ static void copy_sum_funcs(Item_sum **func_ptr); ...@@ -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 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);
static void describe_info(const char *info); static void describe_info(const char *info);
/***************************************************************************** /*****************************************************************************
...@@ -171,6 +172,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -171,6 +172,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
no_order=0; no_order=0;
bzero((char*) &keyuse,sizeof(keyuse)); bzero((char*) &keyuse,sizeof(keyuse));
thd->proc_info="init"; thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (setup_fields(thd,tables,fields,1,&all_fields) || if (setup_fields(thd,tables,fields,1,&all_fields) ||
setup_conds(thd,tables,&conds) || setup_conds(thd,tables,&conds) ||
...@@ -261,7 +263,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -261,7 +263,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join.join_tab=0; join.join_tab=0;
join.tmp_table_param.copy_field=0; join.tmp_table_param.copy_field=0;
join.sum_funcs=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.tmp_table_param.end_write_records= HA_POS_ERROR;
join.first_record=join.sort_and_group=0; join.first_record=join.sort_and_group=0;
join.select_options=select_options; join.select_options=select_options;
...@@ -506,7 +508,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -506,7 +508,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=0; order=0;
select_describe(&join,need_tmp, select_describe(&join,need_tmp,
(order != 0 && (order != 0 &&
(!need_tmp || order != group || simple_group))); (!need_tmp || order != group || simple_group)),
select_distinct);
error=0; error=0;
goto err; goto err;
} }
...@@ -557,6 +560,26 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -557,6 +560,26 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
order=0; 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"; thd->proc_info="Copying to tmp table";
if (do_select(&join,(List<Item> *) 0,tmp_table,0)) if (do_select(&join,(List<Item> *) 0,tmp_table,0))
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
...@@ -2122,7 +2145,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table) ...@@ -2122,7 +2145,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tmp_table_param.copy_field=0; join->tmp_table_param.copy_field=0;
join->first_record=join->sort_and_group=0; join->first_record=join->sort_and_group=0;
join->sum_funcs=0; join->sum_funcs=0;
join->send_records=0L; join->send_records=(ha_rows) 0;
join->group=0; join->group=0;
join_tab->cache.buff=0; /* No cacheing */ join_tab->cache.buff=0; /* No cacheing */
...@@ -2130,15 +2153,16 @@ make_simple_join(JOIN *join,TABLE *tmp_table) ...@@ -2130,15 +2153,16 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->select=0; join_tab->select=0;
join_tab->select_cond=0; join_tab->select_cond=0;
join_tab->quick=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->type= JT_ALL; /* Map through all records */
join_tab->keys= (uint) ~0; /* test everything in quick */ join_tab->keys= (uint) ~0; /* test everything in quick */
join_tab->info=0; join_tab->info=0;
join_tab->on_expr=0; join_tab->on_expr=0;
join_tab->ref.key = -1; 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->status=0;
tmp_table->null_row=0; tmp_table->null_row=0;
join_tab->read_first_record= join_init_read_record;
return FALSE; return FALSE;
} }
...@@ -3256,7 +3280,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -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 || if (item->with_sum_func && type != Item::SUM_FUNC_ITEM ||
item->const_item()) item->const_item())
continue; continue;
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields) if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */ { /* Can't calc group yet */
((Item_sum*) item)->result_field=0; ((Item_sum*) item)->result_field=0;
...@@ -3913,7 +3936,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) ...@@ -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))) 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; READ_RECORD *info= &join_tab->read_record;
do do
...@@ -3932,6 +3957,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) ...@@ -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) if ((error=(*next_select)(join,join_tab+1,0)) < 0)
return error; return error;
if (not_used_in_distinct && found_records != join->found_records)
return 0;
} }
} }
} while (!(error=info->read_record(info))); } while (!(error=info->read_record(info)));
...@@ -4545,23 +4572,21 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -4545,23 +4572,21 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
} }
if (!join->having || join->having->val_int()) if (!join->having || join->having->val_int())
{ {
join->found_records++;
if ((error=table->file->write_row(table->record[0]))) if ((error=table->file->write_row(table->record[0])))
{ {
if (error != HA_ERR_FOUND_DUPP_KEY && if (error == HA_ERR_FOUND_DUPP_KEY ||
error != HA_ERR_FOUND_DUPP_UNIQUE) error == HA_ERR_FOUND_DUPP_UNIQUE)
{ goto end;
if (create_myisam_from_heap(table, &join->tmp_table_param, error,1)) if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
DBUG_RETURN(1); // Not a table_is_full error DBUG_RETURN(1); // Not a table_is_full error
table->uniques=0; // To ensure rows are the same table->uniques=0; // To ensure rows are the same
}
}
else
{
if (++join->send_records >= join->tmp_table_param.end_write_records) if (++join->send_records >= join->tmp_table_param.end_write_records)
DBUG_RETURN(-3); DBUG_RETURN(-3);
} }
} }
} }
end:
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -4585,6 +4610,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -4585,6 +4610,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(-2); /* purecov: inspected */ DBUG_RETURN(-2); /* purecov: inspected */
} }
join->found_records++;
copy_fields(&join->tmp_table_param); // Groups are copied twice. copy_fields(&join->tmp_table_param); // Groups are copied twice.
/* Make a key of group index */ /* Make a key of group index */
for (group=table->group ; group ; group=group->next) 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) ...@@ -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 ** 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; List<Item> field_list;
Item *item; 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("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10)); 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) ...@@ -6356,11 +6383,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order)
item->maybe_null=1; item->maybe_null=1;
field_list.push_back(new Item_real("rows",0.0,0,10)); field_list.push_back(new Item_real("rows",0.0,0,10));
field_list.push_back(new Item_empty_string("Extra",255)); 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 */ return; /* purecov: inspected */
char buff[512],*buff_ptr; 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++) for (uint i=0 ; i < join->tables ; i++)
{ {
JOIN_TAB *tab=join->join_tab+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) ...@@ -6473,11 +6501,22 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order)
} }
buff_ptr=strmov(buff_ptr,"Using filesort"); 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)); 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 */ DBUG_VOID_RETURN; /* purecov: inspected */
// For next iteration
used_tables|=table->map;
} }
send_eof(&join->thd->net); send_eof(&thd->net);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -79,36 +79,36 @@ class JOIN; ...@@ -79,36 +79,36 @@ class JOIN;
typedef struct st_join_table { typedef struct st_join_table {
TABLE *table; TABLE *table;
KEYUSE *keyuse; /* pointer to first used key */
SQL_SELECT *select;
COND *select_cond;
QUICK_SELECT *quick;
Item *on_expr;
const char *info;
int (*read_first_record)(struct st_join_table *tab); int (*read_first_record)(struct st_join_table *tab);
int (*next_select)(JOIN *,struct st_join_table *,bool); int (*next_select)(JOIN *,struct st_join_table *,bool);
bool cached_eq_ref_table,eq_ref_table;
READ_RECORD read_record; READ_RECORD read_record;
uint keys; /* all keys with can be used */ double worst_seeks;
key_map const_keys; /* Keys with constant part */ key_map const_keys; /* Keys with constant part */
key_map checked_keys; /* Keys checked in find_best */ key_map checked_keys; /* Keys checked in find_best */
key_map needed_reg; key_map needed_reg;
ha_rows records,found_records,read_time; ha_rows records,found_records,read_time;
table_map dependent,key_dependent; table_map dependent,key_dependent;
uint keys; /* all keys with can be used */
uint use_quick,index; uint use_quick,index;
uint status; // Save status for cache uint status; // Save status for cache
enum join_type type;
JOIN_CACHE cache;
KEYUSE *keyuse; /* pointer to first used key */
SQL_SELECT *select;
COND *select_cond;
QUICK_SELECT *quick;
Item *on_expr;
uint used_fields,used_fieldlength,used_blobs; uint used_fields,used_fieldlength,used_blobs;
const char *info; enum join_type type;
double worst_seeks; bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
TABLE_REF ref; TABLE_REF ref;
JOIN_CACHE cache;
} JOIN_TAB; } JOIN_TAB;
typedef struct st_position { /* Used in find_best */ typedef struct st_position { /* Used in find_best */
double records_read;
JOIN_TAB *table; JOIN_TAB *table;
KEYUSE *key; KEYUSE *key;
double records_read;
} POSITION; } POSITION;
...@@ -116,16 +116,16 @@ typedef struct st_position { /* Used in find_best */ ...@@ -116,16 +116,16 @@ typedef struct st_position { /* Used in find_best */
class TMP_TABLE_PARAM { class TMP_TABLE_PARAM {
public: public:
uint copy_field_count,field_count,sum_func_count,func_count; List<Item> copy_funcs;
uint group_parts,group_length;
uint quick_group;
Copy_field *copy_field; Copy_field *copy_field;
byte *group_buff; byte *group_buff;
ha_rows end_write_records;
Item_result_field **funcs; Item_result_field **funcs;
List<Item> copy_funcs;
MI_COLUMNDEF *recinfo,*start_recinfo; MI_COLUMNDEF *recinfo,*start_recinfo;
KEY *keyinfo; KEY *keyinfo;
ha_rows end_write_records;
uint copy_field_count,field_count,sum_func_count,func_count;
uint group_parts,group_length;
uint quick_group;
TMP_TABLE_PARAM() :group_parts(0),group_length(0),copy_field(0) {} TMP_TABLE_PARAM() :group_parts(0),group_length(0),copy_field(0) {}
~TMP_TABLE_PARAM() ~TMP_TABLE_PARAM()
...@@ -148,7 +148,7 @@ class JOIN { ...@@ -148,7 +148,7 @@ class JOIN {
uint send_group_parts; uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update; bool sort_and_group,first_record,full_join,group, no_field_update;
table_map const_table_map; table_map const_table_map;
ha_rows send_records; ha_rows send_records,found_records;
POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1]; POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
double best_read; double best_read;
List<Item> *fields; List<Item> *fields;
......
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