Commit 132270d3 authored by Yuchen Pei's avatar Yuchen Pei

MDEV-34541 Clean up spider self reference check

SPIDER_CONN::loop_check_meraged_first is useless, because all
SPIDER_CONN_LOOP_CHECKs are in SPIDER_CONN::loop_check_queue, which in
spider_db_conn::fin_loop_check() is iterated over.

This fixes the use-after-free issue when there are three spider tables
sharing the same remote, and their corresponding
SPIDER_CONN_LOOP_CHECKs getting merged in
spider_conn_queue_and_merge_loop_check()

This also fixes MDEV-34555
parent 0bb98628
for master_1
for child2
for child3
SET SESSION spider_same_server_link=1;
SET sql_mode='';
set @old_table_open_cache=@@global.table_open_cache;
set global table_open_cache=10;
set spider_same_server_link= 1;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t1 (c INT) ENGINE=InnoDB;
CREATE TABLE t2 (c INT) ENGINE=InnoDB;
CREATE TABLE t3 (c INT) ENGINE=InnoDB;
CREATE TABLE ta (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t5 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t6 (c INT KEY) ENGINE=InnoDB PARTITION BY RANGE (c) (PARTITION p VALUES LESS THAN (5));
CREATE TABLE t7 (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t8 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
SELECT * FROM t8;
ERROR HY000: Remote table 'test.t' is not found
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB SELECT * FROM t7;
ERROR HY000: Remote table 'test.t' is not found
CALL foo;
ERROR 42000: PROCEDURE test.foo does not exist
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB;
SELECT * FROM t7 JOIN t6 ON tc=t0.c;
ERROR 42S22: Unknown column 'tc' in 'on clause'
SHOW TABLE STATUS;
drop table ta, t8, t7, t6, t5, t3, t2, t1;
drop table t7;
drop server srv;
set global table_open_cache=@old_table_open_cache;
for master_1
for child2
for child3
for master_1
for child2
for child3
set spider_same_server_link= 1;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE '',user 'Spider', password 'foo');
CREATE TABLE tSpider (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t2 (c INT,c2 CHAR(1)) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
XA START 'a';
SELECT * FROM information_schema.table_constraints;
SELECT SLEEP (1);
SLEEP (1)
0
SELECT * FROM t2;
ERROR HY000: Unable to connect to foreign data source: srv
SELECT SLEEP (1);
SLEEP (1)
0
SELECT * FROM t2;
ERROR HY000: Unable to connect to foreign data source: srv
SELECT SLEEP (1);
SLEEP (1)
0
SELECT * FROM t2;
ERROR HY000: Unable to connect to foreign data source: srv
xa end 'a';
xa rollback 'a';
drop table tSpider, t2;
drop server srv;
for master_1
for child2
for child3
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
SET SESSION spider_same_server_link=1;
SET sql_mode='';
set @old_table_open_cache=@@global.table_open_cache;
set global table_open_cache=10;
set spider_same_server_link= 1;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t1 (c INT) ENGINE=InnoDB;
CREATE TABLE t2 (c INT) ENGINE=InnoDB;
CREATE TABLE t3 (c INT) ENGINE=InnoDB;
CREATE TABLE ta (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t5 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t6 (c INT KEY) ENGINE=InnoDB PARTITION BY RANGE (c) (PARTITION p VALUES LESS THAN (5));
CREATE TABLE t7 (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t8 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
--error 12702
SELECT * FROM t8;
--error 12702
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB SELECT * FROM t7;
--error ER_SP_DOES_NOT_EXIST
CALL foo;
CREATE TEMPORARY TABLE t7 (c INT) ENGINE=InnoDB;
--error ER_BAD_FIELD_ERROR
SELECT * FROM t7 JOIN t6 ON tc=t0.c;
--disable_result_log
SHOW TABLE STATUS;
--enable_result_log
# we need to drop t7 twice
drop table ta, t8, t7, t6, t5, t3, t2, t1;
drop table t7;
drop server srv;
set global table_open_cache=@old_table_open_cache;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
set spider_same_server_link= 1;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE '',user 'Spider', password 'foo');
CREATE TABLE tSpider (a INT) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
CREATE TABLE t2 (c INT,c2 CHAR(1)) ENGINE=Spider COMMENT='WRAPPER "mysql",SRV "srv",TABLE "t"';
XA START 'a';
--disable_result_log
--error 0,ER_CONNECT_TO_FOREIGN_DATA_SOURCE
SELECT * FROM information_schema.table_constraints;
--enable_result_log
SELECT SLEEP (1);
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
SELECT * FROM t2;
SELECT SLEEP (1);
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
SELECT * FROM t2;
SELECT SLEEP (1);
--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE
SELECT * FROM t2;
xa end 'a';
xa rollback 'a';
drop table tSpider, t2;
drop server srv;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log
This diff is collapsed.
......@@ -26,24 +26,62 @@
#define SPIDER_SIMPLE_CHECKSUM_TABLE 4
#endif
/*
The SPIDER_CONN_LOOP_CHECK has been added to the loop_check queue to
check for self-reference.
*/
#define SPIDER_LOP_CHK_QUEUED (1 << 0)
/*
The SPIDER_CONN_LOOP_CHECK is a merge of multiple
SPIDER_CONN_LOOP_CHECKs with the same data node table
*/
#define SPIDER_LOP_CHK_MERAGED (1 << 1)
/*
The SPIDER_CONN_LOOP_CHECK has been ignored because it has already
been marked as checked
*/
#define SPIDER_LOP_CHK_IGNORED (1 << 2)
/* Used for self-reference check. */
typedef struct st_spider_conn_loop_check
{
/*
Could be 0, SPIDER_LOP_CHK_QUEUED, SPIDER_LOP_CHK_MERAGED, or
SPIDER_LOP_CHK_IGNORED
*/
uint flag;
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
/* hash value of to_name, used for the hash conn->loop_checked */
my_hash_value_type hash_value_to;
my_hash_value_type hash_value_full;
#endif
LEX_CSTRING from_name;
/*
The fully qualified name of the current spider table, which will
also be used to construct the user var name to set in the data
node
*/
LEX_CSTRING cur_name;
/*
The fully qualified data node table name, also used as key in
conn->loop_check_queue
*/
LEX_CSTRING to_name;
/*
A concatenation of from_value, cur_name and to_name, used as key
in hash conn->loop_checked
*/
LEX_CSTRING full_name;
/*
The first component of the uservar value on the current server,
consisting of information of a table that uses the current spider
table as a data node
*/
LEX_CSTRING from_value;
/*
The uservar value to set in the data node, a concatenation of info
of tables, mac addresses and process ids of tables that use the
current spider table as the data node
*/
LEX_CSTRING merged_value;
st_spider_conn_loop_check *next;
} SPIDER_CONN_LOOP_CHECK;
uchar *spider_conn_get_key(
......
......@@ -66,7 +66,7 @@ spider_db_conn::spider_db_conn(
DBUG_VOID_RETURN;
}
int spider_db_conn::fin_loop_check()
int spider_db_conn::fin_loop_check() /* reset flags of all relevant SPIDER_CONN_LOOP_CHECKs */
{
st_spider_conn_loop_check *lcptr;
DBUG_ENTER("spider_db_conn::fin_loop_check");
......@@ -82,20 +82,6 @@ int spider_db_conn::fin_loop_check()
}
my_hash_reset(&conn->loop_check_queue);
}
lcptr = conn->loop_check_ignored_first;
while (lcptr)
{
lcptr->flag = 0;
lcptr = lcptr->next;
}
conn->loop_check_ignored_first = NULL;
lcptr = conn->loop_check_meraged_first;
while (lcptr)
{
lcptr->flag = 0;
lcptr = lcptr->next;
}
conn->loop_check_meraged_first = NULL;
DBUG_RETURN(0);
}
......
......@@ -5283,6 +5283,22 @@ int spider_db_mbase_util::append_time_zone(
DBUG_RETURN(0);
}
/*
iterate over loop_check_queue and build queries for loop check
The query is in the form of
set @`spider_lc_.<to_table>` =
'-<mac1>-<pid1>-<from_table1>--<mac2>-<pid2>-<from_table2>-...'
where from_table1, from_table2 etc. are spider tables whose direct
or indirect remote data nodes contain to_table.
e.g. if t0->t1->t2, then the query could be:
set @`spider_lc_./test/t2` =
'-234567890abc-def012-./test/t1--1234567890ab-cdef01-./test/t0-'
*/
int spider_db_mbase_util::append_loop_check(
spider_string *str,
SPIDER_CONN *conn
......
......@@ -793,19 +793,24 @@ typedef struct st_spider_conn
SPIDER_IP_PORT_CONN *ip_port_conn;
pthread_mutex_t loop_check_mutex;
/*
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
SPIDER_CONN_LOOP_CHECK::full_name
*/
HASH loop_checked;
uint loop_checked_id;
const char *loop_checked_func_name;
const char *loop_checked_file_name;
ulong loop_checked_line_no;
/*
A hash of SPIDER_CONN_LOOP_CHECK, indexed by
SPIDER_CONN_LOOP_CHECK::to_name
*/
HASH loop_check_queue;
uint loop_check_queue_id;
const char *loop_check_queue_func_name;
const char *loop_check_queue_file_name;
ulong loop_check_queue_line_no;
SPIDER_CONN_LOOP_CHECK *loop_check_ignored_first;
SPIDER_CONN_LOOP_CHECK *loop_check_ignored_last;
SPIDER_CONN_LOOP_CHECK *loop_check_meraged_first;
} SPIDER_CONN;
typedef struct st_spider_lgtm_tblhnd_share
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment