diff options
author | unknown <serg@serg.mysql.com> | 2001-05-25 13:22:44 +0200 |
---|---|---|
committer | unknown <serg@serg.mysql.com> | 2001-05-25 13:22:44 +0200 |
commit | a6e1bddcd7401ad7066df9d1e4606c473a8e2ee9 (patch) | |
tree | 82fe818d6e0e73ca4b865b4310d2b8a8a00364ab | |
parent | bf79d385938f4f5cdf5f93de3ff995fb27022c95 (diff) | |
parent | 403b38ee5091e74df8adb6ee0c644903a82ffcad (diff) | |
download | mariadb-git-a6e1bddcd7401ad7066df9d1e4606c473a8e2ee9.tar.gz |
Merge work:/home/bk/mysql-4.0
into serg.mysql.com:/usr/home/serg/Abk/mysql-4.0
-rw-r--r-- | libmysql/Makefile.am | 5 | ||||
-rw-r--r-- | libmysql/Makefile.shared | 9 | ||||
-rw-r--r-- | mysql-test/r/count_distinct2.result | 8 | ||||
-rw-r--r-- | mysql-test/t/count_distinct2-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/count_distinct2.test | 29 | ||||
-rw-r--r-- | sql/item_sum.cc | 46 | ||||
-rw-r--r-- | sql/item_sum.h | 17 |
7 files changed, 109 insertions, 6 deletions
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index baf40a389a3..d26212fa7c8 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -35,6 +35,7 @@ link_sources: set -x; \ ss=`echo $(mystringsobjects) | sed "s;\.lo;.c;g"`; \ ds=`echo $(dbugobjects) | sed "s;\.lo;.c;g"`; \ + qs=`echo $(sqlobjects) | sed "s;\.lo;.c;g"`; \ ms=`echo $(mysysobjects) | sed "s;\.lo;.c;g"`; \ for f in $$ss; do \ rm -f $(srcdir)/$$f; \ @@ -44,6 +45,10 @@ link_sources: rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \ done; \ + for f in $$qs; do \ + rm -f $(srcdir)/$$f; \ + @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \ + done; \ for f in $$ds; do \ rm -f $(srcdir)/$$f; \ @LN_CP_F@ $(srcdir)/../dbug/$$f $(srcdir)/$$f; \ diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index cd19868ec33..7b220e12346 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -31,9 +31,12 @@ noinst_PROGRAMS = conf_to_src CHARSET_OBJS=@CHARSET_OBJS@ LTCHARSET_OBJS= ${CHARSET_OBJS:.o=.lo} -target_sources = libmysql.c net.c violite.c password.c \ +target_sources = libmysql.c net.c password.c \ get_password.c errmsg.c +#quick easy dirty hack to make it work after Tonu's changes +#In my opinion, violite.c really belongs into mysys - Sasha +sqlobjects = violite.lo mystringsobjects = strmov.lo strxmov.lo strnmov.lo strmake.lo strend.lo \ strnlen.lo strfill.lo is_prefix.lo \ int2str.lo str2int.lo strinstr.lo strcont.lo \ @@ -59,7 +62,8 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ # Not needed in the minimum library mysysobjects2 = getopt.lo getopt1.lo getvar.lo my_lib.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) -target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) +target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects)\ + $(sqlobjects) target_ldflags = -version-info @SHARED_LIB_VERSION@ CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ $(target) @@ -75,6 +79,7 @@ clean-local: rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \ `echo $(dbugobjects) | sed "s;\.lo;.c;g"` \ `echo $(mysysobjects) | sed "s;\.lo;.c;g"` \ + `echo $(sqlobjects) | sed "s;\.lo;.c;g"` \ $(mystringsextra) $(mysysheaders) ctype_extra_sources.c \ ../linked_client_sources diff --git a/mysql-test/r/count_distinct2.result b/mysql-test/r/count_distinct2.result index b8330835332..3586910e8b3 100644 --- a/mysql-test/r/count_distinct2.result +++ b/mysql-test/r/count_distinct2.result @@ -74,3 +74,11 @@ count(distinct n2) n1 1 NULL 1 1 3 2 +count(distinct n) +5000 +Variable_name Value +Created_tmp_disk_tables 1 +count(distinct s) +5000 +Variable_name Value +Created_tmp_disk_tables 1 diff --git a/mysql-test/t/count_distinct2-master.opt b/mysql-test/t/count_distinct2-master.opt new file mode 100644 index 00000000000..8f1be6dce3a --- /dev/null +++ b/mysql-test/t/count_distinct2-master.opt @@ -0,0 +1 @@ +-O max_heap_table_size=16384 diff --git a/mysql-test/t/count_distinct2.test b/mysql-test/t/count_distinct2.test index 5ddd96198fe..2447a7c3611 100644 --- a/mysql-test/t/count_distinct2.test +++ b/mysql-test/t/count_distinct2.test @@ -43,3 +43,32 @@ select count(distinct n1), count(distinct n2) from t1; select count(distinct n2), n1 from t1 group by n1; drop table t1; + +# test the converstion from tree to MyISAM +create table t1 (n int); +let $1=5000; +while ($1) +{ + eval insert into t1 values($1); + dec $1; +} + +flush status; +select count(distinct n) from t1; +show status like 'Created_tmp_disk_tables'; +drop table t1; + +#test conversion from heap to MyISAM +create table t1 (s text); +let $1=5000; +while ($1) +{ + eval insert into t1 values('$1'); + dec $1; +} + +flush status; +select count(distinct s) from t1; +show status like 'Created_tmp_disk_tables'; +drop table t1; + diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 089f4f56216..879c27178e5 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -830,7 +830,26 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) return 0; } +// helper function for walking the tree when we dump it to MyISAM - +// tree_walk will call it for each +// leaf +int dump_leaf(byte* key, uint32 count __attribute__((unused)), + Item_sum_count_distinct* item) +{ + char* buf = item->table->record[0]; + int error; + memset(buf, 0xff, item->rec_offset); // make up for cheating in the tree + memcpy(buf + item->rec_offset, key, item->tree.size_of_element); + if ((error = item->table->file->write_row(buf))) + { + if (error != HA_ERR_FOUND_DUPP_KEY && + error != HA_ERR_FOUND_DUPP_UNIQUE) + return 1; + } + + return 0; +} Item_sum_count_distinct::~Item_sum_count_distinct() { @@ -916,11 +935,29 @@ bool Item_sum_count_distinct::setup(THD *thd) key_len, compare_key, 0, 0); tree.cmp_arg = cmp_arg; use_tree = 1; + + // the only time key_len could be 0 is if someone does + // count(distinct) on a char(0) field - stupid thing to do, + // but this has to be handled - otherwise someone can crash + // the server with a DoS attack + max_elements_in_tree = (key_len) ? max_heap_table_size/key_len : + max_heap_table_size; } return 0; } +int Item_sum_count_distinct::tree_to_myisam() +{ + if(create_myisam_from_heap(table, tmp_table_param, + HA_ERR_RECORD_FILE_FULL, 1) || + tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this, + left_root_right)) + return 1; + delete_tree(&tree); + use_tree = 0; + return 0; +} void Item_sum_count_distinct::reset() { @@ -947,7 +984,14 @@ bool Item_sum_count_distinct::add() if(use_tree) { - if(!tree_insert(&tree, table->record[0] + rec_offset, 0)) + // if the tree got too big, convert to MyISAM, otherwise + // insert into the tree + if(tree.elements_in_tree > max_elements_in_tree) + { + if(tree_to_myisam()) + return 1; + } + else if(!tree_insert(&tree, table->record[0] + rec_offset, 0)) return 1; } else if ((error=table->file->write_row(table->record[0]))) diff --git a/sql/item_sum.h b/sql/item_sum.h index 863623c3b1a..1aa7f78d786 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -148,15 +148,26 @@ class Item_sum_count_distinct :public Item_sum_int bool fix_fields(THD *thd,TABLE_LIST *tables); TMP_TABLE_PARAM *tmp_table_param; TREE tree; - bool use_tree; // If there are no blobs, we can use a tree, which + uint max_elements_in_tree; + // calculated based on max_heap_table_size. If reached, + // walk the tree and dump it into MyISAM table + + bool use_tree; + // If there are no blobs, we can use a tree, which // is faster than heap table. In that case, we still use the table // to help get things set up, but we insert nothing in it - int rec_offset; // the first few bytes of record ( at least one) + + int rec_offset; + // the first few bytes of record ( at least one) // are just markers for deleted and NULLs. We want to skip them since // they will just bloat the tree without providing any valuable info - friend int composite_key_cmp(void* arg, byte* key1, byte* key2); + int tree_to_myisam(); + friend int composite_key_cmp(void* arg, byte* key1, byte* key2); + friend int dump_leaf(byte* key, uint32 count __attribute__((unused)), + Item_sum_count_distinct* item); + public: Item_sum_count_distinct(List<Item> &list) :Item_sum_int(list),table(0),used_table_cache(~(table_map) 0), |