Skip to content

Commit ebb80e1

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 ebb80e1

4 files changed

Lines changed: 106 additions & 3 deletions

File tree

mysql-test/suite/federated/federated.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ create table t1 (a int);
1717
--replace_result $MASTER_MYPORT MASTER_PORT
1818
eval create table fed (a int) engine=Federated CONNECTION='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1';
1919
drop table t1;
20-
--error 1146,1431
20+
--error ER_NO_SUCH_TABLE,ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
2121
select * from fed;
2222
drop table fed;
2323

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#
2+
# MDEV-39196: INFORMATION_SCHEMA query must succeed with a
3+
# warning when a FederatedX remote table is unreachable.
4+
#
5+
# Verify the federated table works before dropping remote table.
6+
SELECT * FROM federated.t1;
7+
id name
8+
1 foo
9+
# Drop the remote table to simulate unreachable/missing table.
10+
# INFORMATION_SCHEMA query must succeed and issue a warning.
11+
SELECT TABLE_NAME, TABLE_ROWS
12+
FROM information_schema.TABLES
13+
WHERE TABLE_SCHEMA = 'federated'
14+
AND TABLE_NAME = 't1';
15+
TABLE_NAME TABLE_ROWS
16+
t1 1
17+
# Warning must be present.
18+
SHOW WARNINGS;
19+
Level Code Message
20+
Warning 1430 FederatedX: Table 't1' is inaccessible: 1146 : Remote table does not exist
21+
# Cleanup.
22+
DROP TABLE IF EXISTS federated.t1;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# MDEV-39196: SELECT from information_schema fails when FederatedX
2+
# loses underlying table.
3+
--source include/not_embedded.inc
4+
--source include/federated.inc
5+
6+
--echo #
7+
--echo # MDEV-39196: INFORMATION_SCHEMA query must succeed with a
8+
--echo # warning when a FederatedX remote table is unreachable.
9+
--echo #
10+
11+
# Create the remote table on the slave
12+
--connection slave
13+
USE federated;
14+
CREATE TABLE t1 (
15+
id INT NOT NULL,
16+
name VARCHAR(64)
17+
) ENGINE=MyISAM;
18+
INSERT INTO t1 VALUES (1, 'foo');
19+
20+
# Create the federated table on the master pointing to slave
21+
--connection master
22+
USE federated;
23+
--replace_result $SLAVE_MYPORT SLAVE_PORT
24+
eval CREATE TABLE t1 (
25+
id INT NOT NULL,
26+
name VARCHAR(64)
27+
) ENGINE=FEDERATED
28+
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
29+
30+
--echo # Verify the federated table works before dropping remote table.
31+
SELECT * FROM federated.t1;
32+
33+
--echo # Drop the remote table to simulate unreachable/missing table.
34+
--connection slave
35+
USE federated;
36+
DROP TABLE t1;
37+
38+
--connection master
39+
--echo # INFORMATION_SCHEMA query must succeed and issue a warning.
40+
SELECT TABLE_NAME, TABLE_ROWS
41+
FROM information_schema.TABLES
42+
WHERE TABLE_SCHEMA = 'federated'
43+
AND TABLE_NAME = 't1';
44+
45+
--echo # Warning must be present.
46+
SHOW WARNINGS;
47+
48+
--echo # Cleanup.
49+
DROP TABLE IF EXISTS federated.t1;
50+
51+
--source include/federated_cleanup.inc

storage/federatedx/ha_federatedx.cc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,8 +3130,38 @@ 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());
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+
must remain hard errors so callers receive the correct errno.
3139+
*/
3140+
switch (remote_err)
3141+
{
3142+
case 2002: /* CR_CONNECTION_ERROR - can't connect via socket */
3143+
case 2003: /* CR_CONN_HOST_ERROR - can't connect to host */
3144+
case 2005: /* CR_UNKNOWN_HOST - unknown host */
3145+
case 2006: /* CR_SERVER_GONE_ERROR - server has gone away */
3146+
case 2013: /* CR_SERVER_LOST - lost connection during query */
3147+
case 1146: /* ER_NO_SUCH_TABLE - remote table dropped */
3148+
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
3149+
ER_GET_ERRMSG,
3150+
"FederatedX: Table '%s' is inaccessible: "
3151+
"%d : %s",
3152+
share->table_name,
3153+
(*iop)->error_code(),
3154+
(*iop)->error_str());
3155+
error_code= 0;
3156+
break;
3157+
default:
3158+
my_printf_error((*iop)->error_code(),
3159+
"Received error: %d : %s", MYF(0),
3160+
(*iop)->error_code(),
3161+
(*iop)->error_str());
3162+
error_code= (*iop)->error_code();
3163+
break;
3164+
}
31353165
}
31363166
else if (remote_error_number != -1 /* error already reported */)
31373167
{

0 commit comments

Comments
 (0)