Skip to content
/ server Public
Open
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
20 changes: 11 additions & 9 deletions client/mysqldump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4925,10 +4925,10 @@ static int dump_all_users_roles_and_grants()
"SELECT CONCAT(QUOTE(u.user), '@', QUOTE(u.Host)) AS u "
"FROM mysql.user u "
" /*!80001 LEFT JOIN mysql.role_edges e "
" ON u.user=e.from_user "
" AND u.host=e.from_host "
" ON u.user=e.from_user COLLATE utf8mb4_bin "
" AND u.host=e.from_host COLLATE utf8mb4_bin "
" WHERE e.from_user IS NULL */"
" /*M!100005 WHERE is_role='N' */"))
" /*M!100005 WHERE BINARY is_role='N' */"))
return 1;
while ((row= mysql_fetch_row(tableres)))
{
Expand Down Expand Up @@ -4995,7 +4995,7 @@ static int dump_all_users_roles_and_grants()
" (SELECT 1 as n, roles_mapping.*"
" FROM mysql.roles_mapping"
" JOIN mysql.user USING (user,host)"
" WHERE is_role='N'"
" WHERE BINARY is_role='N'"
" AND Admin_option='Y'"
" UNION SELECT c.n+1, r.*"
" FROM create_role_order c"
Expand All @@ -5017,8 +5017,8 @@ static int dump_all_users_roles_and_grants()
" (SELECT 1 AS n,"
" re.*"
" FROM mysql.role_edges re"
" JOIN mysql.user u ON re.TO_HOST=u.HOST"
" AND re.TO_USER = u.USER"
" JOIN mysql.user u ON re.TO_HOST=u.HOST COLLATE utf8mb4_bin"
" AND re.TO_USER = u.USER COLLATE utf8mb4_bin"
" LEFT JOIN mysql.role_edges re2 ON re.TO_USER=re2.FROM_USER"
" AND re2.TO_HOST=re2.FROM_HOST"
" WHERE re2.FROM_USER IS NULL"
Expand Down Expand Up @@ -5061,13 +5061,15 @@ static int dump_all_users_roles_and_grants()
if (maria_roles_exist && mysql_query_with_error_report(mysql, &tableres,
"select IF(default_role='', 'NONE', QUOTE(default_role)) as r,"
"concat(QUOTE(User), '@', QUOTE(Host)) as u FROM mysql.user "
"/*M!100005 WHERE is_role='N' */"))
"/*M!100005 WHERE BINARY is_role='N' */"))
return 1;
if (mysql_roles_exist && mysql_query_with_error_report(mysql, &tableres,
"SELECT IF(DEFAULT_ROLE_HOST IS NULL, 'NONE', CONCAT(QUOTE(DEFAULT_ROLE_USER),"
" '@', QUOTE(DEFAULT_ROLE_HOST))) as r,"
" CONCAT(QUOTE(mu.USER),'@',QUOTE(mu.HOST)) as u "
"FROM mysql.user mu LEFT JOIN mysql.default_roles using (USER, HOST)"))
"FROM mysql.user mu LEFT JOIN mysql.default_roles dr"
" ON mu.USER = dr.USER COLLATE utf8mb4_bin"
" AND mu.HOST = dr.HOST COLLATE utf8mb4_bin"))
{
mysql_free_result(tableres);
return 1;
Expand All @@ -5086,7 +5088,7 @@ static int dump_all_users_roles_and_grants()
"SELECT DISTINCT QUOTE(m.role) AS r "
" FROM mysql.roles_mapping m"
" JOIN mysql.user u ON u.user = m.role"
" WHERE is_role='Y'"
" WHERE BINARY is_role='Y'"
" AND Admin_option='Y'"
" ORDER BY m.role"))
return 1;
Expand Down
33 changes: 33 additions & 0 deletions mysql-test/main/mysqldump-system-collation.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#
# MDEV-37442: Illegal mix of collations during "mariadb-dump --system=user"
#
# After upgrading MariaDB (e.g. 11.2 -> 11.8), the mysql.user view
# retains the old default utf8mb4 collation while the connection uses
# the new one, causing collation mismatch errors in mysqldump --system=user.
#
SET @view_body = (SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user');
CREATE ROLE test_role_37442;
CREATE USER test_user_37442;
GRANT test_role_37442 TO test_user_37442;
SET DEFAULT ROLE test_role_37442 FOR test_user_37442;
ALTER TABLE mysql.roles_mapping ORDER BY Host, User, Role;
SET @save_collation = @@collation_connection;
SET collation_connection = 'utf8mb4_general_ci';
SET @recreate_sql = CONCAT(
"CREATE OR REPLACE DEFINER='mariadb.sys'@'localhost' ",
"SQL SECURITY DEFINER VIEW mysql.user AS ", @view_body);
PREPARE stmt FROM @recreate_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET collation_connection = @save_collation;
# mysqldump --system=user should succeed despite collation mismatch
# Cleanup
DROP USER test_user_37442;
DROP ROLE test_role_37442;
SET @recreate_sql = CONCAT(
"CREATE OR REPLACE DEFINER='mariadb.sys'@'localhost' ",
"SQL SECURITY DEFINER VIEW mysql.user AS ", @view_body);
PREPARE stmt FROM @recreate_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
53 changes: 53 additions & 0 deletions mysql-test/main/mysqldump-system-collation.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--source include/not_embedded.inc

--echo #
--echo # MDEV-37442: Illegal mix of collations during "mariadb-dump --system=user"
--echo #
--echo # After upgrading MariaDB (e.g. 11.2 -> 11.8), the mysql.user view
--echo # retains the old default utf8mb4 collation while the connection uses
--echo # the new one, causing collation mismatch errors in mysqldump --system=user.
--echo #

# Save the mysql.user view definition to recreate it later
SET @view_body = (SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user');

# Create roles so that role-related code paths in mysqldump are exercised
CREATE ROLE test_role_37442;
CREATE USER test_user_37442;
GRANT test_role_37442 TO test_user_37442;
SET DEFAULT ROLE test_role_37442 FOR test_user_37442;
ALTER TABLE mysql.roles_mapping ORDER BY Host, User, Role;

# Recreate the mysql.user view with utf8mb4_general_ci collation
# to simulate a view created before the default collation changed
SET @save_collation = @@collation_connection;
SET collation_connection = 'utf8mb4_general_ci';
SET @recreate_sql = CONCAT(
"CREATE OR REPLACE DEFINER='mariadb.sys'@'localhost' ",
"SQL SECURITY DEFINER VIEW mysql.user AS ", @view_body);
PREPARE stmt FROM @recreate_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

# Restore connection collation to the current default (utf8mb4_uca1400_ai_ci)
# This creates the mismatch: view uses utf8mb4_general_ci, connection uses
# utf8mb4_uca1400_ai_ci
SET collation_connection = @save_collation;

--echo # mysqldump --system=user should succeed despite collation mismatch
--exec $MYSQL_DUMP --skip-comments --system=user > $MYSQLTEST_VARDIR/tmp/mdev37442.sql

--echo # Cleanup
DROP USER test_user_37442;
DROP ROLE test_role_37442;

# Restore the mysql.user view with current collation
SET @recreate_sql = CONCAT(
"CREATE OR REPLACE DEFINER='mariadb.sys'@'localhost' ",
"SQL SECURITY DEFINER VIEW mysql.user AS ", @view_body);
PREPARE stmt FROM @recreate_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

--remove_file $MYSQLTEST_VARDIR/tmp/mdev37442.sql