mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge work:/home/bk/mysql-4.0 into donna.mysql.fi:/home/my/bk/mysql-4.0
This commit is contained in:
@ -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 */
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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";
|
|||||||
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
|
||||||
|
31
mysql-test/r/select_found.result
Normal file
31
mysql-test/r/select_found.result
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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
|
20
mysql-test/t/select_found.test
Normal file
20
mysql-test/t/select_found.test
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#
|
||||||
|
# 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 @@
|
|||||||
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)
|
|||||||
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 \
|
|||||||
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 \
|
|||||||
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 \
|
||||||
|
109
sql/filesort.cc
109
sql/filesort.cc
@ -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 @@
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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(¶m,sort_keys,buffpek,&maxbuffer,&tempfile))
|
if (merge_many_buff(¶m,(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(¶m,sort_keys,buffpek,maxbuffer,&tempfile,outfile))
|
if (merge_index(¶m,(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)
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
BUFFPEK *buffpek,**refpek;
|
BUFFPEK *buffpek,**refpek;
|
||||||
QUEUE queue;
|
QUEUE queue;
|
||||||
volatile bool *killed= ¤t_thd->killed;
|
volatile bool *killed= ¤t_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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 @@ err:
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
#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)
|
|||||||
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)
|
|||||||
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()
|
|||||||
}
|
}
|
||||||
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 @@
|
|||||||
#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
|
|||||||
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 @@
|
|||||||
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 @@ err:
|
|||||||
/* 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);
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
|
|
||||||
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,
|
|||||||
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);
|
|||||||
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);
|
||||||
|
54
sql/sql_sort.h
Normal file
54
sql/sql_sort.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* 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 {
|
|||||||
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 */
|
||||||
|
160
sql/uniques.cc
Normal file
160
sql/uniques.cc
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/* 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;
|
||||||
|
}
|
Reference in New Issue
Block a user