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
|
*.dgcov
|
||||||
libmysqld/create_options.cc
|
libmysqld/create_options.cc
|
||||||
storage/pbxt/bin/xtstat
|
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 MySQL version number.
|
||||||
dnl
|
dnl
|
||||||
dnl Note: the following line must be parseable by win/configure.js:GetVersion()
|
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_CONFIG_SRCDIR([sql/mysqld.cc])
|
||||||
AC_CANONICAL_SYSTEM
|
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
|
Redistribution and use in source and binary forms, with or without
|
||||||
it under the terms of the GNU General Public License as published by
|
modification, are permitted provided that the following conditions are met:
|
||||||
the Free Software Foundation; version 2 of the License.
|
* 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,
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
You should have received a copy of the GNU General Public License
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
along with this program; if not, write to the Free Software
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
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.
|
Code for generell handling of priority Queues.
|
||||||
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
||||||
Copyright Monty Program KB.
|
|
||||||
By monty.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _queues_h
|
#ifndef _queues_h
|
||||||
@@ -31,30 +39,34 @@ typedef struct st_queue {
|
|||||||
void *first_cmp_arg;
|
void *first_cmp_arg;
|
||||||
uint elements;
|
uint elements;
|
||||||
uint max_elements;
|
uint max_elements;
|
||||||
uint offset_to_key; /* compare is done on element+offset */
|
uint offset_to_key; /* compare is done on element+offset */
|
||||||
|
uint offset_to_queue_pos; /* If we want to store position in element */
|
||||||
|
uint auto_extent;
|
||||||
int max_at_top; /* Normally 1, set to -1 if queue_top gives max */
|
int max_at_top; /* Normally 1, set to -1 if queue_top gives max */
|
||||||
int (*compare)(void *, uchar *,uchar *);
|
int (*compare)(void *, uchar *,uchar *);
|
||||||
uint auto_extent;
|
|
||||||
} QUEUE;
|
} QUEUE;
|
||||||
|
|
||||||
|
#define queue_first_element(queue) 1
|
||||||
|
#define queue_last_element(queue) (queue)->elements
|
||||||
#define queue_top(queue) ((queue)->root[1])
|
#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_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_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg
|
||||||
#define queue_set_max_at_top(queue, set_arg) \
|
#define queue_set_max_at_top(queue, set_arg) \
|
||||||
(queue)->max_at_top= set_arg ? -1 : 1
|
(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 *);
|
typedef int (*queue_compare)(void *,uchar *, uchar *);
|
||||||
|
|
||||||
int init_queue(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, queue_compare compare,
|
pbool max_at_top, queue_compare compare,
|
||||||
void *first_cmp_arg);
|
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||||
int init_queue_ex(QUEUE *queue,uint max_elements,uint offset_to_key,
|
uint auto_extent);
|
||||||
pbool max_at_top, queue_compare compare,
|
|
||||||
void *first_cmp_arg, uint auto_extent);
|
|
||||||
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||||
pbool max_at_top, queue_compare compare,
|
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);
|
int resize_queue(QUEUE *queue, uint max_elements);
|
||||||
void delete_queue(QUEUE *queue);
|
void delete_queue(QUEUE *queue);
|
||||||
void queue_insert(QUEUE *queue,uchar *element);
|
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);
|
uchar *queue_remove(QUEUE *queue,uint idx);
|
||||||
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
||||||
#define queue_is_full(queue) (queue->elements == queue->max_elements)
|
#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);
|
void queue_fix(QUEUE *queue);
|
||||||
#define is_queue_inited(queue) ((queue)->root != 0)
|
#define is_queue_inited(queue) ((queue)->root != 0)
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct st_alarm_info
|
typedef struct st_alarm_info
|
||||||
{
|
{
|
||||||
ulong next_alarm_time;
|
time_t next_alarm_time;
|
||||||
uint active_alarms;
|
uint active_alarms;
|
||||||
uint max_used_alarms;
|
uint max_used_alarms;
|
||||||
} ALARM_INFO;
|
} ALARM_INFO;
|
||||||
@@ -78,10 +78,11 @@ typedef int thr_alarm_entry;
|
|||||||
typedef thr_alarm_entry* thr_alarm_t;
|
typedef thr_alarm_entry* thr_alarm_t;
|
||||||
|
|
||||||
typedef struct st_alarm {
|
typedef struct st_alarm {
|
||||||
ulong expire_time;
|
time_t expire_time;
|
||||||
thr_alarm_entry alarmed; /* set when alarm is due */
|
thr_alarm_entry alarmed; /* set when alarm is due */
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
my_thread_id thread_id;
|
my_thread_id thread_id;
|
||||||
|
uint index_in_queue;
|
||||||
my_bool malloced;
|
my_bool malloced;
|
||||||
} ALARM;
|
} ALARM;
|
||||||
|
|
||||||
|
@@ -1413,66 +1413,6 @@ WHERE
|
|||||||
`RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND
|
`RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND
|
||||||
`TESTID`='' AND `UCCHECK`='';
|
`TESTID`='' AND `UCCHECK`='';
|
||||||
drop table t1;
|
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);
|
create table t0 (a int);
|
||||||
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
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),
|
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
|
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
|
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;
|
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;
|
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
|
# Part of MWL#67: DS-MRR backport: add an @@optimizer_switch flag for
|
||||||
# index_condition pushdown:
|
# index_condition pushdown:
|
||||||
# - engine_condition_pushdown does not affect ICP
|
# - engine_condition_pushdown does not affect ICP
|
||||||
select @@optimizer_switch;
|
select @@optimizer_switch like '%index_condition_pushdown=on%';
|
||||||
@@optimizer_switch
|
@@optimizer_switch like '%index_condition_pushdown=on%'
|
||||||
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
|
||||||
create table t0 (a int);
|
create table t0 (a int);
|
||||||
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
create table t1 (a int, b int, key(a));
|
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 0 2
|
||||||
1 1 3
|
1 1 3
|
||||||
1 2 1
|
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
|
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;
|
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
|
||||||
FieldKey LongVal StringVal
|
FieldKey LongVal StringVal
|
||||||
3 1 2
|
3 1 2
|
||||||
|
@@ -1246,3 +1246,29 @@ i
|
|||||||
4
|
4
|
||||||
set session optimizer_switch=@save_optimizer_switch;
|
set session optimizer_switch=@save_optimizer_switch;
|
||||||
drop table t1, t2, t3;
|
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';
|
select @@optimizer_switch like '%materialization=on%';
|
||||||
Variable_name Value
|
@@optimizer_switch like '%materialization=on%'
|
||||||
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
|
||||||
set optimizer_switch='materialization=off';
|
set optimizer_switch='materialization=off';
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
||||||
set @save_optimizer_switch=@@optimizer_switch;
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
@@ -4925,6 +4925,6 @@ DROP TABLE t3;
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
set optimizer_switch=default;
|
set optimizer_switch=default;
|
||||||
show variables like 'optimizer_switch';
|
select @@optimizer_switch like '%materialization=on%';
|
||||||
Variable_name Value
|
@@optimizer_switch like '%materialization=on%'
|
||||||
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
|
||||||
|
@@ -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';
|
set optimizer_switch='materialization=off,semijoin=off';
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
||||||
set @save_optimizer_switch=@@optimizer_switch;
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
@@ -4925,6 +4922,3 @@ DROP TABLE t3;
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
set optimizer_switch=default;
|
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';
|
set optimizer_switch='semijoin=off';
|
||||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
|
||||||
set @save_optimizer_switch=@@optimizer_switch;
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
@@ -4925,6 +4922,3 @@ DROP TABLE t3;
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
set optimizer_switch=default;
|
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
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 103 100.00 Using where; Using join buffer
|
||||||
Warnings:
|
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))
|
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 t0, t1, t2;
|
||||||
drop table t10, t11, t12;
|
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
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 103 100.00 Using where; Using join buffer
|
||||||
Warnings:
|
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))
|
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 t0, t1, t2;
|
||||||
drop table t10, t11, t12;
|
drop table t10, t11, t12;
|
||||||
|
|
||||||
|
@@ -20,78 +20,6 @@ let $merge_table_support= 1;
|
|||||||
--source include/index_merge_2sweeps.inc
|
--source include/index_merge_2sweeps.inc
|
||||||
--source include/index_merge_ror_cpk.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);
|
create table t0 (a int);
|
||||||
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
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),
|
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;
|
explain select * from t1 where a=10 and b=10 or c=10;
|
||||||
|
|
||||||
set optimizer_switch=default;
|
set optimizer_switch=default;
|
||||||
--replace_regex /,table_elimination.on//
|
|
||||||
show variables like 'optimizer_switch';
|
|
||||||
|
|
||||||
drop table t0, t1;
|
drop table t0, t1;
|
||||||
|
|
||||||
|
@@ -103,8 +103,7 @@ drop table t0, t1;
|
|||||||
|
|
||||||
|
|
||||||
# Check that optimizer_switch is present
|
# Check that optimizer_switch is present
|
||||||
--replace_regex /,table_elimination=o[nf]*//
|
select @@optimizer_switch like '%index_condition_pushdown=on%';
|
||||||
select @@optimizer_switch;
|
|
||||||
|
|
||||||
# Check if it affects ICP
|
# Check if it affects ICP
|
||||||
create table t0 (a int);
|
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');
|
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;
|
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
|
||||||
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;
|
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
|
||||||
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
|
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
|
||||||
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;
|
set session optimizer_switch=@save_optimizer_switch;
|
||||||
drop table t1, t2, t3;
|
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)
|
# Run subselect.test without semi-join optimization (test materialize)
|
||||||
#
|
#
|
||||||
--replace_regex /,table_elimination=on//
|
select @@optimizer_switch like '%materialization=on%';
|
||||||
show variables like 'optimizer_switch';
|
|
||||||
set optimizer_switch='materialization=off';
|
set optimizer_switch='materialization=off';
|
||||||
|
|
||||||
--source t/subselect.test
|
--source t/subselect.test
|
||||||
|
|
||||||
set optimizer_switch=default;
|
set optimizer_switch=default;
|
||||||
--replace_regex /,table_elimination=on//
|
select @@optimizer_switch like '%materialization=on%';
|
||||||
show variables like 'optimizer_switch';
|
|
||||||
|
|
||||||
|
@@ -1,13 +1,9 @@
|
|||||||
#
|
#
|
||||||
# Run subselect.test without semi-join optimization (test materialize)
|
# 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';
|
set optimizer_switch='materialization=off,semijoin=off';
|
||||||
|
|
||||||
--source t/subselect.test
|
--source t/subselect.test
|
||||||
|
|
||||||
set optimizer_switch=default;
|
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)
|
# Run subselect.test without semi-join optimization (test materialize)
|
||||||
#
|
#
|
||||||
--replace_regex /,table_elimination=on//
|
|
||||||
show variables like 'optimizer_switch';
|
|
||||||
set optimizer_switch='semijoin=off';
|
set optimizer_switch='semijoin=off';
|
||||||
|
|
||||||
--source t/subselect.test
|
--source t/subselect.test
|
||||||
|
|
||||||
set optimizer_switch=default;
|
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;
|
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);
|
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 t0, t1, t2;
|
||||||
drop table t10, t11, t12;
|
drop table t10, t11, t12;
|
||||||
|
|
||||||
|
633
mysys/queues.c
633
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
|
Redistribution and use in source and binary forms, with or without
|
||||||
it under the terms of the GNU General Public License as published by
|
modification, are permitted provided that the following conditions are met:
|
||||||
the Free Software Foundation; version 2 of the License.
|
* 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,
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
<COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
You should have received a copy of the GNU General Public License
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
along with this program; if not, write to the Free Software
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
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.
|
Code for generell handling of priority Queues.
|
||||||
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
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
|
The queue can optionally store the position in queue in the element
|
||||||
was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm
|
that is in the queue. This allows one to remove any element from the queue
|
||||||
of queue_fix was implemented.
|
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"
|
#include "mysys_priv.h"
|
||||||
@@ -39,47 +56,8 @@
|
|||||||
max_at_top Set to 1 if you want biggest element on top.
|
max_at_top Set to 1 if you want biggest element on top.
|
||||||
compare Compare function for elements, takes 3 arguments.
|
compare Compare function for elements, takes 3 arguments.
|
||||||
first_cmp_arg First argument to compare function
|
first_cmp_arg First argument to compare function
|
||||||
|
offset_to_queue_pos If <> 0, then offset+1 in element to store position
|
||||||
NOTES
|
in queue (for fast delete of element in queue)
|
||||||
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
|
|
||||||
auto_extent When the queue is full and there is insert operation
|
auto_extent When the queue is full and there is insert operation
|
||||||
extend the queue.
|
extend the queue.
|
||||||
|
|
||||||
@@ -91,33 +69,35 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
|||||||
1 Could not allocate memory
|
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 *),
|
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");
|
||||||
DBUG_ENTER("init_queue_ex");
|
if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*),
|
||||||
|
MYF(MY_WME))) == 0)
|
||||||
if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare,
|
DBUG_RETURN(1);
|
||||||
first_cmp_arg)))
|
queue->elements= 0;
|
||||||
DBUG_RETURN(ret);
|
queue->compare= compare;
|
||||||
|
queue->first_cmp_arg= first_cmp_arg;
|
||||||
queue->auto_extent= auto_extent;
|
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);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Reinitialize queue for other usage
|
Reinitialize queue for other usage
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
reinit_queue()
|
reinit_queue()
|
||||||
queue Queue to initialise
|
queue Queue to initialise
|
||||||
max_elements Max elements that will be put in queue
|
For rest of arguments, see init_queue() above
|
||||||
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
|
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
This will delete all elements from the queue. If you don't want this,
|
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
|
RETURN
|
||||||
0 ok
|
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,
|
int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
||||||
pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
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");
|
DBUG_ENTER("reinit_queue");
|
||||||
queue->elements=0;
|
queue->elements= 0;
|
||||||
queue->compare=compare;
|
queue->compare= compare;
|
||||||
queue->first_cmp_arg=first_cmp_arg;
|
queue->first_cmp_arg= first_cmp_arg;
|
||||||
queue->offset_to_key=offset_to_key;
|
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);
|
queue_set_max_at_top(queue, max_at_top);
|
||||||
resize_queue(queue, max_elements);
|
DBUG_RETURN(resize_queue(queue, max_elements));
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -167,8 +149,8 @@ int resize_queue(QUEUE *queue, uint max_elements)
|
|||||||
if (queue->max_elements == max_elements)
|
if (queue->max_elements == max_elements)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
if ((new_root= (uchar **) my_realloc((void *)queue->root,
|
if ((new_root= (uchar **) my_realloc((void *)queue->root,
|
||||||
(max_elements+1)*sizeof(void*),
|
(max_elements + 1)* sizeof(void*),
|
||||||
MYF(MY_WME))) == 0)
|
MYF(MY_WME))) == 0)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
set_if_smaller(queue->elements, max_elements);
|
set_if_smaller(queue->elements, max_elements);
|
||||||
queue->max_elements= max_elements;
|
queue->max_elements= max_elements;
|
||||||
@@ -197,39 +179,58 @@ void delete_queue(QUEUE *queue)
|
|||||||
if (queue->root)
|
if (queue->root)
|
||||||
{
|
{
|
||||||
my_free((uchar*) queue->root,MYF(0));
|
my_free((uchar*) queue->root,MYF(0));
|
||||||
queue->root=0;
|
queue->root=0; /* Allow multiple calls */
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
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)
|
void queue_insert(register QUEUE *queue, uchar *element)
|
||||||
{
|
{
|
||||||
reg2 uint idx, next;
|
reg2 uint idx, next;
|
||||||
|
uint offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||||
DBUG_ASSERT(queue->elements < queue->max_elements);
|
DBUG_ASSERT(queue->elements < queue->max_elements);
|
||||||
queue->root[0]= element;
|
|
||||||
idx= ++queue->elements;
|
idx= ++queue->elements;
|
||||||
/* max_at_top swaps the comparison if we want to order by desc */
|
/* 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,
|
element + queue->offset_to_key,
|
||||||
queue->root[(next= idx >> 1)] +
|
queue->root[(next= idx >> 1)] +
|
||||||
queue->offset_to_key) * queue->max_at_top) < 0)
|
queue->offset_to_key) * queue->max_at_top) < 0)
|
||||||
{
|
{
|
||||||
queue->root[idx]= queue->root[next];
|
queue->root[idx]= queue->root[next];
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
idx= next;
|
idx= next;
|
||||||
}
|
}
|
||||||
queue->root[idx]= element;
|
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.
|
Like queue_insert, but resize queue if queue is full
|
||||||
Return codes:
|
|
||||||
0 - OK
|
SYNOPSIS
|
||||||
1 - Cannot allocate more memory
|
queue_insert_safe()
|
||||||
2 - auto_extend is 0, the operation would
|
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)
|
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)
|
if (!queue->auto_extent)
|
||||||
return 2;
|
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;
|
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 *queue_remove(register QUEUE *queue, uint idx)
|
||||||
{
|
{
|
||||||
uchar *element;
|
uchar *element;
|
||||||
DBUG_ASSERT(idx < queue->max_elements);
|
DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
|
||||||
element= queue->root[++idx]; /* Intern index starts from 1 */
|
element= queue->root[idx];
|
||||||
queue->root[idx]= queue->root[queue->elements--];
|
_downheap(queue, idx, queue->root[queue->elements--]);
|
||||||
_downheap(queue, idx);
|
|
||||||
return element;
|
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);
|
uint elements,half_queue,offset_to_key, next_index, offset_to_queue_pos;
|
||||||
}
|
register uint idx= start_idx;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OLD_VERSION
|
|
||||||
|
|
||||||
void _downheap(register QUEUE *queue, uint idx)
|
|
||||||
{
|
|
||||||
uchar *element;
|
|
||||||
uint elements,half_queue,offset_to_key, next_index;
|
|
||||||
my_bool first= TRUE;
|
my_bool first= TRUE;
|
||||||
uint start_idx= idx;
|
|
||||||
|
|
||||||
offset_to_key=queue->offset_to_key;
|
offset_to_key=queue->offset_to_key;
|
||||||
element=queue->root[idx];
|
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||||
half_queue=(elements=queue->elements) >> 1;
|
half_queue= (elements= queue->elements) >> 1;
|
||||||
|
|
||||||
while (idx <= half_queue)
|
while (idx <= half_queue)
|
||||||
{
|
{
|
||||||
@@ -298,393 +307,49 @@ void _downheap(register QUEUE *queue, uint idx)
|
|||||||
element+offset_to_key) * queue->max_at_top) >= 0)))
|
element+offset_to_key) * queue->max_at_top) >= 0)))
|
||||||
{
|
{
|
||||||
queue->root[idx]= element;
|
queue->root[idx]= element;
|
||||||
|
if (offset_to_queue_pos)
|
||||||
|
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
queue->root[idx]=queue->root[next_index];
|
|
||||||
idx=next_index;
|
|
||||||
first= FALSE;
|
first= FALSE;
|
||||||
}
|
queue->root[idx]= queue->root[next_index];
|
||||||
|
if (offset_to_queue_pos)
|
||||||
next_index= idx >> 1;
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
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];
|
|
||||||
idx=next_index;
|
idx=next_index;
|
||||||
next_index= idx >> 1;
|
|
||||||
}
|
}
|
||||||
queue->root[idx]=element;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
/*
|
/*
|
||||||
The old _downheap version is kept for comparisons with the benchmark
|
Insert the element into the right position. This is the same code
|
||||||
suit or new benchmarks anyone wants to run for comparisons.
|
as we have in queue_insert()
|
||||||
*/
|
*/
|
||||||
/* Fix heap when index have changed */
|
while ((next_index= (idx >> 1)) > start_idx &&
|
||||||
void _downheap(register QUEUE *queue, uint idx)
|
queue->compare(queue->first_cmp_arg,
|
||||||
{
|
element+offset_to_key,
|
||||||
uchar *element;
|
queue->root[next_index]+offset_to_key)*
|
||||||
uint elements,half_queue,next_index,offset_to_key;
|
queue->max_at_top < 0)
|
||||||
|
|
||||||
offset_to_key=queue->offset_to_key;
|
|
||||||
element=queue->root[idx];
|
|
||||||
half_queue=(elements=queue->elements) >> 1;
|
|
||||||
|
|
||||||
while (idx <= half_queue)
|
|
||||||
{
|
{
|
||||||
next_index=idx+idx;
|
queue->root[idx]= queue->root[next_index];
|
||||||
if (next_index < elements &&
|
if (offset_to_queue_pos)
|
||||||
(queue->compare(queue->first_cmp_arg,
|
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||||
queue->root[next_index]+offset_to_key,
|
idx= next_index;
|
||||||
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]=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.
|
Fix heap when every element was changed.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
queue_fix()
|
||||||
|
queue Queue to use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void queue_fix(QUEUE *queue)
|
void queue_fix(QUEUE *queue)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
for (i= queue->elements >> 1; i > 0; 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;
|
time_t next_alarm_expire_time= ~ (time_t) 0;
|
||||||
static sig_handler process_alarm_part2(int sig);
|
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__)
|
#if !defined(__WIN__)
|
||||||
|
|
||||||
static pthread_mutex_t LOCK_alarm;
|
static pthread_mutex_t LOCK_alarm;
|
||||||
@@ -72,8 +85,8 @@ void init_thr_alarm(uint max_alarms)
|
|||||||
DBUG_ENTER("init_thr_alarm");
|
DBUG_ENTER("init_thr_alarm");
|
||||||
alarm_aborted=0;
|
alarm_aborted=0;
|
||||||
next_alarm_expire_time= ~ (time_t) 0;
|
next_alarm_expire_time= ~ (time_t) 0;
|
||||||
init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0,
|
init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0,
|
||||||
compare_ulong,NullS);
|
compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1, 0);
|
||||||
sigfillset(&full_signal_set); /* Neaded to block signals */
|
sigfillset(&full_signal_set); /* Neaded to block signals */
|
||||||
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
|
||||||
pthread_cond_init(&COND_alarm,NULL);
|
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)
|
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
|
#ifndef USE_ONE_SIGNAL_HAND
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
#endif
|
#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));
|
DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec));
|
||||||
|
|
||||||
now= my_time(0);
|
now= my_time(0);
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
if (!alarm_data)
|
||||||
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
{
|
||||||
#endif
|
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 */
|
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
|
||||||
if (alarm_aborted > 0)
|
if (unlikely(alarm_aborted))
|
||||||
{ /* No signal thread */
|
{ /* No signal thread */
|
||||||
DBUG_PRINT("info", ("alarm aborted"));
|
DBUG_PRINT("info", ("alarm aborted"));
|
||||||
*alrm= 0; /* No alarm */
|
if (alarm_aborted > 0)
|
||||||
pthread_mutex_unlock(&LOCK_alarm);
|
goto abort;
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
|
||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
|
||||||
#endif
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
if (alarm_aborted < 0)
|
|
||||||
sec= 1; /* Abort mode */
|
sec= 1; /* Abort mode */
|
||||||
|
}
|
||||||
if (alarm_queue.elements >= max_used_alarms)
|
if (alarm_queue.elements >= max_used_alarms)
|
||||||
{
|
{
|
||||||
if (alarm_queue.elements == alarm_queue.max_elements)
|
if (alarm_queue.elements == alarm_queue.max_elements)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("alarm queue full"));
|
DBUG_PRINT("info", ("alarm queue full"));
|
||||||
fprintf(stderr,"Warning: thr_alarm queue is full\n");
|
fprintf(stderr,"Warning: thr_alarm queue is full\n");
|
||||||
*alrm= 0; /* No alarm */
|
goto abort;
|
||||||
pthread_mutex_unlock(&LOCK_alarm);
|
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
|
||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
|
||||||
#endif
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
}
|
||||||
max_used_alarms=alarm_queue.elements+1;
|
max_used_alarms=alarm_queue.elements+1;
|
||||||
}
|
}
|
||||||
reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec;
|
reschedule= (ulong) next_alarm_expire_time > (ulong) next;
|
||||||
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;
|
|
||||||
queue_insert(&alarm_queue,(uchar*) alarm_data);
|
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 */
|
/* Reschedule alarm if the current one has more than sec left */
|
||||||
if (reschedule)
|
if (unlikely(reschedule))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("reschedule"));
|
DBUG_PRINT("info", ("reschedule"));
|
||||||
if (pthread_equal(pthread_self(),alarm_thread))
|
if (pthread_equal(pthread_self(),alarm_thread))
|
||||||
{
|
{
|
||||||
alarm(sec); /* purecov: inspected */
|
alarm(sec); /* purecov: inspected */
|
||||||
next_alarm_expire_time= now + sec;
|
next_alarm_expire_time= next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
reschedule_alarms(); /* Reschedule alarms */
|
reschedule_alarms(); /* Reschedule alarms */
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&LOCK_alarm);
|
pthread_mutex_unlock(&LOCK_alarm);
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
|
||||||
#endif
|
|
||||||
(*alrm)= &alarm_data->alarmed;
|
(*alrm)= &alarm_data->alarmed;
|
||||||
DBUG_RETURN(0);
|
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
|
#ifndef USE_ONE_SIGNAL_HAND
|
||||||
sigset_t old_mask;
|
sigset_t old_mask;
|
||||||
#endif
|
#endif
|
||||||
uint i, found=0;
|
|
||||||
DBUG_ENTER("thr_end_alarm");
|
DBUG_ENTER("thr_end_alarm");
|
||||||
|
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
||||||
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
|
|
||||||
#endif
|
|
||||||
pthread_mutex_lock(&LOCK_alarm);
|
|
||||||
|
|
||||||
alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
|
alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
|
||||||
for (i=0 ; i < alarm_queue.elements ; i++)
|
pthread_mutex_lock(&LOCK_alarm);
|
||||||
{
|
DBUG_ASSERT(alarm_data->index_in_queue != 0);
|
||||||
if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data)
|
DBUG_ASSERT(queue_element(&alarm_queue, alarm_data->index_in_queue) ==
|
||||||
{
|
alarm_data);
|
||||||
queue_remove(&alarm_queue,i),MYF(0);
|
queue_remove(&alarm_queue, alarm_data->index_in_queue);
|
||||||
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_unlock(&LOCK_alarm);
|
pthread_mutex_unlock(&LOCK_alarm);
|
||||||
#ifndef USE_ONE_SIGNAL_HAND
|
one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
reset_index_in_queue(alarm_data);
|
||||||
#endif
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,12 +323,13 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
|
|||||||
#if defined(MAIN) && !defined(__bsdi__)
|
#if defined(MAIN) && !defined(__bsdi__)
|
||||||
printf("process_alarm\n"); fflush(stdout);
|
printf("process_alarm\n"); fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
if (alarm_queue.elements)
|
if (likely(alarm_queue.elements))
|
||||||
{
|
{
|
||||||
if (alarm_aborted)
|
if (unlikely(alarm_aborted))
|
||||||
{
|
{
|
||||||
uint i;
|
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=(ALARM*) queue_element(&alarm_queue,i);
|
||||||
alarm_data->alarmed=1; /* Info to thread */
|
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");
|
printf("Warning: pthread_kill couldn't find thread!!!\n");
|
||||||
#endif
|
#endif
|
||||||
queue_remove(&alarm_queue,i); /* No thread. Remove alarm */
|
queue_remove(&alarm_queue,i); /* No thread. Remove alarm */
|
||||||
|
reset_index_in_queue(alarm_data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i++; /* Signal next thread */
|
i++; /* Signal next thread */
|
||||||
@@ -371,8 +352,8 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ulong now=(ulong) my_time(0);
|
time_t now= my_time(0);
|
||||||
ulong next=now+10-(now%10);
|
time_t next= now+10-(now%10);
|
||||||
while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
|
while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
|
||||||
{
|
{
|
||||||
alarm_data->alarmed=1; /* Info to thread */
|
alarm_data->alarmed=1; /* Info to thread */
|
||||||
@@ -382,15 +363,16 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
|
|||||||
{
|
{
|
||||||
#ifdef MAIN
|
#ifdef MAIN
|
||||||
printf("Warning: pthread_kill couldn't find thread!!!\n");
|
printf("Warning: pthread_kill couldn't find thread!!!\n");
|
||||||
#endif
|
#endif /* MAIN */
|
||||||
queue_remove(&alarm_queue,0); /* No thread. Remove alarm */
|
queue_remove_top(&alarm_queue); /* No thread. Remove alarm */
|
||||||
|
reset_index_in_queue(alarm_data);
|
||||||
if (!alarm_queue.elements)
|
if (!alarm_queue.elements)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alarm_data->expire_time=next;
|
alarm_data->expire_time=next;
|
||||||
queue_replaced(&alarm_queue);
|
queue_replace_top(&alarm_queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef USE_ALARM_THREAD
|
#ifndef USE_ALARM_THREAD
|
||||||
@@ -486,13 +468,15 @@ void thr_alarm_kill(my_thread_id thread_id)
|
|||||||
if (alarm_aborted)
|
if (alarm_aborted)
|
||||||
return;
|
return;
|
||||||
pthread_mutex_lock(&LOCK_alarm);
|
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);
|
element->expire_time= 0;
|
||||||
tmp->expire_time=0;
|
queue_replace(&alarm_queue, i);
|
||||||
queue_insert(&alarm_queue,(uchar*) tmp);
|
|
||||||
reschedule_alarms();
|
reschedule_alarms();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -508,7 +492,7 @@ void thr_alarm_info(ALARM_INFO *info)
|
|||||||
info->max_used_alarms= max_used_alarms;
|
info->max_used_alarms= max_used_alarms;
|
||||||
if ((info->active_alarms= alarm_queue.elements))
|
if ((info->active_alarms= alarm_queue.elements))
|
||||||
{
|
{
|
||||||
ulong now=(ulong) my_time(0);
|
time_t now= my_time(0);
|
||||||
long time_diff;
|
long time_diff;
|
||||||
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
|
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
|
||||||
time_diff= (long) (alarm_data->expire_time - now);
|
time_diff= (long) (alarm_data->expire_time - now);
|
||||||
@@ -556,7 +540,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
|
|||||||
{
|
{
|
||||||
if (alarm_queue.elements)
|
if (alarm_queue.elements)
|
||||||
{
|
{
|
||||||
ulong sleep_time,now= my_time(0);
|
time_t sleep_time,now= my_time(0);
|
||||||
if (alarm_aborted)
|
if (alarm_aborted)
|
||||||
sleep_time=now+1;
|
sleep_time=now+1;
|
||||||
else
|
else
|
||||||
@@ -792,20 +776,6 @@ static void *test_thread(void *arg)
|
|||||||
return 0;
|
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)))
|
static void *signal_hand(void *arg __attribute__((unused)))
|
||||||
{
|
{
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
@@ -583,9 +583,9 @@ my_bool engine_table_options_frm_read(const uchar *buff, uint length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buff < buff_end)
|
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",
|
"unknown table attributes were ignored",
|
||||||
share->table_name);
|
share->table_name.str);
|
||||||
|
|
||||||
DBUG_RETURN(buff > buff_end);
|
DBUG_RETURN(buff > buff_end);
|
||||||
}
|
}
|
||||||
|
@@ -136,9 +136,9 @@ Event_queue::init_queue(THD *thd)
|
|||||||
|
|
||||||
LOCK_QUEUE_DATA();
|
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,
|
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");
|
sql_print_error("Event Scheduler: Can't initialize the execution queue");
|
||||||
goto err;
|
goto err;
|
||||||
@@ -325,11 +325,13 @@ void
|
|||||||
Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
|
||||||
bool (*comparator)(LEX_STRING, Event_basic *))
|
bool (*comparator)(LEX_STRING, Event_basic *))
|
||||||
{
|
{
|
||||||
uint i= 0;
|
uint i;
|
||||||
DBUG_ENTER("Event_queue::drop_matching_events");
|
DBUG_ENTER("Event_queue::drop_matching_events");
|
||||||
DBUG_PRINT("enter", ("pattern=%s", pattern.str));
|
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);
|
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
|
||||||
DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
|
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
|
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
|
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
|
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);
|
queue_remove(&queue, i);
|
||||||
delete et;
|
delete et;
|
||||||
@@ -403,7 +406,9 @@ Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
|
|||||||
uint i;
|
uint i;
|
||||||
DBUG_ENTER("Event_queue::find_n_remove_event");
|
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);
|
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
|
||||||
DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str,
|
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();
|
LOCK_QUEUE_DATA();
|
||||||
DBUG_PRINT("info", ("%u loaded events to be recalculated", queue.elements));
|
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))->compute_next_execution_time();
|
||||||
((Event_queue_element*)queue_element(&queue, i))->update_timing_fields(thd);
|
((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
|
have removed all. The queue has been ordered in a way the disabled
|
||||||
events are at the end.
|
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)
|
if (element->status != Event_parse_data::DISABLED)
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
This won't cause queue re-order, because we remove
|
This won't cause queue re-order, because we remove
|
||||||
always the last element.
|
always the last element.
|
||||||
*/
|
*/
|
||||||
queue_remove(&queue, i - 1);
|
queue_remove(&queue, i);
|
||||||
delete element;
|
delete element;
|
||||||
}
|
}
|
||||||
UNLOCK_QUEUE_DATA();
|
UNLOCK_QUEUE_DATA();
|
||||||
@@ -499,7 +509,9 @@ Event_queue::empty_queue()
|
|||||||
sql_print_information("Event Scheduler: Purging the queue. %u events",
|
sql_print_information("Event Scheduler: Purging the queue. %u events",
|
||||||
queue.elements);
|
queue.elements);
|
||||||
/* empty the queue */
|
/* 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);
|
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
|
||||||
delete et;
|
delete et;
|
||||||
@@ -525,7 +537,9 @@ Event_queue::dbug_dump_queue(time_t now)
|
|||||||
uint i;
|
uint i;
|
||||||
DBUG_ENTER("Event_queue::dbug_dump_queue");
|
DBUG_ENTER("Event_queue::dbug_dump_queue");
|
||||||
DBUG_PRINT("info", ("Dumping queue . Elements=%u", queue.elements));
|
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));
|
et= ((Event_queue_element*)queue_element(&queue, i));
|
||||||
DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et,
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
top= ((Event_queue_element*) queue_element(&queue, 0));
|
top= (Event_queue_element*) queue_top(&queue);
|
||||||
|
|
||||||
thd->set_current_time(); /* Get current time */
|
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->dbname.str, top->name.str,
|
||||||
top->dropped? "Dropping.":"");
|
top->dropped? "Dropping.":"");
|
||||||
delete top;
|
delete top;
|
||||||
queue_remove(&queue, 0);
|
queue_remove_top(&queue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
|
|
||||||
dbug_dump_queue(thd->query_start());
|
dbug_dump_queue(thd->query_start());
|
||||||
break;
|
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)
|
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
|
||||||
{
|
{
|
||||||
uchar *reuse_end= reuse->base + reuse->max_keys * 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);
|
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
|
||||||
if (bp->base + bp->max_keys * key_length == reuse->base)
|
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;
|
first_cmp_arg= (void*) &sort_length;
|
||||||
}
|
}
|
||||||
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
|
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 */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
||||||
{
|
{
|
||||||
@@ -1277,7 +1279,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
error= 0; /* purecov: inspected */
|
error= 0; /* purecov: inspected */
|
||||||
goto end; /* purecov: inspected */
|
goto end; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
queue_replaced(&queue); // Top element has been used
|
queue_replace_top(&queue); // Top element has been used
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cmp= 0; // Not unique
|
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,
|
if (!(error= (int) read_to_buffer(from_file,buffpek,
|
||||||
rec_length)))
|
rec_length)))
|
||||||
{
|
{
|
||||||
VOID(queue_remove(&queue,0));
|
VOID(queue_remove_top(&queue));
|
||||||
reuse_freed_buff(&queue, buffpek, rec_length);
|
reuse_freed_buff(&queue, buffpek, rec_length);
|
||||||
break; /* One buffer have been removed */
|
break; /* One buffer have been removed */
|
||||||
}
|
}
|
||||||
else if (error == -1)
|
else if (error == -1)
|
||||||
goto err; /* purecov: inspected */
|
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);
|
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.
|
Initialize priority queue, initialized to reading forward.
|
||||||
*/
|
*/
|
||||||
if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS,
|
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;
|
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)
|
int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
uint j= 0;
|
uint j= queue_first_element(&m_queue);
|
||||||
bool found= FALSE;
|
bool found= FALSE;
|
||||||
DBUG_ENTER("ha_partition::handle_ordered_index_scan");
|
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_max_at_top(&m_queue, reverse_order);
|
||||||
queue_set_cmp_arg(&m_queue, (void*)m_curr_key_info);
|
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);
|
queue_fix(&m_queue);
|
||||||
return_top_record(buf);
|
return_top_record(buf);
|
||||||
table->status= 0;
|
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)
|
if (error == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
/* Return next buffered row */
|
/* Return next buffered row */
|
||||||
queue_remove(&m_queue, (uint) 0);
|
queue_remove_top(&m_queue);
|
||||||
if (m_queue.elements)
|
if (m_queue.elements)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Record returned from partition %u (2)",
|
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);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
queue_replaced(&m_queue);
|
queue_replace_top(&m_queue);
|
||||||
return_top_record(buf);
|
return_top_record(buf);
|
||||||
DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry));
|
DBUG_PRINT("info", ("Record returned from partition %u", m_top_entry));
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@@ -4830,7 +4830,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
|
|||||||
{
|
{
|
||||||
if (error == HA_ERR_END_OF_FILE)
|
if (error == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
queue_remove(&m_queue, (uint) 0);
|
queue_remove_top(&m_queue);
|
||||||
if (m_queue.elements)
|
if (m_queue.elements)
|
||||||
{
|
{
|
||||||
return_top_record(buf);
|
return_top_record(buf);
|
||||||
@@ -4842,7 +4842,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
|
|||||||
}
|
}
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
queue_replaced(&m_queue);
|
queue_replace_top(&m_queue);
|
||||||
return_top_record(buf);
|
return_top_record(buf);
|
||||||
DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry));
|
DBUG_PRINT("info", ("Record returned from partition %d", m_top_entry));
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@@ -1129,7 +1129,7 @@ public:
|
|||||||
virtual handlerton *partition_ht() const
|
virtual handlerton *partition_ht() const
|
||||||
{
|
{
|
||||||
handlerton *h= m_file[0]->ht;
|
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);
|
DBUG_ASSERT(h == m_file[i]->ht);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@@ -1778,10 +1778,12 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(uchar *thd_arg)
|
|||||||
if (args[0]->cols() == 1)
|
if (args[0]->cols() == 1)
|
||||||
depends_on.push_front((Item**)args);
|
depends_on.push_front((Item**)args);
|
||||||
else
|
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));
|
depends_on.push_front(args[0]->addr(i));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args[1]->expr_cache_is_needed(thd))
|
if (args[1]->expr_cache_is_needed(thd))
|
||||||
DBUG_RETURN(set_expr_cache(thd, depends_on));
|
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();
|
merge_keys[i]->sort_keys();
|
||||||
|
|
||||||
if (init_queue(&pq, keys_count, 0, FALSE,
|
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 TRUE;
|
||||||
|
|
||||||
return FALSE;
|
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_sort_union=on,"
|
||||||
"index_merge_intersection=on,"
|
"index_merge_intersection=on,"
|
||||||
"index_condition_pushdown=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"
|
"subquery_cache=on"
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
",table_elimination=on";
|
",table_elimination=on";
|
||||||
@@ -7227,7 +7233,9 @@ The minimum value for this variable is 4096.",
|
|||||||
{"optimizer_switch", OPT_OPTIMIZER_SWITCH,
|
{"optimizer_switch", OPT_OPTIMIZER_SWITCH,
|
||||||
"optimizer_switch=option=val[,option=val...], where option={index_merge, "
|
"optimizer_switch=option=val[,option=val...], where option={index_merge, "
|
||||||
"index_merge_union, index_merge_sort_union, index_merge_intersection, "
|
"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
|
#ifndef DBUG_OFF
|
||||||
", table_elimination"
|
", table_elimination"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -262,18 +262,20 @@ static int net_data_is_ready(my_socket sd)
|
|||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove unwanted characters from connection
|
Intialize NET handler for new reads:
|
||||||
and check if disconnected.
|
|
||||||
|
|
||||||
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.
|
what is read.
|
||||||
|
- Initialize net for new net_read/net_write calls.
|
||||||
|
|
||||||
If there is anything when to read 'net_clear' is called this
|
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
|
When connection is properly closed (for TCP it means with
|
||||||
a FIN packet), then select() considers a socket "ready to read",
|
a FIN packet), then select() considers a socket "ready to read",
|
||||||
in the sense that there's EOF to read, but read() returns 0.
|
in the sense that there's EOF to read, but read() returns 0.
|
||||||
|
|
||||||
@param net NET handler
|
@param net NET handler
|
||||||
@param clear_buffer if <> 0, then clear all data from comm buff
|
@param clear_buffer if <> 0, then clear all data from comm buff
|
||||||
@@ -281,20 +283,18 @@ static int net_data_is_ready(my_socket sd)
|
|||||||
|
|
||||||
void net_clear(NET *net, my_bool clear_buffer __attribute__((unused)))
|
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");
|
DBUG_ENTER("net_clear");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We don't do a clear in case of DBUG_OFF to catch bugs
|
We don't do a clear in case of not DBUG_OFF to catch bugs in the
|
||||||
in the protocol handling
|
protocol handling.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)
|
#if (!defined(EMBEDDED_LIBRARY) && defined(DBUG_OFF)) || defined(USE_NET_CLEAR)
|
||||||
if (clear_buffer)
|
if (clear_buffer)
|
||||||
{
|
{
|
||||||
|
size_t count;
|
||||||
|
int ready;
|
||||||
while ((ready= net_data_is_ready(net->vio->sd)) > 0)
|
while ((ready= net_data_is_ready(net->vio->sd)) > 0)
|
||||||
{
|
{
|
||||||
/* The socket is ready */
|
/* 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,
|
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
|
||||||
bool no_alloc, MEM_ROOT *parent_alloc,
|
bool no_alloc, MEM_ROOT *parent_alloc,
|
||||||
bool *create_error)
|
bool *create_error)
|
||||||
:dont_free(0),doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0)
|
:doing_key_read(0),/*error(0),*/free_file(0),/*in_range(0),*/cur_range(NULL),last_range(0),dont_free(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)
|
|
||||||
{
|
{
|
||||||
my_bitmap_map *bitmap;
|
my_bitmap_map *bitmap;
|
||||||
DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT");
|
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");
|
DBUG_ENTER("QUICK_ROR_UNION_SELECT::init");
|
||||||
if (init_queue(&queue, quick_selects.elements, 0,
|
if (init_queue(&queue, quick_selects.elements, 0,
|
||||||
FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
|
FALSE , QUICK_ROR_UNION_SELECT::queue_cmp,
|
||||||
(void*) this))
|
(void*) this, 0, 0))
|
||||||
{
|
{
|
||||||
bzero(&queue, sizeof(QUEUE));
|
bzero(&queue, sizeof(QUEUE));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@@ -8293,12 +8290,12 @@ int QUICK_ROR_UNION_SELECT::get_next()
|
|||||||
{
|
{
|
||||||
if (error != HA_ERR_END_OF_FILE)
|
if (error != HA_ERR_END_OF_FILE)
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
queue_remove(&queue, 0);
|
queue_remove_top(&queue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
quick->save_last_pos();
|
quick->save_last_pos();
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!have_prev_rowid)
|
if (!have_prev_rowid)
|
||||||
|
@@ -2994,14 +2994,28 @@ create_result_table(THD *thd_arg, List<Item> *column_types,
|
|||||||
if (!stat)
|
if (!stat)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
cleanup();
|
reset();
|
||||||
|
|
||||||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||||
return FALSE;
|
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
|
Override select_union::send_data to analyze each row for NULLs and to
|
||||||
update null_statistics before sending data to the client.
|
update null_statistics before sending data to the client.
|
||||||
|
@@ -2907,11 +2907,11 @@ public:
|
|||||||
bool send_data(List<Item> &items);
|
bool send_data(List<Item> &items);
|
||||||
bool send_eof();
|
bool send_eof();
|
||||||
bool flush();
|
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,
|
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||||
bool is_distinct, ulonglong options,
|
bool is_distinct, ulonglong options,
|
||||||
const char *alias, bool bit_fields_as_long);
|
const char *alias, bool bit_fields_as_long);
|
||||||
|
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Base subselect interface class */
|
/* Base subselect interface class */
|
||||||
@@ -2971,6 +2971,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
ha_rows count_rows;
|
ha_rows count_rows;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
select_materialize_with_stats() { tmp_table_param.init(); }
|
select_materialize_with_stats() { tmp_table_param.init(); }
|
||||||
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||||
@@ -2978,12 +2981,7 @@ public:
|
|||||||
const char *alias, bool bit_fields_as_long);
|
const char *alias, bool bit_fields_as_long);
|
||||||
bool init_result_table(ulonglong select_options);
|
bool init_result_table(ulonglong select_options);
|
||||||
bool send_data(List<Item> &items);
|
bool send_data(List<Item> &items);
|
||||||
void cleanup()
|
void cleanup();
|
||||||
{
|
|
||||||
memset(col_stat, 0, table->s->fields * sizeof(Column_statistics));
|
|
||||||
max_nulls_in_row= 0;
|
|
||||||
count_rows= 0;
|
|
||||||
}
|
|
||||||
ha_rows get_null_count_of_col(uint idx)
|
ha_rows get_null_count_of_col(uint idx)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(idx < table->s->fields);
|
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()
|
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 ||
|
if (end <= begin ||
|
||||||
merge_buffer_size < (ulong) (key_length * (end - begin + 1)) ||
|
merge_buffer_size < (ulong) (key_length * (end - begin + 1)) ||
|
||||||
init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0,
|
init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0,
|
||||||
buffpek_compare, &compare_context))
|
buffpek_compare, &compare_context, 0, 0))
|
||||||
return 1;
|
return 1;
|
||||||
/* we need space for one key when a piece of merge buffer is re-read */
|
/* we need space for one key when a piece of merge buffer is re-read */
|
||||||
merge_buffer_size-= key_length;
|
merge_buffer_size-= key_length;
|
||||||
@@ -468,7 +468,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
|
|||||||
*/
|
*/
|
||||||
top->key+= key_length;
|
top->key+= key_length;
|
||||||
if (--top->mem_count)
|
if (--top->mem_count)
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
else /* next piece should be read */
|
else /* next piece should be read */
|
||||||
{
|
{
|
||||||
/* save old_key not to overwrite it in read_to_buffer */
|
/* 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))
|
if (bytes_read == (uint) (-1))
|
||||||
goto end;
|
goto end;
|
||||||
else if (bytes_read > 0) /* top->key, top->mem_count are reset */
|
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
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Tree for old 'top' element is empty: remove it from the queue and
|
Tree for old 'top' element is empty: remove it from the queue and
|
||||||
give all its memory to the nearest tree.
|
give all its memory to the nearest tree.
|
||||||
*/
|
*/
|
||||||
queue_remove(&queue, 0);
|
queue_remove_top(&queue);
|
||||||
reuse_freed_buff(&queue, top, key_length);
|
reuse_freed_buff(&queue, top, key_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -473,14 +473,15 @@ static void _ftb_init_index_search(FT_INFO *ftb)
|
|||||||
int i;
|
int i;
|
||||||
FTB_WORD *ftbw;
|
FTB_WORD *ftbw;
|
||||||
|
|
||||||
if ((ftb->state != READY && ftb->state !=INDEX_DONE) ||
|
if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
|
||||||
ftb->keynr == NO_SUCH_KEY)
|
|
||||||
return;
|
return;
|
||||||
ftb->state=INDEX_SEARCH;
|
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)
|
if (ftbw->flags & FTB_FLAG_TRUNC)
|
||||||
{
|
{
|
||||||
@@ -585,7 +586,7 @@ FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
|
|||||||
sizeof(void *))))
|
sizeof(void *))))
|
||||||
goto err;
|
goto err;
|
||||||
reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0,
|
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)
|
for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev)
|
||||||
queue_insert(&ftb->queue, (uchar *)ftbw);
|
queue_insert(&ftb->queue, (uchar *)ftbw);
|
||||||
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
|
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 */
|
/* update queue */
|
||||||
_ft2_search(ftb, ftbw, 0);
|
_ft2_search(ftb, ftbw, 0);
|
||||||
queue_replaced(& ftb->queue);
|
queue_replace_top(&ftb->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ftbe=ftb->root;
|
ftbe=ftb->root;
|
||||||
|
@@ -253,12 +253,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query,
|
|||||||
{
|
{
|
||||||
QUEUE best;
|
QUEUE best;
|
||||||
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
|
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,
|
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
|
||||||
&best, left_root_right);
|
&best, left_root_right);
|
||||||
while (best.elements)
|
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))
|
if (!(*info->read_record)(info, record, docid))
|
||||||
{
|
{
|
||||||
info->update|= HA_STATE_AKTIV;
|
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,
|
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
|
||||||
(int (*)(void*, uchar *,uchar*)) info->key_cmp,
|
(int (*)(void*, uchar *,uchar*)) info->key_cmp,
|
||||||
(void*) info))
|
(void*) info, 0, 0))
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
|
|
||||||
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
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;
|
uchar *base= buffpek->base;
|
||||||
uint max_keys=buffpek->max_keys;
|
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 */
|
/* Put room used by buffer to use in other buffer */
|
||||||
for (refpek= (BUFFPEK**) &queue_top(&queue);
|
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)
|
else if (error == -1)
|
||||||
goto err; /* purecov: inspected */
|
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);
|
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
|
Create a global priority queue in preparation for making
|
||||||
temporary Huffman trees.
|
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;
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1521,7 +1521,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
|
|||||||
if (queue.max_elements < found)
|
if (queue.max_elements < found)
|
||||||
{
|
{
|
||||||
delete_queue(&queue);
|
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;
|
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
|
Make a priority queue from the queue. Construct its index so that we
|
||||||
have a partially ordered tree.
|
have a partially ordered tree.
|
||||||
*/
|
*/
|
||||||
for (i=found/2 ; i > 0 ; i--)
|
queue_fix(&queue);
|
||||||
_downheap(&queue,i);
|
|
||||||
|
|
||||||
/* The Huffman algorithm. */
|
/* The Huffman algorithm. */
|
||||||
bytes_packed=0; bits_packed=0;
|
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,
|
Popping from a priority queue includes a re-ordering of the queue,
|
||||||
to get the next least incidence element to the top.
|
to get the next least incidence element to the top.
|
||||||
*/
|
*/
|
||||||
a=(HUFF_ELEMENT*) queue_remove(&queue,0);
|
a=(HUFF_ELEMENT*) queue_remove_top(&queue);
|
||||||
/*
|
/* Copy the next least incidence element */
|
||||||
Copy the next least incidence element. The queue implementation
|
b=(HUFF_ELEMENT*) queue_top(&queue);
|
||||||
reserves root[0] for temporary purposes. root[1] is the top.
|
|
||||||
*/
|
|
||||||
b=(HUFF_ELEMENT*) queue.root[1];
|
|
||||||
/* Get a new element from the element buffer. */
|
/* Get a new element from the element buffer. */
|
||||||
new_huff_el=huff_tree->element_buffer+found+i;
|
new_huff_el=huff_tree->element_buffer+found+i;
|
||||||
/* The new element gets the sum of the two least incidence elements. */
|
/* 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
|
Replace the copied top element by the new element and re-order the
|
||||||
queue.
|
queue.
|
||||||
*/
|
*/
|
||||||
queue.root[1]=(uchar*) new_huff_el;
|
queue_top(&queue)= (uchar*) new_huff_el;
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
}
|
}
|
||||||
huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
|
huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
|
||||||
huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
|
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
|
Make a priority queue from the queue. Construct its index so that we
|
||||||
have a partially ordered tree.
|
have a partially ordered tree.
|
||||||
*/
|
*/
|
||||||
for (i=(found+1)/2 ; i > 0 ; i--)
|
queue_fix(&queue);
|
||||||
_downheap(&queue,i);
|
|
||||||
|
|
||||||
/* The Huffman algorithm. */
|
/* The Huffman algorithm. */
|
||||||
for (i=0 ; i < found-1 ; i++)
|
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
|
incidence). Popping from a priority queue includes a re-ordering
|
||||||
of the queue, to get the next least incidence element to the top.
|
of the queue, to get the next least incidence element to the top.
|
||||||
*/
|
*/
|
||||||
a= (my_off_t*) queue_remove(&queue, 0);
|
a= (my_off_t*) queue_remove_top(&queue);
|
||||||
/*
|
/* Copy the next least incidence element. */
|
||||||
Copy the next least incidence element. The queue implementation
|
b= (my_off_t*) queue_top(&queue);
|
||||||
reserves root[0] for temporary purposes. root[1] is the top.
|
|
||||||
*/
|
|
||||||
b= (my_off_t*) queue.root[1];
|
|
||||||
/* Create a new element in a local (automatic) buffer. */
|
/* Create a new element in a local (automatic) buffer. */
|
||||||
new_huff_el= element_buffer + i;
|
new_huff_el= element_buffer + i;
|
||||||
/* The new element gets the sum of the two least incidence elements. */
|
/* 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
|
queue. This successively replaces the references to counts by
|
||||||
references to HUFF_ELEMENTs.
|
references to HUFF_ELEMENTs.
|
||||||
*/
|
*/
|
||||||
queue.root[1]=(uchar*) new_huff_el;
|
queue_top(&queue)= (uchar*) new_huff_el;
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
|
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)
|
static void _ftb_init_index_search(FT_INFO *ftb)
|
||||||
{
|
{
|
||||||
int i;
|
uint i;
|
||||||
FTB_WORD *ftbw;
|
FTB_WORD *ftbw;
|
||||||
|
|
||||||
if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
|
if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
|
||||||
return;
|
return;
|
||||||
ftb->state=INDEX_SEARCH;
|
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)
|
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 *))))
|
sizeof(void *))))
|
||||||
goto err;
|
goto err;
|
||||||
reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0,
|
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)
|
for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev)
|
||||||
queue_insert(&ftb->queue, (uchar *)ftbw);
|
queue_insert(&ftb->queue, (uchar *)ftbw);
|
||||||
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
|
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
|
||||||
sizeof(FTB_WORD *)*ftb->queue.elements);
|
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 *),
|
my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *),
|
||||||
(qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset);
|
(qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset);
|
||||||
if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC;
|
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 */
|
/* update queue */
|
||||||
_ft2_search(ftb, ftbw, 0);
|
_ft2_search(ftb, ftbw, 0);
|
||||||
queue_replaced(& ftb->queue);
|
queue_replace_top(&ftb->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ftbe=ftb->root;
|
ftbe=ftb->root;
|
||||||
|
@@ -250,12 +250,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query,
|
|||||||
{
|
{
|
||||||
QUEUE best;
|
QUEUE best;
|
||||||
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
|
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,
|
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
|
||||||
&best, left_root_right);
|
&best, left_root_right);
|
||||||
while (best.elements)
|
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))
|
if (!(*info->read_record)(info,docid,record))
|
||||||
{
|
{
|
||||||
info->update|= HA_STATE_AKTIV;
|
info->update|= HA_STATE_AKTIV;
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
valgrind="valgrind --alignment=8 --leak-check=yes"
|
valgrind="valgrind --alignment=8 --leak-check=yes"
|
||||||
silent="-s"
|
silent="-s"
|
||||||
|
rm -f test1.TMD
|
||||||
|
|
||||||
if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi
|
if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi
|
||||||
./mi_test1$suffix $silent
|
./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
|
Create a global priority queue in preparation for making
|
||||||
temporary Huffman trees.
|
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;
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1511,7 +1511,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
|
|||||||
if (queue.max_elements < found)
|
if (queue.max_elements < found)
|
||||||
{
|
{
|
||||||
delete_queue(&queue);
|
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;
|
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
|
Make a priority queue from the queue. Construct its index so that we
|
||||||
have a partially ordered tree.
|
have a partially ordered tree.
|
||||||
*/
|
*/
|
||||||
for (i=found/2 ; i > 0 ; i--)
|
queue_fix(&queue);
|
||||||
_downheap(&queue,i);
|
|
||||||
|
|
||||||
/* The Huffman algorithm. */
|
/* The Huffman algorithm. */
|
||||||
bytes_packed=0; bits_packed=0;
|
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,
|
Popping from a priority queue includes a re-ordering of the queue,
|
||||||
to get the next least incidence element to the top.
|
to get the next least incidence element to the top.
|
||||||
*/
|
*/
|
||||||
a=(HUFF_ELEMENT*) queue_remove(&queue,0);
|
a=(HUFF_ELEMENT*) queue_remove_top(&queue);
|
||||||
/*
|
/* Copy the next least incidence element */
|
||||||
Copy the next least incidence element. The queue implementation
|
b=(HUFF_ELEMENT*) queue_top(&queue);
|
||||||
reserves root[0] for temporary purposes. root[1] is the top.
|
|
||||||
*/
|
|
||||||
b=(HUFF_ELEMENT*) queue.root[1];
|
|
||||||
/* Get a new element from the element buffer. */
|
/* Get a new element from the element buffer. */
|
||||||
new_huff_el=huff_tree->element_buffer+found+i;
|
new_huff_el=huff_tree->element_buffer+found+i;
|
||||||
/* The new element gets the sum of the two least incidence elements. */
|
/* 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
|
Replace the copied top element by the new element and re-order the
|
||||||
queue.
|
queue.
|
||||||
*/
|
*/
|
||||||
queue.root[1]=(uchar*) new_huff_el;
|
queue_top(&queue)= (uchar*) new_huff_el;
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
}
|
}
|
||||||
huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
|
huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
|
||||||
huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
|
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
|
Make a priority queue from the queue. Construct its index so that we
|
||||||
have a partially ordered tree.
|
have a partially ordered tree.
|
||||||
*/
|
*/
|
||||||
for (i=(found+1)/2 ; i > 0 ; i--)
|
queue_fix(&queue);
|
||||||
_downheap(&queue,i);
|
|
||||||
|
|
||||||
/* The Huffman algorithm. */
|
/* The Huffman algorithm. */
|
||||||
for (i=0 ; i < found-1 ; i++)
|
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
|
incidence). Popping from a priority queue includes a re-ordering
|
||||||
of the queue, to get the next least incidence element to the top.
|
of the queue, to get the next least incidence element to the top.
|
||||||
*/
|
*/
|
||||||
a= (my_off_t*) queue_remove(&queue, 0);
|
a= (my_off_t*) queue_remove_top(&queue);
|
||||||
/*
|
/* Copy the next least incidence element. */
|
||||||
Copy the next least incidence element. The queue implementation
|
b= (my_off_t*) queue_top(&queue);
|
||||||
reserves root[0] for temporary purposes. root[1] is the top.
|
|
||||||
*/
|
|
||||||
b= (my_off_t*) queue.root[1];
|
|
||||||
/* Create a new element in a local (automatic) buffer. */
|
/* Create a new element in a local (automatic) buffer. */
|
||||||
new_huff_el= element_buffer + i;
|
new_huff_el= element_buffer + i;
|
||||||
/* The new element gets the sum of the two least incidence elements. */
|
/* 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
|
queue. This successively replaces the references to counts by
|
||||||
references to HUFF_ELEMENTs.
|
references to HUFF_ELEMENTs.
|
||||||
*/
|
*/
|
||||||
queue.root[1]=(uchar*) new_huff_el;
|
queue_top(&queue)= (uchar*) new_huff_el;
|
||||||
queue_replaced(&queue);
|
queue_replace_top(&queue);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
|
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,
|
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
|
||||||
(int (*)(void*, uchar *,uchar*)) info->key_cmp,
|
(int (*)(void*, uchar *,uchar*)) info->key_cmp,
|
||||||
(void*) info))
|
(void*) info, 0, 0))
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
|
|
||||||
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
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;
|
uchar *base= buffpek->base;
|
||||||
uint max_keys=buffpek->max_keys;
|
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 */
|
/* Put room used by buffer to use in other buffer */
|
||||||
for (refpek= (BUFFPEK**) &queue_top(&queue);
|
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)
|
else if (error == -1)
|
||||||
goto err; /* purecov: inspected */
|
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);
|
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,
|
if (init_queue(q,info->tables, 0,
|
||||||
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
|
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
|
||||||
queue_key_cmp,
|
queue_key_cmp,
|
||||||
info->open_tables->table->s->keyinfo[inx].seg))
|
info->open_tables->table->s->keyinfo[inx].seg, 0, 0))
|
||||||
error=my_errno;
|
error=my_errno;
|
||||||
}
|
}
|
||||||
else
|
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,
|
if (reinit_queue(q,info->tables, 0,
|
||||||
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
|
(myisam_readnext_vec[search_flag] == SEARCH_SMALLER),
|
||||||
queue_key_cmp,
|
queue_key_cmp,
|
||||||
info->open_tables->table->s->keyinfo[inx].seg))
|
info->open_tables->table->s->keyinfo[inx].seg, 0, 0))
|
||||||
error=my_errno;
|
error=my_errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ int myrg_rnext(MYRG_INFO *info, uchar *buf, int inx)
|
|||||||
{
|
{
|
||||||
if (err == HA_ERR_END_OF_FILE)
|
if (err == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
queue_remove(&(info->by_key),0);
|
queue_remove_top(&(info->by_key));
|
||||||
if (!info->by_key.elements)
|
if (!info->by_key.elements)
|
||||||
return HA_ERR_END_OF_FILE;
|
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 */
|
/* Found here, adding to queue */
|
||||||
queue_top(&(info->by_key))=(uchar *)(info->current_table);
|
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 */
|
/* 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)
|
if (err == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
queue_remove(&(info->by_key),0);
|
queue_remove_top(&(info->by_key));
|
||||||
if (!info->by_key.elements)
|
if (!info->by_key.elements)
|
||||||
return HA_ERR_END_OF_FILE;
|
return HA_ERR_END_OF_FILE;
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ int myrg_rnext_same(MYRG_INFO *info, uchar *buf)
|
|||||||
{
|
{
|
||||||
/* Found here, adding to queue */
|
/* Found here, adding to queue */
|
||||||
queue_top(&(info->by_key))=(uchar *)(info->current_table);
|
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 */
|
/* 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)
|
if (err == HA_ERR_END_OF_FILE)
|
||||||
{
|
{
|
||||||
queue_remove(&(info->by_key),0);
|
queue_remove_top(&(info->by_key));
|
||||||
if (!info->by_key.elements)
|
if (!info->by_key.elements)
|
||||||
return HA_ERR_END_OF_FILE;
|
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 */
|
/* Found here, adding to queue */
|
||||||
queue_top(&(info->by_key))=(uchar *)(info->current_table);
|
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 */
|
/* now, mymerge's read_prev is as simple as one queue_top */
|
||||||
|
Reference in New Issue
Block a user