Commit cc4e7310 authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi

Merge work:/home/bk/mysql-4.0 into donna.mysql.fi:/home/my/bk/mysql-4.0

parents a9e31951 02f00743
...@@ -4,6 +4,7 @@ jcole@abel.spaceapes.com ...@@ -4,6 +4,7 @@ jcole@abel.spaceapes.com
jcole@main.burghcom.com jcole@main.burghcom.com
jcole@tetra.spaceapes.com jcole@tetra.spaceapes.com
monty@donna.mysql.fi monty@donna.mysql.fi
monty@tik.mysql.fi
monty@work.mysql.com monty@work.mysql.com
mwagner@evoq.mwagner.org mwagner@evoq.mwagner.org
paul@central.snake.net paul@central.snake.net
......
...@@ -187,7 +187,7 @@ typedef struct st_columndef /* column information */ ...@@ -187,7 +187,7 @@ typedef struct st_columndef /* column information */
extern my_string myisam_log_filename; /* Name of logfile */ extern my_string myisam_log_filename; /* Name of logfile */
extern uint myisam_block_size; extern uint myisam_block_size;
extern my_bool myisam_flush,myisam_delay_key_write; extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user;
extern my_bool myisam_concurrent_insert; extern my_bool myisam_concurrent_insert;
extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length; extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length;
......
...@@ -412,11 +412,14 @@ int _mi_mark_file_changed(MI_INFO *info) ...@@ -412,11 +412,14 @@ int _mi_mark_file_changed(MI_INFO *info)
share->global_changed=1; share->global_changed=1;
share->state.open_count++; share->state.open_count++;
} }
mi_int2store(buff,share->state.open_count); if (!share->temporary)
buff[2]=1; /* Mark that it's changed */ {
return (my_pwrite(share->kfile,buff,sizeof(buff), mi_int2store(buff,share->state.open_count);
sizeof(share->state.header), buff[2]=1; /* Mark that it's changed */
MYF(MY_NABP))); return (my_pwrite(share->kfile,buff,sizeof(buff),
sizeof(share->state.header),
MYF(MY_NABP)));
}
} }
return 0; return 0;
} }
......
...@@ -777,14 +777,17 @@ uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead) ...@@ -777,14 +777,17 @@ uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
{ {
char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE]; char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
if (pRead) if (!myisam_single_user)
{ {
if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP))) if (pRead)
{
if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
return (MY_FILE_ERROR);
}
else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
return (MY_FILE_ERROR); return (MY_FILE_ERROR);
mi_state_info_read(buff, state);
} }
else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
return (MY_FILE_ERROR);
mi_state_info_read(buff, state);
return 0; return 0;
} }
......
...@@ -32,7 +32,7 @@ my_string myisam_log_filename=(char*) "myisam.log"; ...@@ -32,7 +32,7 @@ my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1; File myisam_log_file= -1;
uint myisam_quick_table_bits=9; uint myisam_quick_table_bits=9;
uint myisam_block_size=MI_KEY_BLOCK_LENGTH; /* Best by test */ uint myisam_block_size=MI_KEY_BLOCK_LENGTH; /* Best by test */
my_bool myisam_flush=0,myisam_delay_key_write=0; my_bool myisam_flush=0, myisam_delay_key_write=0, myisam_single_user=0;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
my_bool myisam_concurrent_insert=1; my_bool myisam_concurrent_insert=1;
#else #else
......
a b
1 2
2 3
3 5
4 5
5 5
6 6
7 7
8 9
FOUND_ROWS()
8
a b
1 2
FOUND_ROWS()
8
a b
8 9
FOUND_ROWS()
8
b
2
FOUND_ROWS()
6
b c
2 1
FOUND_ROWS()
6
a b a b
3 5 5 5
FOUND_ROWS()
8
#
# Testing of found_rows()
#
drop table if exists t1;
create table t1 (a int not null auto_increment, b int not null, primary key(a));
insert into t1 (b) values (2),(3),(5),(5),(5),(6),(7),(9);
select SQL_CALC_FOUND_ROWS * from t1;
select found_rows();
select SQL_CALC_FOUND_ROWS * from t1 limit 1;
select found_rows();
select SQL_CALC_FOUND_ROWS * from t1 order by b desc limit 1;
select found_rows();
select SQL_CALC_FOUND_ROWS distinct b from t1 limit 1;
select found_rows();
select SQL_CALC_FOUND_ROWS b,count(*) as c from t1 group by b order by c limit 1;
select found_rows();
select SQL_CALC_FOUND_ROWS * from t1 left join t1 as t2 on (t1.b=t2.a) limit 2,1;
select found_rows();
drop table t1;
...@@ -19,9 +19,6 @@ ...@@ -19,9 +19,6 @@
get_ptr_compare(len) returns a pointer to a optimal byte-compare function get_ptr_compare(len) returns a pointer to a optimal byte-compare function
for a array of stringpointer where all strings have size len. for a array of stringpointer where all strings have size len.
The bytes are compare as unsigned chars. The bytes are compare as unsigned chars.
Because the size is saved in a static variable.
When using threads the program must have called my_init and the thread
my_init_thread()
*/ */
#include "mysys_priv.h" #include "mysys_priv.h"
......
...@@ -205,7 +205,7 @@ make_tempname (filename) ...@@ -205,7 +205,7 @@ make_tempname (filename)
strcpy (tmpname, filename); strcpy (tmpname, filename);
strcat (tmpname, "/"); strcat (tmpname, "/");
strcat (tmpname, template); strcat (tmpname, template);
mktemp (tmpname); mkstemp (tmpname);
*slash = c; *slash = c;
} }
else else
......
...@@ -57,7 +57,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ...@@ -57,7 +57,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\ sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \
log_event.h mini_client.h sql_repl.h slave.h \ log_event.h mini_client.h sql_repl.h slave.h \
stacktrace.h stacktrace.h sql_sort.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
...@@ -68,7 +68,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -68,7 +68,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \ convert.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \ sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_update.cc sql_delete.cc \ sql_update.cc sql_delete.cc uniques.cc \
procedure.cc item_uniq.cc sql_test.cc \ procedure.cc item_uniq.cc sql_test.cc \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \ log.cc log_event.cc init.cc derror.cc sql_acl.cc \
unireg.cc \ unireg.cc \
......
...@@ -22,13 +22,11 @@ ...@@ -22,13 +22,11 @@
#include <stddef.h> /* for macro offsetof */ #include <stddef.h> /* for macro offsetof */
#endif #endif
#include <m_ctype.h> #include <m_ctype.h>
#include "sql_sort.h"
#ifndef THREAD #ifndef THREAD
#define SKIPP_DBUG_IN_FILESORT #define SKIPP_DBUG_IN_FILESORT
#endif #endif
/* static variabels */
#define MERGEBUFF 7
#define MERGEBUFF2 15
/* How to write record_ref. */ /* How to write record_ref. */
...@@ -36,28 +34,6 @@ ...@@ -36,28 +34,6 @@
if (my_b_write((file),(byte*) (from),param->ref_length)) \ if (my_b_write((file),(byte*) (from),param->ref_length)) \
DBUG_RETURN(1); DBUG_RETURN(1);
typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
my_off_t file_pos; /* Where we are in the sort file */
uchar *base,*key; /* key pointers */
ha_rows count; /* Number of rows in table */
ulong mem_count; /* numbers of keys in memory */
ulong max_keys; /* Max keys in buffert */
} BUFFPEK;
typedef struct st_sort_param {
uint sort_length; /* Length of sortarg */
uint keys; /* Max antal nycklar / buffert */
uint ref_length; /* Length of record ref. */
ha_rows max_rows,examined_rows;
TABLE *sort_form; /* For quicker make_sortkey */
SORT_FIELD *local_sortorder;
SORT_FIELD *end;
#ifdef USE_STRCOLL
char* tmp_buffer;
#endif
} SORTPARAM;
/* functions defined in this file */ /* functions defined in this file */
static char **make_char_array(register uint fields, uint length, myf my_flag); static char **make_char_array(register uint fields, uint length, myf my_flag);
...@@ -70,20 +46,11 @@ static int write_keys(SORTPARAM *param,uchar * *sort_keys, ...@@ -70,20 +46,11 @@ static int write_keys(SORTPARAM *param,uchar * *sort_keys,
IO_CACHE *tempfile); IO_CACHE *tempfile);
static void make_sortkey(SORTPARAM *param,uchar *to, static void make_sortkey(SORTPARAM *param,uchar *to,
byte *ref_pos); byte *ref_pos);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count); static int merge_index(SORTPARAM *param,uchar *sort_buffer,
static int merge_many_buff(SORTPARAM *param,uchar * *sort_keys,
BUFFPEK *buffpek,
uint *maxbuffer, IO_CACHE *t_file);
static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
uint sort_length);
static int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
IO_CACHE *to_file,uchar * *sort_keys,
BUFFPEK *lastbuff,BUFFPEK *Fb,
BUFFPEK *Tb,int flag);
static int merge_index(SORTPARAM *param,uchar * *sort_keys,
BUFFPEK *buffpek, BUFFPEK *buffpek,
uint maxbuffer,IO_CACHE *tempfile, uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile); IO_CACHE *outfile);
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static uint sortlength(SORT_FIELD *sortorder,uint length); static uint sortlength(SORT_FIELD *sortorder,uint length);
/* Makes a indexfil of recordnumbers of a sorted database */ /* Makes a indexfil of recordnumbers of a sorted database */
...@@ -225,12 +192,14 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, ...@@ -225,12 +192,14 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
param.keys=((param.keys*(param.sort_length+sizeof(char*))) / param.keys=((param.keys*(param.sort_length+sizeof(char*))) /
param.sort_length-1); param.sort_length-1);
if (merge_many_buff(&param,sort_keys,buffpek,&maxbuffer,&tempfile)) if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
&tempfile))
goto err; goto err;
if (flush_io_cache(&tempfile) || if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err; goto err;
if (merge_index(&param,sort_keys,buffpek,maxbuffer,&tempfile,outfile)) if (merge_index(&param,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
outfile))
goto err; goto err;
} }
if (records > param.max_rows) if (records > param.max_rows)
...@@ -629,8 +598,8 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count) ...@@ -629,8 +598,8 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
/* Merge buffers to make < MERGEBUFF2 buffers */ /* Merge buffers to make < MERGEBUFF2 buffers */
static int merge_many_buff(SORTPARAM *param, uchar **sort_keys, int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file) BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
{ {
register int i; register int i;
IO_CACHE t_file2,*from_file,*to_file,*temp; IO_CACHE t_file2,*from_file,*to_file,*temp;
...@@ -652,11 +621,11 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys, ...@@ -652,11 +621,11 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
lastbuff=buffpek; lastbuff=buffpek;
for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
{ {
if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++, if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
buffpek+i,buffpek+i+MERGEBUFF-1,0)) buffpek+i,buffpek+i+MERGEBUFF-1,0))
break; /* purecov: inspected */ break; /* purecov: inspected */
} }
if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++, if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
buffpek+i,buffpek+ *maxbuffer,0)) buffpek+i,buffpek+ *maxbuffer,0))
break; /* purecov: inspected */ break; /* purecov: inspected */
if (flush_io_cache(to_file)) if (flush_io_cache(to_file))
...@@ -675,8 +644,8 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys, ...@@ -675,8 +644,8 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
/* Read data to buffer */ /* Read data to buffer */
/* This returns (uint) -1 if something goes wrong */ /* This returns (uint) -1 if something goes wrong */
static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
uint sort_length) uint sort_length)
{ {
register uint count; register uint count;
uint length; uint length;
...@@ -697,10 +666,10 @@ static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, ...@@ -697,10 +666,10 @@ static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
/* Merge buffers to one buffer */ /* Merge buffers to one buffer */
static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
IO_CACHE *to_file, uchar **sort_keys, IO_CACHE *to_file, uchar *sort_buffer,
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
int flag) int flag)
{ {
int error; int error;
uint sort_length,offset; uint sort_length,offset;
...@@ -711,21 +680,21 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -711,21 +680,21 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
BUFFPEK *buffpek,**refpek; BUFFPEK *buffpek,**refpek;
QUEUE queue; QUEUE queue;
volatile bool *killed= &current_thd->killed; volatile bool *killed= &current_thd->killed;
qsort2_cmp cmp;
DBUG_ENTER("merge_buffers"); DBUG_ENTER("merge_buffers");
statistic_increment(filesort_merge_passes, &LOCK_status); statistic_increment(filesort_merge_passes, &LOCK_status);
count=error=0; count=error=0;
offset=param->sort_length-param->ref_length; offset=(sort_length=param->sort_length)-param->ref_length;
maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1)); maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
to_start_filepos=my_b_tell(to_file); to_start_filepos=my_b_tell(to_file);
strpos=(uchar*) sort_keys; strpos=(uchar*) sort_buffer;
sort_length=param->sort_length;
max_rows=param->max_rows; max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*) (void *, byte *,byte*)) (int (*) (void *, byte *,byte*))
get_ptr_compare(sort_length),(void*) &sort_length)) (cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++) for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
{ {
...@@ -739,6 +708,26 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -739,6 +708,26 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
queue_insert(&queue,(byte*) buffpek); queue_insert(&queue,(byte*) buffpek);
} }
if (param->unique_buff)
{
/*
Called by Unique::get()
Copy the first argument to param->unique_buff for unique removal.
Store it also in 'to_file'.
This is safe as we know that there is always more than one element
in each block to merge (This is guaranteed by the Unique:: algorithm
*/
buffpek=(BUFFPEK*) queue_top(&queue);
memcpy(param->unique_buff, buffpek->key, sort_length);
if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
{
error=1; goto err; /* purecov: inspected */
}
}
else
cmp=0; // Not unique
while (queue.elements > 1) while (queue.elements > 1)
{ {
if (*killed) if (*killed)
...@@ -748,6 +737,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -748,6 +737,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
for (;;) for (;;)
{ {
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);
if (cmp) // Remove duplicates
{
if (!cmp(&sort_length, param->unique_buff, (uchar*) buffpek->key))
goto skip_duplicate;
memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
}
if (flag == 0) if (flag == 0)
{ {
if (my_b_write(to_file,(byte*) buffpek->key, sort_length)) if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
...@@ -764,6 +759,8 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -764,6 +759,8 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
error=0; /* purecov: inspected */ error=0; /* purecov: inspected */
goto end; /* purecov: inspected */ goto end; /* purecov: inspected */
} }
skip_duplicate:
buffpek->key+=sort_length; buffpek->key+=sort_length;
if (! --buffpek->mem_count) if (! --buffpek->mem_count)
{ {
...@@ -802,7 +799,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -802,7 +799,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
} }
} }
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);
buffpek->base=(uchar *) sort_keys; buffpek->base= sort_buffer;
buffpek->max_keys=param->keys; buffpek->max_keys=param->keys;
do do
{ {
...@@ -845,12 +842,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -845,12 +842,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
/* Do a merge to output-file (save only positions) */ /* Do a merge to output-file (save only positions) */
static int merge_index(SORTPARAM *param, uchar **sort_keys, static int merge_index(SORTPARAM *param, uchar *sort_buffer,
BUFFPEK *buffpek, uint maxbuffer, BUFFPEK *buffpek, uint maxbuffer,
IO_CACHE *tempfile, IO_CACHE *outfile) IO_CACHE *tempfile, IO_CACHE *outfile)
{ {
DBUG_ENTER("merge_index"); DBUG_ENTER("merge_index");
if (merge_buffers(param,tempfile,outfile,sort_keys,buffpek,buffpek, if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
buffpek+maxbuffer,1)) buffpek+maxbuffer,1))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -867,6 +867,7 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -867,6 +867,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
0, 0, current_lex->options | thd->options))) 0, 0, current_lex->options | thd->options)))
return 1; return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
if(table->db_type == DB_TYPE_HEAP) // no blobs, otherwise it would be if(table->db_type == DB_TYPE_HEAP) // no blobs, otherwise it would be
// MyISAM // MyISAM
......
...@@ -3030,14 +3030,13 @@ static void usage(void) ...@@ -3030,14 +3030,13 @@ static void usage(void)
puts("\ puts("\
-O, --set-variable var=option\n\ -O, --set-variable var=option\n\
Give a variable an value. --help lists variables\n\ Give a variable an value. --help lists variables\n\
-Sg, --skip-grant-tables\n\
Start without grant tables. This gives all users\n\
FULL ACCESS to all tables!\n\
--safe-mode Skip some optimize stages (for testing)\n\ --safe-mode Skip some optimize stages (for testing)\n\
--skip-concurrent-insert\n\ --skip-concurrent-insert\n\
Don't use concurrent insert with MyISAM\n\ Don't use concurrent insert with MyISAM\n\
--skip-delay-key-write\n\ --skip-delay-key-write\n\
Ignore the delay_key_write option for all tables\n\ Ignore the delay_key_write option for all tables\n\
--skip-grant-tables Start without grant tables. This gives all users\n\
FULL ACCESS to all tables!\n\
--skip-host-cache Don't cache host names\n\ --skip-host-cache Don't cache host names\n\
--skip-locking Don't use system locking. To use isamchk one has\n\ --skip-locking Don't use system locking. To use isamchk one has\n\
to shut down the server.\n\ to shut down the server.\n\
...@@ -3174,7 +3173,7 @@ static void set_options(void) ...@@ -3174,7 +3173,7 @@ static void set_options(void)
#endif #endif
#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS ) #if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
my_disable_locking = 1; my_disable_locking=myisam_single_user= 1;
#endif #endif
my_bind_addr = htonl( INADDR_ANY ); my_bind_addr = htonl( INADDR_ANY );
} }
...@@ -3267,20 +3266,6 @@ static void get_options(int argc,char **argv) ...@@ -3267,20 +3266,6 @@ static void get_options(int argc,char **argv)
test_flags= optarg ? (uint) atoi(optarg) : 0; test_flags= optarg ? (uint) atoi(optarg) : 0;
opt_endinfo=1; opt_endinfo=1;
break; break;
case 'S':
if (!optarg)
opt_specialflag|= SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE;
else if (!strcmp(optarg,"l"))
my_disable_locking=1;
else if (!strcmp(optarg,"g"))
opt_noacl=1;
else
{
fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg);
use_help();
exit(1);
}
break;
case (int) OPT_BIG_TABLES: case (int) OPT_BIG_TABLES:
thd_startup_options|=OPTION_BIG_TABLES; thd_startup_options|=OPTION_BIG_TABLES;
break; break;
...@@ -3458,7 +3443,7 @@ static void get_options(int argc,char **argv) ...@@ -3458,7 +3443,7 @@ static void get_options(int argc,char **argv)
opt_noacl=1; opt_noacl=1;
break; break;
case (int) OPT_SKIP_LOCK: case (int) OPT_SKIP_LOCK:
my_disable_locking=1; my_disable_locking=myisam_single_user= 1;
break; break;
case (int) OPT_SKIP_HOST_CACHE: case (int) OPT_SKIP_HOST_CACHE:
opt_specialflag|= SPECIAL_NO_HOST_CACHE; opt_specialflag|= SPECIAL_NO_HOST_CACHE;
...@@ -4024,7 +4009,7 @@ static int get_service_parameters() ...@@ -4024,7 +4009,7 @@ static int get_service_parameters()
} }
else if ( lstrcmp(szKeyValueName, TEXT("KeyBufferSize")) == 0 ) else if ( lstrcmp(szKeyValueName, TEXT("KeyBufferSize")) == 0 )
{ {
SET_CHANGEABLE_VARVAL( "key_buffer" ); SET_CHANGEABLE_VARVAL( "key_buffer_size" );
} }
else if ( lstrcmp(szKeyValueName, TEXT("LongQueryTime")) == 0 ) else if ( lstrcmp(szKeyValueName, TEXT("LongQueryTime")) == 0 )
{ {
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
#include <my_tree.h>
#define DEC_IN_AVG 4 #define DEC_IN_AVG 4
typedef struct st_number_info typedef struct st_number_info
......
...@@ -567,3 +567,32 @@ class user_var_entry ...@@ -567,3 +567,32 @@ class user_var_entry
Item_result type; Item_result type;
}; };
/* Class for unique (removing of duplicates) */
class Unique :public Sql_alloc
{
DYNAMIC_ARRAY file_ptrs;
ulong max_elements, max_in_memory_size;
IO_CACHE file;
TREE tree;
char *record_pointers;
bool flush();
public:
ulong elements;
Unique(qsort_cmp2 comp_func, uint size, ulong max_in_memory_size_arg);
~Unique();
inline bool Unique::unique_add(gptr ptr)
{
if (tree.elements_in_tree > max_elements && flush())
return 1;
return tree_insert(&tree,ptr,0);
}
bool get(TABLE *table);
friend int unique_write_to_file(gptr key, Unique *unique,
element_count count);
friend int unique_write_to_ptrs(gptr key, Unique *unique,
element_count count);
};
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
thd->open_tables=thd->handler_tables; \ thd->open_tables=thd->handler_tables; \
thd->handler_tables=tmp; } thd->handler_tables=tmp; }
static TABLE **find_table_ptr_by_name(THD *thd, char *db, char *table_name); static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *table_name);
int mysql_ha_open(THD *thd, TABLE_LIST *tables) int mysql_ha_open(THD *thd, TABLE_LIST *tables)
{ {
...@@ -231,14 +232,15 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -231,14 +232,15 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
/* Note: this function differs from find_locked_table() because we're looking /* Note: this function differs from find_locked_table() because we're looking
here for alias, not real table name here for alias, not real table name
*/ */
static TABLE **find_table_ptr_by_name(THD *thd, char *db, char *table_name) static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *table_name)
{ {
int dblen; int dblen;
TABLE **ptr; TABLE **ptr;
if (!db || ! *db) db=thd->db; if (!db || ! *db)
if (!db || ! *db) db=""; db= thd->db ? thd->db : "";
dblen=strlen(db); dblen=strlen(db)+1;
ptr=&(thd->handler_tables); ptr=&(thd->handler_tables);
for (TABLE *table=*ptr; table ; table=*ptr) for (TABLE *table=*ptr; table ; table=*ptr)
......
...@@ -69,7 +69,7 @@ static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value); ...@@ -69,7 +69,7 @@ static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table); static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
uint options); ulong options);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table, static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc); Procedure *proc);
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records); static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
...@@ -3317,7 +3317,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type, ...@@ -3317,7 +3317,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
TABLE * TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
bool allow_distinct_limit, uint select_options) bool allow_distinct_limit, ulong select_options)
{ {
TABLE *table; TABLE *table;
uint i,field_count,reclength,null_count,null_pack_length, uint i,field_count,reclength,null_count,null_pack_length,
...@@ -3759,7 +3759,7 @@ static bool open_tmp_table(TABLE *table) ...@@ -3759,7 +3759,7 @@ static bool open_tmp_table(TABLE *table)
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
uint options) ulong options)
{ {
int error; int error;
MI_KEYDEF keydef; MI_KEYDEF keydef;
...@@ -3926,6 +3926,12 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error, ...@@ -3926,6 +3926,12 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
goto err1; goto err1;
table->file->index_end(); table->file->index_end();
table->file->rnd_init(); table->file->rnd_init();
if (table->no_rows)
{
new_table.file->extra(HA_EXTRA_NO_ROWS);
new_table.no_rows=1;
}
/* copy all old rows */ /* copy all old rows */
while (!table->file->rnd_next(new_table.record[1])) while (!table->file->rnd_next(new_table.record[1]))
{ {
......
...@@ -181,7 +181,7 @@ void TEST_join(JOIN *join); ...@@ -181,7 +181,7 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val); bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
bool allow_distinct_limit, uint select_options); bool allow_distinct_limit, ulong select_options);
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);
......
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Defines used by filesort and uniques */
#define MERGEBUFF 7
#define MERGEBUFF2 15
typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
my_off_t file_pos; /* Where we are in the sort file */
uchar *base,*key; /* key pointers */
ha_rows count; /* Number of rows in table */
ulong mem_count; /* numbers of keys in memory */
ulong max_keys; /* Max keys in buffert */
} BUFFPEK;
typedef struct st_sort_param {
uint sort_length; /* Length of sort columns */
uint keys; /* Max keys / buffert */
uint ref_length; /* Length of record ref. */
ha_rows max_rows,examined_rows;
TABLE *sort_form; /* For quicker make_sortkey */
SORT_FIELD *local_sortorder;
SORT_FIELD *end;
uchar *unique_buff;
#ifdef USE_STRCOLL
char* tmp_buffer;
#endif
} SORTPARAM;
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
BUFFPEK *buffpek,
uint *maxbuffer, IO_CACHE *t_file);
uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
uint sort_length);
int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
IO_CACHE *to_file, uchar *sort_buffer,
BUFFPEK *lastbuff,BUFFPEK *Fb,
BUFFPEK *Tb,int flag);
...@@ -89,7 +89,7 @@ struct st_table { ...@@ -89,7 +89,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */ my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */ my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */ my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
my_bool distinct,const_table; my_bool distinct,const_table,no_rows;
my_bool key_read; my_bool key_read;
my_bool crypted; my_bool crypted;
my_bool db_low_byte_first; /* Portable row format */ my_bool db_low_byte_first; /* Portable row format */
......
/* Copyright (C) 2001 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Function to handle quick removal of duplicates
This code is used when doing multi-table deletes to find the rows in
reference tables that needs to be deleted.
The basic idea is as follows:
Store first all strings in a binary tree, ignoring duplicates.
When the three uses more memory than 'max_heap_table_size',
write the tree (in sorted order) out to disk and start with a new tree.
When all data has been generated, merge the trees (removing any found
duplicates).
The unique entries will be returned in sort order, to ensure that we do the
deletes in disk order.
*/
#include "mysql_priv.h"
#include "sql_sort.h"
Unique::Unique(qsort_cmp2 comp_func, uint size, ulong max_in_memory_size_arg)
:max_in_memory_size(max_in_memory_size_arg),elements(0)
{
my_b_clear(&file);
init_tree(&tree, max_in_memory_size / 16, size, comp_func, 0, 0);
/* If the following fail's the next add will also fail */
init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
}
Unique::~Unique()
{
close_cached_file(&file);
delete_tree(&tree);
delete_dynamic(&file_ptrs);
}
/* Write tree to disk; clear tree */
bool Unique::flush()
{
BUFFPEK file_ptr;
elements+= tree.elements_in_tree;
file_ptr.count=tree.elements_in_tree;
file_ptr.file_pos=my_b_tell(&file);
if (tree_walk(&tree, (tree_walk_action) unique_write_to_file,
(void*) this, left_root_right) ||
insert_dynamic(&file_ptrs, (gptr) &file_ptr))
return 1;
delete_tree(&tree);
return 0;
}
int unique_write_to_file(gptr key, Unique *unique, element_count count)
{
return my_b_write(&unique->file, key, unique->tree.size_of_element) ? 1 : 0;
}
int unique_write_to_ptrs(gptr key, Unique *unique, element_count count)
{
memcpy(unique->record_pointers, key, unique->tree.size_of_element);
unique->record_pointers+=unique->tree.size_of_element;
return 0;
}
/*
Modify the TABLE element so that when one calls init_records()
the rows will be read in priority order.
*/
bool Unique::get(TABLE *table)
{
SORTPARAM sort_param;
table->found_records=elements+tree.elements_in_tree;
if (!my_b_inited(&file))
{
/* Whole tree is in memory; Don't use disk if you don't need to */
if ((record_pointers=table->record_pointers= (byte*)
my_malloc(tree.size_of_element * tree.elements_in_tree, MYF(0))))
{
(void) tree_walk(&tree, (tree_walk_action) unique_write_to_ptrs,
this, left_root_right);
return 0;
}
}
/* Not enough memory; Save the result to file */
if (flush())
return 1;
IO_CACHE *outfile=table->io_cache, tempfile;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
uint maxbuffer= file_ptrs.elements;
uchar *sort_buffer;
my_off_t save_pos;
bool error=1;
my_b_clear(&tempfile);
/* Open cached file if it isn't open */
if (! my_b_inited(outfile) &&
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
MYF(MY_WME)))
return 1;
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
sort_param.keys=elements;
sort_param.sort_form=table;
sort_param.sort_length=sort_param.ref_length=tree.size_of_element;
sort_param.keys= max_in_memory_size / sort_param.sort_length;
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
sort_param.sort_length,
MYF(0))))
return 1;
sort_param.unique_buff= sort_buffer+(sort_param.keys*
sort_param.sort_length);
/* Merge the buffers to one file, removing duplicates */
if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&tempfile))
goto err;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
if (merge_buffers(&sort_param, &tempfile, outfile, sort_buffer, file_ptr,
file_ptr, file_ptr+maxbuffer,0))
goto err;
error=0;
err:
x_free((gptr) sort_buffer);
close_cached_file(&tempfile);
if (flush_io_cache(outfile))
error=1;
/* Setup io_cache for reading */
save_pos=outfile->pos_in_file;
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
error=1;
outfile->end_of_file=save_pos;
return error;
}
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