summaryrefslogtreecommitdiff
path: root/storage/federatedx
diff options
context:
space:
mode:
authorOleg Smirnov <olernov@gmail.com>2022-10-25 19:30:42 +0700
committerOleg Smirnov <olernov@gmail.com>2022-10-26 10:52:38 +0700
commit5f296f3a181eb63b6112153c6d4f9186180e6c50 (patch)
tree4e8e8c5b681f5db1e1aec92aa9e64f197cebf904 /storage/federatedx
parent58cd0bd59ef011be54f162237f2ff017c3148e7b (diff)
downloadmariadb-git-5f296f3a181eb63b6112153c6d4f9186180e6c50.tar.gz
MDEV-29640 FederatedX does not properly handle pushdown in case of difference in local and remote table names
FederatedX table may refer to a table with a different name on the remote server: test> CREATE TABLE t2 (...) ENGINE="FEDERATEDX" CONNECTION="mysql://user:pass@192.168.1.111:9308/federatedx/t1"; test> select * from t2 where ...; This could cause an issue with federated_pushdown=1, because FederatedX pushes the query (or derived table's) text to the remote server. The remote server will try to read from table t2 (while it should read from t1). Solution: do not allow pushing down queries with tables that have different db_name.table name on the local and remote server. This patch also fixes: MDEV-29863 Server crashes in federatedx_txn::acquire after select from the FederatedX table with partitions Solution: disallow pushdown when partitioned FederatedX tables are used.
Diffstat (limited to 'storage/federatedx')
-rw-r--r--storage/federatedx/federatedx_pushdown.cc87
-rw-r--r--storage/federatedx/ha_federatedx.cc2
-rw-r--r--storage/federatedx/ha_federatedx.h1
3 files changed, 81 insertions, 9 deletions
diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc
index 15b0b0d3d4e..430bc961167 100644
--- a/storage/federatedx/federatedx_pushdown.cc
+++ b/storage/federatedx/federatedx_pushdown.cc
@@ -35,6 +35,64 @@
*/
+/*
+ Check if table and database names are equal on local and remote servers
+
+ SYNOPSIS
+ local_and_remote_names_match()
+ tbl_share Pointer to current table TABLE_SHARE structure
+ fshare Pointer to current table FEDERATEDX_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(const TABLE_SHARE *tbl_share,
+ const FEDERATEDX_SHARE *fshare)
+{
+
+ if (lower_case_table_names)
+ {
+ if (strcasecmp(fshare->database, tbl_share->db.str) != 0)
+ return true;
+ }
+ else
+ {
+ if (strncmp(fshare->database, tbl_share->db.str, tbl_share->db.length) != 0)
+ return true;
+ }
+
+ return my_strnncoll(system_charset_info, (uchar *) fshare->table_name,
+ strlen(fshare->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)
{
@@ -42,7 +100,6 @@ create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
return 0;
ha_federatedx_derived_handler* handler = NULL;
- handlerton *ht= 0;
SELECT_LEX_UNIT *unit= derived->derived;
@@ -54,9 +111,16 @@ create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
{
if (!tbl->table)
return 0;
- if (!ht)
- ht= tbl->table->file->partition_ht();
- else if (ht != tbl->table->file->partition_ht())
+ /*
+ We intentionally don't support partitioned federatedx tables here, so
+ use file->ht and not file->partition_ht().
+ */
+ if (tbl->table->file->ht != federatedx_hton)
+ return 0;
+
+ const FEDERATEDX_SHARE *fshare=
+ ((ha_federatedx*)tbl->table->file)->get_federatedx_share();
+ if (local_and_remote_names_mismatch(tbl->table->s, fshare))
return 0;
}
}
@@ -170,15 +234,22 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel)
return 0;
ha_federatedx_select_handler* handler = NULL;
- handlerton *ht= 0;
for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global)
{
if (!tbl->table)
return 0;
- if (!ht)
- ht= tbl->table->file->partition_ht();
- else if (ht != tbl->table->file->partition_ht())
+ /*
+ We intentionally don't support partitioned federatedx tables here, so
+ use file->ht and not file->partition_ht().
+ */
+ if (tbl->table->file->ht != federatedx_hton)
+ return 0;
+
+ const FEDERATEDX_SHARE *fshare=
+ ((ha_federatedx*)tbl->table->file)->get_federatedx_share();
+
+ if (local_and_remote_names_mismatch(tbl->table->s, fshare))
return 0;
}
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 085422e6016..e329f5df177 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -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
diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h
index c9d80dd8282..ce09fb2253b 100644
--- a/storage/federatedx/ha_federatedx.h
+++ b/storage/federatedx/ha_federatedx.h
@@ -463,6 +463,7 @@ public:
int reset(void);
int free_result(void);
+ const FEDERATEDX_SHARE *get_federatedx_share() const { return share; }
friend class ha_federatedx_derived_handler;
friend class ha_federatedx_select_handler;
};