diff options
-rw-r--r-- | client/mysqldump.c | 2 | ||||
-rw-r--r-- | include/queues.h | 10 | ||||
-rw-r--r-- | mysql-test/lib/My/SafeProcess/safe_process_win.cc | 2 | ||||
-rwxr-xr-x | mysql-test/mysql-test-run.pl | 2 | ||||
-rw-r--r-- | mysql-test/suite.pm | 5 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_conditional_comments.result | 15 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_fail_register.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_conditional_comments.test | 12 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_fail_register.test | 33 | ||||
-rw-r--r-- | mysys/queues.c | 169 | ||||
-rw-r--r-- | sql-common/client.c | 20 | ||||
-rw-r--r-- | sql/event_scheduler.cc | 4 | ||||
-rw-r--r-- | sql/opt_range.cc | 34 | ||||
-rw-r--r-- | sql/slave.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 18 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake | 6 | ||||
-rw-r--r-- | unittest/mysys/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unittest/mysys/queues-t.c | 139 |
20 files changed, 372 insertions, 121 deletions
diff --git a/client/mysqldump.c b/client/mysqldump.c index 624096189b7..5edb0793642 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -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 diff --git a/include/queues.h b/include/queues.h index f341bbb8148..99e640413e3 100644 --- a/include/queues.h +++ b/include/queues.h @@ -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) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 7d81bf1a1b4..4dd4e24f30d 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -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; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 920d66987e3..43e35bdab6d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -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"; diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index f90679e6f1f..3db419bae84 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -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(); diff --git a/mysql-test/suite/rpl/r/rpl_conditional_comments.result b/mysql-test/suite/rpl/r/rpl_conditional_comments.result index 5668322d4aa..f8ceed3fa36 100644 --- a/mysql-test/suite/rpl/r/rpl_conditional_comments.result +++ b/mysql-test/suite/rpl/r/rpl_conditional_comments.result @@ -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 diff --git a/mysql-test/suite/rpl/r/rpl_fail_register.result b/mysql-test/suite/rpl/r/rpl_fail_register.result new file mode 100644 index 00000000000..4e433636ad9 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_fail_register.result @@ -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 diff --git a/mysql-test/suite/rpl/t/rpl_conditional_comments.test b/mysql-test/suite/rpl/t/rpl_conditional_comments.test index bcc964a92c7..6e4ec8745f4 100644 --- a/mysql-test/suite/rpl/t/rpl_conditional_comments.test +++ b/mysql-test/suite/rpl/t/rpl_conditional_comments.test @@ -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 diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test new file mode 100644 index 00000000000..bfecc9d7f14 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_fail_register.test @@ -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; diff --git a/mysys/queues.c b/mysys/queues.c index 5d09ce2063f..7a0ef2017c2 100644 --- a/mysys/queues.c +++ b/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); } diff --git a/sql-common/client.c b/sql-common/client.c index 4f1cc6c564e..eee0ba8f2dd 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -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 diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 8c49e6f2746..96ea298fd11 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -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(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 92268ba69aa..e0eefe167ce 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -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; diff --git a/sql/slave.cc b/sql/slave.cc index 26fabc2cc52..0ce9c4cbbcd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -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")); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ab105c67507..6897a26bda1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -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)); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 27da1fc16fd..02c0df97cf3 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -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; } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d19cbf5ad9b..656da3b6a79 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -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; diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake index 8f65895cc9c..8b3a0e61418 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake @@ -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}") diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt index dd0db94a77c..9ad7e76f547 100644 --- a/unittest/mysys/CMakeLists.txt +++ b/unittest/mysys/CMakeLists.txt @@ -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}) diff --git a/unittest/mysys/queues-t.c b/unittest/mysys/queues-t.c new file mode 100644 index 00000000000..23cb0da1a32 --- /dev/null +++ b/unittest/mysys/queues-t.c @@ -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(); +} + |