diff options
author | unknown <monty@donna.mysql.fi> | 2001-05-23 23:49:06 +0300 |
---|---|---|
committer | unknown <monty@donna.mysql.fi> | 2001-05-23 23:49:06 +0300 |
commit | 4d13177eb0a2bdbaf6533dac8afc288175151a5a (patch) | |
tree | e403a32b4bf42886f792ab632f87b754b3ab6d9d | |
parent | 607c8d8bd4a4647cd118d2ff308e08b6df7a8b98 (diff) | |
parent | a542f858bf9f14da04f58223933b992749922d32 (diff) | |
download | mariadb-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_ok | 1 | ||||
-rw-r--r-- | include/myisam.h | 2 | ||||
-rw-r--r-- | myisam/mi_locking.c | 13 | ||||
-rw-r--r-- | myisam/mi_open.c | 13 | ||||
-rw-r--r-- | myisam/mi_static.c | 2 | ||||
-rw-r--r-- | mysql-test/r/select_found.result | 31 | ||||
-rw-r--r-- | mysql-test/t/select_found.test | 20 | ||||
-rw-r--r-- | mysys/ptr_cmp.c | 3 | ||||
-rw-r--r-- | pstack/bucomm.c | 2 | ||||
-rw-r--r-- | sql/Makefile.am | 4 | ||||
-rw-r--r-- | sql/filesort.cc | 109 | ||||
-rw-r--r-- | sql/item_sum.cc | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 25 | ||||
-rw-r--r-- | sql/sql_analyse.h | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 29 | ||||
-rw-r--r-- | sql/sql_handler.cc | 12 | ||||
-rw-r--r-- | sql/sql_select.cc | 12 | ||||
-rw-r--r-- | sql/sql_select.h | 2 | ||||
-rw-r--r-- | sql/sql_sort.h | 54 | ||||
-rw-r--r-- | sql/table.h | 2 | ||||
-rw-r--r-- | sql/uniques.cc | 160 |
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(¶m,sort_keys,buffpek,&maxbuffer,&tempfile)) + if (merge_many_buff(¶m,(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(¶m,sort_keys,buffpek,maxbuffer,&tempfile,outfile)) + if (merge_index(¶m,(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= ¤t_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; +} |