summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/federated/federatedx_create_handlers.result23
-rw-r--r--mysql-test/suite/federated/federatedx_create_handlers.test22
-rw-r--r--storage/federatedx/federatedx_pushdown.cc68
-rw-r--r--storage/federatedx/ha_federatedx.cc6
4 files changed, 116 insertions, 3 deletions
diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result
index b115cc73b87..de1f42f0c9c 100644
--- a/mysql-test/suite/federated/federatedx_create_handlers.result
+++ b/mysql-test/suite/federated/federatedx_create_handlers.result
@@ -420,6 +420,29 @@ SELECT * FROM (SELECT * FROM federated.t1 LIMIT 70000) dt;
SELECT COUNT(DISTINCT a) FROM federated.t2;
COUNT(DISTINCT a)
70000
+#
+# MDEV-29640 FederatedX does not properly handle pushdown
+# in case of difference in local and remote table names
+#
+connection master;
+# Use tables from the previous test. Make sure pushdown works:
+EXPLAIN SELECT COUNT(DISTINCT a) FROM federated.t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
+SELECT COUNT(DISTINCT a) FROM federated.t2;
+COUNT(DISTINCT a)
+70000
+# Link remote table `federated.t1` with the local table named `t1_local`
+CREATE TABLE t1_local ENGINE="FEDERATED"
+CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+# No pushdown here due to table names mismatch, retrieve data as usual:
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1_local;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1_local ALL NULL NULL NULL NULL 70000
+SELECT COUNT(DISTINCT a) FROM t1_local;
+COUNT(DISTINCT a)
+70000
+DROP TABLE t1_local;
set global federated_pushdown=0;
connection master;
DROP TABLE IF EXISTS federated.t1;
diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test
index 8863a057b47..ea2bc2f74f2 100644
--- a/mysql-test/suite/federated/federatedx_create_handlers.test
+++ b/mysql-test/suite/federated/federatedx_create_handlers.test
@@ -266,6 +266,28 @@ INSERT INTO federated.t2
SELECT * FROM (SELECT * FROM federated.t1 LIMIT 70000) dt;
SELECT COUNT(DISTINCT a) FROM federated.t2;
+
+--echo #
+--echo # MDEV-29640 FederatedX does not properly handle pushdown
+--echo # in case of difference in local and remote table names
+--echo #
+connection master;
+--echo # Use tables from the previous test. Make sure pushdown works:
+EXPLAIN SELECT COUNT(DISTINCT a) FROM federated.t2;
+SELECT COUNT(DISTINCT a) FROM federated.t2;
+
+--echo # Link remote table `federated.t1` with the local table named `t1_local`
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval
+CREATE TABLE t1_local ENGINE="FEDERATED"
+CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
+
+--echo # No pushdown here due to table names mismatch, retrieve data as usual:
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1_local;
+SELECT COUNT(DISTINCT a) FROM t1_local;
+
+DROP TABLE t1_local;
+
set global federated_pushdown=0;
source include/federated_cleanup.inc;
diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc
index 15b0b0d3d4e..c26fbffa4c1 100644
--- a/storage/federatedx/federatedx_pushdown.cc
+++ b/storage/federatedx/federatedx_pushdown.cc
@@ -35,6 +35,68 @@
*/
+/*
+ Check if table and database names are equal on local and remote servers
+
+ SYNOPSIS
+ local_and_remote_names_match()
+ thd Thread descriptor
+ tbl_share Pointer to current table TABLE_SHARE structure
+
+ DESCRIPTION
+ FederatedX table on the local server may refer to a table having another
+ name on the remote server. The remote table may even reside in a different
+ database. For example:
+
+ -- Remote server
+ CREATE TABLE t1 (id int(32));
+
+ -- Local server
+ CREATE TABLE t2 ENGINE="FEDERATEDX"
+ CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federatedx/t1";
+
+ It's not a problem while the federated_pushdown is disabled 'cause
+ the CONNECTION strings are being parsed for every table during
+ the execution, so the table names are translated from local to remote.
+ But in case of the federated_pushdown the whole query is pushed down
+ to the engine without any translation, so the remote server may try
+ to select data from a nonexistent table (for example, query
+ "SELECT * FROM t2" will try to retrieve data from nonexistent "t2").
+
+ This function checks whether there is a mismatch between local and remote
+ table/database names
+
+ RETURN VALUE
+ false names are equal
+ true names are not equal
+
+*/
+bool local_and_remote_names_mismatch(THD *thd, const TABLE_SHARE *tbl_share)
+{
+ FEDERATEDX_SHARE tmp_share;
+ bzero(&tmp_share, sizeof(tmp_share));
+ if (parse_url(thd->mem_root, &tmp_share, tbl_share, 0))
+ return true;
+
+ if (lower_case_table_names)
+ {
+ if (strcasecmp(tmp_share.database, tbl_share->db.str) != 0)
+ return true;
+ }
+ else
+ {
+ if (strncmp(tmp_share.database, tbl_share->db.str, tbl_share->db.length) !=
+ 0)
+ return true;
+ }
+
+ return my_strnncoll(system_charset_info, (uchar *) tmp_share.table_name,
+ strlen(tmp_share.table_name),
+ (uchar *) tbl_share->table_name.str,
+ tbl_share->table_name.length) != 0;
+}
+
+
static derived_handler*
create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
{
@@ -58,6 +120,9 @@ create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
ht= tbl->table->file->partition_ht();
else if (ht != tbl->table->file->partition_ht())
return 0;
+ if (ht == federatedx_hton &&
+ local_and_remote_names_mismatch(thd, tbl->table->s))
+ return 0;
}
}
@@ -180,6 +245,9 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel)
ht= tbl->table->file->partition_ht();
else if (ht != tbl->table->file->partition_ht())
return 0;
+ if (ht == federatedx_hton &&
+ local_and_remote_names_mismatch(thd, tbl->table->s))
+ return 0;
}
/*
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 085422e6016..2eda3786d9d 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -528,7 +528,7 @@ err:
}
-static int parse_url_error(FEDERATEDX_SHARE *share, TABLE_SHARE *table_s,
+static int parse_url_error(FEDERATEDX_SHARE *share, const TABLE_SHARE *table_s,
int error_num)
{
char buf[FEDERATEDX_QUERY_BUFFER_SIZE];
@@ -609,7 +609,7 @@ error:
parse_url()
mem_root MEM_ROOT pointer for memory allocation
share pointer to FEDERATEDX share
- table pointer to current TABLE class
+ table_s pointer to current TABLE_SHARE class
table_create_flag determines what error to throw
DESCRIPTION
@@ -658,7 +658,7 @@ error:
*/
static int parse_url(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share,
- TABLE_SHARE *table_s, uint table_create_flag)
+ const TABLE_SHARE *table_s, uint table_create_flag)
{
uint error_num= (table_create_flag ?
ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE :