Merge branch '5.5' into 10.1
This commit is contained in:
commit
23c6fb3e62
@ -32,7 +32,7 @@
|
||||
** master/autocommit code by Brian Aker <brian@tangent.org>
|
||||
** SSL by
|
||||
** Andrei Errapart <andreie@no.spam.ee>
|
||||
** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
|
||||
** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
|
||||
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
|
||||
** and adapted to mysqldump 05/11/01 by Jani Tolonen
|
||||
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
|
||||
|
@ -55,7 +55,7 @@ typedef struct st_queue {
|
||||
#define queue_top(queue) ((queue)->root[1])
|
||||
#define queue_element(queue,index) ((queue)->root[index])
|
||||
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
||||
#define queue_replace_top(queue) _downheap(queue, 1, (queue)->root[1])
|
||||
#define queue_replace_top(queue) _downheap(queue, 1)
|
||||
#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg
|
||||
#define queue_set_max_at_top(queue, set_arg) \
|
||||
(queue)->max_at_top= set_arg ? -1 : 1
|
||||
@ -63,23 +63,23 @@ typedef struct st_queue {
|
||||
typedef int (*queue_compare)(void *,uchar *, uchar *);
|
||||
|
||||
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||
pbool max_at_top, queue_compare compare,
|
||||
my_bool max_at_top, queue_compare compare,
|
||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||
uint auto_extent);
|
||||
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
|
||||
pbool max_at_top, queue_compare compare,
|
||||
my_bool max_at_top, queue_compare compare,
|
||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||
uint auto_extent);
|
||||
int resize_queue(QUEUE *queue, uint max_elements);
|
||||
void delete_queue(QUEUE *queue);
|
||||
void queue_insert(QUEUE *queue,uchar *element);
|
||||
void queue_insert(QUEUE *queue, uchar *element);
|
||||
int queue_insert_safe(QUEUE *queue, uchar *element);
|
||||
uchar *queue_remove(QUEUE *queue,uint idx);
|
||||
void queue_replace(QUEUE *queue,uint idx);
|
||||
|
||||
#define queue_remove_all(queue) { (queue)->elements= 0; }
|
||||
#define queue_is_full(queue) (queue->elements == queue->max_elements)
|
||||
void _downheap(QUEUE *queue, uint idx, uchar *element);
|
||||
void _downheap(QUEUE *queue, uint idx);
|
||||
void queue_fix(QUEUE *queue);
|
||||
#define is_queue_inited(queue) ((queue)->root != 0)
|
||||
|
||||
|
@ -206,7 +206,7 @@ int main(int argc, const char** argv )
|
||||
} else {
|
||||
if (strcmp(arg, "--verbose") == 0)
|
||||
verbose++;
|
||||
else if (strncmp(arg, "--parent-pid", 10) == 0)
|
||||
else if (strncmp(arg, "--parent-pid", 12) == 0)
|
||||
{
|
||||
/* Override parent_pid with a value provided by user */
|
||||
const char* start;
|
||||
|
@ -281,7 +281,7 @@ my $current_config_name; # The currently running config file template
|
||||
our @opt_experimentals;
|
||||
our $experimental_test_cases= [];
|
||||
|
||||
my $baseport;
|
||||
our $baseport;
|
||||
# $opt_build_thread may later be set from $opt_port_base
|
||||
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";
|
||||
my $opt_port_base= $ENV{'MTR_PORT_BASE'} || "auto";
|
||||
|
@ -62,9 +62,10 @@ sub skip_combinations {
|
||||
sub ipv6_ok() {
|
||||
use Socket;
|
||||
return 0 unless socket my $sock, PF_INET6, SOCK_STREAM, getprotobyname('tcp');
|
||||
$!="";
|
||||
# eval{}, if there's no Socket::sockaddr_in6 at all, old Perl installation
|
||||
eval { connect $sock, sockaddr_in6(7, Socket::IN6ADDR_LOOPBACK) };
|
||||
return $@ eq "";
|
||||
eval { bind $sock, sockaddr_in6($::baseport, Socket::IN6ADDR_LOOPBACK) };
|
||||
return $@ eq "" && $! eq ""
|
||||
}
|
||||
$skip{'include/check_ipv6.inc'} = 'No IPv6' unless ipv6_ok();
|
||||
|
||||
|
@ -65,5 +65,20 @@ include/diff_tables.inc [master:t1,slave:t1]
|
||||
# comments
|
||||
SELECT c1 FROM /*!999999 t1 WHEREN;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '/*!999999 t1 WHEREN' at line 1
|
||||
insert t1 values (/*!50505 1 /* foo */ */ + 2);
|
||||
insert t1 values (/*!999999 10 /* foo */ */ + 20);
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; insert t1 values (/*!50505 1 /* foo */ */ + 2)
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; insert t1 values (/* 999999 10 (* foo *) */ + 20)
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
select * from t1;
|
||||
c1
|
||||
62
|
||||
3
|
||||
20
|
||||
DROP TABLE t1;
|
||||
include/rpl_end.inc
|
||||
|
16
mysql-test/suite/rpl/r/rpl_fail_register.result
Normal file
16
mysql-test/suite/rpl/r/rpl_fail_register.result
Normal file
@ -0,0 +1,16 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
set @old_dbug=@@global.debug_dbug;
|
||||
set global debug_dbug='d,fail_com_register_slave';
|
||||
stop slave;
|
||||
reset slave;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
start slave;
|
||||
stop slave;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
set global debug_dbug=@old_dbug;
|
||||
kill DUMP_THREAD;
|
||||
show slave hosts;
|
||||
Server_id Host Port Master_id
|
||||
start slave;
|
||||
include/rpl_end.inc
|
@ -68,7 +68,17 @@ sync_slave_with_master;
|
||||
--echo # comments
|
||||
--connection master
|
||||
--error 1064
|
||||
SELECT c1 FROM /*!999999 t1 WHEREN;
|
||||
SELECT c1 FROM /*!999999 t1 WHEREN; #*/
|
||||
|
||||
#
|
||||
# Bug#28388217 - SERVER CAN FAIL WHILE REPLICATING CONDITIONAL COMMENTS
|
||||
#
|
||||
insert t1 values (/*!50505 1 /* foo */ */ + 2);
|
||||
insert t1 values (/*!999999 10 /* foo */ */ + 20);
|
||||
source include/show_binlog_events.inc;
|
||||
sync_slave_with_master;
|
||||
select * from t1;
|
||||
connection master;
|
||||
|
||||
DROP TABLE t1;
|
||||
--source include/rpl_end.inc
|
||||
|
33
mysql-test/suite/rpl/t/rpl_fail_register.test
Normal file
33
mysql-test/suite/rpl/t/rpl_fail_register.test
Normal file
@ -0,0 +1,33 @@
|
||||
source include/have_debug.inc;
|
||||
source include/have_binlog_format_mixed.inc;
|
||||
source include/master-slave.inc;
|
||||
|
||||
connection slave;
|
||||
|
||||
set @old_dbug=@@global.debug_dbug;
|
||||
set global debug_dbug='d,fail_com_register_slave';
|
||||
|
||||
stop slave;
|
||||
reset slave;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
start slave;
|
||||
stop slave;
|
||||
source include/wait_for_slave_to_stop.inc;
|
||||
set global debug_dbug=@old_dbug;
|
||||
|
||||
connection master;
|
||||
|
||||
### why is that needed?
|
||||
let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`;
|
||||
if ($id) {
|
||||
replace_result $id DUMP_THREAD;
|
||||
eval kill $id;
|
||||
let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Binlog Dump';
|
||||
source include/wait_condition.inc;
|
||||
}
|
||||
|
||||
show slave hosts;
|
||||
|
||||
connection slave;
|
||||
start slave;
|
||||
source include/rpl_end.inc;
|
169
mysys/queues.c
169
mysys/queues.c
@ -70,10 +70,9 @@
|
||||
*/
|
||||
|
||||
int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
|
||||
pbool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
||||
my_bool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||
uint auto_extent)
|
||||
|
||||
{
|
||||
DBUG_ENTER("init_queue");
|
||||
if ((queue->root= (uchar **) my_malloc((max_elements + 1) * sizeof(void*),
|
||||
@ -109,7 +108,7 @@ int init_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 *),
|
||||
my_bool max_at_top, int (*compare) (void *, uchar *, uchar *),
|
||||
void *first_cmp_arg, uint offset_to_queue_pos,
|
||||
uint auto_extent)
|
||||
{
|
||||
@ -182,6 +181,28 @@ void delete_queue(QUEUE *queue)
|
||||
}
|
||||
|
||||
|
||||
static void insert_at(QUEUE *queue, uchar *element, uint idx)
|
||||
{
|
||||
uint next_index, offset_to_key= queue->offset_to_key;
|
||||
uint offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||
/* max_at_top swaps the comparison if we want to order by desc */
|
||||
while ((next_index= idx >> 1) > 0 &&
|
||||
queue->compare(queue->first_cmp_arg,
|
||||
element + offset_to_key,
|
||||
queue->root[next_index] + offset_to_key) *
|
||||
queue->max_at_top < 0)
|
||||
{
|
||||
queue->root[idx]= queue->root[next_index];
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||
idx= next_index;
|
||||
}
|
||||
queue->root[idx]= element;
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Insert element in queue
|
||||
|
||||
@ -191,28 +212,10 @@ void delete_queue(QUEUE *queue)
|
||||
element Element to insert
|
||||
*/
|
||||
|
||||
void queue_insert(register QUEUE *queue, uchar *element)
|
||||
void queue_insert(QUEUE *queue, uchar *element)
|
||||
{
|
||||
reg2 uint idx, next;
|
||||
uint offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||
DBUG_ASSERT(queue->elements < queue->max_elements);
|
||||
|
||||
idx= ++queue->elements;
|
||||
/* max_at_top swaps the comparison if we want to order by desc */
|
||||
while (idx > 1 &&
|
||||
(queue->compare(queue->first_cmp_arg,
|
||||
element + queue->offset_to_key,
|
||||
queue->root[(next= idx >> 1)] +
|
||||
queue->offset_to_key) * queue->max_at_top) < 0)
|
||||
{
|
||||
queue->root[idx]= queue->root[next];
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||
idx= next;
|
||||
}
|
||||
queue->root[idx]= element;
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (element+ offset_to_queue_pos-1))= idx;
|
||||
insert_at(queue, element, ++queue->elements);
|
||||
}
|
||||
|
||||
|
||||
@ -230,7 +233,7 @@ void queue_insert(register QUEUE *queue, uchar *element)
|
||||
2 auto_extend is 0; No insertion done
|
||||
*/
|
||||
|
||||
int queue_insert_safe(register QUEUE *queue, uchar *element)
|
||||
int queue_insert_safe(QUEUE *queue, uchar *element)
|
||||
{
|
||||
|
||||
if (queue->elements == queue->max_elements)
|
||||
@ -240,7 +243,7 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
|
||||
if (resize_queue(queue, queue->max_elements + queue->auto_extent))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
queue_insert(queue, element);
|
||||
return 0;
|
||||
}
|
||||
@ -259,81 +262,55 @@ int queue_insert_safe(register QUEUE *queue, uchar *element)
|
||||
pointer to removed element
|
||||
*/
|
||||
|
||||
uchar *queue_remove(register QUEUE *queue, uint idx)
|
||||
uchar *queue_remove(QUEUE *queue, uint idx)
|
||||
{
|
||||
uchar *element;
|
||||
DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
|
||||
DBUG_ASSERT(idx >= 1);
|
||||
DBUG_ASSERT(idx <= queue->elements);
|
||||
element= queue->root[idx];
|
||||
_downheap(queue, idx, queue->root[queue->elements--]);
|
||||
queue->root[idx]= queue->root[queue->elements--];
|
||||
queue_replace(queue, idx);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Add element to fixed position and update heap
|
||||
Restores the heap property from idx down the heap
|
||||
|
||||
SYNOPSIS
|
||||
_downheap()
|
||||
queue Queue to use
|
||||
idx Index of element to change
|
||||
element Element to store at 'idx'
|
||||
|
||||
NOTE
|
||||
This only works if element is >= all elements <= start_idx
|
||||
*/
|
||||
|
||||
void _downheap(register QUEUE *queue, uint start_idx, uchar *element)
|
||||
void _downheap(QUEUE *queue, uint idx)
|
||||
{
|
||||
uint elements,half_queue,offset_to_key, next_index, offset_to_queue_pos;
|
||||
register uint idx= start_idx;
|
||||
my_bool first= TRUE;
|
||||
|
||||
offset_to_key=queue->offset_to_key;
|
||||
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||
half_queue= (elements= queue->elements) >> 1;
|
||||
uchar *element= queue->root[idx];
|
||||
uint next_index,
|
||||
elements= queue->elements,
|
||||
half_queue= elements >> 1,
|
||||
offset_to_key= queue->offset_to_key,
|
||||
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||
|
||||
while (idx <= half_queue)
|
||||
{
|
||||
next_index=idx+idx;
|
||||
next_index= idx+idx;
|
||||
if (next_index < elements &&
|
||||
(queue->compare(queue->first_cmp_arg,
|
||||
queue->root[next_index]+offset_to_key,
|
||||
queue->root[next_index+1]+offset_to_key) *
|
||||
queue->max_at_top) > 0)
|
||||
(queue->compare(queue->first_cmp_arg,
|
||||
queue->root[next_index]+offset_to_key,
|
||||
queue->root[next_index+1]+offset_to_key) *
|
||||
queue->max_at_top) > 0)
|
||||
next_index++;
|
||||
if (first &&
|
||||
(((queue->compare(queue->first_cmp_arg,
|
||||
queue->root[next_index]+offset_to_key,
|
||||
element+offset_to_key) * queue->max_at_top) >= 0)))
|
||||
{
|
||||
queue->root[idx]= element;
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||
return;
|
||||
}
|
||||
first= FALSE;
|
||||
queue->root[idx]= queue->root[next_index];
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||
idx=next_index;
|
||||
}
|
||||
|
||||
/*
|
||||
Insert the element into the right position. This is the same code
|
||||
as we have in queue_insert()
|
||||
*/
|
||||
while ((next_index= (idx >> 1)) > start_idx &&
|
||||
queue->compare(queue->first_cmp_arg,
|
||||
element+offset_to_key,
|
||||
queue->root[next_index]+offset_to_key)*
|
||||
queue->max_at_top < 0)
|
||||
{
|
||||
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];
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||
idx= next_index;
|
||||
}
|
||||
queue->root[idx]= element;
|
||||
queue->root[idx]=element;
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||
}
|
||||
@ -351,7 +328,7 @@ void queue_fix(QUEUE *queue)
|
||||
{
|
||||
uint i;
|
||||
for (i= queue->elements >> 1; i > 0; i--)
|
||||
_downheap(queue, i, queue_element(queue, i));
|
||||
_downheap(queue, i);
|
||||
}
|
||||
|
||||
|
||||
@ -362,13 +339,47 @@ void queue_fix(QUEUE *queue)
|
||||
queue_replace()
|
||||
queue Queue to use
|
||||
idx Index of element to change
|
||||
element Element to store at 'idx'
|
||||
|
||||
NOTE
|
||||
optimized for the case when the new position is close to the end of the
|
||||
heap (typical for queue_remove() replacements).
|
||||
*/
|
||||
|
||||
void queue_replace(QUEUE *queue, uint idx)
|
||||
{
|
||||
uchar *element= queue->root[idx];
|
||||
DBUG_ASSERT(idx >= 1 && idx <= queue->elements);
|
||||
queue_remove(queue, idx);
|
||||
queue_insert(queue, element);
|
||||
uint next_index,
|
||||
elements= queue->elements,
|
||||
half_queue= elements>>1,
|
||||
offset_to_key= queue->offset_to_key,
|
||||
offset_to_queue_pos= queue->offset_to_queue_pos;
|
||||
my_bool first= TRUE;
|
||||
|
||||
while (idx <= half_queue)
|
||||
{
|
||||
next_index= idx + idx;
|
||||
if (next_index < elements &&
|
||||
queue->compare(queue->first_cmp_arg,
|
||||
queue->root[next_index]+offset_to_key,
|
||||
queue->root[next_index+1]+offset_to_key) *
|
||||
queue->max_at_top > 0)
|
||||
next_index++;
|
||||
if (first &&
|
||||
queue->compare(queue->first_cmp_arg,
|
||||
queue->root[next_index]+offset_to_key,
|
||||
element+offset_to_key) * queue->max_at_top >= 0)
|
||||
{
|
||||
queue->root[idx]= element;
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (element + offset_to_queue_pos-1))= idx;
|
||||
break;
|
||||
}
|
||||
first= FALSE;
|
||||
queue->root[idx]= queue->root[next_index];
|
||||
if (offset_to_queue_pos)
|
||||
(*(uint*) (queue->root[idx] + offset_to_queue_pos-1))= idx;
|
||||
idx=next_index;
|
||||
}
|
||||
|
||||
insert_at(queue, element, idx);
|
||||
}
|
||||
|
@ -1403,9 +1403,23 @@ unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
||||
{
|
||||
if (field - result >= (my_ptrdiff_t)fields)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
If any of the row->data[] below is NULL, it can result in a
|
||||
crash. Error out early as it indicates a malformed packet.
|
||||
For data[0], data[1] and data[5], strmake_root will handle
|
||||
NULL values.
|
||||
*/
|
||||
if (!row->data[2] || !row->data[3] || !row->data[4])
|
||||
{
|
||||
free_rows(data);
|
||||
set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
|
||||
field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
|
||||
field->name= strdup_root(alloc,(char*) row->data[1]);
|
||||
field->org_table= field->table= strmake_root(alloc,(char*) row->data[0], lengths[0]);
|
||||
field->name= strmake_root(alloc,(char*) row->data[1], lengths[1]);
|
||||
field->length= (uint) uint3korr(row->data[2]);
|
||||
field->type= (enum enum_field_types) (uchar) row->data[3][0];
|
||||
|
||||
@ -1430,7 +1444,7 @@ unpack_fields(MYSQL *mysql, MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
||||
field->flags|= NUM_FLAG;
|
||||
if (default_value && row->data[5])
|
||||
{
|
||||
field->def=strdup_root(alloc,(char*) row->data[5]);
|
||||
field->def= strmake_root(alloc,(char*) row->data[5], lengths[5]);
|
||||
field->def_length= lengths[5];
|
||||
}
|
||||
else
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
|
||||
/* Copyright (c) 2006, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2020, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -507,6 +508,7 @@ Event_scheduler::run(THD *thd)
|
||||
DBUG_PRINT("info", ("job_data is NULL, the thread was killed"));
|
||||
}
|
||||
DBUG_PRINT("info", ("state=%s", scheduler_states_names[state].str));
|
||||
free_root(thd->mem_root, MYF(0));
|
||||
}
|
||||
|
||||
LOCK_DATA();
|
||||
|
@ -358,9 +358,8 @@ QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
|
||||
uint mrr_buf_size, MEM_ROOT *alloc);
|
||||
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||
bool index_read_must_be_used,
|
||||
bool update_tbl_stats,
|
||||
double read_time,
|
||||
bool ror_scans_required);
|
||||
bool for_range_access,
|
||||
double read_time);
|
||||
static
|
||||
TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
|
||||
double read_time);
|
||||
@ -2599,7 +2598,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
|
||||
/* Get best 'range' plan and prepare data for making other plans */
|
||||
if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE,
|
||||
best_read_time, FALSE)))
|
||||
best_read_time)))
|
||||
{
|
||||
best_trp= range_trp;
|
||||
best_read_time= best_trp->read_cost;
|
||||
@ -4686,7 +4685,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
double roru_index_costs;
|
||||
ha_rows roru_total_records;
|
||||
double roru_intersect_part= 1.0;
|
||||
bool only_ror_scans_required= FALSE;
|
||||
DBUG_ENTER("get_best_disjunct_quick");
|
||||
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
|
||||
|
||||
@ -4713,8 +4711,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
n_child_scans)))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
only_ror_scans_required= !optimizer_flag(param->thd,
|
||||
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION);
|
||||
/*
|
||||
Collect best 'range' scan for each of disjuncts, and, while doing so,
|
||||
analyze possibility of ROR scans. Also calculate some values needed by
|
||||
@ -4727,8 +4723,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
|
||||
"tree in SEL_IMERGE"););
|
||||
if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE,
|
||||
read_time,
|
||||
only_ror_scans_required)))
|
||||
read_time)))
|
||||
{
|
||||
/*
|
||||
One of index scans in this index_merge is more expensive than entire
|
||||
@ -5048,9 +5043,12 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
|
||||
a random order
|
||||
2. the functions that estimate the cost of a range scan and an
|
||||
index merge retrievals are not well calibrated
|
||||
|
||||
As the best range access has been already chosen it does not
|
||||
make sense to evaluate the one obtained from a degenerated
|
||||
index merge.
|
||||
*/
|
||||
trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE,
|
||||
read_time, FALSE);
|
||||
trp= 0;
|
||||
}
|
||||
|
||||
DBUG_RETURN(trp);
|
||||
@ -6777,9 +6775,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
||||
tree make range select for this SEL_TREE
|
||||
index_read_must_be_used if TRUE, assume 'index only' option will be set
|
||||
(except for clustered PK indexes)
|
||||
for_range_access if TRUE the function is called to get the best range
|
||||
plan for range access, not for index merge access
|
||||
read_time don't create read plans with cost > read_time.
|
||||
only_ror_scans_required set to TRUE when we are only interested
|
||||
in ROR scan
|
||||
RETURN
|
||||
Best range read plan
|
||||
NULL if no plan found or error occurred
|
||||
@ -6787,9 +6785,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
||||
|
||||
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||
bool index_read_must_be_used,
|
||||
bool update_tbl_stats,
|
||||
double read_time,
|
||||
bool only_ror_scans_required)
|
||||
bool for_range_access,
|
||||
double read_time)
|
||||
{
|
||||
uint idx, best_idx;
|
||||
SEL_ARG *key_to_read= NULL;
|
||||
@ -6834,10 +6831,11 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
|
||||
(bool) param->table->covering_keys.is_set(keynr);
|
||||
|
||||
found_records= check_quick_select(param, idx, read_index_only, key,
|
||||
update_tbl_stats, &mrr_flags,
|
||||
for_range_access, &mrr_flags,
|
||||
&buf_size, &cost);
|
||||
|
||||
if (only_ror_scans_required && !param->is_ror_scan)
|
||||
if (!for_range_access && !param->is_ror_scan &&
|
||||
!optimizer_flag(param->thd,OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION))
|
||||
{
|
||||
/* The scan is not a ROR-scan, just skip it */
|
||||
continue;
|
||||
|
@ -4304,6 +4304,7 @@ connected:
|
||||
goto err;
|
||||
goto connected;
|
||||
}
|
||||
DBUG_EXECUTE_IF("fail_com_register_slave", goto err;);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info",("Starting reading binary log from master"));
|
||||
|
@ -71,6 +71,7 @@
|
||||
#ifdef HAVE_SYS_SYSCALL_H
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
#include "repl_failsafe.h"
|
||||
|
||||
/*
|
||||
The following is used to initialise Table_ident with a internal
|
||||
@ -1593,6 +1594,7 @@ THD::~THD()
|
||||
if (rgi_slave)
|
||||
rgi_slave->cleanup_after_session();
|
||||
my_free(semisync_info);
|
||||
unregister_slave(this, true, true);
|
||||
#endif
|
||||
main_lex.free_set_stmt_mem_root();
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2018, MariaDB Corporation
|
||||
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2020, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -1181,17 +1181,27 @@ static inline uint int_token(const char *str,uint length)
|
||||
*/
|
||||
bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
|
||||
{
|
||||
// only one level of nested comments are allowed
|
||||
DBUG_ASSERT(remaining_recursions_permitted == 0 ||
|
||||
remaining_recursions_permitted == 1);
|
||||
uchar c;
|
||||
while (! lip->eof())
|
||||
{
|
||||
c= lip->yyGet();
|
||||
|
||||
if (remaining_recursions_permitted > 0)
|
||||
if (remaining_recursions_permitted == 1)
|
||||
{
|
||||
if ((c == '/') && (lip->yyPeek() == '*'))
|
||||
{
|
||||
lip->yyUnput('('); // Replace nested "/*..." with "(*..."
|
||||
lip->yySkip(); // and skip "("
|
||||
|
||||
lip->yySkip(); /* Eat asterisk */
|
||||
consume_comment(lip, remaining_recursions_permitted-1);
|
||||
if (consume_comment(lip, 0))
|
||||
return true;
|
||||
|
||||
lip->yyUnput(')'); // Replace "...*/" with "...*)"
|
||||
lip->yySkip(); // and skip ")"
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1739,7 +1739,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos);
|
||||
if (nlen < FN_REFLEN)
|
||||
mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags);
|
||||
unregister_slave(thd,1,1);
|
||||
/* fake COM_QUIT -- if we get here, the thread needs to terminate */
|
||||
error = TRUE;
|
||||
break;
|
||||
|
@ -170,9 +170,9 @@ if (NOT CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set_cflags_if_supported(-Wcast-align)
|
||||
endif ()
|
||||
|
||||
## always want these in debug builds
|
||||
set(CMAKE_C_FLAGS_DEBUG "-Wall -Werror ${CMAKE_C_FLAGS_DEBUG}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Werror ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
## never want these
|
||||
set(CMAKE_C_FLAGS "-Wno-error ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-Wno-error ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# pick language dialect
|
||||
set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}")
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring
|
||||
aes
|
||||
LINK_LIBRARIES mysys)
|
||||
queues LINK_LIBRARIES mysys)
|
||||
MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
|
||||
|
||||
ADD_DEFINITIONS(${SSL_DEFINES})
|
||||
|
139
unittest/mysys/queues-t.c
Normal file
139
unittest/mysys/queues-t.c
Normal file
@ -0,0 +1,139 @@
|
||||
/* Copyright (c) 2020, MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include <queues.h>
|
||||
#include <my_rnd.h>
|
||||
#include "tap.h"
|
||||
|
||||
int cmp(void *arg __attribute__((unused)), uchar *a, uchar *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b;
|
||||
}
|
||||
|
||||
#define rnd(R) ((uint)(my_rnd(R) * INT_MAX32))
|
||||
|
||||
#define el(Q,I) ((uint)*queue_element(Q, I))
|
||||
|
||||
my_bool verbose;
|
||||
|
||||
my_bool check_queue(QUEUE *queue)
|
||||
{
|
||||
char b[1024]={0}, *s, *e=b+sizeof(b)-2;
|
||||
my_bool ok=1;
|
||||
uint i;
|
||||
|
||||
s= b + my_snprintf(b, e-b, "%x", el(queue, 1));
|
||||
for (i=2; i <= queue->elements; i++)
|
||||
{
|
||||
s+= my_snprintf(s, e-s, ", %x", el(queue, i));
|
||||
ok &= el(queue, i) <= el(queue, i>>1);
|
||||
}
|
||||
if (!ok || verbose)
|
||||
diag("%s", b);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main(int argc __attribute__((unused)), char *argv[])
|
||||
{
|
||||
QUEUE q, *queue=&q;
|
||||
MY_INIT(argv[0]);
|
||||
plan(19);
|
||||
|
||||
verbose=1;
|
||||
|
||||
init_queue(queue, 256, 0, 1, cmp, NULL, 0, 0);
|
||||
queue_insert(queue, (uchar*)"\x99");
|
||||
queue_insert(queue, (uchar*)"\x19");
|
||||
queue_insert(queue, (uchar*)"\x36");
|
||||
queue_insert(queue, (uchar*)"\x17");
|
||||
queue_insert(queue, (uchar*)"\x12");
|
||||
queue_insert(queue, (uchar*)"\x05");
|
||||
queue_insert(queue, (uchar*)"\x25");
|
||||
queue_insert(queue, (uchar*)"\x09");
|
||||
queue_insert(queue, (uchar*)"\x15");
|
||||
queue_insert(queue, (uchar*)"\x06");
|
||||
queue_insert(queue, (uchar*)"\x11");
|
||||
queue_insert(queue, (uchar*)"\x01");
|
||||
queue_insert(queue, (uchar*)"\x04");
|
||||
queue_insert(queue, (uchar*)"\x13");
|
||||
queue_insert(queue, (uchar*)"\x24");
|
||||
ok(check_queue(queue), "after insert");
|
||||
queue_remove(queue, 5);
|
||||
ok(check_queue(queue), "after remove 5th");
|
||||
|
||||
queue_element(queue, 1) = (uchar*)"\x01";
|
||||
queue_element(queue, 2) = (uchar*)"\x10";
|
||||
queue_element(queue, 3) = (uchar*)"\x04";
|
||||
queue_element(queue, 4) = (uchar*)"\x09";
|
||||
queue_element(queue, 5) = (uchar*)"\x13";
|
||||
queue_element(queue, 6) = (uchar*)"\x03";
|
||||
queue_element(queue, 7) = (uchar*)"\x08";
|
||||
queue_element(queue, 8) = (uchar*)"\x07";
|
||||
queue_element(queue, 9) = (uchar*)"\x06";
|
||||
queue_element(queue,10) = (uchar*)"\x12";
|
||||
queue_element(queue,11) = (uchar*)"\x05";
|
||||
queue_element(queue,12) = (uchar*)"\x02";
|
||||
queue_element(queue,13) = (uchar*)"\x11";
|
||||
queue->elements= 13;
|
||||
ok(!check_queue(queue), "manually filled (queue property violated)");
|
||||
|
||||
queue_fix(queue);
|
||||
ok(check_queue(queue), "fixed");
|
||||
|
||||
ok(*queue_remove_top(queue) == 0x13, "remove top 13");
|
||||
ok(*queue_remove_top(queue) == 0x12, "remove top 12");
|
||||
ok(*queue_remove_top(queue) == 0x11, "remove top 11");
|
||||
ok(*queue_remove_top(queue) == 0x10, "remove top 10");
|
||||
ok(*queue_remove_top(queue) == 0x09, "remove top 9");
|
||||
ok(*queue_remove_top(queue) == 0x08, "remove top 8");
|
||||
ok(*queue_remove_top(queue) == 0x07, "remove top 7");
|
||||
ok(*queue_remove_top(queue) == 0x06, "remove top 6");
|
||||
ok(*queue_remove_top(queue) == 0x05, "remove top 5");
|
||||
ok(*queue_remove_top(queue) == 0x04, "remove top 4");
|
||||
ok(*queue_remove_top(queue) == 0x03, "remove top 3");
|
||||
ok(*queue_remove_top(queue) == 0x02, "remove top 2");
|
||||
ok(*queue_remove_top(queue) == 0x01, "remove top 1");
|
||||
|
||||
/* random test */
|
||||
{
|
||||
int i, res;
|
||||
struct my_rnd_struct rand;
|
||||
my_rnd_init(&rand, (ulong)(intptr)&i, (ulong)(intptr)argv);
|
||||
verbose=0;
|
||||
|
||||
for (res= i=1; i <= 250; i++)
|
||||
{
|
||||
uchar *s=alloca(2);
|
||||
*s= rnd(&rand) % 251;
|
||||
queue_insert(queue, s);
|
||||
res &= check_queue(queue);
|
||||
}
|
||||
ok(res, "inserted 250");
|
||||
|
||||
while (queue->elements)
|
||||
{
|
||||
queue_remove(queue, (rnd(&rand) % queue->elements) + 1);
|
||||
res &= check_queue(queue);
|
||||
}
|
||||
ok(res, "removed 250");
|
||||
}
|
||||
|
||||
delete_queue(queue);
|
||||
my_end(0);
|
||||
return exit_status();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user