#At file:///home/tsk/mprog/src/5.3-mwl89/ based on revid:timour@askmonty.org-20100716105202-8narq4tzhka2n1a5 2802 timour@askmonty.org 2010-07-16 [merge] Merge main 5.3 into 5.3-mwl89. added: mysql-test/r/optimizer_switch.result mysql-test/t/optimizer_switch.test modified: .bzrignore configure.in include/queues.h include/thr_alarm.h mysql-test/r/index_merge_myisam.result mysql-test/r/myisam_mrr.result mysql-test/r/order_by.result mysql-test/r/subselect_mat.result mysql-test/r/subselect_no_mat.result mysql-test/r/subselect_no_opts.result mysql-test/r/subselect_no_semijoin.result mysql-test/r/subselect_sj.result mysql-test/r/subselect_sj_jcl6.result mysql-test/t/index_merge_myisam.test mysql-test/t/myisam_mrr.test mysql-test/t/order_by.test mysql-test/t/subselect_mat.test mysql-test/t/subselect_no_mat.test mysql-test/t/subselect_no_opts.test mysql-test/t/subselect_no_semijoin.test mysql-test/t/subselect_sj.test mysys/queues.c mysys/thr_alarm.c sql/create_options.cc sql/event_queue.cc sql/filesort.cc sql/ha_partition.cc sql/ha_partition.h sql/item_cmpfunc.cc sql/item_subselect.cc sql/mysqld.cc sql/net_serv.cc sql/opt_range.cc sql/sql_class.cc sql/sql_class.h sql/sql_union.cc sql/uniques.cc storage/maria/ma_ft_boolean_search.c storage/maria/ma_ft_nlq_search.c storage/maria/ma_sort.c storage/maria/maria_pack.c storage/myisam/ft_boolean_search.c storage/myisam/ft_nlq_search.c storage/myisam/mi_test_all.sh storage/myisam/myisampack.c storage/myisam/sort.c storage/myisammrg/myrg_queue.c storage/myisammrg/myrg_rnext.c storage/myisammrg/myrg_rnext_same.c storage/myisammrg/myrg_rprev.c === modified file '.bzrignore' --- a/.bzrignore 2010-06-26 10:05:41 +0000 +++ b/.bzrignore 2010-07-16 07:33:01 +0000 @@ -1940,3 +1940,4 @@ sql/client_plugin.c *.dgcov libmysqld/create_options.cc storage/pbxt/bin/xtstat +libmysqld/sql_expression_cache.cc === modified file 'configure.in' --- a/configure.in 2010-06-26 19:55:33 +0000 +++ b/configure.in 2010-07-16 08:02:05 +0000 @@ -17,7 +17,7 @@ dnl When merging new MySQL releases, upd dnl MySQL version number. dnl dnl Note: the following line must be parseable by win/configure.js:GetVersion() -AC_INIT([MariaDB Server], [5.2.1-MariaDB-beta], [], [mysql]) +AC_INIT([MariaDB Server], [5.3.0-MariaDB-alpha], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM === modified file 'include/queues.h' --- a/include/queues.h 2007-11-14 18:20:31 +0000 +++ b/include/queues.h 2010-07-16 07:33:01 +0000 @@ -1,23 +1,31 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2010 Monty Program Ab + All Rights reserved - 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; version 2 of the License. - - 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 */ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ /* Code for generell handling of priority Queues. Implemention of queues from "Algoritms in C" by Robert Sedgewick. - Copyright Monty Program KB. - By monty. */ #ifndef _queues_h @@ -31,30 +39,34 @@ typedef struct st_queue { void *first_cmp_arg; uint elements; uint max_elements; - uint offset_to_key; /* compare is done on element+offset */ + uint offset_to_key; /* compare is done on element+offset */ + uint offset_to_queue_pos; /* If we want to store position in element */ + uint auto_extent; int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ int (*compare)(void *, uchar *,uchar *); - uint auto_extent; } QUEUE; +#define queue_first_element(queue) 1 +#define queue_last_element(queue) (queue)->elements #define queue_top(queue) ((queue)->root[1]) -#define queue_element(queue,index) ((queue)->root[index+1]) +#define queue_element(queue,index) ((queue)->root[index]) #define queue_end(queue) ((queue)->root[(queue)->elements]) -#define queue_replaced(queue) _downheap(queue,1) +#define queue_replace(queue, idx) _downheap(queue, idx, (queue)->root[idx]) +#define queue_replace_top(queue) _downheap(queue, 1, (queue)->root[1]) #define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg #define queue_set_max_at_top(queue, set_arg) \ (queue)->max_at_top= set_arg ? -1 : 1 +#define queue_remove_top(queue_arg) queue_remove((queue_arg), queue_first_element(queue_arg)) typedef int (*queue_compare)(void *,uchar *, uchar *); int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, pbool max_at_top, queue_compare compare, - void *first_cmp_arg); -int init_queue_ex(QUEUE *queue,uint max_elements,uint offset_to_key, - pbool max_at_top, queue_compare compare, - void *first_cmp_arg, uint auto_extent); + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent); int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key, pbool max_at_top, queue_compare compare, - void *first_cmp_arg); + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent); int resize_queue(QUEUE *queue, uint max_elements); void delete_queue(QUEUE *queue); void queue_insert(QUEUE *queue,uchar *element); @@ -62,7 +74,7 @@ int queue_insert_safe(QUEUE *queue, ucha uchar *queue_remove(QUEUE *queue,uint idx); #define queue_remove_all(queue) { (queue)->elements= 0; } #define queue_is_full(queue) (queue->elements == queue->max_elements) -void _downheap(QUEUE *queue,uint idx); +void _downheap(QUEUE *queue, uint idx, uchar *element); void queue_fix(QUEUE *queue); #define is_queue_inited(queue) ((queue)->root != 0) === modified file 'include/thr_alarm.h' --- a/include/thr_alarm.h 2008-04-28 16:24:05 +0000 +++ b/include/thr_alarm.h 2010-07-16 07:33:01 +0000 @@ -34,7 +34,7 @@ extern "C" { typedef struct st_alarm_info { - ulong next_alarm_time; + time_t next_alarm_time; uint active_alarms; uint max_used_alarms; } ALARM_INFO; @@ -78,10 +78,11 @@ typedef int thr_alarm_entry; typedef thr_alarm_entry* thr_alarm_t; typedef struct st_alarm { - ulong expire_time; + time_t expire_time; thr_alarm_entry alarmed; /* set when alarm is due */ pthread_t thread; my_thread_id thread_id; + uint index_in_queue; my_bool malloced; } ALARM; === modified file 'mysql-test/r/index_merge_myisam.result' --- a/mysql-test/r/index_merge_myisam.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/index_merge_myisam.result 2010-07-16 08:58:24 +0000 @@ -1413,66 +1413,6 @@ WHERE `RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND `TESTID`='' AND `UCCHECK`=''; drop table t1; -# -# Generic @@optimizer_switch tests (move those into a separate file if -# we get another @@optimizer_switch user) -# -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='index_merge=off,index_merge_union=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='index_merge_union=on'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,index_merge_sort_union=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch=4; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of '4' -set optimizer_switch=NULL; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'NULL' -set optimizer_switch='default,index_merge'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge' -set optimizer_switch='index_merge=index_merge'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=index_merge' -set optimizer_switch='index_merge=on,but...'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'but...' -set optimizer_switch='index_merge='; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=' -set optimizer_switch='index_merge'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge' -set optimizer_switch='on'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'on' -set optimizer_switch='index_merge=on,index_merge=off'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off' -set optimizer_switch='index_merge_union=on,index_merge_union=default'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge_union=default' -set optimizer_switch='default,index_merge=on,index_merge=off,default'; -ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off,default' -set optimizer_switch=default; -set optimizer_switch='index_merge=off,index_merge_union=off,default'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch=default; -select @@global.optimizer_switch; -@@global.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set @@global.optimizer_switch=default; -select @@global.optimizer_switch; -@@global.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -# -# Check index_merge's @@optimizer_switch flags -# -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on create table t0 (a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 (a int, b int, c int, filler char(100), @@ -1580,7 +1520,4 @@ explain select * from t1 where a=10 and id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using sort_union(a,c); Using where set optimizer_switch=default; -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on drop table t0, t1; === modified file 'mysql-test/r/myisam_mrr.result' --- a/mysql-test/r/myisam_mrr.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/myisam_mrr.result 2010-07-16 08:58:24 +0000 @@ -392,9 +392,9 @@ drop table t0, t1; # Part of MWL#67: DS-MRR backport: add an @@optimizer_switch flag for # index_condition pushdown: # - engine_condition_pushdown does not affect ICP -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +select @@optimizer_switch like '%index_condition_pushdown=on%'; +@@optimizer_switch like '%index_condition_pushdown=on%' +1 create table t0 (a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 (a int, b int, key(a)); === added file 'mysql-test/r/optimizer_switch.result' --- a/mysql-test/r/optimizer_switch.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/r/optimizer_switch.result 2010-07-16 08:58:24 +0000 @@ -0,0 +1,99 @@ +# +# Generic @@optimizer_switch tests +# +# +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='index_merge=off,index_merge_union=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='index_merge_union=on'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,index_merge_sort_union=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch=4; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of '4' +set optimizer_switch=NULL; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'NULL' +set optimizer_switch='default,index_merge'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge' +set optimizer_switch='index_merge=index_merge'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=index_merge' +set optimizer_switch='index_merge=on,but...'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'but...' +set optimizer_switch='index_merge='; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=' +set optimizer_switch='index_merge'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge' +set optimizer_switch='on'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'on' +set optimizer_switch='index_merge=on,index_merge=off'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off' +set optimizer_switch='index_merge_union=on,index_merge_union=default'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge_union=default' +set optimizer_switch='default,index_merge=on,index_merge=off,default'; +ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off,default' +set optimizer_switch=default; +set optimizer_switch='index_merge=off,index_merge_union=off,default'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch=default; +select @@global.optimizer_switch; +@@global.optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set @@global.optimizer_switch=default; +select @@global.optimizer_switch; +@@global.optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +# +# Check index_merge's @@optimizer_switch flags +# +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on + +BUG#37120 optimizer_switch allowable values not according to specification + +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,materialization=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,semijoin=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,loosescan=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,semijoin=off,materialization=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,materialization=off,semijoin=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,semijoin=off,loosescan=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch='default,materialization=off,loosescan=off'; +select @@optimizer_switch; +@@optimizer_switch +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +set optimizer_switch=default; === modified file 'mysql-test/r/order_by.result' --- a/mysql-test/r/order_by.result 2010-03-20 12:01:47 +0000 +++ b/mysql-test/r/order_by.result 2010-07-15 14:07:01 +0000 @@ -607,9 +607,14 @@ FieldKey LongVal StringVal 1 0 2 1 1 3 1 2 1 -EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal; +DS-MRR: use two IGNORE INDEX queries, otherwise we get cost races, because +DS-MRR: records_in_range/read_time return the same numbers for all three indexes +EXPLAIN SELECT * FROM t1 IGNORE INDEX (LongField, StringField) WHERE FieldKey > '2' ORDER BY LongVal; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 38 NULL 4 Using index condition; Using where; Using MRR; Using filesort +1 SIMPLE t1 range FieldKey FieldKey 38 NULL 4 Using index condition; Using MRR; Using filesort +EXPLAIN SELECT * FROM t1 IGNORE INDEX (FieldKey, LongField) WHERE FieldKey > '2' ORDER BY LongVal; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range StringField StringField 38 NULL 4 Using where; Using filesort SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal; FieldKey LongVal StringVal 3 1 2 === modified file 'mysql-test/r/subselect_mat.result' --- a/mysql-test/r/subselect_mat.result 2010-07-16 10:52:02 +0000 +++ b/mysql-test/r/subselect_mat.result 2010-07-16 12:10:55 +0000 @@ -1246,3 +1246,29 @@ i 4 set session optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; +create table t0 (a int); +insert into t0 values (0),(1),(2); +create table t1 (a int); +insert into t1 values (0),(1),(2); +explain select a, a in (select a from t1) from t0; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t0 ALL NULL NULL NULL NULL 3 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +select a, a in (select a from t1) from t0; +a a in (select a from t1) +0 1 +1 1 +2 1 +prepare s from 'select a, a in (select a from t1) from t0'; +execute s; +a a in (select a from t1) +0 1 +1 1 +2 1 +update t1 set a=123; +execute s; +a a in (select a from t1) +0 0 +1 0 +2 0 +drop table t0, t1; === modified file 'mysql-test/r/subselect_no_mat.result' --- a/mysql-test/r/subselect_no_mat.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/subselect_no_mat.result 2010-07-16 08:58:24 +0000 @@ -1,6 +1,6 @@ -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +select @@optimizer_switch like '%materialization=on%'; +@@optimizer_switch like '%materialization=on%' +1 set optimizer_switch='materialization=off'; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12; set @save_optimizer_switch=@@optimizer_switch; @@ -4925,6 +4925,6 @@ DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; set optimizer_switch=default; -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on +select @@optimizer_switch like '%materialization=on%'; +@@optimizer_switch like '%materialization=on%' +1 === modified file 'mysql-test/r/subselect_no_opts.result' --- a/mysql-test/r/subselect_no_opts.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/subselect_no_opts.result 2010-07-16 08:58:24 +0000 @@ -1,6 +1,3 @@ -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on set optimizer_switch='materialization=off,semijoin=off'; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12; set @save_optimizer_switch=@@optimizer_switch; @@ -4925,6 +4922,3 @@ DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; set optimizer_switch=default; -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on === modified file 'mysql-test/r/subselect_no_semijoin.result' --- a/mysql-test/r/subselect_no_semijoin.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/subselect_no_semijoin.result 2010-07-16 08:58:24 +0000 @@ -1,6 +1,3 @@ -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on set optimizer_switch='semijoin=off'; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12; set @save_optimizer_switch=@@optimizer_switch; @@ -4925,6 +4922,3 @@ DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; set optimizer_switch=default; -show variables like 'optimizer_switch'; -Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on === modified file 'mysql-test/r/subselect_sj.result' --- a/mysql-test/r/subselect_sj.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/subselect_sj.result 2010-07-16 08:58:24 +0000 @@ -197,45 +197,6 @@ id select_type table type possible_keys 1 PRIMARY t1 ALL NULL NULL NULL NULL 103 100.00 Using where; Using join buffer Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t10` join `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t10`.`pk`) and (`test`.`t10`.`pk` < 3)) - -BUG#37120 optimizer_switch allowable values not according to specification - -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,materialization=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off,semijoin=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch=default; drop table t0, t1, t2; drop table t10, t11, t12; === modified file 'mysql-test/r/subselect_sj_jcl6.result' --- a/mysql-test/r/subselect_sj_jcl6.result 2010-07-10 10:37:30 +0000 +++ b/mysql-test/r/subselect_sj_jcl6.result 2010-07-16 08:58:24 +0000 @@ -201,45 +201,6 @@ id select_type table type possible_keys 1 PRIMARY t1 ALL NULL NULL NULL NULL 103 100.00 Using where; Using join buffer Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t10` join `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t10`.`pk`) and (`test`.`t10`.`pk` < 3)) - -BUG#37120 optimizer_switch allowable values not according to specification - -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,materialization=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off,semijoin=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=on,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,semijoin=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch='default,materialization=off,loosescan=off'; -select @@optimizer_switch; -@@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_condition_pushdown=on,firstmatch=on,loosescan=off,materialization=off,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on -set optimizer_switch=default; drop table t0, t1, t2; drop table t10, t11, t12; === modified file 'mysql-test/t/index_merge_myisam.test' --- a/mysql-test/t/index_merge_myisam.test 2009-08-24 19:10:48 +0000 +++ b/mysql-test/t/index_merge_myisam.test 2010-07-16 08:58:24 +0000 @@ -20,78 +20,6 @@ let $merge_table_support= 1; --source include/index_merge_2sweeps.inc --source include/index_merge_ror_cpk.inc ---echo # ---echo # Generic @@optimizer_switch tests (move those into a separate file if ---echo # we get another @@optimizer_switch user) ---echo # - ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='index_merge=off,index_merge_union=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='index_merge_union=on'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,index_merge_sort_union=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch=4; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch=NULL; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='default,index_merge'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge=index_merge'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge=on,but...'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge='; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='on'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge=on,index_merge=off'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='index_merge_union=on,index_merge_union=default'; - ---error ER_WRONG_VALUE_FOR_VAR -set optimizer_switch='default,index_merge=on,index_merge=off,default'; - -set optimizer_switch=default; -set optimizer_switch='index_merge=off,index_merge_union=off,default'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; -set optimizer_switch=default; - -# Check setting defaults for global vars ---replace_regex /,table_elimination=on// -select @@global.optimizer_switch; -set @@global.optimizer_switch=default; ---replace_regex /,table_elimination=on// -select @@global.optimizer_switch; - ---echo # ---echo # Check index_merge's @@optimizer_switch flags ---echo # ---replace_regex /,table_elimination.on// -select @@optimizer_switch; - create table t0 (a int); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); create table t1 (a int, b int, c int, filler char(100), @@ -190,8 +118,6 @@ set optimizer_switch='default,index_merg explain select * from t1 where a=10 and b=10 or c=10; set optimizer_switch=default; ---replace_regex /,table_elimination.on// -show variables like 'optimizer_switch'; drop table t0, t1; === modified file 'mysql-test/t/myisam_mrr.test' --- a/mysql-test/t/myisam_mrr.test 2009-12-22 14:43:00 +0000 +++ b/mysql-test/t/myisam_mrr.test 2010-07-16 08:58:24 +0000 @@ -103,8 +103,7 @@ drop table t0, t1; # Check that optimizer_switch is present ---replace_regex /,table_elimination=o[nf]*// -select @@optimizer_switch; +select @@optimizer_switch like '%index_condition_pushdown=on%'; # Check if it affects ICP create table t0 (a int); === added file 'mysql-test/t/optimizer_switch.test' --- a/mysql-test/t/optimizer_switch.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/t/optimizer_switch.test 2010-07-16 08:58:24 +0000 @@ -0,0 +1,113 @@ +--echo # +--echo # Generic @@optimizer_switch tests +--echo # +--echo # + +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='index_merge=off,index_merge_union=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='index_merge_union=on'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,index_merge_sort_union=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch=4; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch=NULL; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='default,index_merge'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge=index_merge'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge=on,but...'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge='; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='on'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge=on,index_merge=off'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='index_merge_union=on,index_merge_union=default'; + +--error ER_WRONG_VALUE_FOR_VAR +set optimizer_switch='default,index_merge=on,index_merge=off,default'; + +set optimizer_switch=default; +set optimizer_switch='index_merge=off,index_merge_union=off,default'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; +set optimizer_switch=default; + +# Check setting defaults for global vars +--replace_regex /,table_elimination=on// +select @@global.optimizer_switch; +set @@global.optimizer_switch=default; +--replace_regex /,table_elimination=on// +select @@global.optimizer_switch; + +--echo # +--echo # Check index_merge's @@optimizer_switch flags +--echo # +--replace_regex /,table_elimination.on// +select @@optimizer_switch; + +--echo +--echo BUG#37120 optimizer_switch allowable values not according to specification +--echo + +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,materialization=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,semijoin=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,loosescan=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,semijoin=off,materialization=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,materialization=off,semijoin=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,semijoin=off,loosescan=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; + +set optimizer_switch='default,materialization=off,loosescan=off'; +--replace_regex /,table_elimination=on// +select @@optimizer_switch; +set optimizer_switch=default; + + === modified file 'mysql-test/t/order_by.test' --- a/mysql-test/t/order_by.test 2010-03-04 08:03:07 +0000 +++ b/mysql-test/t/order_by.test 2010-07-15 14:07:01 +0000 @@ -402,7 +402,11 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3'); EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal; -EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal; +--echo DS-MRR: use two IGNORE INDEX queries, otherwise we get cost races, because +--echo DS-MRR: records_in_range/read_time return the same numbers for all three indexes +EXPLAIN SELECT * FROM t1 IGNORE INDEX (LongField, StringField) WHERE FieldKey > '2' ORDER BY LongVal; +EXPLAIN SELECT * FROM t1 IGNORE INDEX (FieldKey, LongField) WHERE FieldKey > '2' ORDER BY LongVal; + SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal; EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal; SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal; === modified file 'mysql-test/t/subselect_mat.test' --- a/mysql-test/t/subselect_mat.test 2010-03-13 20:04:52 +0000 +++ b/mysql-test/t/subselect_mat.test 2010-07-16 11:02:15 +0000 @@ -905,3 +905,19 @@ select * from t1 where t1.i in (select t set session optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; +# +# Test that the contents of the temp table of a materialized subquery is +# cleaned up between PS re-executions. +# + +create table t0 (a int); +insert into t0 values (0),(1),(2); +create table t1 (a int); +insert into t1 values (0),(1),(2); +explain select a, a in (select a from t1) from t0; +select a, a in (select a from t1) from t0; +prepare s from 'select a, a in (select a from t1) from t0'; +execute s; +update t1 set a=123; +execute s; +drop table t0, t1; === modified file 'mysql-test/t/subselect_no_mat.test' --- a/mysql-test/t/subselect_no_mat.test 2010-02-21 07:33:54 +0000 +++ b/mysql-test/t/subselect_no_mat.test 2010-07-16 08:58:24 +0000 @@ -1,13 +1,11 @@ # # Run subselect.test without semi-join optimization (test materialize) # ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; +select @@optimizer_switch like '%materialization=on%'; set optimizer_switch='materialization=off'; --source t/subselect.test set optimizer_switch=default; ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; +select @@optimizer_switch like '%materialization=on%'; === modified file 'mysql-test/t/subselect_no_opts.test' --- a/mysql-test/t/subselect_no_opts.test 2010-02-21 07:33:54 +0000 +++ b/mysql-test/t/subselect_no_opts.test 2010-07-16 08:58:24 +0000 @@ -1,13 +1,9 @@ # # Run subselect.test without semi-join optimization (test materialize) # ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; set optimizer_switch='materialization=off,semijoin=off'; --source t/subselect.test set optimizer_switch=default; ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; === modified file 'mysql-test/t/subselect_no_semijoin.test' --- a/mysql-test/t/subselect_no_semijoin.test 2010-02-21 07:33:54 +0000 +++ b/mysql-test/t/subselect_no_semijoin.test 2010-07-16 08:58:24 +0000 @@ -1,13 +1,8 @@ # # Run subselect.test without semi-join optimization (test materialize) # ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; set optimizer_switch='semijoin=off'; --source t/subselect.test set optimizer_switch=default; ---replace_regex /,table_elimination=on// -show variables like 'optimizer_switch'; - === modified file 'mysql-test/t/subselect_sj.test' --- a/mysql-test/t/subselect_sj.test 2010-03-15 06:32:54 +0000 +++ b/mysql-test/t/subselect_sj.test 2010-07-16 08:58:24 +0000 @@ -92,46 +92,6 @@ execute s1; insert into t1 select (A.a + 10 * B.a),1 from t0 A, t0 B; explain extended select * from t1 where a in (select pk from t10 where pk<3); ---echo ---echo BUG#37120 optimizer_switch allowable values not according to specification ---echo - ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,materialization=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,semijoin=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,loosescan=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,semijoin=off,materialization=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,materialization=off,semijoin=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,semijoin=off,materialization=off,loosescan=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,semijoin=off,loosescan=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; - -set optimizer_switch='default,materialization=off,loosescan=off'; ---replace_regex /,table_elimination=on// -select @@optimizer_switch; -set optimizer_switch=default; - drop table t0, t1, t2; drop table t10, t11, t12; === modified file 'mysys/queues.c' --- a/mysys/queues.c 2008-02-18 22:29:39 +0000 +++ b/mysys/queues.c 2010-07-16 07:33:01 +0000 @@ -1,25 +1,42 @@ -/* Copyright (C) 2000, 2005 MySQL AB +/* Copyright (C) 2010 Monty Program Ab + All Rights reserved - 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; version 2 of the License. - - 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 */ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ /* + This code originates from the Unireg project. + Code for generell handling of priority Queues. Implemention of queues from "Algoritms in C" by Robert Sedgewick. - An optimisation of _downheap suggested in Exercise 7.51 in "Data - Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition - was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm - of queue_fix was implemented. + + The queue can optionally store the position in queue in the element + that is in the queue. This allows one to remove any element from the queue + in O(1) time. + + Optimisation of _downheap() and queue_fix() is inspired by code done + by Mikael Ronström, based on an optimisation of _downheap from + Exercise 7.51 in "Data Structures & Algorithms in C++" by Mark Allen + Weiss, Second Edition. */ #include "mysys_priv.h" @@ -39,6 +56,10 @@ max_at_top Set to 1 if you want biggest element on top. compare Compare function for elements, takes 3 arguments. first_cmp_arg First argument to compare function + offset_to_queue_pos If <> 0, then offset+1 in element to store position + in queue (for fast delete of element in queue) + auto_extent When the queue is full and there is insert operation + extend the queue. NOTES Will allocate max_element pointers for queue array @@ -50,74 +71,33 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, pbool max_at_top, int (*compare) (void *, uchar *, uchar *), - void *first_cmp_arg) + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent) + { DBUG_ENTER("init_queue"); - if ((queue->root= (uchar **) my_malloc((max_elements+1)*sizeof(void*), + if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*), MYF(MY_WME))) == 0) DBUG_RETURN(1); - queue->elements=0; - queue->compare=compare; - queue->first_cmp_arg=first_cmp_arg; - queue->max_elements=max_elements; - queue->offset_to_key=offset_to_key; + queue->elements= 0; + queue->compare= compare; + queue->first_cmp_arg= first_cmp_arg; + queue->max_elements= max_elements; + queue->offset_to_key= offset_to_key; + queue->offset_to_queue_pos= offset_to_queue_pos; + queue->auto_extent= auto_extent; queue_set_max_at_top(queue, max_at_top); DBUG_RETURN(0); } - -/* - Init queue, uses init_queue internally for init work but also accepts - auto_extent as parameter - - SYNOPSIS - init_queue_ex() - queue Queue to initialise - max_elements Max elements that will be put in queue - offset_to_key Offset to key in element stored in queue - Used when sending pointers to compare function - max_at_top Set to 1 if you want biggest element on top. - compare Compare function for elements, takes 3 arguments. - first_cmp_arg First argument to compare function - auto_extent When the queue is full and there is insert operation - extend the queue. - - NOTES - Will allocate max_element pointers for queue array - - RETURN - 0 ok - 1 Could not allocate memory -*/ - -int init_queue_ex(QUEUE *queue, uint max_elements, uint offset_to_key, - pbool max_at_top, int (*compare) (void *, uchar *, uchar *), - void *first_cmp_arg, uint auto_extent) -{ - int ret; - DBUG_ENTER("init_queue_ex"); - - if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare, - first_cmp_arg))) - DBUG_RETURN(ret); - - queue->auto_extent= auto_extent; - DBUG_RETURN(0); -} - /* Reinitialize queue for other usage SYNOPSIS reinit_queue() queue Queue to initialise - max_elements Max elements that will be put in queue - offset_to_key Offset to key in element stored in queue - Used when sending pointers to compare function - max_at_top Set to 1 if you want biggest element on top. - compare Compare function for elements, takes 3 arguments. - first_cmp_arg First argument to compare function + For rest of arguments, see init_queue() above NOTES This will delete all elements from the queue. If you don't want this, @@ -125,21 +105,23 @@ int init_queue_ex(QUEUE *queue, uint max RETURN 0 ok - EE_OUTOFMEMORY Wrong max_elements + 1 Wrong max_elements; Queue has old size */ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, pbool max_at_top, int (*compare) (void *, uchar *, uchar *), - void *first_cmp_arg) + void *first_cmp_arg, uint offset_to_queue_pos, + uint auto_extent) { DBUG_ENTER("reinit_queue"); - queue->elements=0; - queue->compare=compare; - queue->first_cmp_arg=first_cmp_arg; - queue->offset_to_key=offset_to_key; + queue->elements= 0; + queue->compare= compare; + queue->first_cmp_arg= first_cmp_arg; + queue->offset_to_key= offset_to_key; + queue->offset_to_queue_pos= offset_to_queue_pos; + queue->auto_extent= auto_extent; queue_set_max_at_top(queue, max_at_top); - resize_queue(queue, max_elements); - DBUG_RETURN(0); + DBUG_RETURN(resize_queue(queue, max_elements)); } @@ -167,8 +149,8 @@ int resize_queue(QUEUE *queue, uint max_ if (queue->max_elements == max_elements) DBUG_RETURN(0); if ((new_root= (uchar **) my_realloc((void *)queue->root, - (max_elements+1)*sizeof(void*), - MYF(MY_WME))) == 0) + (max_elements + 1)* sizeof(void*), + MYF(MY_WME))) == 0) DBUG_RETURN(1); set_if_smaller(queue->elements, max_elements); queue->max_elements= max_elements; @@ -197,39 +179,58 @@ void delete_queue(QUEUE *queue) if (queue->root) { my_free((uchar*) queue->root,MYF(0)); - queue->root=0; + queue->root=0; /* Allow multiple calls */ } DBUG_VOID_RETURN; } - /* Code for insert, search and delete of elements */ +/* + Insert element in queue + + SYNOPSIS + queue_insert() + queue Queue to use + element Element to insert +*/ void queue_insert(register QUEUE *queue, uchar *element) { reg2 uint idx, next; + uint offset_to_queue_pos= queue->offset_to_queue_pos; DBUG_ASSERT(queue->elements < queue->max_elements); - queue->root[0]= element; + idx= ++queue->elements; /* max_at_top swaps the comparison if we want to order by desc */ - while ((queue->compare(queue->first_cmp_arg, + while (idx > 1 && + (queue->compare(queue->first_cmp_arg, element + queue->offset_to_key, queue->root[(next= idx >> 1)] + queue->offset_to_key) * queue->max_at_top) < 0) { queue->root[idx]= queue->root[next]; + if (offset_to_queue_pos) + (*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx; idx= next; } queue->root[idx]= element; + if (offset_to_queue_pos) + (*(uint*) (element+ offset_to_queue_pos-1))= idx; } + /* - Does safe insert. If no more space left on the queue resize it. - Return codes: - 0 - OK - 1 - Cannot allocate more memory - 2 - auto_extend is 0, the operation would - + Like queue_insert, but resize queue if queue is full + + SYNOPSIS + queue_insert_safe() + queue Queue to use + element Element to insert + + RETURN + 0 OK + 1 Cannot allocate more memory + 2 auto_extend is 0; No insertion done */ int queue_insert_safe(register QUEUE *queue, uchar *element) @@ -239,7 +240,7 @@ int queue_insert_safe(register QUEUE *qu { if (!queue->auto_extent) return 2; - else if (resize_queue(queue, queue->max_elements + queue->auto_extent)) + if (resize_queue(queue, queue->max_elements + queue->auto_extent)) return 1; } @@ -248,40 +249,48 @@ int queue_insert_safe(register QUEUE *qu } - /* Remove item from queue */ - /* Returns pointer to removed element */ +/* + Remove item from queue + + SYNOPSIS + queue_remove() + queue Queue to use + element Index of element to remove. + First element in queue is 'queue_first_element(queue)' + + RETURN + pointer to removed element +*/ uchar *queue_remove(register QUEUE *queue, uint idx) { uchar *element; - DBUG_ASSERT(idx < queue->max_elements); - element= queue->root[++idx]; /* Intern index starts from 1 */ - queue->root[idx]= queue->root[queue->elements--]; - _downheap(queue, idx); + DBUG_ASSERT(idx >= 1 && idx <= queue->elements); + element= queue->root[idx]; + _downheap(queue, idx, queue->root[queue->elements--]); return element; } - /* Fix when element on top has been replaced */ -#ifndef queue_replaced -void queue_replaced(QUEUE *queue) -{ - _downheap(queue,1); -} -#endif +/* + Add element to fixed position and update heap -#ifndef OLD_VERSION + SYNOPSIS + _downheap() + queue Queue to use + idx Index of element to change + element Element to store at 'idx' +*/ -void _downheap(register QUEUE *queue, uint idx) +void _downheap(register QUEUE *queue, uint start_idx, uchar *element) { - uchar *element; - uint elements,half_queue,offset_to_key, next_index; + uint elements,half_queue,offset_to_key, next_index, offset_to_queue_pos; + register uint idx= start_idx; my_bool first= TRUE; - uint start_idx= idx; offset_to_key=queue->offset_to_key; - element=queue->root[idx]; - half_queue=(elements=queue->elements) >> 1; + offset_to_queue_pos= queue->offset_to_queue_pos; + half_queue= (elements= queue->elements) >> 1; while (idx <= half_queue) { @@ -298,393 +307,49 @@ void _downheap(register QUEUE *queue, ui element+offset_to_key) * queue->max_at_top) >= 0))) { queue->root[idx]= element; + if (offset_to_queue_pos) + (*(uint*) (element + offset_to_queue_pos-1))= idx; return; } - queue->root[idx]=queue->root[next_index]; - idx=next_index; first= FALSE; - } - - next_index= idx >> 1; - while (next_index > start_idx) - { - if ((queue->compare(queue->first_cmp_arg, - queue->root[next_index]+offset_to_key, - element+offset_to_key) * - queue->max_at_top) < 0) - break; - queue->root[idx]=queue->root[next_index]; + queue->root[idx]= queue->root[next_index]; + if (offset_to_queue_pos) + (*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx; idx=next_index; - next_index= idx >> 1; } - queue->root[idx]=element; -} -#else /* - The old _downheap version is kept for comparisons with the benchmark - suit or new benchmarks anyone wants to run for comparisons. + Insert the element into the right position. This is the same code + as we have in queue_insert() */ - /* Fix heap when index have changed */ -void _downheap(register QUEUE *queue, uint idx) -{ - uchar *element; - uint elements,half_queue,next_index,offset_to_key; - - offset_to_key=queue->offset_to_key; - element=queue->root[idx]; - half_queue=(elements=queue->elements) >> 1; - - while (idx <= half_queue) - { - next_index=idx+idx; - if (next_index < elements && - (queue->compare(queue->first_cmp_arg, - queue->root[next_index]+offset_to_key, - queue->root[next_index+1]+offset_to_key) * - queue->max_at_top) > 0) - next_index++; - if ((queue->compare(queue->first_cmp_arg, - queue->root[next_index]+offset_to_key, - element+offset_to_key) * queue->max_at_top) >= 0) - break; - queue->root[idx]=queue->root[next_index]; - idx=next_index; + while ((next_index= (idx >> 1)) > start_idx && + queue->compare(queue->first_cmp_arg, + element+offset_to_key, + queue->root[next_index]+offset_to_key)* + queue->max_at_top < 0) + { + queue->root[idx]= queue->root[next_index]; + if (offset_to_queue_pos) + (*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx; + idx= next_index; } - queue->root[idx]=element; + queue->root[idx]= element; + if (offset_to_queue_pos) + (*(uint*) (element + offset_to_queue_pos-1))= idx; } -#endif - /* Fix heap when every element was changed. + + SYNOPSIS + queue_fix() + queue Queue to use */ void queue_fix(QUEUE *queue) { uint i; for (i= queue->elements >> 1; i > 0; i--) - _downheap(queue, i); -} - -#ifdef MAIN - /* - A test program for the priority queue implementation. - It can also be used to benchmark changes of the implementation - Build by doing the following in the directory mysys - make test_priority_queue - ./test_priority_queue - - Written by Mikael Ronström, 2005 - */ - -static uint num_array[1025]; -static uint tot_no_parts= 0; -static uint tot_no_loops= 0; -static uint expected_part= 0; -static uint expected_num= 0; -static bool max_ind= 0; -static bool fix_used= 0; -static ulonglong start_time= 0; - -static bool is_divisible_by(uint num, uint divisor) -{ - uint quotient= num / divisor; - if (quotient * divisor == num) - return TRUE; - return FALSE; -} - -void calculate_next() -{ - uint part= expected_part, num= expected_num; - uint no_parts= tot_no_parts; - if (max_ind) - { - do - { - while (++part <= no_parts) - { - if (is_divisible_by(num, part) && - (num <= ((1 << 21) + part))) - { - expected_part= part; - expected_num= num; - return; - } - } - part= 0; - } while (--num); - } - else - { - do - { - while (--part > 0) - { - if (is_divisible_by(num, part)) - { - expected_part= part; - expected_num= num; - return; - } - } - part= no_parts + 1; - } while (++num); - } -} - -void calculate_end_next(uint part) -{ - uint no_parts= tot_no_parts, num; - num_array[part]= 0; - if (max_ind) - { - expected_num= 0; - for (part= no_parts; part > 0 ; part--) - { - if (num_array[part]) - { - num= num_array[part] & 0x3FFFFF; - if (num >= expected_num) - { - expected_num= num; - expected_part= part; - } - } - } - if (expected_num == 0) - expected_part= 0; - } - else - { - expected_num= 0xFFFFFFFF; - for (part= 1; part <= no_parts; part++) - { - if (num_array[part]) - { - num= num_array[part] & 0x3FFFFF; - if (num <= expected_num) - { - expected_num= num; - expected_part= part; - } - } - } - if (expected_num == 0xFFFFFFFF) - expected_part= 0; - } - return; -} -static int test_compare(void *null_arg, uchar *a, uchar *b) -{ - uint a_num= (*(uint*)a) & 0x3FFFFF; - uint b_num= (*(uint*)b) & 0x3FFFFF; - uint a_part, b_part; - if (a_num > b_num) - return +1; - if (a_num < b_num) - return -1; - a_part= (*(uint*)a) >> 22; - b_part= (*(uint*)b) >> 22; - if (a_part < b_part) - return +1; - if (a_part > b_part) - return -1; - return 0; -} - -bool check_num(uint num_part) -{ - uint part= num_part >> 22; - uint num= num_part & 0x3FFFFF; - if (part == expected_part) - if (num == expected_num) - return FALSE; - printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n", - expected_part, expected_num, part, num, max_ind, fix_used); - return TRUE; -} - - -void perform_insert(QUEUE *queue) -{ - uint i= 1, no_parts= tot_no_parts; - uint backward_start= 0; - - expected_part= 1; - expected_num= 1; - - if (max_ind) - backward_start= 1 << 21; - - do - { - uint num= (i + backward_start); - if (max_ind) - { - while (!is_divisible_by(num, i)) - num--; - if (max_ind && (num > expected_num || - (num == expected_num && i < expected_part))) - { - expected_num= num; - expected_part= i; - } - } - num_array[i]= num + (i << 22); - if (fix_used) - queue_element(queue, i-1)= (uchar*)&num_array[i]; - else - queue_insert(queue, (uchar*)&num_array[i]); - } while (++i <= no_parts); - if (fix_used) - { - queue->elements= no_parts; - queue_fix(queue); - } -} - -bool perform_ins_del(QUEUE *queue, bool max_ind) -{ - uint i= 0, no_loops= tot_no_loops, j= tot_no_parts; - do - { - uint num_part= *(uint*)queue_top(queue); - uint part= num_part >> 22; - if (check_num(num_part)) - return TRUE; - if (j++ >= no_loops) - { - calculate_end_next(part); - queue_remove(queue, (uint) 0); - } - else - { - calculate_next(); - if (max_ind) - num_array[part]-= part; - else - num_array[part]+= part; - queue_top(queue)= (uchar*)&num_array[part]; - queue_replaced(queue); - } - } while (++i < no_loops); - return FALSE; -} - -bool do_test(uint no_parts, uint l_max_ind, bool l_fix_used) -{ - QUEUE queue; - bool result; - max_ind= l_max_ind; - fix_used= l_fix_used; - init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL); - tot_no_parts= no_parts; - tot_no_loops= 1024; - perform_insert(&queue); - if ((result= perform_ins_del(&queue, max_ind))) - delete_queue(&queue); - if (result) - { - printf("Error\n"); - return TRUE; - } - return FALSE; -} - -static void start_measurement() -{ - start_time= my_getsystime(); -} - -static void stop_measurement() -{ - ulonglong stop_time= my_getsystime(); - uint time_in_micros; - stop_time-= start_time; - stop_time/= 10; /* Convert to microseconds */ - time_in_micros= (uint)stop_time; - printf("Time expired is %u microseconds \n", time_in_micros); -} - -static void benchmark_test() -{ - QUEUE queue_real; - QUEUE *queue= &queue_real; - uint i, add; - fix_used= TRUE; - max_ind= FALSE; - tot_no_parts= 1024; - init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL); - /* - First benchmark whether queue_fix is faster than using queue_insert - for sizes of 16 partitions. - */ - for (tot_no_parts= 2, add=2; tot_no_parts < 128; - tot_no_parts+= add, add++) - { - printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts); - start_measurement(); - for (i= 0; i < 128; i++) - { - perform_insert(queue); - queue_remove_all(queue); - } - stop_measurement(); - - fix_used= FALSE; - printf("Start benchmark queue_insert\n"); - start_measurement(); - for (i= 0; i < 128; i++) - { - perform_insert(queue); - queue_remove_all(queue); - } - stop_measurement(); - } - /* - Now benchmark insertion and deletion of 16400 elements. - Used in consecutive runs this shows whether the optimised _downheap - is faster than the standard implementation. - */ - printf("Start benchmarking _downheap \n"); - start_measurement(); - perform_insert(queue); - for (i= 0; i < 65536; i++) - { - uint num, part; - num= *(uint*)queue_top(queue); - num+= 16; - part= num >> 22; - num_array[part]= num; - queue_top(queue)= (uchar*)&num_array[part]; - queue_replaced(queue); - } - for (i= 0; i < 16; i++) - queue_remove(queue, (uint) 0); - queue_remove_all(queue); - stop_measurement(); -} - -int main() -{ - int i, add= 1; - for (i= 1; i < 1024; i+=add, add++) - { - printf("Start test for priority queue of size %u\n", i); - if (do_test(i, 0, 1)) - return -1; - if (do_test(i, 1, 1)) - return -1; - if (do_test(i, 0, 0)) - return -1; - if (do_test(i, 1, 0)) - return -1; - } - benchmark_test(); - printf("OK\n"); - return 0; + _downheap(queue, i, queue_element(queue, i)); } -#endif === modified file 'mysys/thr_alarm.c' --- a/mysys/thr_alarm.c 2008-10-10 15:28:41 +0000 +++ b/mysys/thr_alarm.c 2010-07-16 07:33:01 +0000 @@ -41,6 +41,19 @@ volatile my_bool alarm_thread_running= 0 time_t next_alarm_expire_time= ~ (time_t) 0; static sig_handler process_alarm_part2(int sig); +#ifdef DBUG_OFF +#define reset_index_in_queue(alarm_data) +#else +#define reset_index_in_queue(alarm_data) alarm_data->index_in_queue= 0; +#endif /* DBUG_OFF */ + +#ifndef USE_ONE_SIGNAL_HAND +#define one_signal_hand_sigmask(A,B,C) pthread_sigmask((A), (B), (C)) +#else +#define one_signal_hand_sigmask(A,B,C) +#endif + + #if !defined(__WIN__) static pthread_mutex_t LOCK_alarm; @@ -72,8 +85,8 @@ void init_thr_alarm(uint max_alarms) DBUG_ENTER("init_thr_alarm"); alarm_aborted=0; next_alarm_expire_time= ~ (time_t) 0; - init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, - compare_ulong,NullS); + init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0, + compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1, 0); sigfillset(&full_signal_set); /* Neaded to block signals */ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_alarm,NULL); @@ -151,7 +164,7 @@ void resize_thr_alarm(uint max_alarms) my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) { - time_t now; + time_t now, next; #ifndef USE_ONE_SIGNAL_HAND sigset_t old_mask; #endif @@ -161,79 +174,68 @@ my_bool thr_alarm(thr_alarm_t *alrm, uin DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); now= my_time(0); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); -#endif + if (!alarm_data) + { + if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) + goto abort_no_unlock; + alarm_data->malloced= 1; + } + else + alarm_data->malloced= 0; + next= now + sec; + alarm_data->expire_time= next; + alarm_data->alarmed= 0; + alarm_data->thread= current_my_thread_var->pthread_self; + alarm_data->thread_id= current_my_thread_var->id; + + one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ - if (alarm_aborted > 0) + if (unlikely(alarm_aborted)) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); - *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); - } - if (alarm_aborted < 0) + if (alarm_aborted > 0) + goto abort; sec= 1; /* Abort mode */ - + } if (alarm_queue.elements >= max_used_alarms) { if (alarm_queue.elements == alarm_queue.max_elements) { DBUG_PRINT("info", ("alarm queue full")); fprintf(stderr,"Warning: thr_alarm queue is full\n"); - *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); + goto abort; } max_used_alarms=alarm_queue.elements+1; } - reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec; - if (!alarm_data) - { - if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) - { - DBUG_PRINT("info", ("failed my_malloc()")); - *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); - } - alarm_data->malloced=1; - } - else - alarm_data->malloced=0; - alarm_data->expire_time=now+sec; - alarm_data->alarmed=0; - alarm_data->thread= current_my_thread_var->pthread_self; - alarm_data->thread_id= current_my_thread_var->id; + reschedule= (ulong) next_alarm_expire_time > (ulong) next; queue_insert(&alarm_queue,(uchar*) alarm_data); + assert(alarm_data->index_in_queue > 0); /* Reschedule alarm if the current one has more than sec left */ - if (reschedule) + if (unlikely(reschedule)) { DBUG_PRINT("info", ("reschedule")); if (pthread_equal(pthread_self(),alarm_thread)) { alarm(sec); /* purecov: inspected */ - next_alarm_expire_time= now + sec; + next_alarm_expire_time= next; } else reschedule_alarms(); /* Reschedule alarms */ } pthread_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif + one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); (*alrm)= &alarm_data->alarmed; DBUG_RETURN(0); + +abort: + if (alarm_data->malloced) + my_free(alarm_data, MYF(0)); + pthread_mutex_unlock(&LOCK_alarm); + one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); +abort_no_unlock: + *alrm= 0; /* No alarm */ + DBUG_RETURN(1); } @@ -247,41 +249,18 @@ void thr_end_alarm(thr_alarm_t *alarmed) #ifndef USE_ONE_SIGNAL_HAND sigset_t old_mask; #endif - uint i, found=0; DBUG_ENTER("thr_end_alarm"); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); -#endif - pthread_mutex_lock(&LOCK_alarm); - + one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); - for (i=0 ; i < alarm_queue.elements ; i++) - { - if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data) - { - queue_remove(&alarm_queue,i),MYF(0); - if (alarm_data->malloced) - my_free((uchar*) alarm_data,MYF(0)); - found++; -#ifdef DBUG_OFF - break; -#endif - } - } - DBUG_ASSERT(!*alarmed || found == 1); - if (!found) - { - if (*alarmed) - fprintf(stderr,"Warning: Didn't find alarm 0x%lx in queue of %d alarms\n", - (long) *alarmed, alarm_queue.elements); - DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n", - (long) *alarmed)); - } + pthread_mutex_lock(&LOCK_alarm); + DBUG_ASSERT(alarm_data->index_in_queue != 0); + DBUG_ASSERT(queue_element(&alarm_queue, alarm_data->index_in_queue) == + alarm_data); + queue_remove(&alarm_queue, alarm_data->index_in_queue); pthread_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif + one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); + reset_index_in_queue(alarm_data); DBUG_VOID_RETURN; } @@ -344,12 +323,13 @@ static sig_handler process_alarm_part2(i #if defined(MAIN) && !defined(__bsdi__) printf("process_alarm\n"); fflush(stdout); #endif - if (alarm_queue.elements) + if (likely(alarm_queue.elements)) { - if (alarm_aborted) + if (unlikely(alarm_aborted)) { uint i; - for (i=0 ; i < alarm_queue.elements ;) + for (i= queue_first_element(&alarm_queue) ; + i <= queue_last_element(&alarm_queue) ;) { alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data->alarmed=1; /* Info to thread */ @@ -360,6 +340,7 @@ static sig_handler process_alarm_part2(i printf("Warning: pthread_kill couldn't find thread!!!\n"); #endif queue_remove(&alarm_queue,i); /* No thread. Remove alarm */ + reset_index_in_queue(alarm_data); } else i++; /* Signal next thread */ @@ -371,8 +352,8 @@ static sig_handler process_alarm_part2(i } else { - ulong now=(ulong) my_time(0); - ulong next=now+10-(now%10); + time_t now= my_time(0); + time_t next= now+10-(now%10); while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) { alarm_data->alarmed=1; /* Info to thread */ @@ -382,15 +363,16 @@ static sig_handler process_alarm_part2(i { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); -#endif - queue_remove(&alarm_queue,0); /* No thread. Remove alarm */ +#endif /* MAIN */ + queue_remove_top(&alarm_queue); /* No thread. Remove alarm */ + reset_index_in_queue(alarm_data); if (!alarm_queue.elements) break; } else { alarm_data->expire_time=next; - queue_replaced(&alarm_queue); + queue_replace_top(&alarm_queue); } } #ifndef USE_ALARM_THREAD @@ -486,13 +468,15 @@ void thr_alarm_kill(my_thread_id thread_ if (alarm_aborted) return; pthread_mutex_lock(&LOCK_alarm); - for (i=0 ; i < alarm_queue.elements ; i++) + for (i= queue_first_element(&alarm_queue) ; + i <= queue_last_element(&alarm_queue); + i++) { - if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id) + ALARM *element= (ALARM*) queue_element(&alarm_queue,i); + if (element->thread_id == thread_id) { - ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); - tmp->expire_time=0; - queue_insert(&alarm_queue,(uchar*) tmp); + element->expire_time= 0; + queue_replace(&alarm_queue, i); reschedule_alarms(); break; } @@ -508,7 +492,7 @@ void thr_alarm_info(ALARM_INFO *info) info->max_used_alarms= max_used_alarms; if ((info->active_alarms= alarm_queue.elements)) { - ulong now=(ulong) my_time(0); + time_t now= my_time(0); long time_diff; ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); time_diff= (long) (alarm_data->expire_time - now); @@ -556,7 +540,7 @@ static void *alarm_handler(void *arg __a { if (alarm_queue.elements) { - ulong sleep_time,now= my_time(0); + time_t sleep_time,now= my_time(0); if (alarm_aborted) sleep_time=now+1; else @@ -792,20 +776,6 @@ static void *test_thread(void *arg) return 0; } -#ifdef USE_ONE_SIGNAL_HAND -static sig_handler print_signal_warning(int sig) -{ - printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); - fflush(stdout); -#ifdef DONT_REMEMBER_SIGNAL - my_sigset(sig,print_signal_warning); /* int. thread system calls */ -#endif - if (sig == SIGALRM) - alarm(2); /* reschedule alarm */ -} -#endif /* USE_ONE_SIGNAL_HAND */ - - static void *signal_hand(void *arg __attribute__((unused))) { sigset_t set; === modified file 'sql/create_options.cc' --- a/sql/create_options.cc 2010-05-12 17:56:05 +0000 +++ b/sql/create_options.cc 2010-07-16 07:33:01 +0000 @@ -583,9 +583,9 @@ my_bool engine_table_options_frm_read(co } if (buff < buff_end) - sql_print_warning("Table %`s was created in a later MariaDB version - " + sql_print_warning("Table '%s' was created in a later MariaDB version - " "unknown table attributes were ignored", - share->table_name); + share->table_name.str); DBUG_RETURN(buff > buff_end); } === modified file 'sql/event_queue.cc' --- a/sql/event_queue.cc 2008-12-02 22:02:52 +0000 +++ b/sql/event_queue.cc 2010-07-16 07:33:01 +0000 @@ -136,9 +136,9 @@ Event_queue::init_queue(THD *thd) LOCK_QUEUE_DATA(); - if (init_queue_ex(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/, - 0 /*max_on_top*/, event_queue_element_compare_q, - NULL, EVENT_QUEUE_EXTENT)) + if (::init_queue(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/, + 0 /*max_on_top*/, event_queue_element_compare_q, + NullS, 0, EVENT_QUEUE_EXTENT)) { sql_print_error("Event Scheduler: Can't initialize the execution queue"); goto err; @@ -325,11 +325,13 @@ void Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern, bool (*comparator)(LEX_STRING, Event_basic *)) { - uint i= 0; + uint i; DBUG_ENTER("Event_queue::drop_matching_events"); DBUG_PRINT("enter", ("pattern=%s", pattern.str)); - while (i < queue.elements) + for (i= queue_first_element(&queue) ; + i <= queue_last_element(&queue) ; + ) { Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str)); @@ -339,7 +341,8 @@ Event_queue::drop_matching_events(THD *t The queue is ordered. If we remove an element, then all elements after it will shift one position to the left, if we imagine it as an array from left to the right. In this case we should not - increment the counter and the (i < queue.elements) condition is ok. + increment the counter and the (i <= queue_last_element() condition + is ok. */ queue_remove(&queue, i); delete et; @@ -403,7 +406,9 @@ Event_queue::find_n_remove_event(LEX_STR uint i; DBUG_ENTER("Event_queue::find_n_remove_event"); - for (i= 0; i < queue.elements; ++i) + for (i= queue_first_element(&queue); + i <= queue_last_element(&queue); + i++) { Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str, @@ -441,7 +446,9 @@ Event_queue::recalculate_activation_time LOCK_QUEUE_DATA(); DBUG_PRINT("info", ("%u loaded events to be recalculated", queue.elements)); - for (i= 0; i < queue.elements; i++) + for (i= queue_first_element(&queue); + i <= queue_last_element(&queue); + i++) { ((Event_queue_element*)queue_element(&queue, i))->compute_next_execution_time(); ((Event_queue_element*)queue_element(&queue, i))->update_timing_fields(thd); @@ -454,16 +461,19 @@ Event_queue::recalculate_activation_time have removed all. The queue has been ordered in a way the disabled events are at the end. */ - for (i= queue.elements; i > 0; i--) + for (i= queue_last_element(&queue); + (int) i >= (int) queue_first_element(&queue); + i--) { - Event_queue_element *element = (Event_queue_element*)queue_element(&queue, i - 1); + Event_queue_element *element= + (Event_queue_element*)queue_element(&queue, i); if (element->status != Event_parse_data::DISABLED) break; /* This won't cause queue re-order, because we remove always the last element. */ - queue_remove(&queue, i - 1); + queue_remove(&queue, i); delete element; } UNLOCK_QUEUE_DATA(); @@ -499,7 +509,9 @@ Event_queue::empty_queue() sql_print_information("Event Scheduler: Purging the queue. %u events", queue.elements); /* empty the queue */ - for (i= 0; i < queue.elements; ++i) + for (i= queue_first_element(&queue); + i <= queue_last_element(&queue); + i++) { Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i); delete et; @@ -525,7 +537,9 @@ Event_queue::dbug_dump_queue(time_t now) uint i; DBUG_ENTER("Event_queue::dbug_dump_queue"); DBUG_PRINT("info", ("Dumping queue . Elements=%u", queue.elements)); - for (i = 0; i < queue.elements; i++) + for (i= queue_first_element(&queue); + i <= queue_last_element(&queue); + i++) { et= ((Event_queue_element*)queue_element(&queue, i)); DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et, @@ -592,7 +606,7 @@ Event_queue::get_top_for_execution_if_ti continue; } - top= ((Event_queue_element*) queue_element(&queue, 0)); + top= (Event_queue_element*) queue_top(&queue); thd->set_current_time(); /* Get current time */ @@ -634,10 +648,10 @@ Event_queue::get_top_for_execution_if_ti top->dbname.str, top->name.str, top->dropped? "Dropping.":""); delete top; - queue_remove(&queue, 0); + queue_remove_top(&queue); } else - queue_replaced(&queue); + queue_replace_top(&queue); dbug_dump_queue(thd->query_start()); break; === modified file 'sql/filesort.cc' --- a/sql/filesort.cc 2010-06-01 19:52:20 +0000 +++ b/sql/filesort.cc 2010-07-16 07:33:01 +0000 @@ -1151,7 +1151,9 @@ uint read_to_buffer(IO_CACHE *fromfile, void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) { uchar *reuse_end= reuse->base + reuse->max_keys * key_length; - for (uint i= 0; i < queue->elements; ++i) + for (uint i= queue_first_element(queue); + i <= queue_last_element(queue); + i++) { BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i); if (bp->base + bp->max_keys * key_length == reuse->base) @@ -1240,7 +1242,7 @@ int merge_buffers(SORTPARAM *param, IO_C first_cmp_arg= (void*) &sort_length; } if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0, - (queue_compare) cmp, first_cmp_arg)) + (queue_compare) cmp, first_cmp_arg, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) { @@ -1277,7 +1279,7 @@ int merge_buffers(SORTPARAM *param, IO_C error= 0; /* purecov: inspected */ goto end; /* purecov: inspected */ } - queue_replaced(&queue); // Top element has been used + queue_replace_top(&queue); // Top element has been used } else cmp= 0; // Not unique @@ -1325,14 +1327,14 @@ int merge_buffers(SORTPARAM *param, IO_C if (!(error= (int) read_to_buffer(from_file,buffpek, rec_length))) { - VOID(queue_remove(&queue,0)); + VOID(queue_remove_top(&queue)); reuse_freed_buff(&queue, buffpek, rec_length); break; /* One buffer have been removed */ } else if (error == -1) goto err; /* purecov: inspected */ } - queue_replaced(&queue); /* Top element has been replaced */ + queue_replace_top(&queue); /* Top element has been replaced */ } } buffpek= (BUFFPEK*) queue_top(&queue); === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2010-06-05 14:53:36 +0000 +++ b/sql/ha_partition.cc 2010-07-16 07:33:01 +0000 @@ -2567,7 +2567,7 @@ int ha_partition::open(const char *name, Initialize priority queue, initialized to reading forward. */ if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS, - 0, key_rec_cmp, (void*)this))) + 0, key_rec_cmp, (void*)this, 0, 0))) goto err_handler; /* @@ -4622,7 +4622,7 @@ int ha_partition::handle_unordered_scan_ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) { uint i; - uint j= 0; + uint j= queue_first_element(&m_queue); bool found= FALSE; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); @@ -4716,7 +4716,7 @@ int ha_partition::handle_ordered_index_s */ queue_set_max_at_top(&m_queue, reverse_order); queue_set_cmp_arg(&m_queue, (void*)m_curr_key_info); - m_queue.elements= j; + m_queue.elements= j - queue_first_element(&m_queue); queue_fix(&m_queue); return_top_record(buf); table->status= 0; @@ -4787,7 +4787,7 @@ int ha_partition::handle_ordered_next(uc if (error == HA_ERR_END_OF_FILE) { /* Return next buffered row */ - queue_remove(&m_queue, (uint) 0); + queue_remove_top(&m_queue); if (m_queue.elements) { DBUG_PRINT("info", ("Record returned from partition %u (2)", @@ -4799,7 +4799,7 @@ int ha_partition::handle_ordered_next(uc } DBUG_RETURN(error); } - queue_replaced(&m_queue); + queue_replace_top(&m_queue); return_top_record(buf); DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry)); DBUG_RETURN(0); @@ -4830,7 +4830,7 @@ int ha_partition::handle_ordered_prev(uc { if (error == HA_ERR_END_OF_FILE) { - queue_remove(&m_queue, (uint) 0); + queue_remove_top(&m_queue); if (m_queue.elements) { return_top_record(buf); @@ -4842,7 +4842,7 @@ int ha_partition::handle_ordered_prev(uc } DBUG_RETURN(error); } - queue_replaced(&m_queue); + queue_replace_top(&m_queue); return_top_record(buf); DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry)); DBUG_RETURN(0); === modified file 'sql/ha_partition.h' --- a/sql/ha_partition.h 2010-06-05 14:53:36 +0000 +++ b/sql/ha_partition.h 2010-07-16 07:33:01 +0000 @@ -1129,7 +1129,7 @@ public: virtual handlerton *partition_ht() const { handlerton *h= m_file[0]->ht; - for (int i=1; i < m_tot_parts; i++) + for (uint i=1; i < m_tot_parts; i++) DBUG_ASSERT(h == m_file[i]->ht); return h; } === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2010-07-10 10:37:30 +0000 +++ b/sql/item_cmpfunc.cc 2010-07-16 07:33:01 +0000 @@ -1778,10 +1778,12 @@ Item *Item_in_optimizer::expr_cache_inse if (args[0]->cols() == 1) depends_on.push_front((Item**)args); else - for (int i= 0; i < args[0]->cols(); i++) + { + for (uint i= 0; i < args[0]->cols(); i++) { depends_on.push_front(args[0]->addr(i)); } + } if (args[1]->expr_cache_is_needed(thd)) DBUG_RETURN(set_expr_cache(thd, depends_on)); === modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2010-07-16 10:52:02 +0000 +++ b/sql/item_subselect.cc 2010-07-16 12:10:55 +0000 @@ -4880,7 +4880,8 @@ subselect_rowid_merge_engine::init(MY_BI merge_keys[i]->sort_keys(); if (init_queue(&pq, keys_count, 0, FALSE, - subselect_rowid_merge_engine::cmp_keys_by_cur_rownum, NULL)) + subselect_rowid_merge_engine::cmp_keys_by_cur_rownum, NULL, + 0, 0)) return TRUE; return FALSE; === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2010-07-10 10:37:30 +0000 +++ b/sql/mysqld.cc 2010-07-16 08:58:24 +0000 @@ -409,6 +409,12 @@ static const char *optimizer_switch_str= "index_merge_sort_union=on," "index_merge_intersection=on," "index_condition_pushdown=on," + "firstmatch=on," + "loosescan=on," + "materialization=on," + "semijoin=on," + "partial_match_rowid_merge=on," + "partial_match_table_scan=on," "subquery_cache=on" #ifndef DBUG_OFF ",table_elimination=on"; @@ -7227,7 +7233,9 @@ The minimum value for this variable is 4 {"optimizer_switch", OPT_OPTIMIZER_SWITCH, "optimizer_switch=option=val[,option=val...], where option={index_merge, " "index_merge_union, index_merge_sort_union, index_merge_intersection, " - "index_condition_pushdown, subquery_cache" + "index_condition_pushdown, firstmatch, loosescan, materialization, " + "semijoin, partial_match_rowid_merge, partial_match_table_scan, " + "subquery_cache" #ifndef DBUG_OFF ", table_elimination" #endif === modified file 'sql/net_serv.cc' --- a/sql/net_serv.cc 2010-05-26 18:55:40 +0000 +++ b/sql/net_serv.cc 2010-07-16 07:33:01 +0000 @@ -262,18 +262,20 @@ static int net_data_is_ready(my_socket s #endif /* EMBEDDED_LIBRARY */ /** - Remove unwanted characters from connection - and check if disconnected. + Intialize NET handler for new reads: - Read from socket until there is nothing more to read. Discard - what is read. - - If there is anything when to read 'net_clear' is called this - normally indicates an error in the protocol. - - When connection is properly closed (for TCP it means with - a FIN packet), then select() considers a socket "ready to read", - in the sense that there's EOF to read, but read() returns 0. + - Read from socket until there is nothing more to read. Discard + what is read. + - Initialize net for new net_read/net_write calls. + + If there is anything when to read 'net_clear' is called this + normally indicates an error in the protocol. Normally one should not + need to do clear the communication buffer. If one compiles without + -DUSE_NET_CLEAR then one wins one read call / query. + + When connection is properly closed (for TCP it means with + a FIN packet), then select() considers a socket "ready to read", + in the sense that there's EOF to read, but read() returns 0. @param net NET handler @param clear_buffer if <> 0, then clear all data from comm buff @@ -281,20 +283,18 @@ static int net_data_is_ready(my_socket s void net_clear(NET *net, my_bool clear_buffer __attribute__((unused))) { -#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF) - size_t count; - int ready; -#endif DBUG_ENTER("net_clear"); /* - We don't do a clear in case of DBUG_OFF to catch bugs - in the protocol handling + We don't do a clear in case of not DBUG_OFF to catch bugs in the + protocol handling. */ -#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF) +#if (!defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)) || defined(USE_NET_CLEAR) if (clear_buffer) { + size_t count; + int ready; while ((ready= net_data_is_ready(net->vio->sd)) > 0) { /* The socket is ready */ === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2010-07-10 10:37:30 +0000 +++ b/sql/opt_range.cc 2010-07-16 07:33:01 +0000 @@ -1155,10 +1155,7 @@ QUICK_SELECT_I::QUICK_SELECT_I() QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc, MEM_ROOT *parent_alloc, bool *create_error) - :dont_free(0),doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0) - //psergey3-merge: check whether we need doing_key_read and last_range - // was: - // :free_file(0),cur_range(NULL),last_range(0),dont_free(0) + :doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0),dont_free(0) { my_bitmap_map *bitmap; DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT"); @@ -1594,7 +1591,7 @@ int QUICK_ROR_UNION_SELECT::init() DBUG_ENTER("QUICK_ROR_UNION_SELECT::init"); if (init_queue(&queue, quick_selects.elements, 0, FALSE , QUICK_ROR_UNION_SELECT::queue_cmp, - (void*) this)) + (void*) this, 0, 0)) { bzero(&queue, sizeof(QUEUE)); DBUG_RETURN(1); @@ -8293,12 +8290,12 @@ int QUICK_ROR_UNION_SELECT::get_next() { if (error != HA_ERR_END_OF_FILE) DBUG_RETURN(error); - queue_remove(&queue, 0); + queue_remove_top(&queue); } else { quick->save_last_pos(); - queue_replaced(&queue); + queue_replace_top(&queue); } if (!have_prev_rowid) === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-07-16 10:52:02 +0000 +++ b/sql/sql_class.cc 2010-07-16 12:10:55 +0000 @@ -2994,14 +2994,28 @@ create_result_table(THD *thd_arg, List<I if (!stat) return TRUE; - cleanup(); - + reset(); table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); return FALSE; } +void select_materialize_with_stats::reset() +{ + memset(col_stat, 0, table->s->fields * sizeof(Column_statistics)); + max_nulls_in_row= 0; + count_rows= 0; +} + + +void select_materialize_with_stats::cleanup() +{ + reset(); + select_union::cleanup(); +} + + /** Override select_union::send_data to analyze each row for NULLs and to update null_statistics before sending data to the client. === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-07-16 10:52:02 +0000 +++ b/sql/sql_class.h 2010-07-16 12:10:55 +0000 @@ -2907,11 +2907,11 @@ public: bool send_data(List<Item> &items); bool send_eof(); bool flush(); - TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; } - + void cleanup(); virtual bool create_result_table(THD *thd, List<Item> *column_types, bool is_distinct, ulonglong options, const char *alias, bool bit_fields_as_long); + TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; } }; /* Base subselect interface class */ @@ -2971,6 +2971,9 @@ protected: */ ha_rows count_rows; +protected: + void reset(); + public: select_materialize_with_stats() { tmp_table_param.init(); } virtual bool create_result_table(THD *thd, List<Item> *column_types, @@ -2978,12 +2981,7 @@ public: const char *alias, bool bit_fields_as_long); bool init_result_table(ulonglong select_options); bool send_data(List<Item> &items); - void cleanup() - { - memset(col_stat, 0, table->s->fields * sizeof(Column_statistics)); - max_nulls_in_row= 0; - count_rows= 0; - } + void cleanup(); ha_rows get_null_count_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); === modified file 'sql/sql_union.cc' --- a/sql/sql_union.cc 2010-07-10 10:37:30 +0000 +++ b/sql/sql_union.cc 2010-07-16 11:02:15 +0000 @@ -136,6 +136,22 @@ select_union::create_result_table(THD *t } +/** + Reset and empty the temporary table that stores the materialized query result. + + @note The cleanup performed here is exactly the same as for the two temp + tables of JOIN - exec_tmp_table_[1 | 2]. +*/ + +void select_union::cleanup() +{ + table->file->extra(HA_EXTRA_RESET_STATE); + table->file->ha_delete_all_rows(); + free_io_cache(table); + filesort_free_buffers(table,0); +} + + /* initialization procedures before fake_select_lex preparation() === modified file 'sql/uniques.cc' --- a/sql/uniques.cc 2009-09-07 20:50:10 +0000 +++ b/sql/uniques.cc 2010-07-16 07:33:01 +0000 @@ -423,7 +423,7 @@ static bool merge_walk(uchar *merge_buff if (end <= begin || merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0, - buffpek_compare, &compare_context)) + buffpek_compare, &compare_context, 0, 0)) return 1; /* we need space for one key when a piece of merge buffer is re-read */ merge_buffer_size-= key_length; @@ -468,7 +468,7 @@ static bool merge_walk(uchar *merge_buff */ top->key+= key_length; if (--top->mem_count) - queue_replaced(&queue); + queue_replace_top(&queue); else /* next piece should be read */ { /* save old_key not to overwrite it in read_to_buffer */ @@ -478,14 +478,14 @@ static bool merge_walk(uchar *merge_buff if (bytes_read == (uint) (-1)) goto end; else if (bytes_read > 0) /* top->key, top->mem_count are reset */ - queue_replaced(&queue); /* in read_to_buffer */ + queue_replace_top(&queue); /* in read_to_buffer */ else { /* Tree for old 'top' element is empty: remove it from the queue and give all its memory to the nearest tree. */ - queue_remove(&queue, 0); + queue_remove_top(&queue); reuse_freed_buff(&queue, top, key_length); } } === modified file 'storage/maria/ma_ft_boolean_search.c' --- a/storage/maria/ma_ft_boolean_search.c 2010-01-06 19:20:16 +0000 +++ b/storage/maria/ma_ft_boolean_search.c 2010-07-16 07:33:01 +0000 @@ -473,14 +473,15 @@ static void _ftb_init_index_search(FT_IN int i; FTB_WORD *ftbw; - if ((ftb->state != READY && ftb->state !=INDEX_DONE) || - ftb->keynr == NO_SUCH_KEY) + if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY) return; ftb->state=INDEX_SEARCH; - for (i=ftb->queue.elements; i; i--) + for (i= queue_last_element(&ftb->queue); + (int) i >= (int) queue_first_element(&ftb->queue); + i--) { - ftbw=(FTB_WORD *)(ftb->queue.root[i]); + ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i)); if (ftbw->flags & FTB_FLAG_TRUNC) { @@ -585,7 +586,7 @@ FT_INFO * maria_ft_init_boolean_search(M sizeof(void *)))) goto err; reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0, - (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0); + (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0); for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev) queue_insert(&ftb->queue, (uchar *)ftbw); ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, @@ -828,7 +829,7 @@ int maria_ft_boolean_read_next(FT_INFO * /* update queue */ _ft2_search(ftb, ftbw, 0); - queue_replaced(& ftb->queue); + queue_replace_top(&ftb->queue); } ftbe=ftb->root; === modified file 'storage/maria/ma_ft_nlq_search.c' --- a/storage/maria/ma_ft_nlq_search.c 2009-11-30 13:36:06 +0000 +++ b/storage/maria/ma_ft_nlq_search.c 2010-07-16 07:33:01 +0000 @@ -253,12 +253,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_ { QUEUE best; init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp, - 0); + 0, 0, 0); tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push, &best, left_root_right); while (best.elements) { - my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; + my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos; if (!(*info->read_record)(info, record, docid)) { info->update|= HA_STATE_AKTIV; === modified file 'storage/maria/ma_sort.c' --- a/storage/maria/ma_sort.c 2009-11-29 23:08:56 +0000 +++ b/storage/maria/ma_sort.c 2010-07-16 07:33:01 +0000 @@ -933,7 +933,7 @@ merge_buffers(MARIA_SORT_PARAM *info, ui if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, (int (*)(void*, uchar *,uchar*)) info->key_cmp, - (void*) info)) + (void*) info, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) @@ -982,7 +982,7 @@ merge_buffers(MARIA_SORT_PARAM *info, ui uchar *base= buffpek->base; uint max_keys=buffpek->max_keys; - VOID(queue_remove(&queue,0)); + VOID(queue_remove_top(&queue)); /* Put room used by buffer to use in other buffer */ for (refpek= (BUFFPEK**) &queue_top(&queue); @@ -1007,7 +1007,7 @@ merge_buffers(MARIA_SORT_PARAM *info, ui } else if (error == -1) goto err; /* purecov: inspected */ - queue_replaced(&queue); /* Top element has been replaced */ + queue_replace_top(&queue); /* Top element has been replaced */ } } buffpek=(BUFFPEK*) queue_top(&queue); === modified file 'storage/maria/maria_pack.c' --- a/storage/maria/maria_pack.c 2009-02-19 09:01:25 +0000 +++ b/storage/maria/maria_pack.c 2010-07-16 07:33:01 +0000 @@ -590,7 +590,7 @@ static int compress(PACK_MRG_INFO *mrg,c Create a global priority queue in preparation for making temporary Huffman trees. */ - if (init_queue(&queue,256,0,0,compare_huff_elements,0)) + if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0)) goto err; /* @@ -1521,7 +1521,7 @@ static int make_huff_tree(HUFF_TREE *huf if (queue.max_elements < found) { delete_queue(&queue); - if (init_queue(&queue,found,0,0,compare_huff_elements,0)) + if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0)) return -1; } @@ -1625,8 +1625,7 @@ static int make_huff_tree(HUFF_TREE *huf Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=found/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ bytes_packed=0; bits_packed=0; @@ -1637,12 +1636,9 @@ static int make_huff_tree(HUFF_TREE *huf Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b=(HUFF_ELEMENT*) queue.root[1]; + a=(HUFF_ELEMENT*) queue_remove_top(&queue); + /* Copy the next least incidence element */ + b=(HUFF_ELEMENT*) queue_top(&queue); /* Get a new element from the element buffer. */ new_huff_el=huff_tree->element_buffer+found+i; /* The new element gets the sum of the two least incidence elements. */ @@ -1664,8 +1660,8 @@ static int make_huff_tree(HUFF_TREE *huf Replace the copied top element by the new element and re-order the queue. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; @@ -1796,8 +1792,7 @@ static my_off_t calc_packed_length(HUFF_ Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=(found+1)/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ for (i=0 ; i < found-1 ; i++) @@ -1811,12 +1806,9 @@ static my_off_t calc_packed_length(HUFF_ incidence). Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a= (my_off_t*) queue_remove(&queue, 0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b= (my_off_t*) queue.root[1]; + a= (my_off_t*) queue_remove_top(&queue); + /* Copy the next least incidence element. */ + b= (my_off_t*) queue_top(&queue); /* Create a new element in a local (automatic) buffer. */ new_huff_el= element_buffer + i; /* The new element gets the sum of the two least incidence elements. */ @@ -1836,8 +1828,8 @@ static my_off_t calc_packed_length(HUFF_ queue. This successively replaces the references to counts by references to HUFF_ELEMENTs. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } DBUG_RETURN(bytes_packed+(bits_packed+7)/8); } === modified file 'storage/myisam/ft_boolean_search.c' --- a/storage/myisam/ft_boolean_search.c 2010-06-01 19:52:20 +0000 +++ b/storage/myisam/ft_boolean_search.c 2010-07-16 07:33:01 +0000 @@ -482,16 +482,18 @@ static int _ft2_search(FTB *ftb, FTB_WOR static void _ftb_init_index_search(FT_INFO *ftb) { - int i; + uint i; FTB_WORD *ftbw; if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY) return; ftb->state=INDEX_SEARCH; - for (i=ftb->queue.elements; i; i--) + for (i= queue_last_element(&ftb->queue); + (int) i >= (int) queue_first_element(&ftb->queue); + i--) { - ftbw=(FTB_WORD *)(ftb->queue.root[i]); + ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i)); if (ftbw->flags & FTB_FLAG_TRUNC) { @@ -595,12 +597,12 @@ FT_INFO * ft_init_boolean_search(MI_INFO sizeof(void *)))) goto err; reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0, - (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0); + (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0); for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev) queue_insert(&ftb->queue, (uchar *)ftbw); ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, sizeof(FTB_WORD *)*ftb->queue.elements); - memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements); + memcpy(ftb->list, &queue_top(&ftb->queue), sizeof(FTB_WORD *)*ftb->queue.elements); my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), (qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset); if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; @@ -839,7 +841,7 @@ int ft_boolean_read_next(FT_INFO *ftb, c /* update queue */ _ft2_search(ftb, ftbw, 0); - queue_replaced(& ftb->queue); + queue_replace_top(&ftb->queue); } ftbe=ftb->root; === modified file 'storage/myisam/ft_nlq_search.c' --- a/storage/myisam/ft_nlq_search.c 2010-01-27 21:53:08 +0000 +++ b/storage/myisam/ft_nlq_search.c 2010-07-16 07:33:01 +0000 @@ -250,12 +250,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *inf { QUEUE best; init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp, - 0); + 0, 0, 0); tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push, &best, left_root_right); while (best.elements) { - my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; + my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos; if (!(*info->read_record)(info,docid,record)) { info->update|= HA_STATE_AKTIV; === modified file 'storage/myisam/mi_test_all.sh' --- a/storage/myisam/mi_test_all.sh 2007-07-28 11:36:20 +0000 +++ b/storage/myisam/mi_test_all.sh 2010-07-16 07:33:01 +0000 @@ -5,6 +5,7 @@ valgrind="valgrind --alignment=8 --leak-check=yes" silent="-s" +rm -f test1.TMD if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi ./mi_test1$suffix $silent === modified file 'storage/myisam/myisampack.c' --- a/storage/myisam/myisampack.c 2009-02-19 09:01:25 +0000 +++ b/storage/myisam/myisampack.c 2010-07-16 07:33:01 +0000 @@ -576,7 +576,7 @@ static int compress(PACK_MRG_INFO *mrg,c Create a global priority queue in preparation for making temporary Huffman trees. */ - if (init_queue(&queue,256,0,0,compare_huff_elements,0)) + if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0)) goto err; /* @@ -1511,7 +1511,7 @@ static int make_huff_tree(HUFF_TREE *huf if (queue.max_elements < found) { delete_queue(&queue); - if (init_queue(&queue,found,0,0,compare_huff_elements,0)) + if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0)) return -1; } @@ -1615,8 +1615,7 @@ static int make_huff_tree(HUFF_TREE *huf Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=found/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ bytes_packed=0; bits_packed=0; @@ -1627,12 +1626,9 @@ static int make_huff_tree(HUFF_TREE *huf Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b=(HUFF_ELEMENT*) queue.root[1]; + a=(HUFF_ELEMENT*) queue_remove_top(&queue); + /* Copy the next least incidence element */ + b=(HUFF_ELEMENT*) queue_top(&queue); /* Get a new element from the element buffer. */ new_huff_el=huff_tree->element_buffer+found+i; /* The new element gets the sum of the two least incidence elements. */ @@ -1654,8 +1650,8 @@ static int make_huff_tree(HUFF_TREE *huf Replace the copied top element by the new element and re-order the queue. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; @@ -1786,8 +1782,7 @@ static my_off_t calc_packed_length(HUFF_ Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=(found+1)/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ for (i=0 ; i < found-1 ; i++) @@ -1801,12 +1796,9 @@ static my_off_t calc_packed_length(HUFF_ incidence). Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a= (my_off_t*) queue_remove(&queue, 0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b= (my_off_t*) queue.root[1]; + a= (my_off_t*) queue_remove_top(&queue); + /* Copy the next least incidence element. */ + b= (my_off_t*) queue_top(&queue); /* Create a new element in a local (automatic) buffer. */ new_huff_el= element_buffer + i; /* The new element gets the sum of the two least incidence elements. */ @@ -1826,8 +1818,8 @@ static my_off_t calc_packed_length(HUFF_ queue. This successively replaces the references to counts by references to HUFF_ELEMENTs. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } DBUG_RETURN(bytes_packed+(bits_packed+7)/8); } === modified file 'storage/myisam/sort.c' --- a/storage/myisam/sort.c 2010-04-28 12:52:24 +0000 +++ b/storage/myisam/sort.c 2010-07-16 07:33:01 +0000 @@ -920,7 +920,7 @@ merge_buffers(MI_SORT_PARAM *info, uint if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, (int (*)(void*, uchar *,uchar*)) info->key_cmp, - (void*) info)) + (void*) info, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) @@ -969,7 +969,7 @@ merge_buffers(MI_SORT_PARAM *info, uint uchar *base= buffpek->base; uint max_keys=buffpek->max_keys; - VOID(queue_remove(&queue,0)); + VOID(queue_remove_top(&queue)); /* Put room used by buffer to use in other buffer */ for (refpek= (BUFFPEK**) &queue_top(&queue); @@ -994,7 +994,7 @@ merge_buffers(MI_SORT_PARAM *info, uint } else if (error == -1) goto err; /* purecov: inspected */ - queue_replaced(&queue); /* Top element has been replaced */ + queue_replace_top(&queue); /* Top element has been replaced */ } } buffpek=(BUFFPEK*) queue_top(&queue); === modified file 'storage/myisammrg/myrg_queue.c' --- a/storage/myisammrg/myrg_queue.c 2007-05-10 09:59:39 +0000 +++ b/storage/myisammrg/myrg_queue.c 2010-07-16 07:33:01 +0000 @@ -52,7 +52,7 @@ int _myrg_init_queue(MYRG_INFO *info,int if (init_queue(q,info->tables, 0, (myisam_readnext_vec[search_flag] == SEARCH_SMALLER), queue_key_cmp, - info->open_tables->table->s->keyinfo[inx].seg)) + info->open_tables->table->s->keyinfo[inx].seg, 0, 0)) error=my_errno; } else @@ -60,7 +60,7 @@ int _myrg_init_queue(MYRG_INFO *info,int if (reinit_queue(q,info->tables, 0, (myisam_readnext_vec[search_flag] == SEARCH_SMALLER), queue_key_cmp, - info->open_tables->table->s->keyinfo[inx].seg)) + info->open_tables->table->s->keyinfo[inx].seg, 0, 0)) error=my_errno; } } === modified file 'storage/myisammrg/myrg_rnext.c' --- a/storage/myisammrg/myrg_rnext.c 2007-05-10 09:59:39 +0000 +++ b/storage/myisammrg/myrg_rnext.c 2010-07-16 07:33:01 +0000 @@ -32,7 +32,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *b { if (err == HA_ERR_END_OF_FILE) { - queue_remove(&(info->by_key),0); + queue_remove_top(&(info->by_key)); if (!info->by_key.elements) return HA_ERR_END_OF_FILE; } @@ -43,7 +43,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *b { /* Found here, adding to queue */ queue_top(&(info->by_key))=(uchar *)(info->current_table); - queue_replaced(&(info->by_key)); + queue_replace_top(&(info->by_key)); } /* now, mymerge's read_next is as simple as one queue_top */ === modified file 'storage/myisammrg/myrg_rnext_same.c' --- a/storage/myisammrg/myrg_rnext_same.c 2007-05-10 09:59:39 +0000 +++ b/storage/myisammrg/myrg_rnext_same.c 2010-07-16 07:33:01 +0000 @@ -29,7 +29,7 @@ int myrg_rnext_same(MYRG_INFO *info, uch { if (err == HA_ERR_END_OF_FILE) { - queue_remove(&(info->by_key),0); + queue_remove_top(&(info->by_key)); if (!info->by_key.elements) return HA_ERR_END_OF_FILE; } @@ -40,7 +40,7 @@ int myrg_rnext_same(MYRG_INFO *info, uch { /* Found here, adding to queue */ queue_top(&(info->by_key))=(uchar *)(info->current_table); - queue_replaced(&(info->by_key)); + queue_replace_top(&(info->by_key)); } /* now, mymerge's read_next is as simple as one queue_top */ === modified file 'storage/myisammrg/myrg_rprev.c' --- a/storage/myisammrg/myrg_rprev.c 2007-05-10 09:59:39 +0000 +++ b/storage/myisammrg/myrg_rprev.c 2010-07-16 07:33:01 +0000 @@ -32,7 +32,7 @@ int myrg_rprev(MYRG_INFO *info, uchar *b { if (err == HA_ERR_END_OF_FILE) { - queue_remove(&(info->by_key),0); + queue_remove_top(&(info->by_key)); if (!info->by_key.elements) return HA_ERR_END_OF_FILE; } @@ -43,7 +43,7 @@ int myrg_rprev(MYRG_INFO *info, uchar *b { /* Found here, adding to queue */ queue_top(&(info->by_key))=(uchar *)(info->current_table); - queue_replaced(&(info->by_key)); + queue_replace_top(&(info->by_key)); } /* now, mymerge's read_prev is as simple as one queue_top */