mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge main 5.3 into 5.3-mwl89.
This commit is contained in:
@@ -1940,3 +1940,4 @@ sql/client_plugin.c
|
||||
*.dgcov
|
||||
libmysqld/create_options.cc
|
||||
storage/pbxt/bin/xtstat
|
||||
libmysqld/sql_expression_cache.cc
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Code for generell handling of priority Queues.
|
||||
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
||||
Copyright Monty Program KB.
|
||||
By monty.
|
||||
*/
|
||||
|
||||
#ifndef _queues_h
|
||||
@@ -32,29 +40,33 @@ typedef struct st_queue {
|
||||
uint elements;
|
||||
uint max_elements;
|
||||
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)
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
99
mysql-test/r/optimizer_switch.result
Normal file
99
mysql-test/r/optimizer_switch.result
Normal file
@@ -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;
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
113
mysql-test/t/optimizer_switch.test
Normal file
113
mysql-test/t/optimizer_switch.test
Normal file
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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%';
|
||||
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
629
mysys/queues.c
629
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
|
||||
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
This code originates from the Unireg project.
|
||||
|
||||
Code for generell handling of priority Queues.
|
||||
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
||||
An optimisation of _downheap suggested in Exercise 7.51 in "Data
|
||||
Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition
|
||||
was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm
|
||||
of queue_fix was implemented.
|
||||
|
||||
The queue can optionally store the position in queue in the element
|
||||
that is in the queue. This allows one to remove any element from the queue
|
||||
in O(1) time.
|
||||
|
||||
Optimisation of _downheap() and queue_fix() is inspired by code done
|
||||
by Mikael Ronström, based on an optimisation of _downheap from
|
||||
Exercise 7.51 in "Data Structures & Algorithms in C++" by Mark Allen
|
||||
Weiss, Second Edition.
|
||||
*/
|
||||
|
||||
#include "mysys_priv.h"
|
||||
@@ -39,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);
|
||||
|
||||
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,7 +149,7 @@ 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*),
|
||||
(max_elements + 1)* sizeof(void*),
|
||||
MYF(MY_WME))) == 0)
|
||||
DBUG_RETURN(1);
|
||||
set_if_smaller(queue->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
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -136,9 +136,9 @@ Event_queue::init_queue(THD *thd)
|
||||
|
||||
LOCK_QUEUE_DATA();
|
||||
|
||||
if (init_queue_ex(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/,
|
||||
if (::init_queue(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/,
|
||||
0 /*max_on_top*/, event_queue_element_compare_q,
|
||||
NULL, EVENT_QUEUE_EXTENT))
|
||||
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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -262,14 +262,16 @@ 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
|
||||
- Read from socket until there is nothing more to read. Discard
|
||||
what is read.
|
||||
- Initialize net for new net_read/net_write calls.
|
||||
|
||||
If there is anything when to read 'net_clear' is called this
|
||||
normally indicates an error in the protocol.
|
||||
normally 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",
|
||||
@@ -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 */
|
||||
|
@@ -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)
|
||||
|
@@ -2994,14 +2994,28 @@ create_result_table(THD *thd_arg, List<Item> *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.
|
||||
|
@@ -2907,11 +2907,11 @@ public:
|
||||
bool send_data(List<Item> &items);
|
||||
bool send_eof();
|
||||
bool flush();
|
||||
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
||||
|
||||
void cleanup();
|
||||
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||
bool is_distinct, ulonglong options,
|
||||
const char *alias, bool bit_fields_as_long);
|
||||
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
||||
};
|
||||
|
||||
/* Base subselect interface class */
|
||||
@@ -2971,6 +2971,9 @@ protected:
|
||||
*/
|
||||
ha_rows count_rows;
|
||||
|
||||
protected:
|
||||
void reset();
|
||||
|
||||
public:
|
||||
select_materialize_with_stats() { tmp_table_param.init(); }
|
||||
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||
@@ -2978,12 +2981,7 @@ public:
|
||||
const char *alias, bool bit_fields_as_long);
|
||||
bool init_result_table(ulonglong select_options);
|
||||
bool send_data(List<Item> &items);
|
||||
void cleanup()
|
||||
{
|
||||
memset(col_stat, 0, table->s->fields * sizeof(Column_statistics));
|
||||
max_nulls_in_row= 0;
|
||||
count_rows= 0;
|
||||
}
|
||||
void cleanup();
|
||||
ha_rows get_null_count_of_col(uint idx)
|
||||
{
|
||||
DBUG_ASSERT(idx < table->s->fields);
|
||||
|
@@ -136,6 +136,22 @@ select_union::create_result_table(THD *thd_arg, List<Item> *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()
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user