Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mysql-test/suite/federated/federated.test
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ create table t1 (a int);
--replace_result $MASTER_MYPORT MASTER_PORT
eval create table fed (a int) engine=Federated CONNECTION='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1';
drop table t1;
--error 1146,1431
--error ER_NO_SUCH_TABLE,ER_GET_ERRMSG,ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST
Comment thread
gkodinov marked this conversation as resolved.
select * from fed;
drop table fed;

Expand Down
53 changes: 53 additions & 0 deletions mysql-test/suite/federated/federatedx_mdev39196.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
connect master,127.0.0.1,root,,test,$MASTER_MYPORT,;
connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,;
connection master;
CREATE DATABASE federated;
connection slave;
CREATE DATABASE federated;
#
# MDEV-39196: INFORMATION_SCHEMA query must succeed with a
# warning when a FederatedX remote table is unreachable.
#
connection slave;
USE federated;
CREATE TABLE t1 (
id INT NOT NULL,
name VARCHAR(64)
) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1, 'foo');
connection master;
USE federated;
CREATE TABLE t1 (
id INT NOT NULL,
name VARCHAR(64)
) ENGINE=FEDERATED
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
# Verify the federated table works before dropping remote table.
SELECT * FROM federated.t1;
id name
1 foo
# Drop the remote table to simulate unreachable/missing table.
connection slave;
USE federated;
DROP TABLE t1;
connection master;
# INFORMATION_SCHEMA query must succeed and issue a warning.
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'federated'
AND TABLE_NAME = 't1';
TABLE_NAME TABLE_ROWS
t1 1
Warnings:
Warning 1430 FederatedX: Table 't1' is inaccessible: 1146 : Remote table does not exist
# Warning must be present.
SHOW WARNINGS;
Level Code Message
Warning 1430 FederatedX: Table 't1' is inaccessible: 1146 : Remote table does not exist
# Cleanup.
connection master;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
connection slave;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
46 changes: 46 additions & 0 deletions mysql-test/suite/federated/federatedx_mdev39196.test
Comment thread
gkodinov marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--source include/not_embedded.inc
--source have_federatedx.inc
--source include/federated.inc

--echo #
--echo # MDEV-39196: INFORMATION_SCHEMA query must succeed with a
--echo # warning when a FederatedX remote table is unreachable.
--echo #

connection slave;
USE federated;
CREATE TABLE t1 (
id INT NOT NULL,
name VARCHAR(64)
) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1, 'foo');

connection master;
USE federated;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE t1 (
id INT NOT NULL,
name VARCHAR(64)
) ENGINE=FEDERATED
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';

--echo # Verify the federated table works before dropping remote table.
SELECT * FROM federated.t1;

--echo # Drop the remote table to simulate unreachable/missing table.
connection slave;
USE federated;
DROP TABLE t1;

connection master;
--echo # INFORMATION_SCHEMA query must succeed and issue a warning.
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'federated'
AND TABLE_NAME = 't1';

--echo # Warning must be present.
SHOW WARNINGS;

--echo # Cleanup.
--source include/federated_cleanup.inc
26 changes: 23 additions & 3 deletions storage/federatedx/federatedx_io_mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class federatedx_io_mysql :public federatedx_io
DYNAMIC_ARRAY savepoints;
bool requested_autocommit;
bool actual_autocommit;
int stored_error_code;
char stored_error_msg[MYSQL_ERRMSG_SIZE];

int actual_query(const char *buffer, size_t length);
bool test_all_restrict() const;
Expand Down Expand Up @@ -134,12 +136,14 @@ federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,

federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver)
: federatedx_io(aserver),
requested_autocommit(TRUE), actual_autocommit(TRUE)
requested_autocommit(TRUE), actual_autocommit(TRUE),
stored_error_code(0)
{
DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql");

bzero(&mysql, sizeof(MYSQL));
bzero(&savepoints, sizeof(DYNAMIC_ARRAY));
stored_error_msg[0]= 0;

my_init_dynamic_array(PSI_INSTRUMENT_ME, &savepoints, sizeof(SAVEPT), 16, 16, MYF(0));

Expand Down Expand Up @@ -483,12 +487,19 @@ my_ulonglong federatedx_io_mysql::last_insert_id() const

int federatedx_io_mysql::error_code()
{
if (stored_error_code)
return stored_error_code;
return mysql_errno(&mysql);
}


const char *federatedx_io_mysql::error_str()
{
if (stored_error_code)
{
DBUG_ASSERT(stored_error_msg[0] != 0);
return stored_error_msg;
Comment thread
gkodinov marked this conversation as resolved.
}
return mysql_error(&mysql);
}
Comment on lines 488 to 504

Expand Down Expand Up @@ -583,7 +594,11 @@ bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
goto error;

if (!(row= fetch_row(result)))
{
stored_error_code= 0;
stored_error_msg[0]= 0;
goto error;
}

/*
deleted is set in ha_federatedx::info
Expand Down Expand Up @@ -618,8 +633,13 @@ bool federatedx_io_mysql::table_metadata(ha_statistics *stats,
error:
if (!mysql_errno(&mysql))
{
mysql.net.last_errno= ER_NO_SUCH_TABLE;
strmake_buf(mysql.net.last_error, "Remote table does not exist");
stored_error_code= ER_NO_SUCH_TABLE;
strmake_buf(stored_error_msg, "Remote table does not exist");
}
else
{
stored_error_code= mysql_errno(&mysql);
strmake_buf(stored_error_msg, mysql_error(&mysql));
}
free_result(result);
return 1;
Expand Down
40 changes: 38 additions & 2 deletions storage/federatedx/ha_federatedx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3130,12 +3130,48 @@ int ha_federatedx::info(uint flag)
error:
if (iop && *iop)
{
my_printf_error((*iop)->error_code(), "Received error: %d : %s", MYF(0),
(*iop)->error_code(), (*iop)->error_str());
if ((flag & HA_STATUS_VARIABLE) && !(flag & HA_STATUS_NO_LOCK))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a comment here explaining what is it that you're testing for.

{
Comment on lines +3133 to +3134
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_QUERY_ON_FOREIGN_DATA_SOURCE,
"FederatedX: Table '%s' is inaccessible: "
"%d : %s",
share->table_name,
(*iop)->error_code(),
(*iop)->error_str());
error_code= 0;
}
else
{
my_printf_error((*iop)->error_code(),
": %d : %s", MYF(0),
(*iop)->error_code(), (*iop)->error_str());
Comment on lines +3146 to +3148
error_code= (*iop)->error_code();
}
}
else if (remote_error_number != -1 /* error already reported */)
{
error_code= remote_error_number;
/*
* Downgrade remote errors to warnings only when called from the
* INFORMATION_SCHEMA table scan path.
*
* INFORMATION_SCHEMA scans (sql_show.cc, fill_schema_table_by_open)
* call ha_federatedx::info() with HA_STATUS_VARIABLE set but WITHOUT
* HA_STATUS_NO_LOCK. All other callers that trigger the error path
* (e.g. direct SELECT, DELETE, SHOW TABLE STATUS) pass
* HA_STATUS_NO_LOCK alongside HA_STATUS_VARIABLE.
*
* This combination is therefore used as an indirect signal that we are
* inside an I_S scan, where aborting with a hard error would break the
* entire query rather than just skipping the inaccessible table.
*
* NOTE: This is an indirect inference based on current caller conventions.
* If a future caller passes HA_STATUS_VARIABLE without HA_STATUS_NO_LOCK
* for a non-I_S purpose, it would unintentionally receive
* warning-downgrade behavior. A cleaner long-term solution would be an
* explicit flag or context distinguishing I_S scans from direct access.
*/
my_error(error_code, MYF(0), ER_THD(thd, error_code));
}
Comment on lines 3152 to 3176
fail:
Expand Down