mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
0fb88806e4
BitKeeper/etc/logging_ok: auto-union Build-tools/Do-compile: Auto merged acinclude.m4: Auto merged configure.in: Auto merged dbug/dbug.c: Auto merged include/config-win.h: Auto merged include/my_base.h: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/mysql.h: Auto merged include/mysql_com.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/row/row0umod.c: Auto merged innobase/row/row0upd.c: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_dbug.c: Auto merged myisam/mi_open.c: Auto merged mysql-test/r/auto_increment.result: Auto merged mysql-test/r/bdb.result: Auto merged mysql-test/r/func_op.result: Auto merged Build-tools/Bootstrap: Merge with 4.0 client/mysql.cc: Merge with 4.0 client/mysqldump.c: Merge with 4.0 client/mysqltest.c: Use local version innobase/btr/btr0cur.c: Merge with 4.0 (Heikki should check if we should remove btr_cur_update_sec_rec_in_place() libmysql/libmysql.c: Merge with 4.0 libmysqld/lib_sql.cc: Merge with 4.0 myisam/mi_key.c: Merge with 4.0 myisam/mi_search.c: Merge with 4.0 mysql-test/r/binary.result: Merge with 4.0 mysql-test/r/func_group.result: Merge with 4.0 mysql-test/r/func_str.result: Merge with 4.0 mysql-test/r/func_time.result: Merge with 4.0 mysql-test/r/group_by.result: Merge with 4.0 mysql-test/r/handler.result: Merge with 4.0 mysql-test/r/innodb.result: Merge with 4.0 mysql-test/r/insert.result: Merge with 4.0 mysql-test/r/join_outer.result: Merge with 4.0 mysql-test/r/loaddata.result: Merge with 4.0 mysql-test/r/lowercase_table.result: Merge with 4.0 mysql-test/r/multi_update.result: Merge with 4.0 mysql-test/r/mysqldump.result: Merge with 4.0 mysql-test/r/query_cache.result: Merge with 4.0 mysql-test/r/rpl_max_relay_size.result: Merge with 4.0 mysql-test/r/rpl_rotate_logs.result: Merge with 4.0 mysql-test/r/rpl_trunc_binlog.result: Merge with 4.0 mysql-test/r/select_found.result: Merge with 4.0 mysql-test/r/symlink.result: Merge with 4.0 mysql-test/r/truncate.result: Merge with 4.0 mysql-test/r/type_blob.result: Merge with 4.0 mysql-test/r/type_datetime.result: Merge with 4.0 mysql-test/r/type_decimal.result: Merge with 4.0 mysql-test/r/type_enum.result: Merge with 4.0 mysql-test/r/type_timestamp.result: Merge with 4.0 mysql-test/r/union.result: Merge with 4.0 mysql-test/t/auto_increment.test: Merge with 4.0 mysql-test/t/bdb.test: Merge with 4.0 mysql-test/t/func_group.test: Merge with 4.0 mysql-test/t/func_op.test: Merge with 4.0 mysql-test/t/func_str.test: Merge with 4.0 mysql-test/t/func_time.test: Merge with 4.0 mysql-test/t/group_by.test: Merge with 4.0 mysql-test/t/handler.test: Merge with 4.0 mysql-test/t/innodb.test: Merge with 4.0 mysql-test/t/insert.test: Merge with 4.0 mysql-test/t/join_outer.test: Merge with 4.0 mysql-test/t/limit.test: Merge with 4.0 mysql-test/t/loaddata.test: Merge with 4.0 mysql-test/t/lowercase_table.test: Merge with 4.0 mysql-test/t/multi_update.test: Merge with 4.0 mysql-test/t/mysqldump.test: Merge with 4.0 mysql-test/t/query_cache.test: Merge with 4.0 mysql-test/t/rpl_log_pos.test: Merge with 4.0 mysql-test/t/rpl_max_relay_size.test: Merge with 4.0 mysql-test/t/rpl_rotate_logs.test: Merge with 4.0 mysql-test/t/rpl_trunc_binlog.test: Merge with 4.0 mysql-test/t/select_found.test: Merge with 4.0 mysql-test/t/symlink.test: Merge with 4.0 mysql-test/t/truncate.test: Merge with 4.0 mysql-test/t/type_blob.test: Merge with 4.0 mysql-test/t/type_datetime.test: Merge with 4.0 mysql-test/t/type_decimal.test: Merge with 4.0 mysql-test/t/type_enum.test: Merge with 4.0 mysql-test/t/type_timestamp.test: Merge with 4.0 mysql-test/t/union.test: Merge with 4.0 mysys/charset.c: Merge with 4.0 mysys/my_init.c: Merge with 4.0 mysys/my_symlink.c: Merge with 4.0 mysys/my_thr_init.c: Merge with 4.0 regex/reginit.c: Merge with 4.0 sql/field.cc: Change fix_datetime() to print errors sql/field.h: Merge with 4.0 sql/ha_innodb.cc: Merge with 4.0 sql/item.cc: Merge with 4.0 sql/item.h: Merge with 4.0 sql/item_cmpfunc.cc: Merge with 4.0 sql/item_func.cc: Merge with 4.0 sql/item_func.h: Merge with 4.0 sql/item_strfunc.cc: Merge with 4.0 sql/item_strfunc.h: Merge with 4.0 sql/item_sum.cc: Merge with 4.0 sql/item_sum.h: Merge with 4.0 sql/item_timefunc.cc: Merge with 4.0 sql/lex.h: Merge with 4.0 sql/log.cc: Merge with 4.0 sql/log_event.cc: Merge with 4.0 sql/log_event.h: Merge with 4.0 sql/mysql_priv.h: Merge with 4.0 sql/mysqld.cc: Merge with 4.0 sql/nt_servc.cc: Merge with 4.0 sql/opt_range.cc: Merge with 4.0 sql/records.cc: Merge with 4.0 sql/repl_failsafe.cc: Merge with 4.0 sql/slave.cc: Merge with 4.0 sql/sql_acl.cc: Merge with 4.0 sql/sql_analyse.cc: Merge with 4.0 sql/sql_base.cc: Merge with 4.0 sql/sql_cache.cc: Merge with 4.0 sql/sql_class.h: Merge with 4.0 sql/sql_db.cc: Merge with 4.0 sql/sql_delete.cc: Merge with 4.0 sql/sql_insert.cc: Merge with 4.0 sql/sql_load.cc: Merge with 4.0 sql/sql_parse.cc: Merge with 4.0 sql/sql_rename.cc: Merge with 4.0 sql/sql_select.cc: Merge with 4.0 sql/sql_show.cc: Merge with 4.0 sql/sql_table.cc: Merge with 4.0 sql/sql_update.cc: Merge with 4.0 sql/sql_yacc.yy: Merge with 4.0 sql/table.cc: Merge with 4.0 sql/table.h: Merge with 4.0 sql/time.cc: Merge with 4.0 sql/uniques.cc: Merge with 4.0 strings/ctype-tis620.c: Merge with 4.0 strings/strto.c: Merge with 4.0 support-files/mysql.server.sh: Merge with 4.0 support-files/mysql.spec.sh: Merge with 4.0
174 lines
5.4 KiB
C++
174 lines
5.4 KiB
C++
/* 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 tree 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"
|
|
|
|
|
|
int unique_write_to_file(gptr key, element_count count, Unique *unique)
|
|
{
|
|
/*
|
|
Use unique->size (size of element stored in the tree) and not
|
|
unique->tree.size_of_element. The latter is different from unique->size
|
|
when tree implementation chooses to store pointer to key in TREE_ELEMENT
|
|
(instead of storing the element itself there)
|
|
*/
|
|
return my_b_write(&unique->file, (byte*) key,
|
|
unique->size) ? 1 : 0;
|
|
}
|
|
|
|
int unique_write_to_ptrs(gptr key, element_count count, Unique *unique)
|
|
{
|
|
memcpy(unique->record_pointers, key, unique->size);
|
|
unique->record_pointers+=unique->size;
|
|
return 0;
|
|
}
|
|
|
|
Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
|
|
uint size_arg, ulong max_in_memory_size_arg)
|
|
:max_in_memory_size(max_in_memory_size_arg), size(size_arg), elements(0)
|
|
{
|
|
my_b_clear(&file);
|
|
init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL,
|
|
comp_func_fixed_arg);
|
|
/* If the following fail's the next add will also fail */
|
|
my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
|
|
max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
|
|
open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
|
|
MYF(MY_WME));
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
/*
|
|
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->sort.found_records=elements+tree.elements_in_tree;
|
|
|
|
if (my_b_tell(&file) == 0)
|
|
{
|
|
/* Whole tree is in memory; Don't use disk if you don't need to */
|
|
if ((record_pointers=table->sort.record_pointers= (byte*)
|
|
my_malloc(size * 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->sort.io_cache;
|
|
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
|
|
uint maxbuffer= file_ptrs.elements - 1;
|
|
uchar *sort_buffer;
|
|
my_off_t save_pos;
|
|
bool error=1;
|
|
|
|
/* Open cached file if it isn't open */
|
|
outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
|
|
MYF(MY_ZEROFILL));
|
|
|
|
if (!outfile || ! 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);
|
|
|
|
bzero((char*) &sort_param,sizeof(sort_param));
|
|
sort_param.max_rows= elements;
|
|
sort_param.sort_form=table;
|
|
sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
|
|
size;
|
|
sort_param.keys= max_in_memory_size / sort_param.sort_length;
|
|
sort_param.not_killable=1;
|
|
|
|
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,&file))
|
|
goto err;
|
|
if (flush_io_cache(&file) ||
|
|
reinit_io_cache(&file,READ_CACHE,0L,0,0))
|
|
goto err;
|
|
if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr,
|
|
file_ptr, file_ptr+maxbuffer,0))
|
|
goto err;
|
|
error=0;
|
|
err:
|
|
x_free((gptr) sort_buffer);
|
|
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;
|
|
}
|