summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@donna.mysql.fi>2001-05-23 23:49:06 +0300
committerunknown <monty@donna.mysql.fi>2001-05-23 23:49:06 +0300
commit4d13177eb0a2bdbaf6533dac8afc288175151a5a (patch)
treee403a32b4bf42886f792ab632f87b754b3ab6d9d
parent607c8d8bd4a4647cd118d2ff308e08b6df7a8b98 (diff)
parenta542f858bf9f14da04f58223933b992749922d32 (diff)
downloadmariadb-git-4d13177eb0a2bdbaf6533dac8afc288175151a5a.tar.gz
Merge work:/home/bk/mysql-4.0 into donna.mysql.fi:/home/my/bk/mysql-4.0
BitKeeper/etc/logging_ok: auto-union sql/Makefile.am: Auto merged sql/mysqld.cc: Auto merged
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--include/myisam.h2
-rw-r--r--myisam/mi_locking.c13
-rw-r--r--myisam/mi_open.c13
-rw-r--r--myisam/mi_static.c2
-rw-r--r--mysql-test/r/select_found.result31
-rw-r--r--mysql-test/t/select_found.test20
-rw-r--r--mysys/ptr_cmp.c3
-rw-r--r--pstack/bucomm.c2
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/filesort.cc109
-rw-r--r--sql/item_sum.cc1
-rw-r--r--sql/mysqld.cc25
-rw-r--r--sql/sql_analyse.h2
-rw-r--r--sql/sql_class.h29
-rw-r--r--sql/sql_handler.cc12
-rw-r--r--sql/sql_select.cc12
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_sort.h54
-rw-r--r--sql/table.h2
-rw-r--r--sql/uniques.cc160
21 files changed, 393 insertions, 106 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 8c4c3a7efed..3fefd0e3dc2 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -4,6 +4,7 @@ jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@tetra.spaceapes.com
monty@donna.mysql.fi
+monty@tik.mysql.fi
monty@work.mysql.com
mwagner@evoq.mwagner.org
paul@central.snake.net
diff --git a/include/myisam.h b/include/myisam.h
index 8e68a3f75c9..34babba163c 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -187,7 +187,7 @@ typedef struct st_columndef /* column information */
extern my_string myisam_log_filename; /* Name of logfile */
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_off_t myisam_max_temp_length,myisam_max_extra_temp_length;
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index e067e80fcf3..8ef5db1d344 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -412,11 +412,14 @@ int _mi_mark_file_changed(MI_INFO *info)
share->global_changed=1;
share->state.open_count++;
}
- mi_int2store(buff,share->state.open_count);
- buff[2]=1; /* Mark that it's changed */
- return (my_pwrite(share->kfile,buff,sizeof(buff),
- sizeof(share->state.header),
- MYF(MY_NABP)));
+ if (!share->temporary)
+ {
+ mi_int2store(buff,share->state.open_count);
+ buff[2]=1; /* Mark that it's changed */
+ return (my_pwrite(share->kfile,buff,sizeof(buff),
+ sizeof(share->state.header),
+ MYF(MY_NABP)));
+ }
}
return 0;
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 28f984006df..7f94de9ffa2 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -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];
- 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);
+ 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;
}
diff --git a/myisam/mi_static.c b/myisam/mi_static.c
index f790f90ca78..bb7fece4d18 100644
--- a/myisam/mi_static.c
+++ b/myisam/mi_static.c
@@ -32,7 +32,7 @@ my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1;
uint myisam_quick_table_bits=9;
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)
my_bool myisam_concurrent_insert=1;
#else
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
new file mode 100644
index 00000000000..fcbe8958748
--- /dev/null
+++ b/mysql-test/r/select_found.result
@@ -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
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
new file mode 100644
index 00000000000..d86ef1e0907
--- /dev/null
+++ b/mysql-test/t/select_found.test
@@ -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;
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 65b2c51aafd..f9b3e34d702 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -19,9 +19,6 @@
get_ptr_compare(len) returns a pointer to a optimal byte-compare function
for a array of stringpointer where all strings have size len.
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"
diff --git a/pstack/bucomm.c b/pstack/bucomm.c
index 2b44239d1d3..6c491d80bb5 100644
--- a/pstack/bucomm.c
+++ b/pstack/bucomm.c
@@ -205,7 +205,7 @@ make_tempname (filename)
strcpy (tmpname, filename);
strcat (tmpname, "/");
strcat (tmpname, template);
- mktemp (tmpname);
+ mkstemp (tmpname);
*slash = c;
}
else
diff --git a/sql/Makefile.am b/sql/Makefile.am
index b3e3e4c915c..218ff6bbd73 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -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\
lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.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 \
item.cc item_sum.cc item_buff.cc item_func.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 \
convert.cc sql_parse.cc sql_yacc.yy \
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 \
log.cc log_event.cc init.cc derror.cc sql_acl.cc \
unireg.cc \
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 610fe2e966f..e5e6c7d97c8 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -22,13 +22,11 @@
#include <stddef.h> /* for macro offsetof */
#endif
#include <m_ctype.h>
+#include "sql_sort.h"
+
#ifndef THREAD
#define SKIPP_DBUG_IN_FILESORT
#endif
- /* static variabels */
-
-#define MERGEBUFF 7
-#define MERGEBUFF2 15
/* How to write record_ref. */
@@ -36,28 +34,6 @@
if (my_b_write((file),(byte*) (from),param->ref_length)) \
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 */
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);
static void make_sortkey(SORTPARAM *param,uchar *to,
byte *ref_pos);
-static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
-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,
+static int merge_index(SORTPARAM *param,uchar *sort_buffer,
BUFFPEK *buffpek,
uint maxbuffer,IO_CACHE *tempfile,
IO_CACHE *outfile);
+static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
static uint sortlength(SORT_FIELD *sortorder,uint length);
/* 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.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;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
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;
}
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 */
-static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
- BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
+int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
+ BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
{
register int i;
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;
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))
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))
break; /* purecov: inspected */
if (flush_io_cache(to_file))
@@ -675,8 +644,8 @@ static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
/* Read data to buffer */
/* This returns (uint) -1 if something goes wrong */
-static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
- uint sort_length)
+uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
+ uint sort_length)
{
register uint count;
uint length;
@@ -697,10 +666,10 @@ static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
/* Merge buffers to one buffer */
-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)
+int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
+ IO_CACHE *to_file, uchar *sort_buffer,
+ BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
+ int flag)
{
int error;
uint sort_length,offset;
@@ -711,21 +680,21 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
BUFFPEK *buffpek,**refpek;
QUEUE queue;
volatile bool *killed= &current_thd->killed;
+ qsort2_cmp cmp;
DBUG_ENTER("merge_buffers");
statistic_increment(filesort_merge_passes, &LOCK_status);
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));
to_start_filepos=my_b_tell(to_file);
- strpos=(uchar*) sort_keys;
- sort_length=param->sort_length;
+ strpos=(uchar*) sort_buffer;
max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(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 */
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);
}
+ 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)
{
if (*killed)
@@ -748,6 +737,12 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
for (;;)
{
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 (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 */
goto end; /* purecov: inspected */
}
+
+ skip_duplicate:
buffpek->key+=sort_length;
if (! --buffpek->mem_count)
{
@@ -802,7 +799,7 @@ static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
}
}
buffpek=(BUFFPEK*) queue_top(&queue);
- buffpek->base=(uchar *) sort_keys;
+ buffpek->base= sort_buffer;
buffpek->max_keys=param->keys;
do
{
@@ -845,12 +842,12 @@ err:
/* 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,
IO_CACHE *tempfile, IO_CACHE *outfile)
{
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))
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(0);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index ad1918e01e3..089f4f56216 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -867,6 +867,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
0, 0, current_lex->options | thd->options)))
return 1;
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
// MyISAM
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 13dcb87382d..306a7311922 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3030,14 +3030,13 @@ static void usage(void)
puts("\
-O, --set-variable var=option\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\
--skip-concurrent-insert\n\
Don't use concurrent insert with MyISAM\n\
--skip-delay-key-write\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-locking Don't use system locking. To use isamchk one has\n\
to shut down the server.\n\
@@ -3174,7 +3173,7 @@ static void set_options(void)
#endif
#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
- my_disable_locking = 1;
+ my_disable_locking=myisam_single_user= 1;
#endif
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;
opt_endinfo=1;
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:
thd_startup_options|=OPTION_BIG_TABLES;
break;
@@ -3458,7 +3443,7 @@ static void get_options(int argc,char **argv)
opt_noacl=1;
break;
case (int) OPT_SKIP_LOCK:
- my_disable_locking=1;
+ my_disable_locking=myisam_single_user= 1;
break;
case (int) OPT_SKIP_HOST_CACHE:
opt_specialflag|= SPECIAL_NO_HOST_CACHE;
@@ -4024,7 +4009,7 @@ static int get_service_parameters()
}
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 )
{
diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h
index b5554314439..1d26b34dad9 100644
--- a/sql/sql_analyse.h
+++ b/sql/sql_analyse.h
@@ -21,8 +21,6 @@
#pragma interface /* gcc class implementation */
#endif
-#include <my_tree.h>
-
#define DEC_IN_AVG 4
typedef struct st_number_info
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a67c0d13682..603e4bdeeb9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -567,3 +567,32 @@ class user_var_entry
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);
+};
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 3da9b96786d..a605984aef7 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -43,7 +43,8 @@
thd->open_tables=thd->handler_tables; \
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)
{
@@ -231,14 +232,15 @@ err:
/* Note: this function differs from find_locked_table() because we're looking
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;
TABLE **ptr;
- if (!db || ! *db) db=thd->db;
- if (!db || ! *db) db="";
- dblen=strlen(db);
+ if (!db || ! *db)
+ db= thd->db ? thd->db : "";
+ dblen=strlen(db)+1;
ptr=&(thd->handler_tables);
for (TABLE *table=*ptr; table ; table=*ptr)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9e6b0b40f29..90b3c6eefaf 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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 open_tmp_table(TABLE *table);
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,
Procedure *proc);
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 *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &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;
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,
- uint options)
+ ulong options)
{
int error;
MI_KEYDEF keydef;
@@ -3926,6 +3926,12 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
goto err1;
table->file->index_end();
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 */
while (!table->file->rnd_next(new_table.record[1]))
{
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 87157b1465f..bb9bb374c76 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -181,7 +181,7 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &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 count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
new file mode 100644
index 00000000000..498a5262b53
--- /dev/null
+++ b/sql/sql_sort.h
@@ -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);
diff --git a/sql/table.h b/sql/table.h
index 706c499d852..b25e2d82132 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -89,7 +89,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */
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 crypted;
my_bool db_low_byte_first; /* Portable row format */
diff --git a/sql/uniques.cc b/sql/uniques.cc
new file mode 100644
index 00000000000..78fd8fe6e60
--- /dev/null
+++ b/sql/uniques.cc
@@ -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;
+}