Skip to content

Commit 03992bd

Browse files
committed
MDEV-39196: SELECT from information schema fails when FederatedX loses underlying table
When a remote table is unavailable, FederatedX was passing a hard error back to the SQL layer, causing INFORMATION_SCHEMA queries to abort entirely. This patch intercepts the remote error in ha_federatedx::info, downgrades it to a warning using push_warning_printf, and includes the local table name in the warning message so the user knows which table is inaccessible. Signed-off-by: Anway Durge <124391429+itzanway@users.noreply.github.com>
1 parent b4bc43e commit 03992bd

3 files changed

Lines changed: 125 additions & 7 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# MDEV-39196: SELECT from information_schema fails when FederatedX
2+
# loses underlying table.
3+
#
4+
# Test that INFORMATION_SCHEMA queries succeed with a warning
5+
# when a FederatedX remote table is unreachable, instead of
6+
# returning a hard error.
7+
#
8+
# Verify the federated table works before dropping remote table.
9+
SELECT * FROM t1;
10+
id name
11+
1 foo
12+
# Drop the remote table to simulate an unreachable/missing table.
13+
# Now SELECT from INFORMATION_SCHEMA should succeed and push a
14+
# warning instead of returning a hard error.
15+
# The query must succeed (not error out).
16+
SELECT TABLE_NAME, TABLE_ROWS
17+
FROM information_schema.TABLES
18+
WHERE TABLE_SCHEMA = 'federated';
19+
TABLE_NAME TABLE_ROWS
20+
t1 NULL
21+
# Confirm a warning was issued for the inaccessible table.
22+
SHOW WARNINGS;
23+
Level Code Message
24+
Warning 1296 FederatedX: Table 't1' is inaccessible: 1146 : Table 'federated.t1' doesn't exist
25+
# Cleanup
26+
DROP TABLE IF EXISTS t1;
27+
DROP DATABASE federated;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# MDEV-39196: SELECT from information_schema fails when FederatedX
2+
# loses underlying table.
3+
--source include/not_embedded.inc
4+
--source include/have_federatedx.inc
5+
6+
--echo #
7+
--echo # Test that INFORMATION_SCHEMA queries succeed with a warning
8+
--echo # when a FederatedX remote table is unreachable, instead of
9+
--echo # returning a hard error.
10+
--echo #
11+
12+
# ---------------------------------------------------------------
13+
# Setup: two servers via federated suite infrastructure
14+
# ---------------------------------------------------------------
15+
--connection slave
16+
CREATE DATABASE federated;
17+
18+
--connection master
19+
CREATE DATABASE federated;
20+
21+
--connection slave
22+
USE federated;
23+
CREATE TABLE t1 (id INT NOT NULL, name VARCHAR(64)) ENGINE=MyISAM;
24+
INSERT INTO t1 VALUES (1, 'foo');
25+
26+
--connection master
27+
USE federated;
28+
29+
--eval CREATE TABLE t1 (id INT NOT NULL, name VARCHAR(64)) \
30+
ENGINE=FEDERATED \
31+
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'
32+
33+
--echo # Verify the federated table works before dropping remote table.
34+
SELECT * FROM t1;
35+
36+
--echo # Drop the remote table to simulate an unreachable/missing table.
37+
--connection slave
38+
USE federated;
39+
DROP TABLE t1;
40+
41+
--echo # Now SELECT from INFORMATION_SCHEMA should succeed and push a
42+
--echo # warning instead of returning a hard error.
43+
--connection master
44+
USE federated;
45+
46+
--echo # The query must succeed (not error out).
47+
--disable_warnings
48+
SELECT TABLE_NAME, TABLE_ROWS
49+
FROM information_schema.TABLES
50+
WHERE TABLE_SCHEMA = 'federated';
51+
--enable_warnings
52+
53+
--echo # Confirm a warning was issued for the inaccessible table.
54+
SHOW WARNINGS;
55+
56+
--echo # Cleanup
57+
DROP TABLE IF EXISTS t1;
58+
DROP DATABASE federated;
59+
60+
--connection slave
61+
DROP DATABASE IF EXISTS federated;
62+
63+
--connection master

storage/federatedx/ha_federatedx.cc

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,13 +3130,41 @@ int ha_federatedx::info(uint flag)
31303130
error:
31313131
if (iop && *iop)
31323132
{
3133-
my_printf_error((*iop)->error_code(), "Received error: %d : %s", MYF(0),
3134-
(*iop)->error_code(), (*iop)->error_str());
3135-
}
3136-
else if (remote_error_number != -1 /* error already reported */)
3137-
{
3138-
error_code= remote_error_number;
3139-
my_error(error_code, MYF(0), ER_THD(thd, error_code));
3133+
uint remote_err= (uint)(*iop)->error_code();
3134+
/*
3135+
Only downgrade to a warning for errors that mean the remote server
3136+
or table is temporarily unreachable (connection failure, table
3137+
dropped on remote side). All other errors — including access-denied
3138+
errors — must remain hard errors so that callers like
3139+
federated_server.test that expect ER_DBACCESS_DENIED_ERROR still
3140+
receive them correctly.
3141+
*/
3142+
switch (remote_err)
3143+
{
3144+
/* CR_* client-side connection errors */
3145+
case 2002: /* CR_CONNECTION_ERROR - can't connect via socket */
3146+
case 2003: /* CR_CONN_HOST_ERROR - can't connect to host */
3147+
case 2005: /* CR_UNKNOWN_HOST - unknown host */
3148+
case 2006: /* CR_SERVER_GONE_ERROR - server has gone away */
3149+
case 2013: /* CR_SERVER_LOST - lost connection during query */
3150+
/* Server-side: remote table no longer exists */
3151+
case 1146: /* ER_NO_SUCH_TABLE */
3152+
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
3153+
ER_QUERY_ON_FOREIGN_DATA_SOURCE,
3154+
"FederatedX: Table '%s' is inaccessible: %d : %s",
3155+
share->table_name,
3156+
(*iop)->error_code(),
3157+
(*iop)->error_str());
3158+
error_code= 0;
3159+
break;
3160+
default:
3161+
/*
3162+
For all other errors (e.g. ER_DBACCESS_DENIED_ERROR = 1044),
3163+
keep the error so it propagates back to the user.
3164+
*/
3165+
error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
3166+
break;
3167+
}
31403168
}
31413169
fail:
31423170
tmp_txn->release(&tmp_io);

0 commit comments

Comments
 (0)