summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-04-30 17:36:41 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-04-30 17:36:41 +0200
commit23c6fb3e6231b8939331e2d9f157092f24ed8f4f (patch)
treeff0f65edbc442afcc3f3a3159753c8a2284d9c95
parentde8c9b538f7e77f18470ccfcacf723a9c2e31b38 (diff)
parent6a31aea5a1a50614af3a6591a085dc47061cdd0e (diff)
downloadmariadb-git-23c6fb3e6231b8939331e2d9f157092f24ed8f4f.tar.gz
Merge branch '5.5' into 10.1
-rw-r--r--client/mysqldump.c2
-rw-r--r--include/queues.h10
-rw-r--r--mysql-test/lib/My/SafeProcess/safe_process_win.cc2
-rwxr-xr-xmysql-test/mysql-test-run.pl2
-rw-r--r--mysql-test/suite.pm5
-rw-r--r--mysql-test/suite/rpl/r/rpl_conditional_comments.result15
-rw-r--r--mysql-test/suite/rpl/r/rpl_fail_register.result16
-rw-r--r--mysql-test/suite/rpl/t/rpl_conditional_comments.test12
-rw-r--r--mysql-test/suite/rpl/t/rpl_fail_register.test33
-rw-r--r--mysys/queues.c169
-rw-r--r--sql-common/client.c20
-rw-r--r--sql/event_scheduler.cc4
-rw-r--r--sql/opt_range.cc34
-rw-r--r--sql/slave.cc1
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_lex.cc18
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake6
-rw-r--r--unittest/mysys/CMakeLists.txt2
-rw-r--r--unittest/mysys/queues-t.c139
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(&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;
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();
+}
+