diff --git a/.bzrignore b/.bzrignore index f2bc6d0e483..a38e39107f1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1940,3 +1940,4 @@ sql/client_plugin.c *.dgcov libmysqld/create_options.cc storage/pbxt/bin/xtstat +libmysqld/sql_expression_cache.cc diff --git a/configure.in b/configure.in index 187d65684ea..1e4ea8cfdce 100644 --- a/configure.in +++ b/configure.in @@ -17,7 +17,7 @@ dnl When merging new MySQL releases, update the version number to match the 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 diff --git a/include/queues.h b/include/queues.h index d01b73ba999..f5f09359cbc 100644 --- a/include/queues.h +++ b/include/queues.h @@ -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. + 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 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 */ + 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 + 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, uchar *element); 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) diff --git a/include/thr_alarm.h b/include/thr_alarm.h index fb906039269..99812ed808c 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -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; diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index 2c4408f3ff3..9da4e21a84d 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -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 b=10 or c=10; 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; diff --git a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result index 70bc0cd36be..5db03db85ac 100644 --- a/mysql-test/r/myisam_mrr.result +++ b/mysql-test/r/myisam_mrr.result @@ -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)); diff --git a/mysql-test/r/optimizer_switch.result b/mysql-test/r/optimizer_switch.result new file mode 100644 index 00000000000..6bccefe54be --- /dev/null +++ b/mysql-test/r/optimizer_switch.result @@ -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; diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 58e0e244fd3..dcd40f66365 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -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 diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index c8ebfc9b5d4..c9be1014f02 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -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; diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 48205830e78..84d02f2ff35 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -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 diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 5ad1f2b714c..1b04c836560 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -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 diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index f372e3b7822..e4e58db93a5 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -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 diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 2a689719f52..648a066f185 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -197,45 +197,6 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 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; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index e6db7be4495..5af207432ff 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -201,45 +201,6 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 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; diff --git a/mysql-test/t/index_merge_myisam.test b/mysql-test/t/index_merge_myisam.test index 0c4b9c6886c..b3514e3f053 100644 --- a/mysql-test/t/index_merge_myisam.test +++ b/mysql-test/t/index_merge_myisam.test @@ -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_merge_union=off'; 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; diff --git a/mysql-test/t/myisam_mrr.test b/mysql-test/t/myisam_mrr.test index 4ea60b4f694..d9afdf3140d 100644 --- a/mysql-test/t/myisam_mrr.test +++ b/mysql-test/t/myisam_mrr.test @@ -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); diff --git a/mysql-test/t/optimizer_switch.test b/mysql-test/t/optimizer_switch.test new file mode 100644 index 00000000000..713262197d4 --- /dev/null +++ b/mysql-test/t/optimizer_switch.test @@ -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; + + diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index de380e09e8a..77607fac5f7 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -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; diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test index 54b1b5e15f9..1c2869c628a 100644 --- a/mysql-test/t/subselect_mat.test +++ b/mysql-test/t/subselect_mat.test @@ -905,3 +905,19 @@ select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i = 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; diff --git a/mysql-test/t/subselect_no_mat.test b/mysql-test/t/subselect_no_mat.test index d9b95ea7261..5fbbef5caed 100644 --- a/mysql-test/t/subselect_no_mat.test +++ b/mysql-test/t/subselect_no_mat.test @@ -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%'; diff --git a/mysql-test/t/subselect_no_opts.test b/mysql-test/t/subselect_no_opts.test index 1ce66ac4d33..a26e8dd4c0d 100644 --- a/mysql-test/t/subselect_no_opts.test +++ b/mysql-test/t/subselect_no_opts.test @@ -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'; diff --git a/mysql-test/t/subselect_no_semijoin.test b/mysql-test/t/subselect_no_semijoin.test index ab0eee26216..e9f2e0654ce 100644 --- a/mysql-test/t/subselect_no_semijoin.test +++ b/mysql-test/t/subselect_no_semijoin.test @@ -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'; - diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 7c6ba1d28cf..33f3e936482 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -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; diff --git a/mysys/queues.c b/mysys/queues.c index 9c85e493141..a65a7f8914c 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -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. + 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 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 */ + 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 + 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,47 +56,8 @@ 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 - - NOTES - Will allocate max_element pointers for queue array - - RETURN - 0 ok - 1 Could not allocate memory -*/ - -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) -{ - DBUG_ENTER("init_queue"); - 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_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 + 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. @@ -91,33 +69,35 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, 1 Could not allocate memory */ -int init_queue_ex(QUEUE *queue, uint max_elements, uint offset_to_key, +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, uint auto_extent) + void *first_cmp_arg, uint offset_to_queue_pos, + 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_ENTER("init_queue"); + 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->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); } + /* 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_elements, uint offset_to_key, 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_elements) 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 *queue, uchar *element) { 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 *queue, uchar *element) } - /* 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) +/* + Add element to fixed position and update heap + + SYNOPSIS + _downheap() + queue Queue to use + idx Index of element to change + element Element to store at 'idx' +*/ + +void _downheap(register QUEUE *queue, uint start_idx, uchar *element) { - _downheap(queue,1); -} -#endif - -#ifndef OLD_VERSION - -void _downheap(register QUEUE *queue, uint idx) -{ - 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, uint idx) 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) + 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) { - 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; + 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); + _downheap(queue, i, queue_element(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; -} -#endif diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index b710a7eee39..680ec985aeb 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -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, uint sec, ALARM *alarm_data) 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(int sig __attribute__((unused))) #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(int sig __attribute__((unused))) 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(int sig __attribute__((unused))) } 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(int sig __attribute__((unused))) { #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_id) 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 __attribute__((unused))) { 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; diff --git a/sql/create_options.cc b/sql/create_options.cc index c7ede1b2331..6d682853ae6 100644 --- a/sql/create_options.cc +++ b/sql/create_options.cc @@ -583,9 +583,9 @@ my_bool engine_table_options_frm_read(const uchar *buff, uint length, } 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); } diff --git a/sql/event_queue.cc b/sql/event_queue.cc index d68dc8ef479..2a354fe6cfd 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -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 *thd, LEX_STRING pattern, 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_STRING db, LEX_STRING name) 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_times(THD *thd) 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_times(THD *thd) 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_time(THD *thd, 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_time(THD *thd, 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; diff --git a/sql/filesort.cc b/sql/filesort.cc index 33c838f1bcb..41410929f15 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1151,7 +1151,9 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, 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_CACHE *from_file, 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_CACHE *from_file, 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_CACHE *from_file, 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); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 1b430275d59..09c2fbef6f3 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2567,7 +2567,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) 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_next_partition(uchar * buf) 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_scan(uchar *buf, bool reverse_order) */ 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(uchar *buf, bool is_next_same) 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(uchar *buf, bool is_next_same) } 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(uchar *buf) { 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(uchar *buf) } 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); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 7fc33b46b16..e1339abc081 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -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; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d382b3b7a4e..d1ef5fb5264 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1778,10 +1778,12 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg) 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)); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index fd9da843f31..f9a9e7dfdd7 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -4880,7 +4880,8 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, 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; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5bc26154790..1593a584454 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -409,6 +409,12 @@ static const char *optimizer_switch_str="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" #ifndef DBUG_OFF ",table_elimination=on"; @@ -7227,7 +7233,9 @@ The minimum value for this variable is 4096.", {"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 diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 5df98662fe7..b2f40d576f7 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -262,18 +262,20 @@ static int net_data_is_ready(my_socket sd) #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. + - 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. + 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. + 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 sd) 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 */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 83abf3beac8..1d521f78209 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -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) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8fd73fec960..a4e8c84401b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2994,14 +2994,28 @@ create_result_table(THD *thd_arg, List *column_types, 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. diff --git a/sql/sql_class.h b/sql/sql_class.h index 9784fe01536..21db9fdb234 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2907,11 +2907,11 @@ public: bool send_data(List &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 *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 *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 &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); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 21fe3de4c17..374e92c6a52 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -136,6 +136,22 @@ select_union::create_result_table(THD *thd_arg, List *column_types, } +/** + 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() diff --git a/sql/uniques.cc b/sql/uniques.cc index 3d1ea9243b9..561b1068097 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -423,7 +423,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, 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_buffer, ulong merge_buffer_size, */ 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_buffer, ulong merge_buffer_size, 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); } } diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index d302892ce05..0783f679843 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -473,14 +473,15 @@ static void _ftb_init_index_search(FT_INFO *ftb) 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(MARIA_HA *info, uint keynr, 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 *ftb, char *record) /* update queue */ _ft2_search(ftb, ftbw, 0); - queue_replaced(& ftb->queue); + queue_replace_top(&ftb->queue); } ftbe=ftb->root; diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index 927f34f8b72..3bb7defcaaf 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -253,12 +253,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query, { 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; diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 387563ebaac..cb3e6bc3ee3 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -933,7 +933,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file, 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, uint keys, IO_CACHE *from_file, 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, uint keys, IO_CACHE *from_file, } 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); diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index 78cf86fc6a9..6c38cab294e 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -590,7 +590,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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_COUNTS *huff_counts, 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_COUNTS *huff_counts, 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_COUNTS *huff_counts, 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); } diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 3a6368f338d..dc7eb763b77 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -482,16 +482,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) 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 *info, uint keynr, uchar *query, 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, char *record) /* update queue */ _ft2_search(ftb, ftbw, 0); - queue_replaced(& ftb->queue); + queue_replace_top(&ftb->queue); } ftbe=ftb->root; diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 90ad2d635b7..bcce2cc8d60 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -250,12 +250,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, { 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; diff --git a/storage/myisam/mi_test_all.sh b/storage/myisam/mi_test_all.sh index 5989d9cfaf0..c6bc686e885 100755 --- a/storage/myisam/mi_test_all.sh +++ b/storage/myisam/mi_test_all.sh @@ -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 diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 3d96dfaafa1..300bab58305 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -576,7 +576,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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 *huff_tree, HUFF_COUNTS *huff_counts) 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_COUNTS *huff_counts, 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_COUNTS *huff_counts, 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_COUNTS *huff_counts, 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); } diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index fd0bd971e10..2b6d5167c93 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -920,7 +920,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, 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 keys, IO_CACHE *from_file, 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 keys, IO_CACHE *from_file, } 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); diff --git a/storage/myisammrg/myrg_queue.c b/storage/myisammrg/myrg_queue.c index d2579053784..cf862b53b86 100644 --- a/storage/myisammrg/myrg_queue.c +++ b/storage/myisammrg/myrg_queue.c @@ -52,7 +52,7 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag) 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 inx,enum ha_rkey_function search_flag) 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; } } diff --git a/storage/myisammrg/myrg_rnext.c b/storage/myisammrg/myrg_rnext.c index 82d5cbf38b1..1442ee08dd4 100644 --- a/storage/myisammrg/myrg_rnext.c +++ b/storage/myisammrg/myrg_rnext.c @@ -32,7 +32,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *buf, int inx) { 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 *buf, int inx) { /* 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 */ diff --git a/storage/myisammrg/myrg_rnext_same.c b/storage/myisammrg/myrg_rnext_same.c index ad7bbfb0f6e..14b41dbe756 100644 --- a/storage/myisammrg/myrg_rnext_same.c +++ b/storage/myisammrg/myrg_rnext_same.c @@ -29,7 +29,7 @@ int myrg_rnext_same(MYRG_INFO *info, uchar *buf) { 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, uchar *buf) { /* 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 */ diff --git a/storage/myisammrg/myrg_rprev.c b/storage/myisammrg/myrg_rprev.c index 66c94974940..0c560a0b73d 100644 --- a/storage/myisammrg/myrg_rprev.c +++ b/storage/myisammrg/myrg_rprev.c @@ -32,7 +32,7 @@ int myrg_rprev(MYRG_INFO *info, uchar *buf, int inx) { 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 *buf, int inx) { /* 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 */