Merge branch '5.5' into 10.1

This commit is contained in:
Oleksandr Byelkin 2020-04-30 17:36:41 +02:00
commit 23c6fb3e62
20 changed files with 372 additions and 121 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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";

View File

@ -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();

View File

@ -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

View 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

View File

@ -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

View 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;

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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(&param, 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;

View File

@ -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"));

View File

@ -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));

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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}")

View File

@ -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
View 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();
}