From 2b28d1c424104429eeed43115ee6d8a803671d52 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 8 Jul 2026 18:01:05 +0200 Subject: [PATCH] MDEV-40311 mariadb-dump doesn't always quote identifiers covers: * DROP TRIGGER * CHANGE MASTER * CREATE FUNCTION * CREATE SERVER * INSTALL PLUGIN --- client/mysqldump.c | 101 +++++++++++++-------- mysql-test/main/mysqldump-nl.result | 46 ++++++++++ mysql-test/main/mysqldump-nl.test | 27 ++++++ mysql-test/main/mysqldump-system,win.rdiff | 16 ++-- mysql-test/main/mysqldump-system.result | 55 +++++++---- mysql-test/main/mysqldump-system.test | 15 ++- mysql-test/main/mysqldump.result | 2 +- 7 files changed, 194 insertions(+), 68 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index cf90b8485c6..383907a3eb7 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3660,7 +3660,7 @@ static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs, if (opt_drop_trigger) fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n", - (*show_trigger_row)[0]); + quote_name((*show_trigger_row)[0], name_buff, 0)); fprintf(sql_file, "DELIMITER ;;\n" @@ -3717,6 +3717,7 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, { MYSQL_ROW row; char *query_str; + char name_buff[NAME_LEN*4+3]; int db_cl_altered= FALSE; DBUG_ENTER("dump_trigger"); @@ -3744,7 +3745,7 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs, if (opt_drop_trigger) fprintf(sql_file, "/*!50032 DROP TRIGGER IF EXISTS %s */;\n", - row[0]); + quote_name(row[0],name_buff,0)); query_str= cover_definer_clause(row[2], strlen(row[2]), C_STRING_WITH_LEN("50017"), @@ -4816,6 +4817,7 @@ static int dump_all_plugins() /* Name, Status, Type, Library, License */ while ((row= mysql_fetch_row(tableres))) { + char name_buff[NAME_LEN*2+3]; if (strcmp("ACTIVE", row[1]) != 0) continue; /* Should we be skipping builtins? */ @@ -4824,11 +4826,14 @@ static int dump_all_plugins() if (opt_replace_into) { fprintf(md_result_file, "/*M!100401 UNINSTALL PLUGIN IF EXIST %s */;\n", - row[0]); + quote_name(row[0], name_buff, 0)); } - fprintf(md_result_file, - "INSTALL PLUGIN %s %s SONAME '%s';\n", row[0], - opt_ignore ? "/*M!100401 IF NOT EXISTS */" : "", row[3]); + fprintf(md_result_file, "INSTALL PLUGIN %s %s SONAME ", + quote_name(row[0], name_buff, 0), + opt_ignore ? "/*M!100401 IF NOT EXISTS */" : ""); + unescape(md_result_file, row[3], strlen(row[3])); + fputs(";\n", md_result_file); + check_io(md_result_file); } mysql_free_result(tableres); @@ -4853,6 +4858,7 @@ static int dump_all_udfs() /* Name, ret, dl, type*/ while ((row= mysql_fetch_row(tableres))) { + char name_buff[NAME_LEN*2+3]; retresult= atoi(row[1]); if (retresult < 0 || array_elements(udf_types) <= (size_t) retresult) { @@ -4864,13 +4870,17 @@ static int dump_all_udfs() if (opt_replace_into) { fprintf(md_result_file, "/*!50701 DROP FUNCTION IF EXISTS %s */;\n", - row[0]); + quote_name(row[0], name_buff, 0)); } fprintf(md_result_file, - "CREATE %s%sFUNCTION %s%s RETURNS %s SONAME '%s';\n", + "CREATE %s%sFUNCTION %s%s RETURNS %s SONAME ", opt_replace_into ? "/*M!100103 OR REPLACE */ ": "", - (strcmp("AGGREGATE", row[2])==0 ? "AGGREGATE " : ""), - opt_ignore ? "IF NOT EXISTS " : "", row[0], udf_types[retresult], row[2]); + (strcmp("aggregate", row[3])==0 ? "AGGREGATE " : ""), + opt_ignore ? "IF NOT EXISTS " : "", + quote_name(row[0], name_buff, 0), udf_types[retresult]); + unescape(md_result_file, row[2], strlen(row[2])); + fputs(";\n", md_result_file); + check_io(md_result_file); } mysql_free_result(tableres); @@ -4889,28 +4899,37 @@ static int dump_all_servers() MYSQL_RES *tableres; MYSQL_FIELD *f; unsigned int num_fields, i; - my_bool comma_prepend= 0; - const char *qstring; + char name_buff[NAME_LEN*2+3]; - if (mysql_query_with_error_report(mysql, &tableres, "SELECT * FROM mysql.servers")) + /* alias Db/Username to the Database/User option keywords, emitted as-is below */ + if (mysql_query_with_error_report(mysql, &tableres, + "SELECT Server_name, Host, Db AS `Database`, Username AS `User`, " + "Password, Port, Socket, Wrapper, Owner FROM mysql.servers")) return 1; num_fields= mysql_num_fields(tableres); while ((row= mysql_fetch_row(tableres))) { - fprintf(md_result_file,"CREATE %sSERVER %s%s FOREIGN DATA WRAPPER %s OPTIONS (", + my_bool comma_prepend= 0; + fprintf(md_result_file,"CREATE %sSERVER %s%s FOREIGN DATA WRAPPER ", opt_replace_into ? "/*M!100103 OR REPLACE */ ": "", - opt_ignore ? "/*M!100103 IF NOT EXISTS */ " : "", row[0], row[7]); + opt_ignore ? "/*M!100103 IF NOT EXISTS */ " : "", + quote_name(row[0], name_buff, 0)); + unescape(md_result_file, row[7], strlen(row[7])); + fprintf(md_result_file," OPTIONS ("); for (i= 1; i < num_fields; i++) { if (i == 7 || row[i][0] == '\0') /* Wrapper or empty string */ continue; f= &tableres->fields[i]; - qstring= (f->type == MYSQL_TYPE_STRING || f->type == MYSQL_TYPE_VAR_STRING) ? "'" : ""; - fprintf(md_result_file, "%s%s %s%s%s", - (comma_prepend ? ", " : ""), f->name, qstring, row[i], qstring); + fprintf(md_result_file, "%s%s ", (comma_prepend ? ", " : ""), f->name); + if (f->type == MYSQL_TYPE_STRING || f->type == MYSQL_TYPE_VAR_STRING) + unescape(md_result_file, row[i], strlen(row[i])); + else + fputs(row[i], md_result_file); comma_prepend= 1; } fputs(");\n", md_result_file); + check_io(md_result_file); } mysql_free_result(tableres); @@ -6218,6 +6237,7 @@ static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid, (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : ""; const char *gtid_comment_prefix= (use_gtid ? comment_prefix : "-- "); const char *nogtid_comment_prefix= (!use_gtid ? comment_prefix : "-- "); + char name_buff[FN_REFLEN*2+3]; if (mysql_query_with_error_report(mysql_con, &slave, multi_source ? @@ -6270,8 +6290,9 @@ static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid, if (use_gtid) { if (multi_source) - fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO " - "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix, row[0]); + fprintf(md_result_file, "%sCHANGE MASTER %s TO " + "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix, + quote_for_equal(row[0], name_buff)); else fprintf(md_result_file, "%sCHANGE MASTER TO " "MASTER_USE_GTID=slave_pos;\n", gtid_comment_prefix); @@ -6279,21 +6300,24 @@ static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid, /* SHOW MASTER STATUS reports file and position */ if (multi_source) - fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ", - nogtid_comment_prefix, row[0]); + fprintf(md_result_file, "%sCHANGE MASTER %s TO ", + nogtid_comment_prefix, quote_for_equal(row[0], name_buff)); else fprintf(md_result_file, "%sCHANGE MASTER TO ", nogtid_comment_prefix); if (opt_include_master_host_port) { if (row[1 + multi_source]) - fprintf(md_result_file, "MASTER_HOST='%s', ", row[1 + multi_source]); + fprintf(md_result_file, "MASTER_HOST=%s, ", + quote_for_equal(row[1 + multi_source], name_buff)); if (row[3]) - fprintf(md_result_file, "MASTER_PORT=%s, ", row[3 + multi_source]); + fprintf(md_result_file, "MASTER_PORT=%llu, ", + atoll(row[3 + multi_source])); } fprintf(md_result_file, - "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", - row[9 + multi_source], row[21 + multi_source]); + "MASTER_LOG_FILE=%s, MASTER_LOG_POS=%llu;\n", + quote_for_equal(row[9 + multi_source], name_buff), + atoll(row[21 + multi_source])); check_io(md_result_file); } @@ -7169,24 +7193,25 @@ int main(int argc, char **argv) } } - if (opt_system & OPT_SYSTEM_PLUGINS) - dump_all_plugins(); + if ((opt_system & OPT_SYSTEM_PLUGINS) && dump_all_plugins() && !first_error) + first_error= EX_MYSQLERR; - if (opt_system & OPT_SYSTEM_USERS) - dump_all_users_roles_and_grants(); + if ((opt_system & OPT_SYSTEM_USERS) && + dump_all_users_roles_and_grants() && !first_error) + first_error= EX_MYSQLERR; - if (opt_system & OPT_SYSTEM_UDFS) - dump_all_udfs(); + if ((opt_system & OPT_SYSTEM_UDFS) && dump_all_udfs() && !first_error) + first_error= EX_MYSQLERR; - if (opt_system & OPT_SYSTEM_SERVERS) - dump_all_servers(); + if ((opt_system & OPT_SYSTEM_SERVERS) && dump_all_servers() && !first_error) + first_error= EX_MYSQLERR; /* These must be last as they explicitly change the current database to mysql */ - if (opt_system & OPT_SYSTEM_STATS) - dump_all_stats(); + if ((opt_system & OPT_SYSTEM_STATS) && dump_all_stats() && !first_error) + first_error= EX_MYSQLERR; - if (opt_system & OPT_SYSTEM_TIMEZONES) - dump_all_timezones(); + if ((opt_system & OPT_SYSTEM_TIMEZONES) && dump_all_timezones() && !first_error) + first_error= EX_MYSQLERR; if (opt_master_data && master_set_gtid_pos[0]) do_print_set_gtid_slave_pos(master_set_gtid_pos, TRUE); diff --git a/mysql-test/main/mysqldump-nl.result b/mysql-test/main/mysqldump-nl.result index 72a1099be6c..938db0acda7 100644 --- a/mysql-test/main/mysqldump-nl.result +++ b/mysql-test/main/mysqldump-nl.result @@ -169,3 +169,49 @@ drop database `test```; drop database `test\`` \! ls #`; +# End of 10.3 tests +# +# MDEV-40311 mariadb-dump doesn't always quote identifiers +# +create table t1 (a int); +create trigger `tr 1` before insert on t1 for each row set new.a=new.a+1; +/*M!999999\- enable the sandbox mode */ +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = latin1 */ ; +/*!50003 SET character_set_results = latin1 */ ; +/*!50003 SET collation_connection = latin1_swedish_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; +/*!50032 DROP TRIGGER IF EXISTS `tr 1` */; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 trigger `tr 1` before insert on t1 for each row set new.a=new.a+1 +*/;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +drop table t1; +insert into mysql.func values('foo bar', 0, 'udf''example.so', 'function'); +/*M!999999\- enable the sandbox mode */ +CREATE FUNCTION `foo bar` RETURNS STRING SONAME 'udf\'example.so'; +delete from mysql.func; +change master to master_host='master''host', master_port=3306, +master_log_file='b''n.000001', master_log_pos=4; +/*M!999999\- enable the sandbox mode */ +CHANGE MASTER '' TO MASTER_HOST='master''host', MASTER_PORT=3306, MASTER_LOG_FILE='b''n.000001', MASTER_LOG_POS=4; + +-- SET GLOBAL gtid_slave_pos=''; +call mtr.add_suppression('Slave I/O: Fatal error: .* Connection attempt terminated'); +stop slave; +reset slave; +change master to master_host='127.0.0.1', master_user='root'; +# End of 10.6 tests diff --git a/mysql-test/main/mysqldump-nl.test b/mysql-test/main/mysqldump-nl.test index 4451b0605c2..20d0246ab05 100644 --- a/mysql-test/main/mysqldump-nl.test +++ b/mysql-test/main/mysqldump-nl.test @@ -57,3 +57,30 @@ drop database `test```; drop database `test\`` \! ls #`; + +--echo # End of 10.3 tests + +--echo # +--echo # MDEV-40311 mariadb-dump doesn't always quote identifiers +--echo # +create table t1 (a int); +create trigger `tr 1` before insert on t1 for each row set new.a=new.a+1; +exec $MYSQL_DUMP --compact --add-drop-trigger test; +drop table t1; + +insert into mysql.func values('foo bar', 0, 'udf''example.so', 'function'); +exec $MYSQL_DUMP --compact --system=udfs test; +delete from mysql.func; + +change master to master_host='master''host', master_port=3306, + master_log_file='b''n.000001', master_log_pos=4; + +exec $MYSQL_DUMP --compact --dump-slave --include-master-host-port test; + +# cleanup after mariadb-dump executed START SLAVE +call mtr.add_suppression('Slave I/O: Fatal error: .* Connection attempt terminated'); +stop slave; +reset slave; +change master to master_host='127.0.0.1', master_user='root'; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/mysqldump-system,win.rdiff b/mysql-test/main/mysqldump-system,win.rdiff index c6d8d5bd379..b85aef33700 100644 --- a/mysql-test/main/mysqldump-system,win.rdiff +++ b/mysql-test/main/mysqldump-system,win.rdiff @@ -1,26 +1,26 @@ --- mysqldump-system.result +++ mysqldump-system,win.result -@@ -449,9 +449,9 @@ +@@ -463,9 +463,9 @@ Table Checksum mysql.roles_mapping 2510045525 mysql.time_zone_transition 3895294076 -mysql.plugin 1587119305 +mysql.plugin 2184891911 - mysql.servers 2180549486 --mysql.func 3241572444 -+mysql.func 310494789 + mysql.servers 4086772068 +-mysql.func 2140302938 ++mysql.func 2154697260 mysql.innodb_table_stats 347867921 mysql.table_stats 664320059 # Opps.... -@@ -484,9 +484,9 @@ +@@ -500,9 +500,9 @@ Table Checksum mysql.roles_mapping 2510045525 mysql.time_zone_transition 3895294076 -mysql.plugin 1587119305 +mysql.plugin 2184891911 - mysql.servers 2180549486 --mysql.func 3241572444 -+mysql.func 310494789 + mysql.servers 4086772068 +-mysql.func 2140302938 ++mysql.func 2154697260 mysql.innodb_table_stats 347867921 mysql.table_stats 664320059 DROP FUNCTION IF EXISTS metaphon; diff --git a/mysql-test/main/mysqldump-system.result b/mysql-test/main/mysqldump-system.result index a7973d4c6df..ae60d50524e 100644 --- a/mysql-test/main/mysqldump-system.result +++ b/mysql-test/main/mysqldump-system.result @@ -34,8 +34,12 @@ update mysql.innodb_index_stats set last_update="2020-01-01" where database_name update mysql.innodb_table_stats set last_update="2020-01-01" where database_name="mysql" and table_name="tz"; set global innodb_stats_persistent= @save_innodb_stats_persistent; alter table mysql.time_zone_name ORDER BY Name; -CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(Host 'localhost'); +CREATE SERVER s1 FOREIGN DATA WRAPPER mysql +OPTIONS (HOST 'localhost', DATABASE 'd''b', USER 'o''brien', PASSWORD 'pw''d'); +CREATE SERVER `s'2` FOREIGN DATA WRAPPER 'my''sql' + OPTIONS (HOST 'h2', DATABASE 'db2', USER 'u2'); CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; # # mysqldump of system tables with --system=all # @@ -51,8 +55,8 @@ CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -INSTALL PLUGIN test_plugin_server SONAME 'AUTH_TEST_PLUGIN_LIB'; -INSTALL PLUGIN cleartext_plugin_server SONAME 'AUTH_TEST_PLUGIN_LIB'; +INSTALL PLUGIN `test_plugin_server` SONAME 'AUTH_TEST_PLUGIN_LIB'; +INSTALL PLUGIN `cleartext_plugin_server` SONAME 'AUTH_TEST_PLUGIN_LIB'; CREATE USER `mariadb.sys`@`localhost` PASSWORD EXPIRE; CREATE USER `root`@`localhost`; CREATE USER `foobar`@`%` IDENTIFIED VIA test_plugin_server USING 'plug_dest'; @@ -87,8 +91,10 @@ GRANT USAGE ON *.* TO `role_2`; SET ROLE NONE; DROP ROLE mariadb_dump_import_role; /*M!100203 EXECUTE IMMEDIATE CONCAT('SET ROLE ', @current_role) */; -CREATE FUNCTION metaphon RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; -CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (Host 'localhost', Port 3306); +CREATE FUNCTION `metaphon` RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; +CREATE AGGREGATE FUNCTION `avgcost` RETURNS REAL SONAME 'UDF_EXAMPLE_LIB'; +CREATE SERVER `s1` FOREIGN DATA WRAPPER 'mysql' OPTIONS (Host 'localhost', Database 'd\'b', User 'o\'brien', Password 'pw\'d', Port 3306); +CREATE SERVER `s'2` FOREIGN DATA WRAPPER 'my\'sql' OPTIONS (Host 'h2', Database 'db2', User 'u2', Port 0); USE mysql; @@ -178,10 +184,10 @@ UNLOCK TABLES; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -/*M!100401 UNINSTALL PLUGIN IF EXIST test_plugin_server */; -INSTALL PLUGIN test_plugin_server SONAME 'AUTH_TEST_PLUGIN_LIB'; -/*M!100401 UNINSTALL PLUGIN IF EXIST cleartext_plugin_server */; -INSTALL PLUGIN cleartext_plugin_server SONAME 'AUTH_TEST_PLUGIN_LIB'; +/*M!100401 UNINSTALL PLUGIN IF EXIST `test_plugin_server` */; +INSTALL PLUGIN `test_plugin_server` SONAME 'AUTH_TEST_PLUGIN_LIB'; +/*M!100401 UNINSTALL PLUGIN IF EXIST `cleartext_plugin_server` */; +INSTALL PLUGIN `cleartext_plugin_server` SONAME 'AUTH_TEST_PLUGIN_LIB'; DELIMITER | /*M!100101 IF current_user()='''mariadb.sys''@''localhost''' THEN SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=30001, MESSAGE_TEXT="Don't remove current user 'mariadb.sys'@'localhost''"; @@ -236,9 +242,12 @@ GRANT USAGE ON *.* TO `role_2`; SET ROLE NONE; DROP ROLE mariadb_dump_import_role; /*M!100203 EXECUTE IMMEDIATE CONCAT('SET ROLE ', @current_role) */; -/*!50701 DROP FUNCTION IF EXISTS metaphon */; -CREATE /*M!100103 OR REPLACE */ FUNCTION metaphon RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; -CREATE /*M!100103 OR REPLACE */ SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (Host 'localhost', Port 3306); +/*!50701 DROP FUNCTION IF EXISTS `metaphon` */; +CREATE /*M!100103 OR REPLACE */ FUNCTION `metaphon` RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; +/*!50701 DROP FUNCTION IF EXISTS `avgcost` */; +CREATE /*M!100103 OR REPLACE */ AGGREGATE FUNCTION `avgcost` RETURNS REAL SONAME 'UDF_EXAMPLE_LIB'; +CREATE /*M!100103 OR REPLACE */ SERVER `s1` FOREIGN DATA WRAPPER 'mysql' OPTIONS (Host 'localhost', Database 'd\'b', User 'o\'brien', Password 'pw\'d', Port 3306); +CREATE /*M!100103 OR REPLACE */ SERVER `s'2` FOREIGN DATA WRAPPER 'my\'sql' OPTIONS (Host 'h2', Database 'db2', User 'u2', Port 0); USE mysql; @@ -328,8 +337,8 @@ UNLOCK TABLES; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -INSTALL PLUGIN test_plugin_server /*M!100401 IF NOT EXISTS */ SONAME 'AUTH_TEST_PLUGIN_LIB'; -INSTALL PLUGIN cleartext_plugin_server /*M!100401 IF NOT EXISTS */ SONAME 'AUTH_TEST_PLUGIN_LIB'; +INSTALL PLUGIN `test_plugin_server` /*M!100401 IF NOT EXISTS */ SONAME 'AUTH_TEST_PLUGIN_LIB'; +INSTALL PLUGIN `cleartext_plugin_server` /*M!100401 IF NOT EXISTS */ SONAME 'AUTH_TEST_PLUGIN_LIB'; CREATE USER IF NOT EXISTS `mariadb.sys`@`localhost` PASSWORD EXPIRE; CREATE USER IF NOT EXISTS `root`@`localhost`; CREATE USER IF NOT EXISTS `foobar`@`%` IDENTIFIED VIA test_plugin_server USING 'plug_dest'; @@ -364,8 +373,10 @@ GRANT USAGE ON *.* TO `role_2`; SET ROLE NONE; DROP ROLE mariadb_dump_import_role; /*M!100203 EXECUTE IMMEDIATE CONCAT('SET ROLE ', @current_role) */; -CREATE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; -CREATE SERVER /*M!100103 IF NOT EXISTS */ s1 FOREIGN DATA WRAPPER mysql OPTIONS (Host 'localhost', Port 3306); +CREATE FUNCTION IF NOT EXISTS `metaphon` RETURNS STRING SONAME 'UDF_EXAMPLE_LIB'; +CREATE AGGREGATE FUNCTION IF NOT EXISTS `avgcost` RETURNS REAL SONAME 'UDF_EXAMPLE_LIB'; +CREATE SERVER /*M!100103 IF NOT EXISTS */ `s1` FOREIGN DATA WRAPPER 'mysql' OPTIONS (Host 'localhost', Database 'd\'b', User 'o\'brien', Password 'pw\'d', Port 3306); +CREATE SERVER /*M!100103 IF NOT EXISTS */ `s'2` FOREIGN DATA WRAPPER 'my\'sql' OPTIONS (Host 'h2', Database 'db2', User 'u2', Port 0); USE mysql; @@ -453,8 +464,8 @@ Table Checksum mysql.roles_mapping 2510045525 mysql.time_zone_transition 3895294076 mysql.plugin 1587119305 -mysql.servers 2180549486 -mysql.func 3241572444 +mysql.servers 4086772068 +mysql.func 2140302938 mysql.innodb_table_stats 347867921 mysql.table_stats 664320059 # Opps.... @@ -471,7 +482,9 @@ delete from mysql.time_zone; delete from mysql.time_zone_name; delete from mysql.time_zone_leap_second; DROP FUNCTION IF EXISTS metaphon; +DROP FUNCTION IF EXISTS avgcost; DROP SERVER s1; +DROP SERVER `s'2`; set time_zone= @@global.time_zone; # Restore from mysqldump DROP USER mariadb_test_restore; @@ -488,12 +501,14 @@ Table Checksum mysql.roles_mapping 2510045525 mysql.time_zone_transition 3895294076 mysql.plugin 1587119305 -mysql.servers 2180549486 -mysql.func 3241572444 +mysql.servers 4086772068 +mysql.func 2140302938 mysql.innodb_table_stats 347867921 mysql.table_stats 664320059 DROP FUNCTION IF EXISTS metaphon; +DROP FUNCTION IF EXISTS avgcost; DROP SERVER s1; +DROP SERVER `s'2`; DELETE FROM mysql.column_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos'); DELETE FROM mysql.index_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos'); DELETE FROM mysql.table_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos'); diff --git a/mysql-test/main/mysqldump-system.test b/mysql-test/main/mysqldump-system.test index 7e85fcc1a11..4b3a72449c4 100644 --- a/mysql-test/main/mysqldump-system.test +++ b/mysql-test/main/mysqldump-system.test @@ -53,10 +53,19 @@ update mysql.innodb_table_stats set last_update="2020-01-01" where database_name set global innodb_stats_persistent= @save_innodb_stats_persistent; alter table mysql.time_zone_name ORDER BY Name; -CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(Host 'localhost'); +# single quotes in option values must be escaped; Db/Username map to Database/User; +# a server name with special chars must be quoted; multiple servers must dump with +# correct option separators +CREATE SERVER s1 FOREIGN DATA WRAPPER mysql + OPTIONS (HOST 'localhost', DATABASE 'd''b', USER 'o''brien', PASSWORD 'pw''d'); +CREATE SERVER `s'2` FOREIGN DATA WRAPPER 'my''sql' + OPTIONS (HOST 'h2', DATABASE 'db2', USER 'u2'); --replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; +# an aggregate UDF must round-trip as CREATE AGGREGATE FUNCTION +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; # @@ -117,7 +126,9 @@ delete from mysql.time_zone; delete from mysql.time_zone_name; delete from mysql.time_zone_leap_second; DROP FUNCTION IF EXISTS metaphon; +DROP FUNCTION IF EXISTS avgcost; DROP SERVER s1; +DROP SERVER `s'2`; set time_zone= @@global.time_zone; --echo # Restore from mysqldump @@ -138,8 +149,10 @@ CHECKSUM TABLE mysql.roles_mapping, mysql.time_zone_transition, mysql.plugin, # DROP FUNCTION IF EXISTS metaphon; +DROP FUNCTION IF EXISTS avgcost; DROP SERVER s1; +DROP SERVER `s'2`; # EITS && innodb stats DELETE FROM mysql.column_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos'); diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index 9bee735b071..7e561110ac9 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -5802,7 +5802,7 @@ USE `test`; /*!50003 SET collation_connection = utf8mb3_general_ci */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = '' */ ; -/*!50032 DROP TRIGGER IF EXISTS tt1_t1 */; +/*!50032 DROP TRIGGER IF EXISTS `tt1_t1` */; DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER tt1_t1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.b=NEW.a + 10