From c169838611e13c9f0559b2f49ba8c36aec11a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Sun, 17 Jan 2016 17:00:19 +0200 Subject: [PATCH 01/37] [MDEV-7978] Update grammar for new syntax Extend the syntax accepted by the grammar to account for the new create user and alter user syntax. --- sql/mysqld.cc | 1 + sql/sp_head.cc | 1 + sql/sql_acl.cc | 20 ++++++++++++++++ sql/sql_acl.h | 1 + sql/sql_cmd.h | 1 + sql/sql_parse.cc | 10 +++++++- sql/sql_yacc.yy | 59 ++++++++++++++++++++++++++++++++---------------- 7 files changed, 73 insertions(+), 20 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8d00b5af948..7e18251c670 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3676,6 +3676,7 @@ SHOW_VAR com_status_vars[]= { {"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)}, {"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)}, {"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)}, + {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)}, {"analyze", STMT_STATUS(SQLCOM_ANALYZE)}, {"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)}, {"begin", STMT_STATUS(SQLCOM_BEGIN)}, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0428c0198a1..5749d5df18d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -309,6 +309,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_USER: case SQLCOM_CREATE_ROLE: case SQLCOM_ALTER_TABLE: + case SQLCOM_ALTER_USER: case SQLCOM_GRANT: case SQLCOM_GRANT_ROLE: case SQLCOM_REVOKE: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index cf0b1d87bd7..9178b1f8cc3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9840,6 +9840,26 @@ bool mysql_rename_user(THD *thd, List &list) DBUG_RETURN(result); } +/* + Alter a user's connection and resource settings. + + SYNOPSIS + mysql_alter_user() + thd The current thread. + list The users to alter. + + RETURN + > 0 Error. Error message already sent. + 0 OK. + < 0 Error. Error message not yet sent. +*/ +int mysql_alter_user(THD* thd, List &users_list) +{ + DBUG_ENTER("mysql_alter_user"); + int result= 0; + // TODO implement the alter user logic. + DBUG_RETURN(result); +} /* Revoke all privileges from a list of users. diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 3bd896cab79..ac6a064c7e0 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -253,6 +253,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc); bool mysql_create_user(THD *thd, List &list, bool handle_as_role); bool mysql_drop_user(THD *thd, List &list, bool handle_as_role); bool mysql_rename_user(THD *thd, List &list); +int mysql_alter_user(THD *thd, List &list); bool mysql_revoke_all(THD *thd, List &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index c237bb9270a..5c697c4cd10 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -93,6 +93,7 @@ enum enum_sql_command { SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE, SQLCOM_COMPOUND, SQLCOM_SHOW_GENERIC, + SQLCOM_ALTER_USER, /* When a command is added here, be sure it's also added in mysqld.cc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14ac657862f..77b6f053e79 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -443,6 +443,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA; + sql_command_flags[SQLCOM_ALTER_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_ROLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT_ROLE]= CF_CHANGES_DATA; @@ -506,6 +507,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CHECKSUM]= CF_REPORT_PROGRESS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS; + sql_command_flags[SQLCOM_ALTER_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS; @@ -601,6 +603,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS; @@ -4403,6 +4406,7 @@ mysql_execute_command(THD *thd) my_ok(thd); break; } + case SQLCOM_ALTER_USER: case SQLCOM_RENAME_USER: { if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) && @@ -4410,7 +4414,11 @@ mysql_execute_command(THD *thd) break; /* Conditionally writes to binlog */ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) - if (!(res= mysql_rename_user(thd, lex->users_list))) + if (lex->sql_command == SQLCOM_ALTER_USER) + res= mysql_alter_user(thd, lex->users_list); + else + res= mysql_rename_user(thd, lex->users_list); + if (!res) my_ok(thd); break; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2a46bb2a027..0cb13fe5a2b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2531,7 +2531,8 @@ create: Lex->create_view_suid= TRUE; } view_or_trigger_or_sp_or_event { } - | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list + | create_or_replace USER opt_if_not_exists clear_privileges grant_list + require_clause resource_options { if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3)) MYSQL_YYABORT; @@ -7106,6 +7107,11 @@ alter: lex->sql_command= SQLCOM_ALTER_SERVER; lex->server_options.reset($3); } OPTIONS_SYM '(' server_options_list ')' { } + | ALTER opt_if_exists USER clear_privileges user_list + require_clause resource_options + { + Lex->sql_command= SQLCOM_ALTER_USER; + } ; ev_alter_on_schedule_completion: @@ -15412,24 +15418,8 @@ require_clause: } ; -grant_options: - /* empty */ {} - | WITH grant_option_list - ; - -opt_grant_option: - /* empty */ {} - | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} - ; - -grant_option_list: - grant_option_list grant_option {} - | grant_option {} - ; - -grant_option: - GRANT OPTION { Lex->grant |= GRANT_ACL;} - | MAX_QUERIES_PER_HOUR ulong_num +resource_option: + MAX_QUERIES_PER_HOUR ulong_num { LEX *lex=Lex; lex->mqh.questions=$2; @@ -15461,6 +15451,37 @@ grant_option: } ; +resource_option_list: + resource_option_list resource_option {} + | resource_option {} + ; + +resource_options: + /* empty */ {} + | WITH resource_option_list + ; + + +grant_options: + /* empty */ {} + | WITH grant_option_list {} + ; + +opt_grant_option: + /* empty */ {} + | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} + ; + +grant_option_list: + grant_option_list grant_option {} + | grant_option {} + ; + +grant_option: + GRANT OPTION { Lex->grant |= GRANT_ACL;} + | resource_option {} + ; + begin: BEGIN_SYM { From a701e9e6c390c3cbac69872e95b1aec565341d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 18 Jan 2016 02:16:59 +0200 Subject: [PATCH 02/37] [MDEV-7978] Implement alter user and tested create user Implemented the alter user syntax. Also tested that create user creates users accordingly. --- mysql-test/r/alter_user.result | 79 +++++++++++++++++++++++++++++++++ mysql-test/r/create_user.result | 72 ++++++++++++++++++++++++++++++ mysql-test/t/alter_user.test | 71 +++++++++++++++++++++++++++++ mysql-test/t/create_user.test | 58 ++++++++++++++++++++++++ sql/sql_acl.cc | 51 ++++++++++++++++++++- sql/sql_yacc.yy | 3 +- 6 files changed, 331 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/alter_user.result create mode 100644 mysql-test/r/create_user.result create mode 100644 mysql-test/t/alter_user.test create mode 100644 mysql-test/t/create_user.test diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result new file mode 100644 index 00000000000..2acc2493acb --- /dev/null +++ b/mysql-test/r/alter_user.result @@ -0,0 +1,79 @@ +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +# Test syntax +# +# These 2 selects should have no changes from the first one. +alter user CURRENT_USER; +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +alter user CURRENT_USER(); +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +create user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +alter user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +# Test super privilege works correctly with a read only database. +SET @start_read_only = @@global.read_only; +SET GLOBAL read_only=1; +grant create user on *.* to foo; +# Currently no super privileges. +connect a, localhost, foo; +select @@global.read_only; +@@global.read_only +1 +alter user foo; +ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement +# Grant super privilege to the user. +connection default; +grant super on *.* to foo; +# We now have super privilege. We should be able to run alter user. +connect b, localhost, foo; +alter user foo; +connection default; +SET GLOBAL read_only = @start_read_only; +# Test inexistant user. +alter user boo; +ERROR HY000: Operation ALTER USER failed for 'boo' +#--warning ER_CANNOT_USER +alter if exists user boo; +Warnings: +Error 1133 Can't find any matching row in the user table +Note 1396 Operation ALTER USER failed for 'boo' +# Test SSL related altering. +alter user foo identified by 'something'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified by 'something2'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified with 'somecoolplugin'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin N N 0.000000 +alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 +# Test resource limits altering. +alter user foo with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 10 20 30 40 somecoolplugin somecoolpassphrase N N 0.000000 +drop user foo; diff --git a/mysql-test/r/create_user.result b/mysql-test/r/create_user.result new file mode 100644 index 00000000000..1411f2e8792 --- /dev/null +++ b/mysql-test/r/create_user.result @@ -0,0 +1,72 @@ +create user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require SSL; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require X509; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher' + SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher' +AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo, foo2 identified by 'password' require CIPHER 'cipher' +AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +#--warning ER_USER_CREATE_EXISTS +create user if not exists foo, foo2 identified by 'password2' + require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; +Warnings: +Note 1973 Can't create user 'foo'@'%'; it already exists +Note 1973 Can't create user 'foo2'@'%'; it already exists +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +drop user foo, foo2; +create user foo with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40; +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 +drop user foo; diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test new file mode 100644 index 00000000000..3a3a7d74ba5 --- /dev/null +++ b/mysql-test/t/alter_user.test @@ -0,0 +1,71 @@ +--source include/not_embedded.inc +--enable_connect_log + + +select * from mysql.user where user = 'root' and host = 'localhost'; +--echo # Test syntax +--echo # +--echo # These 2 selects should have no changes from the first one. +alter user CURRENT_USER; +select * from mysql.user where user = 'root' and host = 'localhost'; +alter user CURRENT_USER(); +select * from mysql.user where user = 'root' and host = 'localhost'; + +create user foo; +select * from mysql.user where user = 'foo'; +alter user foo; +select * from mysql.user where user = 'foo'; + +--echo # Test super privilege works correctly with a read only database. +SET @start_read_only = @@global.read_only; +SET GLOBAL read_only=1; +grant create user on *.* to foo; + +--echo # Currently no super privileges. +connect (a, localhost, foo); +select @@global.read_only; + +--error ER_OPTION_PREVENTS_STATEMENT +alter user foo; + +--echo # Grant super privilege to the user. +connection default; +grant super on *.* to foo; + +--echo # We now have super privilege. We should be able to run alter user. +connect (b, localhost, foo); +alter user foo; + +connection default; +SET GLOBAL read_only = @start_read_only; + +--echo # Test inexistant user. +--error ER_CANNOT_USER +alter user boo; +--echo #--warning ER_CANNOT_USER +alter if exists user boo; + +--echo # Test SSL related altering. +alter user foo identified by 'something'; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something2'; +select * from mysql.user where user = 'foo'; + +alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; +select * from mysql.user where user = 'foo'; + +alter user foo identified with 'somecoolplugin'; +select * from mysql.user where user = 'foo'; + +alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +select * from mysql.user where user = 'foo'; + +--echo # Test resource limits altering. +alter user foo with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40; +select * from mysql.user where user = 'foo'; +drop user foo; +--disable_connect_log diff --git a/mysql-test/t/create_user.test b/mysql-test/t/create_user.test new file mode 100644 index 00000000000..f04cb3e302a --- /dev/null +++ b/mysql-test/t/create_user.test @@ -0,0 +1,58 @@ +--source include/not_embedded.inc + +create user foo; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require SSL; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require X509; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher' + SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher' + AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo, foo2 identified by 'password' require CIPHER 'cipher' + AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user like 'foo'; + +--echo #--warning ER_USER_CREATE_EXISTS +create user if not exists foo, foo2 identified by 'password2' + require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; +select * from mysql.user where user like 'foo'; +drop user foo, foo2; + +create user foo with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40; +select * from mysql.user where user like 'foo'; +drop user foo; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9178b1f8cc3..24f4042d2a5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9851,13 +9851,60 @@ bool mysql_rename_user(THD *thd, List &list) RETURN > 0 Error. Error message already sent. 0 OK. - < 0 Error. Error message not yet sent. */ int mysql_alter_user(THD* thd, List &users_list) { DBUG_ENTER("mysql_alter_user"); int result= 0; - // TODO implement the alter user logic. + TABLE_LIST tables[TABLES_MAX]; + String wrong_users; + // The only table we're altering is the user table. + if ((result= open_grant_tables(thd, tables, TL_WRITE, Table_user))) + DBUG_RETURN(result); + + // Lock ACL data structures until we finish altering all users. + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); + + LEX_USER *tmp_lex_user; + List_iterator users_list_iterator(users_list); + while ((tmp_lex_user= users_list_iterator++)) + { + LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false); + if (!lex_user || + fix_lex_user(thd, lex_user) || + replace_user_table(thd, tables[USER_TABLE].table, *lex_user,0, + false, false, true)) + { + thd->clear_error(); + append_user(thd, &wrong_users, tmp_lex_user); + result= TRUE; + continue; + } + } + + // Unlock ACL data structures. + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); + + if (result) + { + // 'if exists' flag leads to warnings instead of errors. + if (thd->lex->create_info.if_exists()) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_CANNOT_USER, + ER_THD(thd, ER_CANNOT_USER), + "ALTER USER", wrong_users.c_ptr_safe()); + result= FALSE; + } + else + { + my_error(ER_CANNOT_USER, MYF(0), + "ALTER USER", + wrong_users.c_ptr_safe()); + } + } DBUG_RETURN(result); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0cb13fe5a2b..dd9f2fdf0ae 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7107,9 +7107,10 @@ alter: lex->sql_command= SQLCOM_ALTER_SERVER; lex->server_options.reset($3); } OPTIONS_SYM '(' server_options_list ')' { } - | ALTER opt_if_exists USER clear_privileges user_list + | ALTER opt_if_exists USER clear_privileges grant_list require_clause resource_options { + Lex->create_info.set($2); Lex->sql_command= SQLCOM_ALTER_USER; } ; From 6b6f066fdd9f5f64813ded550e7dbda176ee3c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 19 Jan 2016 13:01:28 +0200 Subject: [PATCH 03/37] [MDEV-7978] Update test cases Adding an extra statement requires test cases update. --- mysql-test/r/mysqld--help.result | 2 +- mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index dce1578adee..398625992ac 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1360,7 +1360,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 150 -performance-schema-max-statement-classes 178 +performance-schema-max-statement-classes 179 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 21f1f905de8..5f05be1b65e 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3021,9 +3021,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 178 +GLOBAL_VALUE 179 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 178 +DEFAULT_VALUE 179 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. From f8b8d202bc83d3de46c89ef86333fe602e711265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 19 Jan 2016 14:30:19 +0200 Subject: [PATCH 04/37] [MDEV-7978] Updated syntax for SHOW CREATE USER --- sql/mysqld.cc | 1 + sql/sp_head.cc | 1 + sql/sql_acl.cc | 4 ++++ sql/sql_acl.h | 1 + sql/sql_cmd.h | 1 + sql/sql_parse.cc | 17 ++++++++++++++++- sql/sql_yacc.yy | 12 ++++++++++++ 7 files changed, 36 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7e18251c670..b28cea5ac46 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3766,6 +3766,7 @@ SHOW_VAR com_status_vars[]= { {"show_create_proc", STMT_STATUS(SQLCOM_SHOW_CREATE_PROC)}, {"show_create_table", STMT_STATUS(SQLCOM_SHOW_CREATE)}, {"show_create_trigger", STMT_STATUS(SQLCOM_SHOW_CREATE_TRIGGER)}, + {"show_create_user", STMT_STATUS(SQLCOM_SHOW_CREATE_USER)}, {"show_databases", STMT_STATUS(SQLCOM_SHOW_DATABASES)}, {"show_engine_logs", STMT_STATUS(SQLCOM_SHOW_ENGINE_LOGS)}, {"show_engine_mutex", STMT_STATUS(SQLCOM_SHOW_ENGINE_MUTEX)}, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5749d5df18d..a27f0ef4250 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -241,6 +241,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_CREATE_PROC: case SQLCOM_SHOW_CREATE_EVENT: case SQLCOM_SHOW_CREATE_TRIGGER: + case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_ERRORS: case SQLCOM_SHOW_EXPLAIN: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 24f4042d2a5..74ceb611a8f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7811,6 +7811,10 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data) return 0; } +bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) +{ + return FALSE; +} void mysql_show_grants_get_fields(THD *thd, List *fields, const char *name) diff --git a/sql/sql_acl.h b/sql/sql_acl.h index ac6a064c7e0..b480d488bc3 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -246,6 +246,7 @@ bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username, void mysql_show_grants_get_fields(THD *thd, List *fields, const char *name); bool mysql_show_grants(THD *thd, LEX_USER *user); +bool mysql_show_create_user(THD *thd, LEX_USER *user); int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond); void get_privilege_desc(char *to, uint max_length, ulong access); diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index 5c697c4cd10..2350b4be56c 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -94,6 +94,7 @@ enum enum_sql_command { SQLCOM_COMPOUND, SQLCOM_SHOW_GENERIC, SQLCOM_ALTER_USER, + SQLCOM_SHOW_CREATE_USER, /* When a command is added here, be sure it's also added in mysqld.cc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 77b6f053e79..a5837585b7d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -422,6 +422,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_USER]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; @@ -4715,6 +4716,7 @@ mysql_execute_command(THD *thd) break; #ifndef NO_EMBEDDED_ACCESS_CHECKS + case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_GRANTS: { LEX_USER *grant_user= lex->grant_user; @@ -4722,7 +4724,20 @@ mysql_execute_command(THD *thd) goto error; WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW); - res = mysql_show_grants(thd, grant_user); + if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) && + grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str)) + grant_user->user= current_user; + + if (grant_user->user.str == current_user.str || + grant_user->user.str == current_role.str || + grant_user->user.str == current_user_and_current_role.str || + !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) + { + if (lex->sql_command == SQLCOM_SHOW_GRANTS) + res = mysql_show_grants(thd, grant_user); + else + res = mysql_show_create_user(thd, grant_user); + } break; } #endif diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dd9f2fdf0ae..d7e4fb34005 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -12493,6 +12493,18 @@ show_param: lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER; lex->spname= $3; } + | CREATE USER + { + Lex->sql_command= SQLCOM_SHOW_CREATE_USER; + if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER)))) + MYSQL_YYABORT; + Lex->grant_user->user= current_user_and_current_role; + } + | CREATE USER user + { + Lex->sql_command= SQLCOM_SHOW_CREATE_USER; + Lex->grant_user= $3; + } | PROCEDURE_SYM STATUS_SYM wild_and_where { LEX *lex= Lex; From a470b3570a7ce2534c9021f3b84d7457a3ba08e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 19 Jan 2016 14:33:00 +0200 Subject: [PATCH 05/37] [MDEV-7978] Update test cases Update test to account for the new SHOW CREATE USER command. --- mysql-test/r/mysqld--help.result | 2 +- mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 398625992ac..a008affa9f8 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1360,7 +1360,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 150 -performance-schema-max-statement-classes 179 +performance-schema-max-statement-classes 180 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 5f05be1b65e..4c358fd456a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3021,9 +3021,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 179 +GLOBAL_VALUE 180 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 179 +DEFAULT_VALUE 180 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. From f3f45e46b614bddcef0a37f4352c5909ca565d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 21 Jan 2016 13:20:40 +0200 Subject: [PATCH 06/37] [MDEV-7978] Added show create user implementation. --- mysql-test/r/show_create_user.result | 39 +++++ mysql-test/t/show_create_user.test | 32 ++++ sql/sql_acl.cc | 253 +++++++++++++++++---------- sql/sql_yacc.yy | 2 +- 4 files changed, 233 insertions(+), 93 deletions(-) create mode 100644 mysql-test/r/show_create_user.result create mode 100644 mysql-test/t/show_create_user.test diff --git a/mysql-test/r/show_create_user.result b/mysql-test/r/show_create_user.result new file mode 100644 index 00000000000..63013eca074 --- /dev/null +++ b/mysql-test/r/show_create_user.result @@ -0,0 +1,39 @@ +create user foo; +show create user foo; +CREATE USER for foo@% +CREATE USER 'foo'@'%' +create user foo@test; +show create user foo@test; +CREATE USER for foo@test +CREATE USER 'foo'@'test' +create user foo2@test identified by 'password'; +show create user foo2@test; +CREATE USER for foo2@test +CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' +alter user foo2@test identified with 'someplugin' as 'somepassword'; +show create user foo2@test; +CREATE USER for foo2@test +CREATE USER 'foo2'@'test' IDENTIFIED VIA someplugin USING 'somepassword' +create user foo3@test require SSL; +show create user foo3@test; +CREATE USER for foo3@test +CREATE USER 'foo3'@'test' REQUIRE SSL +create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +show create user foo4@test; +CREATE USER for foo4@test +CREATE USER 'foo4'@'test' REQUIRE ISSUER 'foo_issuer' SUBJECT 'foo_subject' CIPHER 'text' +create user foo5@test require SSL +with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40 +MAX_STATEMENT_TIME 0.5; +show create user foo5@test; +CREATE USER for foo5@test +CREATE USER 'foo5'@'test' REQUIRE SSL WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40 MAX_STATEMENT_TIME 0.500000 +drop user foo5@test; +drop user foo4@test; +drop user foo3@test; +drop user foo2@test; +drop user foo@test; +drop user foo; diff --git a/mysql-test/t/show_create_user.test b/mysql-test/t/show_create_user.test new file mode 100644 index 00000000000..124856ad564 --- /dev/null +++ b/mysql-test/t/show_create_user.test @@ -0,0 +1,32 @@ +create user foo; +show create user foo; + +create user foo@test; +show create user foo@test; + +create user foo2@test identified by 'password'; +show create user foo2@test; + +alter user foo2@test identified with 'someplugin' as 'somepassword'; +show create user foo2@test; + +create user foo3@test require SSL; +show create user foo3@test; + +create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +show create user foo4@test; + +create user foo5@test require SSL + with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40 + MAX_STATEMENT_TIME 0.5; +show create user foo5@test; + +drop user foo5@test; +drop user foo4@test; +drop user foo3@test; +drop user foo2@test; +drop user foo@test; +drop user foo; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 74ceb611a8f..11272f586c9 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7756,6 +7756,94 @@ static void add_user_option(String *grant, double value, const char *name) } } +static void add_user_parameters(String *result, ACL_USER* acl_user, + bool with_grant) +{ + result->append(STRING_WITH_LEN("@'")); + result->append(acl_user->host.hostname, acl_user->hostname_length, + system_charset_info); + result->append('\''); + + if (acl_user->plugin.str == native_password_plugin_name.str || + acl_user->plugin.str == old_password_plugin_name.str) + { + if (acl_user->auth_string.length) + { + DBUG_ASSERT(acl_user->salt_len); + result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); + result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append('\''); + } + } + else + { + result->append(STRING_WITH_LEN(" IDENTIFIED VIA ")); + result->append(acl_user->plugin.str, acl_user->plugin.length); + if (acl_user->auth_string.length) + { + result->append(STRING_WITH_LEN(" USING '")); + result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append('\''); + } + } + /* "show grants" SSL related stuff */ + if (acl_user->ssl_type == SSL_TYPE_ANY) + result->append(STRING_WITH_LEN(" REQUIRE SSL")); + else if (acl_user->ssl_type == SSL_TYPE_X509) + result->append(STRING_WITH_LEN(" REQUIRE X509")); + else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) + { + int ssl_options = 0; + result->append(STRING_WITH_LEN(" REQUIRE ")); + if (acl_user->x509_issuer) + { + ssl_options++; + result->append(STRING_WITH_LEN("ISSUER \'")); + result->append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + result->append('\''); + } + if (acl_user->x509_subject) + { + if (ssl_options++) + result->append(' '); + result->append(STRING_WITH_LEN("SUBJECT \'")); + result->append(acl_user->x509_subject,strlen(acl_user->x509_subject), + system_charset_info); + result->append('\''); + } + if (acl_user->ssl_cipher) + { + if (ssl_options++) + result->append(' '); + result->append(STRING_WITH_LEN("CIPHER '")); + result->append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + system_charset_info); + result->append('\''); + } + } + if (with_grant || + (acl_user->user_resource.questions || + acl_user->user_resource.updates || + acl_user->user_resource.conn_per_hour || + acl_user->user_resource.user_conn || + acl_user->user_resource.max_statement_time != 0.0)) + { + result->append(STRING_WITH_LEN(" WITH")); + if (with_grant) + result->append(STRING_WITH_LEN(" GRANT OPTION")); + add_user_option(result, acl_user->user_resource.questions, + "MAX_QUERIES_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.updates, + "MAX_UPDATES_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.conn_per_hour, + "MAX_CONNECTIONS_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.user_conn, + "MAX_USER_CONNECTIONS", true); + add_user_option(result, acl_user->user_resource.max_statement_time, + "MAX_STATEMENT_TIME"); + } +} + static const char *command_array[]= { "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD", @@ -7802,6 +7890,78 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role) } +bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) +{ + const char *username = safe_str(lex_user->user.str); + const char *hostname = safe_str(lex_user->host.str); + char buff[1024]; //Show create user should not take more than 1024 bytes. + Protocol *protocol= thd->protocol; + bool error= false; + ACL_USER *acl_user; + DBUG_ENTER("mysql_show_create_user"); + + // Check if the command specifies a username or not. + if (lex_user->user.str == current_user.str) + { + username= thd->security_ctx->priv_user; + hostname= thd->security_ctx->priv_host; + } + + String field_name(buff, sizeof(buff), system_charset_info); + List field_list; + strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS); + Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0); + if (!field) + { + my_error(ER_OUTOFMEMORY, MYF(0)); + DBUG_RETURN(true); + } + + field->name= buff; + field->max_length= sizeof(buff); + field_list.push_back(field, thd->mem_root); + if (protocol->send_result_set_metadata(&field_list, + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) + DBUG_RETURN(true); + + String result(buff, sizeof(buff), system_charset_info); + result.length(0); + mysql_rwlock_rdlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); + + acl_user= find_user_exact(hostname, username); + + // User not found in the internal data structures. + if (!acl_user) + { + my_error(ER_PASSWORD_NO_MATCH, MYF(0)); + error= true; + goto end; + } + + result.append("CREATE USER '"); + result.append(username); + result.append('\''); + + add_user_parameters(&result, acl_user, false); + + protocol->prepare_for_resend(); + protocol->store(result.ptr(), result.length(), result.charset()); + if (protocol->write()) + { + error= true; + } + my_eof(thd); + +end: + mysql_rwlock_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + + DBUG_RETURN(error); +} + + static int show_grants_callback(ACL_USER_BASE *role, void *data) { THD *thd= (THD *)data; @@ -7811,11 +7971,6 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data) return 0; } -bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) -{ - return FALSE; -} - void mysql_show_grants_get_fields(THD *thd, List *fields, const char *name) { @@ -8090,93 +8245,7 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, global.append('\''); if (!handle_as_role) - { - ACL_USER *acl_user= (ACL_USER *)acl_entry; - - global.append (STRING_WITH_LEN("@'")); - global.append(acl_user->host.hostname, acl_user->hostname_length, - system_charset_info); - global.append ('\''); - - if (acl_user->plugin.str == native_password_plugin_name.str || - acl_user->plugin.str == old_password_plugin_name.str) - { - if (acl_user->auth_string.length) - { - DBUG_ASSERT(acl_user->salt_len); - global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); - global.append(acl_user->auth_string.str, acl_user->auth_string.length); - global.append('\''); - } - } - else - { - global.append(STRING_WITH_LEN(" IDENTIFIED VIA ")); - global.append(acl_user->plugin.str, acl_user->plugin.length); - if (acl_user->auth_string.length) - { - global.append(STRING_WITH_LEN(" USING '")); - global.append(acl_user->auth_string.str, acl_user->auth_string.length); - global.append('\''); - } - } - /* "show grants" SSL related stuff */ - if (acl_user->ssl_type == SSL_TYPE_ANY) - global.append(STRING_WITH_LEN(" REQUIRE SSL")); - else if (acl_user->ssl_type == SSL_TYPE_X509) - global.append(STRING_WITH_LEN(" REQUIRE X509")); - else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) - { - int ssl_options = 0; - global.append(STRING_WITH_LEN(" REQUIRE ")); - if (acl_user->x509_issuer) - { - ssl_options++; - global.append(STRING_WITH_LEN("ISSUER \'")); - global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); - global.append('\''); - } - if (acl_user->x509_subject) - { - if (ssl_options++) - global.append(' '); - global.append(STRING_WITH_LEN("SUBJECT \'")); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), - system_charset_info); - global.append('\''); - } - if (acl_user->ssl_cipher) - { - if (ssl_options++) - global.append(' '); - global.append(STRING_WITH_LEN("CIPHER '")); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), - system_charset_info); - global.append('\''); - } - } - if ((want_access & GRANT_ACL) || - (acl_user->user_resource.questions || - acl_user->user_resource.updates || - acl_user->user_resource.conn_per_hour || - acl_user->user_resource.user_conn || - acl_user->user_resource.max_statement_time != 0.0)) - { - global.append(STRING_WITH_LEN(" WITH")); - if (want_access & GRANT_ACL) - global.append(STRING_WITH_LEN(" GRANT OPTION")); - add_user_option(&global, acl_user->user_resource.questions, - "MAX_QUERIES_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.updates, - "MAX_UPDATES_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.conn_per_hour, - "MAX_CONNECTIONS_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.user_conn, - "MAX_USER_CONNECTIONS", true); - add_user_option(&global, acl_user->user_resource.max_statement_time, - "MAX_STATEMENT_TIME"); - } - } + add_user_parameters(&global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL)); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d7e4fb34005..14616d33fbe 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -12498,7 +12498,7 @@ show_param: Lex->sql_command= SQLCOM_SHOW_CREATE_USER; if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER)))) MYSQL_YYABORT; - Lex->grant_user->user= current_user_and_current_role; + Lex->grant_user->user= current_user; } | CREATE USER user { From 85b085972b729f6c049050f851692c9a5b86f3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 8 Mar 2016 00:35:03 +0200 Subject: [PATCH 07/37] [MDEV-7978] Post review fixes and cleanups. * Maintain coding style in sql_yacc.yy in regards to optional clauses. * Remove unused variable from sql_acl.cc. * Update test case --- mysql-test/r/alter_user.result | 18 ++++++++++++++++-- mysql-test/t/alter_user.test | 13 ++++++++++++- sql/sql_acl.cc | 1 - sql/sql_yacc.yy | 17 +++++++++-------- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result index 2acc2493acb..ac668bba8fa 100644 --- a/mysql-test/r/alter_user.result +++ b/mysql-test/r/alter_user.result @@ -47,7 +47,7 @@ alter if exists user boo; Warnings: Error 1133 Can't find any matching row in the user table Note 1396 Operation ALTER USER failed for 'boo' -# Test SSL related altering. +# Test password related altering. alter user foo identified by 'something'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time @@ -68,6 +68,20 @@ alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time % foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 +# Test ssl related altering. +alter user foo identified by 'something' require SSL; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N ANY 0 0 0 0 N N 0.000000 +alter user foo identified by 'something' require X509; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N X509 0 0 0 0 N N 0.000000 +alter user foo identified by 'something' +require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000 # Test resource limits altering. alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 @@ -75,5 +89,5 @@ MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 10 20 30 40 somecoolplugin somecoolpassphrase N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 drop user foo; diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test index 3a3a7d74ba5..e32d0c29f2e 100644 --- a/mysql-test/t/alter_user.test +++ b/mysql-test/t/alter_user.test @@ -45,7 +45,7 @@ alter user boo; --echo #--warning ER_CANNOT_USER alter if exists user boo; ---echo # Test SSL related altering. +--echo # Test password related altering. alter user foo identified by 'something'; select * from mysql.user where user = 'foo'; @@ -61,6 +61,17 @@ select * from mysql.user where user = 'foo'; alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; select * from mysql.user where user = 'foo'; +--echo # Test ssl related altering. +alter user foo identified by 'something' require SSL; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something' require X509; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something' +require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +select * from mysql.user where user = 'foo'; + --echo # Test resource limits altering. alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 11272f586c9..2b6ababa8dd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7907,7 +7907,6 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) hostname= thd->security_ctx->priv_host; } - String field_name(buff, sizeof(buff), system_charset_info); List field_list; strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS); Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 14616d33fbe..6799781f5e0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2532,7 +2532,7 @@ create: } view_or_trigger_or_sp_or_event { } | create_or_replace USER opt_if_not_exists clear_privileges grant_list - require_clause resource_options + opt_require_clause opt_resource_options { if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3)) MYSQL_YYABORT; @@ -7107,8 +7107,9 @@ alter: lex->sql_command= SQLCOM_ALTER_SERVER; lex->server_options.reset($3); } OPTIONS_SYM '(' server_options_list ')' { } + /* ALTER USER foo is allowed for MySQL compatibility. */ | ALTER opt_if_exists USER clear_privileges grant_list - require_clause resource_options + opt_require_clause opt_resource_options { Lex->create_info.set($2); Lex->sql_command= SQLCOM_ALTER_USER; @@ -15055,14 +15056,14 @@ grant: grant_command: grant_privileges ON opt_table grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; lex->sql_command= SQLCOM_GRANT; lex->type= 0; } | grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15074,7 +15075,7 @@ grant_command: lex->type= TYPE_ENUM_FUNCTION; } | grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15411,7 +15412,7 @@ column_list_id: } ; -require_clause: +opt_require_clause: /* empty */ | REQUIRE_SYM require_list { @@ -15469,13 +15470,13 @@ resource_option_list: | resource_option {} ; -resource_options: +opt_resource_options: /* empty */ {} | WITH resource_option_list ; -grant_options: +opt_grant_options: /* empty */ {} | WITH grant_option_list {} ; From 0ff897807fc2f4a32e1ba1ae148005930ea604b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 8 Mar 2016 10:50:04 +0200 Subject: [PATCH 08/37] [MDEV-7978] Make show_create_user testcase not run on embedded build --- mysql-test/t/show_create_user.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/show_create_user.test b/mysql-test/t/show_create_user.test index 124856ad564..a10c8aeeda6 100644 --- a/mysql-test/t/show_create_user.test +++ b/mysql-test/t/show_create_user.test @@ -1,3 +1,5 @@ +--source include/not_embedded.inc + create user foo; show create user foo; From 053653a23cac6f3f2e5288979438de27c9d0100a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 8 Mar 2016 11:05:32 +0200 Subject: [PATCH 09/37] [MDEV-7978] Update test cases for sysvars_server_embedded. --- mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 865b5a8ca2f..6be27560d89 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2825,9 +2825,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 178 +GLOBAL_VALUE 180 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 178 +DEFAULT_VALUE 180 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. From 594c11fffc94500c627bdb78e287f65cffacc312 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 1 Sep 2020 12:49:09 +0200 Subject: [PATCH 10/37] Ukrainian error text translations added. --- sql/share/errmsg-utf8.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index a4465ae0083..4bb1ae951af 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1800,9 +1800,10 @@ ER_WRONG_AUTO_KEY 42000 S1009 slo "Môžete mať iba jedno AUTO pole a to musí byť definované ako kľúč" spa "Puede ser solamente un campo automatico y este debe ser definido como una clave" swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel" - ukr "Невірне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ" + ukr "Хибне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ" ER_BINLOG_CANT_DELETE_GTID_DOMAIN eng "Could not delete gtid domain. Reason: %s." + ukr "Не можу видалити домен gtid. Причина: %s." ER_NORMAL_SHUTDOWN cze "%s (%s): normální ukončení" dan "%s (%s): Normal nedlukning" @@ -2203,6 +2204,7 @@ ER_INSERT_INFO ER_UPDATE_TABLE_USED eng "Table '%-.192s' is specified twice, both as a target for '%s' and as a separate source for data" swe "Table '%-.192s' är använd två gånger. Både för '%s' och för att hämta data" + ukr "Таблиця '%-.192s' вказується двічі, як цільова для '%s', так і як окреме джерело даних" ER_NO_SUCH_THREAD cze "Neznámá identifikace threadu: %lu" dan "Ukendt tråd id: %lu" @@ -2824,6 +2826,7 @@ ER_WRONG_OUTER_JOIN 42000 ER_NULL_COLUMN_IN_INDEX 42000 eng "Table handler doesn't support NULL in given index. Please change column '%-.192s' to be NOT NULL or use another handler" swe "Tabell hanteraren kan inte indexera NULL kolumner för den givna index typen. Ändra '%-.192s' till NOT NULL eller använd en annan hanterare" + ukr "Вказівник таблиці не підтримує NULL у зазначенному індексі. Будь ласка, зменіть стовпчик '%-.192s' на NOT NULL або використайте інший вказівник таблиці." ER_CANT_FIND_UDF cze "Nemohu načíst funkci '%-.192s'" dan "Kan ikke læse funktionen '%-.192s'" @@ -4314,6 +4317,7 @@ ER_MASTER_INFO jpn "'master info '%.*s''構造体の初期化ができませんでした。MariaDBエラーログでエラーメッセージを確認してください。" serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info' '%.*s'" swe "Kunde inte initialisera replikationsstrukturerna för '%.*s'. See MariaDB fel fil för mera information" + ukr "Інформаційна структура з'єднання головного і підлеглого (master.info) для '%.*s' не може бути ініціалізована" ER_SLAVE_THREAD dan "Kunne ikke danne en slave-tråd; check systemressourcerne" nla "Kon slave thread niet aanmaken, controleer systeem resources" @@ -4478,6 +4482,7 @@ ER_UNION_TABLES_IN_DIFFERENT_DIR serbian "Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka" spa "Incorrecta definición de la tabla; Todas las tablas MERGE deben estar en el mismo banco de datos" swe "Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas" + ukr "Хибне визначення таблиці; всі MERGE-таблиці повинні належити до однієї бази ланних." ER_LOCK_DEADLOCK 40001 nla "Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie" eng "Deadlock found when trying to get lock; try restarting transaction" @@ -4491,6 +4496,7 @@ ER_LOCK_DEADLOCK 40001 serbian "Unakrsno zaključavanje pronađeno kada sam pokušao da dobijem pravo na zaključavanje; Probajte da restartujete transakciju" spa "Encontrado deadlock cuando tentando obtener el bloqueo; Tente recomenzar la transición" swe "Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen" + ukr "Взаємне блокування знайдено під час спроби отримати блокування; спробуйте перезапустити транзакцію." ER_TABLE_CANT_HANDLE_FT nla "Het gebruikte tabel type (%s) ondersteund geen FULLTEXT indexen" eng "The storage engine %s doesn't support FULLTEXT indexes" @@ -4517,6 +4523,7 @@ ER_CANNOT_ADD_FOREIGN serbian "Ne mogu da dodam proveru spoljnog ključa" spa "No puede adicionar clave extranjera constraint" swe "Kan inte lägga till 'FOREIGN KEY constraint'" + ukr "Не можу додати обмеження зовнішнього ключа" ER_NO_REFERENCED_ROW 23000 nla "Kan onderliggende rij niet toevoegen: foreign key beperking gefaald" eng "Cannot add or update a child row: a foreign key constraint fails" @@ -4531,6 +4538,7 @@ ER_NO_REFERENCED_ROW 23000 rus "Невозможно добавить или обновить дочернюю строку: проверка ограничений внешнего ключа не выполняется" spa "No puede adicionar una línea hijo: falla de clave extranjera constraint" swe "FOREIGN KEY-konflikt: Kan inte skriva barn" + ukr "Не вдається додати або оновити дочірній рядок: невдала перевірка обмеження зовнішнього ключа" ER_ROW_IS_REFERENCED 23000 eng "Cannot delete or update a parent row: a foreign key constraint fails" fre "Impossible de supprimer un enregistrement père : une constrainte externe l'empèche" From 0448558a0dd88c8031b66a9ea0296ee05b6333d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Sep 2020 12:14:05 +0300 Subject: [PATCH 11/37] Fix GCC 10.2.0 -Og -fsanitize=undefined -Wformat-overflow For some reason, adding -fsanitize=undefined (cmake -DWITH_UBSAN=ON) to the compilation flags will cause even more warnings to be emitted. The warning was a bogus one: tests/mysql_client_test.c:8632:22: error: '%d' directive writing between 1 and 11 bytes into a region of size 9 [-Werror=format-overflow=] 8632 | sprintf(field, "c%d int", i); | ^~ tests/mysql_client_test.c:8632:20: note: directive argument in the range [-2147483648, 999] The warning does not take into account that the lower bound of the variable actually is 0. But, we can help the compiler and use an unsigned variable. --- tests/mysql_client_test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ec878ae830c..9a90862e93f 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. - Copyright (c) 2008, 2017, MariaDB + Copyright (c) 2008, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -8457,7 +8457,8 @@ static void test_mem_overun() char buffer[10000], field[10]; MYSQL_STMT *stmt; MYSQL_RES *field_res; - int rc, i, length; + int rc, length; + unsigned i; myheader("test_mem_overun"); @@ -8471,7 +8472,7 @@ static void test_mem_overun() strxmov(buffer, "create table t_mem_overun(", NullS); for (i= 0; i < 1000; i++) { - sprintf(field, "c%d int", i); + sprintf(field, "c%u int", i); strxmov(buffer, buffer, field, ", ", NullS); } length= strlen(buffer); From af40a2b43e94cab6b25c9efe4b18c3112b4a9e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Sep 2020 12:27:56 +0300 Subject: [PATCH 12/37] Fix GCC 10.2.0 -Og -fsanitize=undefined -Wmaybe-uninitialized For some reason, adding -fsanitize=undefined (cmake -DWITH_UBSAN=ON) to the compilation flags will cause even more warnings to be emitted. The warnings do look bogus, but the code can be simplified. --- sql/item_geofunc.cc | 16 +++++++++------- sql/opt_subselect.cc | 13 ++++--------- storage/innobase/btr/btr0sea.cc | 6 +----- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 0db8d7075f6..1c3fafc0582 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2003, 2016, Oracle and/or its affiliates. - Copyright (c) 2011, 2016, MariaDB + Copyright (c) 2011, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -456,16 +456,18 @@ String *Item_func_boundary::val_str(String *str_value) DBUG_ASSERT(fixed == 1); String arg_val; String *swkb= args[0]->val_str(&arg_val); + + if ((null_value= args[0]->null_value)) + DBUG_RETURN(0); + Geometry_buffer buffer; - Geometry *g; uint32 srid= 0; Transporter trn(&res_receiver); - - if ((null_value= - args[0]->null_value || - !(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) + + Geometry *g= Geometry::construct(&buffer, swkb->ptr(), swkb->length()); + if (!g) DBUG_RETURN(0); - + if (g->store_shapes(&trn)) goto mem_error; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 45aa625389d..fec4e8b2828 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2634,16 +2634,11 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables) do { uint key= keyuse->key; - KEY *keyinfo; key_part_map bound_parts= 0; - bool is_excluded_key= keyuse->is_for_hash_join(); - if (!is_excluded_key) - { - keyinfo= table->key_info + key; - is_excluded_key= !MY_TEST(keyinfo->flags & HA_NOSAME); - } - if (!is_excluded_key) + if (!keyuse->is_for_hash_join() && + (table->key_info[key].flags & HA_NOSAME)) { + KEY *keyinfo= table->key_info + key; do /* For all equalities on all key parts */ { /* diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index ea34b4034e4..ee39aacf162 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1731,7 +1731,6 @@ func_exit: void btr_search_update_hash_on_insert(btr_cur_t* cursor) { - hash_table_t* table; buf_block_t* block; dict_index_t* index; const rec_t* rec; @@ -1798,6 +1797,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) } rw_lock_t* const latch = btr_get_search_latch(index); + hash_table_t* const table = btr_get_search_table(index); bool locked = false; if (!page_rec_is_infimum(rec)) { @@ -1814,7 +1814,6 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) goto function_exit; } - table = btr_get_search_table(index); ha_insert_for_fold(table, ins_fold, block, ins_rec); } @@ -1830,7 +1829,6 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) if (!btr_search_enabled || !block->index) { goto function_exit; } - table = btr_get_search_table(index); } if (!left_side) { @@ -1851,7 +1849,6 @@ check_next_rec: if (!btr_search_enabled || !block->index) { goto function_exit; } - table = btr_get_search_table(index); } ha_insert_for_fold(table, ins_fold, block, ins_rec); @@ -1868,7 +1865,6 @@ check_next_rec: if (!btr_search_enabled || !block->index) { goto function_exit; } - table = btr_get_search_table(index); } if (!left_side) { From 70960bd33d2699bc96821ec0a0381ca6de86e93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Sep 2020 12:42:30 +0300 Subject: [PATCH 13/37] UBSAN: Fix a bit shift overflow Shifting a 16-bit type by 16 bits is undefined behaviour. The result is at least 32 bits, so let us cast the shift operand to a wider type before shifting. --- sql-common/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index b66eee2a508..ff36b757957 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1,5 +1,5 @@ /* Copyright (c) 2003, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3295,7 +3295,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* New protocol with 16 bytes to describe server characteristics */ mysql->server_language=end[2]; mysql->server_status=uint2korr(end+3); - mysql->server_capabilities|= uint2korr(end+5) << 16; + mysql->server_capabilities|= ((unsigned) uint2korr(end+5)) << 16; pkt_scramble_len= end[7]; if (pkt_scramble_len < 0) { From 7c5519c12d46ead947d341cbdcbb6fbbe4d4fe1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Sep 2020 12:47:49 +0300 Subject: [PATCH 14/37] MDEV-22387: Do not violate __attribute__((nonnull)) Passing a null pointer to a nonnull argument is not only undefined behaviour, but it also grants the compiler the permission to optimize away further checks whether the pointer is null. GCC -O2 at least starting with version 8 may do that, potentially causing SIGSEGV. --- sql/protocol.cc | 8 +++++--- sql/sql_string.cc | 2 +- strings/ctype-mb.c | 6 ++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index aa795b9d12a..de6d1b96f76 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2008, 2012, Monty Program Ab + Copyright (c) 2008, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,7 +58,8 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) packet->realloc(packet_length+9+length)) return 1; uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length); - memcpy(to,from,length); + if (length) + memcpy(to,from,length); packet->length((uint) (to+length-(uchar*) packet->ptr())); return 0; } @@ -715,7 +716,8 @@ void net_send_progress_packet(THD *thd) uchar *net_store_data(uchar *to, const uchar *from, size_t length) { to=net_store_length_fast(to,length); - memcpy(to,from,length); + if (length) + memcpy(to,from,length); return to+length; } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 177d2a77d09..b79ca82698b 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -826,7 +826,7 @@ int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) int stringcmp(const String *s,const String *t) { uint32 s_len=s->length(),t_len=t->length(),len=MY_MIN(s_len,t_len); - int cmp= memcmp(s->ptr(), t->ptr(), len); + int cmp= len ? memcmp(s->ptr(), t->ptr(), len) : 0; return (cmp) ? cmp : (int) (s_len - t_len); } diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 3bcd29bbb8b..cabc940065b 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -407,7 +407,9 @@ my_copy_fix_mb(CHARSET_INFO *cs, src, src + src_length, nchars, status); DBUG_ASSERT(well_formed_nchars <= nchars); - memmove(dst, src, (well_formed_length= status->m_source_end_pos - src)); + well_formed_length= status->m_source_end_pos - src; + if (well_formed_length) + memmove(dst, src, well_formed_length); if (!status->m_well_formed_error_pos) return well_formed_length; From 8370a38dc07ba8a84bab0893792b999fcd020931 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 23 Sep 2020 15:42:11 +0200 Subject: [PATCH 15/37] Window , MTR : fix lookup for mysql_install_db.exe Fixes (rare) case when mysql-test is included into "noinstall" ZIP. --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index d6abda9eb36..0eacdd9125d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2332,7 +2332,8 @@ sub environment_setup { $ENV{'MYSQL_EMBEDDED'}= $exe_mysql_embedded; if(IS_WINDOWS) { - $ENV{'MYSQL_INSTALL_DB_EXE'}= mtr_exe_exists("$bindir/sql$opt_vs_config/mysql_install_db"); + $ENV{'MYSQL_INSTALL_DB_EXE'}= mtr_exe_exists("$bindir/sql$opt_vs_config/mysql_install_db", + "$bindir/bin/mysql_install_db"); } my $client_config_exe= From 4ddaa571faeca88309709bce8064b0b6df80159c Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 24 Sep 2020 08:05:56 +1000 Subject: [PATCH 16/37] MDEV-23697: perl -w -> perl Leave debian/additions/mysqlreport as #!/usr/bin/perl Acknowledge that `env perl` is a hack, a complete fix needs to consider which path perl is at and insert into these scripts. The usefulness of these scripts is questionable. --- debian/additions/mysqlreport | 2 +- scripts/mytop.sh | 2 +- tests/drop_test.pl | 2 +- tests/fork2_test.pl | 2 +- tests/fork_big.pl | 2 +- tests/fork_big2.pl | 2 +- tests/index_corrupt.pl | 2 +- tests/insert_and_repair.pl | 2 +- tests/mail_to_db.pl | 2 +- tests/pmail.pl | 2 +- tests/rename_test.pl | 2 +- tests/test_delayed_insert.pl | 2 +- tests/truncate.pl | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/debian/additions/mysqlreport b/debian/additions/mysqlreport index 1bdcfc544a8..86a57bff19c 100755 --- a/debian/additions/mysqlreport +++ b/debian/additions/mysqlreport @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/perl # mysqlreport v4.0 Oct 23 2015 # http://hackmysql.com/mysqlreport diff --git a/scripts/mytop.sh b/scripts/mytop.sh index e985d518c01..e7b9040c3a8 100644 --- a/scripts/mytop.sh +++ b/scripts/mytop.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # # $Id: mytop,v 1.91 2012/01/18 16:49:12 mgrennan Exp $ diff --git a/tests/drop_test.pl b/tests/drop_test.pl index e4ae5a2671f..6ed05abb7ab 100755 --- a/tests/drop_test.pl +++ b/tests/drop_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000 MySQL AB # Use is subject to license terms diff --git a/tests/fork2_test.pl b/tests/fork2_test.pl index a05a9b96679..55e494dcedc 100755 --- a/tests/fork2_test.pl +++ b/tests/fork2_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/fork_big.pl b/tests/fork_big.pl index b5f8770c903..bd048e8fcb0 100755 --- a/tests/fork_big.pl +++ b/tests/fork_big.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl use strict; # Copyright (c) 2001, 2006 MySQL AB diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl index 7f055609108..d0c17af8cb1 100644 --- a/tests/fork_big2.pl +++ b/tests/fork_big2.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (c) 2002, 2003, 2005, 2006 MySQL AB # Use is subject to license terms diff --git a/tests/index_corrupt.pl b/tests/index_corrupt.pl index 8194982755a..e40bb7afdbb 100755 --- a/tests/index_corrupt.pl +++ b/tests/index_corrupt.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2005 MySQL AB # Use is subject to license terms diff --git a/tests/insert_and_repair.pl b/tests/insert_and_repair.pl index 91333746e79..a8e74e5f30e 100755 --- a/tests/insert_and_repair.pl +++ b/tests/insert_and_repair.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/mail_to_db.pl b/tests/mail_to_db.pl index 6e5c115f543..bab9e7eb74a 100755 --- a/tests/mail_to_db.pl +++ b/tests/mail_to_db.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright Abandoned 1998 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind # diff --git a/tests/pmail.pl b/tests/pmail.pl index 97e5914f794..cf46f5a054d 100755 --- a/tests/pmail.pl +++ b/tests/pmail.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000, 2005 MySQL AB # Use is subject to license terms diff --git a/tests/rename_test.pl b/tests/rename_test.pl index ec7254a4cf6..aa0befa125d 100755 --- a/tests/rename_test.pl +++ b/tests/rename_test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/test_delayed_insert.pl b/tests/test_delayed_insert.pl index 2f8f97b25c6..f0702e6378b 100755 --- a/tests/test_delayed_insert.pl +++ b/tests/test_delayed_insert.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2000, 2001 MySQL AB # Use is subject to license terms diff --git a/tests/truncate.pl b/tests/truncate.pl index e83ebab9291..21d469662d9 100755 --- a/tests/truncate.pl +++ b/tests/truncate.pl @@ -1,4 +1,4 @@ -#!/usr/bin/env perl -w +#!/usr/bin/env perl # Copyright (C) 2002 MySQL AB # Use is subject to license terms From 3d28d1f3aaad17115f2109e133e41c0d04c44f65 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 24 Sep 2020 08:16:30 +1000 Subject: [PATCH 17/37] MDEV-23697: /usr/bin/perl for debian scripts --- debian/additions/innotop/innotop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/additions/innotop/innotop b/debian/additions/innotop/innotop index ee0488580f6..b995f44a007 100644 --- a/debian/additions/innotop/innotop +++ b/debian/additions/innotop/innotop @@ -1,4 +1,4 @@ -#!/usr/bin/env perl +#!/usr/bin/perl # vim: tw=160:nowrap:expandtab:tabstop=3:shiftwidth=3:softtabstop=3 From 1be8ac390d3665d061141fe50a1c9e63b7b4b294 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 24 Sep 2020 13:48:21 +1000 Subject: [PATCH 18/37] Revert "[MDEV-7978] add show create user" Appoligies, had a dirty branch before pushing: This reverts commit 053653a23cac6f3f2e5288979438de27c9d0100a. This reverts commit 0ff897807fc2f4a32e1ba1ae148005930ea604b5. This reverts commit 85b085972b729f6c049050f851692c9a5b86f3d5. This reverts commit f3f45e46b614bddcef0a37f4352c5909ca565d1d. This reverts commit a470b3570a7ce2534c9021f3b84d7457a3ba08e1. This reverts commit f8b8d202bc83d3de46c89ef86333fe602e711265. This reverts commit 6b6f066fdd9f5f64813ded550e7dbda176ee3c82. This reverts commit a701e9e6c390c3cbac69872e95b1aec565341d30. This reverts commit c169838611e13c9f0559b2f49ba8c36aec11a78b. --- mysql-test/r/alter_user.result | 93 ------ mysql-test/r/create_user.result | 72 ---- mysql-test/r/mysqld--help.result | 2 +- mysql-test/r/show_create_user.result | 39 --- .../sys_vars/r/sysvars_server_embedded.result | 4 +- .../r/sysvars_server_notembedded.result | 4 +- mysql-test/t/alter_user.test | 82 ----- mysql-test/t/create_user.test | 58 ---- mysql-test/t/show_create_user.test | 34 -- sql/mysqld.cc | 2 - sql/sp_head.cc | 2 - sql/sql_acl.cc | 315 +++++------------- sql/sql_acl.h | 2 - sql/sql_cmd.h | 2 - sql/sql_parse.cc | 27 +- sql/sql_yacc.yy | 81 ++--- 16 files changed, 118 insertions(+), 701 deletions(-) delete mode 100644 mysql-test/r/alter_user.result delete mode 100644 mysql-test/r/create_user.result delete mode 100644 mysql-test/r/show_create_user.result delete mode 100644 mysql-test/t/alter_user.test delete mode 100644 mysql-test/t/create_user.test delete mode 100644 mysql-test/t/show_create_user.test diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result deleted file mode 100644 index ac668bba8fa..00000000000 --- a/mysql-test/r/alter_user.result +++ /dev/null @@ -1,93 +0,0 @@ -select * from mysql.user where user = 'root' and host = 'localhost'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 -# Test syntax -# -# These 2 selects should have no changes from the first one. -alter user CURRENT_USER; -select * from mysql.user where user = 'root' and host = 'localhost'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 -alter user CURRENT_USER(); -select * from mysql.user where user = 'root' and host = 'localhost'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 -create user foo; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 -alter user foo; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 -# Test super privilege works correctly with a read only database. -SET @start_read_only = @@global.read_only; -SET GLOBAL read_only=1; -grant create user on *.* to foo; -# Currently no super privileges. -connect a, localhost, foo; -select @@global.read_only; -@@global.read_only -1 -alter user foo; -ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement -# Grant super privilege to the user. -connection default; -grant super on *.* to foo; -# We now have super privilege. We should be able to run alter user. -connect b, localhost, foo; -alter user foo; -connection default; -SET GLOBAL read_only = @start_read_only; -# Test inexistant user. -alter user boo; -ERROR HY000: Operation ALTER USER failed for 'boo' -#--warning ER_CANNOT_USER -alter if exists user boo; -Warnings: -Error 1133 Can't find any matching row in the user table -Note 1396 Operation ALTER USER failed for 'boo' -# Test password related altering. -alter user foo identified by 'something'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 -alter user foo identified by 'something2'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 -alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 -alter user foo identified with 'somecoolplugin'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin N N 0.000000 -alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 -# Test ssl related altering. -alter user foo identified by 'something' require SSL; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N ANY 0 0 0 0 N N 0.000000 -alter user foo identified by 'something' require X509; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N X509 0 0 0 0 N N 0.000000 -alter user foo identified by 'something' -require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000 -# Test resource limits altering. -alter user foo with MAX_QUERIES_PER_HOUR 10 -MAX_UPDATES_PER_HOUR 20 -MAX_CONNECTIONS_PER_HOUR 30 -MAX_USER_CONNECTIONS 40; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 -drop user foo; diff --git a/mysql-test/r/create_user.result b/mysql-test/r/create_user.result deleted file mode 100644 index 1411f2e8792..00000000000 --- a/mysql-test/r/create_user.result +++ /dev/null @@ -1,72 +0,0 @@ -create user foo; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require SSL; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require X509; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require CIPHER 'cipher'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require ISSUER 'issuer'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require SUBJECT 'subject'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require CIPHER 'cipher' - SUBJECT 'subject'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 -drop user foo; -create user foo identified by 'password' require CIPHER 'cipher' -AND SUBJECT 'subject' - AND ISSUER 'issuer'; -select * from mysql.user where user = 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 -drop user foo; -create user foo, foo2 identified by 'password' require CIPHER 'cipher' -AND SUBJECT 'subject' - AND ISSUER 'issuer'; -select * from mysql.user where user like 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 -#--warning ER_USER_CREATE_EXISTS -create user if not exists foo, foo2 identified by 'password2' - require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; -Warnings: -Note 1973 Can't create user 'foo'@'%'; it already exists -Note 1973 Can't create user 'foo2'@'%'; it already exists -select * from mysql.user where user like 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 -drop user foo, foo2; -create user foo with MAX_QUERIES_PER_HOUR 10 -MAX_UPDATES_PER_HOUR 20 -MAX_CONNECTIONS_PER_HOUR 30 -MAX_USER_CONNECTIONS 40; -select * from mysql.user where user like 'foo'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 -drop user foo; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index a008affa9f8..dce1578adee 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1360,7 +1360,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 150 -performance-schema-max-statement-classes 180 +performance-schema-max-statement-classes 178 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 diff --git a/mysql-test/r/show_create_user.result b/mysql-test/r/show_create_user.result deleted file mode 100644 index 63013eca074..00000000000 --- a/mysql-test/r/show_create_user.result +++ /dev/null @@ -1,39 +0,0 @@ -create user foo; -show create user foo; -CREATE USER for foo@% -CREATE USER 'foo'@'%' -create user foo@test; -show create user foo@test; -CREATE USER for foo@test -CREATE USER 'foo'@'test' -create user foo2@test identified by 'password'; -show create user foo2@test; -CREATE USER for foo2@test -CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' -alter user foo2@test identified with 'someplugin' as 'somepassword'; -show create user foo2@test; -CREATE USER for foo2@test -CREATE USER 'foo2'@'test' IDENTIFIED VIA someplugin USING 'somepassword' -create user foo3@test require SSL; -show create user foo3@test; -CREATE USER for foo3@test -CREATE USER 'foo3'@'test' REQUIRE SSL -create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; -show create user foo4@test; -CREATE USER for foo4@test -CREATE USER 'foo4'@'test' REQUIRE ISSUER 'foo_issuer' SUBJECT 'foo_subject' CIPHER 'text' -create user foo5@test require SSL -with MAX_QUERIES_PER_HOUR 10 -MAX_UPDATES_PER_HOUR 20 -MAX_CONNECTIONS_PER_HOUR 30 -MAX_USER_CONNECTIONS 40 -MAX_STATEMENT_TIME 0.5; -show create user foo5@test; -CREATE USER for foo5@test -CREATE USER 'foo5'@'test' REQUIRE SSL WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40 MAX_STATEMENT_TIME 0.500000 -drop user foo5@test; -drop user foo4@test; -drop user foo3@test; -drop user foo2@test; -drop user foo@test; -drop user foo; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 6be27560d89..865b5a8ca2f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2825,9 +2825,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 180 +GLOBAL_VALUE 178 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 180 +DEFAULT_VALUE 178 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 4c358fd456a..21f1f905de8 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3021,9 +3021,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 180 +GLOBAL_VALUE 178 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 180 +DEFAULT_VALUE 178 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test deleted file mode 100644 index e32d0c29f2e..00000000000 --- a/mysql-test/t/alter_user.test +++ /dev/null @@ -1,82 +0,0 @@ ---source include/not_embedded.inc ---enable_connect_log - - -select * from mysql.user where user = 'root' and host = 'localhost'; ---echo # Test syntax ---echo # ---echo # These 2 selects should have no changes from the first one. -alter user CURRENT_USER; -select * from mysql.user where user = 'root' and host = 'localhost'; -alter user CURRENT_USER(); -select * from mysql.user where user = 'root' and host = 'localhost'; - -create user foo; -select * from mysql.user where user = 'foo'; -alter user foo; -select * from mysql.user where user = 'foo'; - ---echo # Test super privilege works correctly with a read only database. -SET @start_read_only = @@global.read_only; -SET GLOBAL read_only=1; -grant create user on *.* to foo; - ---echo # Currently no super privileges. -connect (a, localhost, foo); -select @@global.read_only; - ---error ER_OPTION_PREVENTS_STATEMENT -alter user foo; - ---echo # Grant super privilege to the user. -connection default; -grant super on *.* to foo; - ---echo # We now have super privilege. We should be able to run alter user. -connect (b, localhost, foo); -alter user foo; - -connection default; -SET GLOBAL read_only = @start_read_only; - ---echo # Test inexistant user. ---error ER_CANNOT_USER -alter user boo; ---echo #--warning ER_CANNOT_USER -alter if exists user boo; - ---echo # Test password related altering. -alter user foo identified by 'something'; -select * from mysql.user where user = 'foo'; - -alter user foo identified by 'something2'; -select * from mysql.user where user = 'foo'; - -alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; -select * from mysql.user where user = 'foo'; - -alter user foo identified with 'somecoolplugin'; -select * from mysql.user where user = 'foo'; - -alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; -select * from mysql.user where user = 'foo'; - ---echo # Test ssl related altering. -alter user foo identified by 'something' require SSL; -select * from mysql.user where user = 'foo'; - -alter user foo identified by 'something' require X509; -select * from mysql.user where user = 'foo'; - -alter user foo identified by 'something' -require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; -select * from mysql.user where user = 'foo'; - ---echo # Test resource limits altering. -alter user foo with MAX_QUERIES_PER_HOUR 10 - MAX_UPDATES_PER_HOUR 20 - MAX_CONNECTIONS_PER_HOUR 30 - MAX_USER_CONNECTIONS 40; -select * from mysql.user where user = 'foo'; -drop user foo; ---disable_connect_log diff --git a/mysql-test/t/create_user.test b/mysql-test/t/create_user.test deleted file mode 100644 index f04cb3e302a..00000000000 --- a/mysql-test/t/create_user.test +++ /dev/null @@ -1,58 +0,0 @@ ---source include/not_embedded.inc - -create user foo; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require SSL; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require X509; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require CIPHER 'cipher'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require ISSUER 'issuer'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require SUBJECT 'subject'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require CIPHER 'cipher' - SUBJECT 'subject'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo identified by 'password' require CIPHER 'cipher' - AND SUBJECT 'subject' - AND ISSUER 'issuer'; -select * from mysql.user where user = 'foo'; -drop user foo; - -create user foo, foo2 identified by 'password' require CIPHER 'cipher' - AND SUBJECT 'subject' - AND ISSUER 'issuer'; -select * from mysql.user where user like 'foo'; - ---echo #--warning ER_USER_CREATE_EXISTS -create user if not exists foo, foo2 identified by 'password2' - require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; -select * from mysql.user where user like 'foo'; -drop user foo, foo2; - -create user foo with MAX_QUERIES_PER_HOUR 10 - MAX_UPDATES_PER_HOUR 20 - MAX_CONNECTIONS_PER_HOUR 30 - MAX_USER_CONNECTIONS 40; -select * from mysql.user where user like 'foo'; -drop user foo; diff --git a/mysql-test/t/show_create_user.test b/mysql-test/t/show_create_user.test deleted file mode 100644 index a10c8aeeda6..00000000000 --- a/mysql-test/t/show_create_user.test +++ /dev/null @@ -1,34 +0,0 @@ ---source include/not_embedded.inc - -create user foo; -show create user foo; - -create user foo@test; -show create user foo@test; - -create user foo2@test identified by 'password'; -show create user foo2@test; - -alter user foo2@test identified with 'someplugin' as 'somepassword'; -show create user foo2@test; - -create user foo3@test require SSL; -show create user foo3@test; - -create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; -show create user foo4@test; - -create user foo5@test require SSL - with MAX_QUERIES_PER_HOUR 10 - MAX_UPDATES_PER_HOUR 20 - MAX_CONNECTIONS_PER_HOUR 30 - MAX_USER_CONNECTIONS 40 - MAX_STATEMENT_TIME 0.5; -show create user foo5@test; - -drop user foo5@test; -drop user foo4@test; -drop user foo3@test; -drop user foo2@test; -drop user foo@test; -drop user foo; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b28cea5ac46..8d00b5af948 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3676,7 +3676,6 @@ SHOW_VAR com_status_vars[]= { {"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)}, {"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)}, {"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)}, - {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)}, {"analyze", STMT_STATUS(SQLCOM_ANALYZE)}, {"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)}, {"begin", STMT_STATUS(SQLCOM_BEGIN)}, @@ -3766,7 +3765,6 @@ SHOW_VAR com_status_vars[]= { {"show_create_proc", STMT_STATUS(SQLCOM_SHOW_CREATE_PROC)}, {"show_create_table", STMT_STATUS(SQLCOM_SHOW_CREATE)}, {"show_create_trigger", STMT_STATUS(SQLCOM_SHOW_CREATE_TRIGGER)}, - {"show_create_user", STMT_STATUS(SQLCOM_SHOW_CREATE_USER)}, {"show_databases", STMT_STATUS(SQLCOM_SHOW_DATABASES)}, {"show_engine_logs", STMT_STATUS(SQLCOM_SHOW_ENGINE_LOGS)}, {"show_engine_mutex", STMT_STATUS(SQLCOM_SHOW_ENGINE_MUTEX)}, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a27f0ef4250..0428c0198a1 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -241,7 +241,6 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_CREATE_PROC: case SQLCOM_SHOW_CREATE_EVENT: case SQLCOM_SHOW_CREATE_TRIGGER: - case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_ERRORS: case SQLCOM_SHOW_EXPLAIN: @@ -310,7 +309,6 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_USER: case SQLCOM_CREATE_ROLE: case SQLCOM_ALTER_TABLE: - case SQLCOM_ALTER_USER: case SQLCOM_GRANT: case SQLCOM_GRANT_ROLE: case SQLCOM_REVOKE: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2b6ababa8dd..cf0b1d87bd7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7756,94 +7756,6 @@ static void add_user_option(String *grant, double value, const char *name) } } -static void add_user_parameters(String *result, ACL_USER* acl_user, - bool with_grant) -{ - result->append(STRING_WITH_LEN("@'")); - result->append(acl_user->host.hostname, acl_user->hostname_length, - system_charset_info); - result->append('\''); - - if (acl_user->plugin.str == native_password_plugin_name.str || - acl_user->plugin.str == old_password_plugin_name.str) - { - if (acl_user->auth_string.length) - { - DBUG_ASSERT(acl_user->salt_len); - result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); - result->append(acl_user->auth_string.str, acl_user->auth_string.length); - result->append('\''); - } - } - else - { - result->append(STRING_WITH_LEN(" IDENTIFIED VIA ")); - result->append(acl_user->plugin.str, acl_user->plugin.length); - if (acl_user->auth_string.length) - { - result->append(STRING_WITH_LEN(" USING '")); - result->append(acl_user->auth_string.str, acl_user->auth_string.length); - result->append('\''); - } - } - /* "show grants" SSL related stuff */ - if (acl_user->ssl_type == SSL_TYPE_ANY) - result->append(STRING_WITH_LEN(" REQUIRE SSL")); - else if (acl_user->ssl_type == SSL_TYPE_X509) - result->append(STRING_WITH_LEN(" REQUIRE X509")); - else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) - { - int ssl_options = 0; - result->append(STRING_WITH_LEN(" REQUIRE ")); - if (acl_user->x509_issuer) - { - ssl_options++; - result->append(STRING_WITH_LEN("ISSUER \'")); - result->append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); - result->append('\''); - } - if (acl_user->x509_subject) - { - if (ssl_options++) - result->append(' '); - result->append(STRING_WITH_LEN("SUBJECT \'")); - result->append(acl_user->x509_subject,strlen(acl_user->x509_subject), - system_charset_info); - result->append('\''); - } - if (acl_user->ssl_cipher) - { - if (ssl_options++) - result->append(' '); - result->append(STRING_WITH_LEN("CIPHER '")); - result->append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), - system_charset_info); - result->append('\''); - } - } - if (with_grant || - (acl_user->user_resource.questions || - acl_user->user_resource.updates || - acl_user->user_resource.conn_per_hour || - acl_user->user_resource.user_conn || - acl_user->user_resource.max_statement_time != 0.0)) - { - result->append(STRING_WITH_LEN(" WITH")); - if (with_grant) - result->append(STRING_WITH_LEN(" GRANT OPTION")); - add_user_option(result, acl_user->user_resource.questions, - "MAX_QUERIES_PER_HOUR", false); - add_user_option(result, acl_user->user_resource.updates, - "MAX_UPDATES_PER_HOUR", false); - add_user_option(result, acl_user->user_resource.conn_per_hour, - "MAX_CONNECTIONS_PER_HOUR", false); - add_user_option(result, acl_user->user_resource.user_conn, - "MAX_USER_CONNECTIONS", true); - add_user_option(result, acl_user->user_resource.max_statement_time, - "MAX_STATEMENT_TIME"); - } -} - static const char *command_array[]= { "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD", @@ -7890,77 +7802,6 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role) } -bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) -{ - const char *username = safe_str(lex_user->user.str); - const char *hostname = safe_str(lex_user->host.str); - char buff[1024]; //Show create user should not take more than 1024 bytes. - Protocol *protocol= thd->protocol; - bool error= false; - ACL_USER *acl_user; - DBUG_ENTER("mysql_show_create_user"); - - // Check if the command specifies a username or not. - if (lex_user->user.str == current_user.str) - { - username= thd->security_ctx->priv_user; - hostname= thd->security_ctx->priv_host; - } - - List field_list; - strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS); - Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0); - if (!field) - { - my_error(ER_OUTOFMEMORY, MYF(0)); - DBUG_RETURN(true); - } - - field->name= buff; - field->max_length= sizeof(buff); - field_list.push_back(field, thd->mem_root); - if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | - Protocol::SEND_EOF)) - DBUG_RETURN(true); - - String result(buff, sizeof(buff), system_charset_info); - result.length(0); - mysql_rwlock_rdlock(&LOCK_grant); - mysql_mutex_lock(&acl_cache->lock); - - acl_user= find_user_exact(hostname, username); - - // User not found in the internal data structures. - if (!acl_user) - { - my_error(ER_PASSWORD_NO_MATCH, MYF(0)); - error= true; - goto end; - } - - result.append("CREATE USER '"); - result.append(username); - result.append('\''); - - add_user_parameters(&result, acl_user, false); - - protocol->prepare_for_resend(); - protocol->store(result.ptr(), result.length(), result.charset()); - if (protocol->write()) - { - error= true; - } - my_eof(thd); - -end: - mysql_rwlock_unlock(&LOCK_grant); - mysql_mutex_unlock(&acl_cache->lock); - - DBUG_RETURN(error); -} - - static int show_grants_callback(ACL_USER_BASE *role, void *data) { THD *thd= (THD *)data; @@ -7970,6 +7811,7 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data) return 0; } + void mysql_show_grants_get_fields(THD *thd, List *fields, const char *name) { @@ -8244,7 +8086,93 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, global.append('\''); if (!handle_as_role) - add_user_parameters(&global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL)); + { + ACL_USER *acl_user= (ACL_USER *)acl_entry; + + global.append (STRING_WITH_LEN("@'")); + global.append(acl_user->host.hostname, acl_user->hostname_length, + system_charset_info); + global.append ('\''); + + if (acl_user->plugin.str == native_password_plugin_name.str || + acl_user->plugin.str == old_password_plugin_name.str) + { + if (acl_user->auth_string.length) + { + DBUG_ASSERT(acl_user->salt_len); + global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); + global.append(acl_user->auth_string.str, acl_user->auth_string.length); + global.append('\''); + } + } + else + { + global.append(STRING_WITH_LEN(" IDENTIFIED VIA ")); + global.append(acl_user->plugin.str, acl_user->plugin.length); + if (acl_user->auth_string.length) + { + global.append(STRING_WITH_LEN(" USING '")); + global.append(acl_user->auth_string.str, acl_user->auth_string.length); + global.append('\''); + } + } + /* "show grants" SSL related stuff */ + if (acl_user->ssl_type == SSL_TYPE_ANY) + global.append(STRING_WITH_LEN(" REQUIRE SSL")); + else if (acl_user->ssl_type == SSL_TYPE_X509) + global.append(STRING_WITH_LEN(" REQUIRE X509")); + else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) + { + int ssl_options = 0; + global.append(STRING_WITH_LEN(" REQUIRE ")); + if (acl_user->x509_issuer) + { + ssl_options++; + global.append(STRING_WITH_LEN("ISSUER \'")); + global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + global.append('\''); + } + if (acl_user->x509_subject) + { + if (ssl_options++) + global.append(' '); + global.append(STRING_WITH_LEN("SUBJECT \'")); + global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), + system_charset_info); + global.append('\''); + } + if (acl_user->ssl_cipher) + { + if (ssl_options++) + global.append(' '); + global.append(STRING_WITH_LEN("CIPHER '")); + global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + system_charset_info); + global.append('\''); + } + } + if ((want_access & GRANT_ACL) || + (acl_user->user_resource.questions || + acl_user->user_resource.updates || + acl_user->user_resource.conn_per_hour || + acl_user->user_resource.user_conn || + acl_user->user_resource.max_statement_time != 0.0)) + { + global.append(STRING_WITH_LEN(" WITH")); + if (want_access & GRANT_ACL) + global.append(STRING_WITH_LEN(" GRANT OPTION")); + add_user_option(&global, acl_user->user_resource.questions, + "MAX_QUERIES_PER_HOUR", false); + add_user_option(&global, acl_user->user_resource.updates, + "MAX_UPDATES_PER_HOUR", false); + add_user_option(&global, acl_user->user_resource.conn_per_hour, + "MAX_CONNECTIONS_PER_HOUR", false); + add_user_option(&global, acl_user->user_resource.user_conn, + "MAX_USER_CONNECTIONS", true); + add_user_option(&global, acl_user->user_resource.max_statement_time, + "MAX_STATEMENT_TIME"); + } + } protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); @@ -9912,73 +9840,6 @@ bool mysql_rename_user(THD *thd, List &list) DBUG_RETURN(result); } -/* - Alter a user's connection and resource settings. - - SYNOPSIS - mysql_alter_user() - thd The current thread. - list The users to alter. - - RETURN - > 0 Error. Error message already sent. - 0 OK. -*/ -int mysql_alter_user(THD* thd, List &users_list) -{ - DBUG_ENTER("mysql_alter_user"); - int result= 0; - TABLE_LIST tables[TABLES_MAX]; - String wrong_users; - // The only table we're altering is the user table. - if ((result= open_grant_tables(thd, tables, TL_WRITE, Table_user))) - DBUG_RETURN(result); - - // Lock ACL data structures until we finish altering all users. - mysql_rwlock_wrlock(&LOCK_grant); - mysql_mutex_lock(&acl_cache->lock); - - LEX_USER *tmp_lex_user; - List_iterator users_list_iterator(users_list); - while ((tmp_lex_user= users_list_iterator++)) - { - LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false); - if (!lex_user || - fix_lex_user(thd, lex_user) || - replace_user_table(thd, tables[USER_TABLE].table, *lex_user,0, - false, false, true)) - { - thd->clear_error(); - append_user(thd, &wrong_users, tmp_lex_user); - result= TRUE; - continue; - } - } - - // Unlock ACL data structures. - mysql_mutex_unlock(&acl_cache->lock); - mysql_rwlock_unlock(&LOCK_grant); - - if (result) - { - // 'if exists' flag leads to warnings instead of errors. - if (thd->lex->create_info.if_exists()) - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_CANNOT_USER, - ER_THD(thd, ER_CANNOT_USER), - "ALTER USER", wrong_users.c_ptr_safe()); - result= FALSE; - } - else - { - my_error(ER_CANNOT_USER, MYF(0), - "ALTER USER", - wrong_users.c_ptr_safe()); - } - } - DBUG_RETURN(result); -} /* Revoke all privileges from a list of users. diff --git a/sql/sql_acl.h b/sql/sql_acl.h index b480d488bc3..3bd896cab79 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -246,7 +246,6 @@ bool get_show_user(THD *thd, LEX_USER *lex_user, const char **username, void mysql_show_grants_get_fields(THD *thd, List *fields, const char *name); bool mysql_show_grants(THD *thd, LEX_USER *user); -bool mysql_show_create_user(THD *thd, LEX_USER *user); int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond); void get_privilege_desc(char *to, uint max_length, ulong access); @@ -254,7 +253,6 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc); bool mysql_create_user(THD *thd, List &list, bool handle_as_role); bool mysql_drop_user(THD *thd, List &list, bool handle_as_role); bool mysql_rename_user(THD *thd, List &list); -int mysql_alter_user(THD *thd, List &list); bool mysql_revoke_all(THD *thd, List &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index 2350b4be56c..c237bb9270a 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -93,8 +93,6 @@ enum enum_sql_command { SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE, SQLCOM_COMPOUND, SQLCOM_SHOW_GENERIC, - SQLCOM_ALTER_USER, - SQLCOM_SHOW_CREATE_USER, /* When a command is added here, be sure it's also added in mysqld.cc diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a5837585b7d..14ac657862f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -422,7 +422,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; - sql_command_flags[SQLCOM_SHOW_CREATE_USER]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; @@ -444,7 +443,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_ALTER_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_ROLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT_ROLE]= CF_CHANGES_DATA; @@ -508,7 +506,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CHECKSUM]= CF_REPORT_PROGRESS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS; - sql_command_flags[SQLCOM_ALTER_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS; @@ -604,7 +601,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS; - sql_command_flags[SQLCOM_ALTER_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS; @@ -4407,7 +4403,6 @@ mysql_execute_command(THD *thd) my_ok(thd); break; } - case SQLCOM_ALTER_USER: case SQLCOM_RENAME_USER: { if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) && @@ -4415,11 +4410,7 @@ mysql_execute_command(THD *thd) break; /* Conditionally writes to binlog */ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) - if (lex->sql_command == SQLCOM_ALTER_USER) - res= mysql_alter_user(thd, lex->users_list); - else - res= mysql_rename_user(thd, lex->users_list); - if (!res) + if (!(res= mysql_rename_user(thd, lex->users_list))) my_ok(thd); break; } @@ -4716,7 +4707,6 @@ mysql_execute_command(THD *thd) break; #ifndef NO_EMBEDDED_ACCESS_CHECKS - case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_GRANTS: { LEX_USER *grant_user= lex->grant_user; @@ -4724,20 +4714,7 @@ mysql_execute_command(THD *thd) goto error; WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW); - if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) && - grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str)) - grant_user->user= current_user; - - if (grant_user->user.str == current_user.str || - grant_user->user.str == current_role.str || - grant_user->user.str == current_user_and_current_role.str || - !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) - { - if (lex->sql_command == SQLCOM_SHOW_GRANTS) - res = mysql_show_grants(thd, grant_user); - else - res = mysql_show_create_user(thd, grant_user); - } + res = mysql_show_grants(thd, grant_user); break; } #endif diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6799781f5e0..2a46bb2a027 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2531,8 +2531,7 @@ create: Lex->create_view_suid= TRUE; } view_or_trigger_or_sp_or_event { } - | create_or_replace USER opt_if_not_exists clear_privileges grant_list - opt_require_clause opt_resource_options + | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list { if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3)) MYSQL_YYABORT; @@ -7107,13 +7106,6 @@ alter: lex->sql_command= SQLCOM_ALTER_SERVER; lex->server_options.reset($3); } OPTIONS_SYM '(' server_options_list ')' { } - /* ALTER USER foo is allowed for MySQL compatibility. */ - | ALTER opt_if_exists USER clear_privileges grant_list - opt_require_clause opt_resource_options - { - Lex->create_info.set($2); - Lex->sql_command= SQLCOM_ALTER_USER; - } ; ev_alter_on_schedule_completion: @@ -12494,18 +12486,6 @@ show_param: lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER; lex->spname= $3; } - | CREATE USER - { - Lex->sql_command= SQLCOM_SHOW_CREATE_USER; - if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER)))) - MYSQL_YYABORT; - Lex->grant_user->user= current_user; - } - | CREATE USER user - { - Lex->sql_command= SQLCOM_SHOW_CREATE_USER; - Lex->grant_user= $3; - } | PROCEDURE_SYM STATUS_SYM wild_and_where { LEX *lex= Lex; @@ -15056,14 +15036,14 @@ grant: grant_command: grant_privileges ON opt_table grant_ident TO_SYM grant_list - opt_require_clause opt_grant_options + require_clause grant_options { LEX *lex= Lex; lex->sql_command= SQLCOM_GRANT; lex->type= 0; } | grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list - opt_require_clause opt_grant_options + require_clause grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15075,7 +15055,7 @@ grant_command: lex->type= TYPE_ENUM_FUNCTION; } | grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list - opt_require_clause opt_grant_options + require_clause grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15412,7 +15392,7 @@ column_list_id: } ; -opt_require_clause: +require_clause: /* empty */ | REQUIRE_SYM require_list { @@ -15432,8 +15412,24 @@ opt_require_clause: } ; -resource_option: - MAX_QUERIES_PER_HOUR ulong_num +grant_options: + /* empty */ {} + | WITH grant_option_list + ; + +opt_grant_option: + /* empty */ {} + | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} + ; + +grant_option_list: + grant_option_list grant_option {} + | grant_option {} + ; + +grant_option: + GRANT OPTION { Lex->grant |= GRANT_ACL;} + | MAX_QUERIES_PER_HOUR ulong_num { LEX *lex=Lex; lex->mqh.questions=$2; @@ -15465,37 +15461,6 @@ resource_option: } ; -resource_option_list: - resource_option_list resource_option {} - | resource_option {} - ; - -opt_resource_options: - /* empty */ {} - | WITH resource_option_list - ; - - -opt_grant_options: - /* empty */ {} - | WITH grant_option_list {} - ; - -opt_grant_option: - /* empty */ {} - | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} - ; - -grant_option_list: - grant_option_list grant_option {} - | grant_option {} - ; - -grant_option: - GRANT OPTION { Lex->grant |= GRANT_ACL;} - | resource_option {} - ; - begin: BEGIN_SYM { From a50ce9445844c0bdcf8aab8578cdf1244d969d42 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Wed, 2 Sep 2020 20:38:25 +0200 Subject: [PATCH 19/37] MDEV-23559: Galera LeakSanitizer: detected memory leaks in galera.GAL-419 When process is aborted WSREP deinitialization and memory cleanup is not properly handled. Other reported leaks are in Galera library and should be fixed there. --- sql/mysqld.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c9bf6045867..26012f317f9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1900,13 +1900,10 @@ extern "C" void unireg_abort(int exit_code) WSREP_INFO("Some threads may fail to exit."); } - if (WSREP_ON) + if (WSREP_ON && wsrep_inited) { - /* In bootstrap mode we deinitialize wsrep here. */ - if (opt_bootstrap || wsrep_recovery) - { - if (wsrep_inited) wsrep_deinit(true); - } + wsrep_deinit(true); + wsrep_deinit_server(); } #endif // WITH_WSREP From 920824c24e94efefc6b1ce135499e7d7e5290ae9 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 23 Jul 2020 11:35:40 +0300 Subject: [PATCH 20/37] Backported setting of transcation.on=1 in THD::reset_for_reuse() This is to ensure code in 10.4 and 10.5 is logically identical for this variable --- sql/sql_class.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7327f270c33..8f6356b15c7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1640,6 +1640,7 @@ void THD::reset_for_reuse() abort_on_warning= 0; free_connection_done= 0; m_command= COM_CONNECT; + transaction.on= 1; #if defined(ENABLED_PROFILING) profiling.reset(); #endif From 3cdbaa04bd573f2f09e2f7ff69c71e8b97ca078b Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 14 Sep 2020 21:22:32 +0300 Subject: [PATCH 21/37] Fixed BUILD script to make plugin-file_key_management DYNAMIC This ensures that all tests can be run. Before this patch some encryption test failed --- BUILD/SETUP.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 992cfa1286f..44e74441de9 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -211,7 +211,7 @@ fi max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max" max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache" -max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic --with-plugin-test_sql_discovery=DYNAMIC" +max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent --without-plugin=plugin_file_key_management --with-plugin-rocksdb=dynamic --with-plugin-test_sql_discovery=DYNAMIC --with-plugin-file_key_management=DYNAMIC" all_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-innodb_plugin --with-libevent" # From 16ea692ed490a1a2c6dc0b855247d5bd02bd2345 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 7 Sep 2020 10:38:12 +0300 Subject: [PATCH 22/37] MDEV-23586 Mariabackup: GTID saved for replication in 10.4.14 is wrong MDEV-21953 deadlock between BACKUP STAGE BLOCK_COMMIT and parallel replication Fixed by partly reverting MDEV-21953 to put back MDL_BACKUP_COMMIT locking before log_and_order. The original problem for MDEV-21953 was that while a thread was waiting in for another threads to commit in 'log_and_order', it had the MDL_BACKUP_COMMIT lock. The backup thread was waiting to get the MDL_BACKUP_WAIT_COMMIT lock, which blocks all new MDL_BACKUP_COMMIT locks. This causes a deadlock as the waited-for thread can never get past the MDL_BACKUP_COMMIT lock in ha_commit_trans. The main part of the bug fix is to release the MDL_BACKUP_COMMIT lock while a thread is waiting for other 'previous' threads to commit. This ensures that no transactional thread keeps MDL_BACKUP_COMMIT while waiting, which ensures that there are no deadlocks anymore. --- sql/handler.cc | 101 ++++++++++++++++++++++++----------------------- sql/handler.h | 2 +- sql/log.cc | 55 +++++++++++++++++++++++--- sql/sql_class.cc | 30 ++++++++++++-- sql/sql_class.h | 3 ++ sql/xa.cc | 2 +- 6 files changed, 134 insertions(+), 59 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 40dea349272..d7562bcd2ae 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -114,7 +114,7 @@ static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; uint known_extensions_id= 0; static int commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, - bool is_real_trans, bool rw_trans); + bool is_real_trans); static plugin_ref ha_default_plugin(THD *thd) @@ -1490,9 +1490,40 @@ int ha_commit_trans(THD *thd, bool all) /* rw_trans is TRUE when we in a transaction changing data */ bool rw_trans= is_real_trans && (rw_ha_count > (thd->is_current_stmt_binlog_disabled()?0U:1U)); + MDL_request mdl_backup; DBUG_PRINT("info", ("is_real_trans: %d rw_trans: %d rw_ha_count: %d", is_real_trans, rw_trans, rw_ha_count)); + if (rw_trans) + { + /* + Acquire a metadata lock which will ensure that COMMIT is blocked + by an active FLUSH TABLES WITH READ LOCK (and vice versa: + COMMIT in progress blocks FTWRL). + + We allow the owner of FTWRL to COMMIT; we assume that it knows + what it does. + */ + mdl_backup.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT); + + if (!WSREP(thd)) + { + if (thd->mdl_context.acquire_lock(&mdl_backup, + thd->variables.lock_wait_timeout)) + { + ha_rollback_trans(thd, all); + DBUG_RETURN(1); + } + thd->backup_commit_lock= &mdl_backup; + } + DEBUG_SYNC(thd, "ha_commit_trans_after_acquire_commit_lock"); + + /* Use shortcut as we already have the MDL_BACKUP_COMMIT lock */ + ha_maria::implicit_commit(thd, TRUE); + } + else + ha_maria_implicit_commit(thd, TRUE); + if (rw_trans && opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) && @@ -1532,7 +1563,7 @@ int ha_commit_trans(THD *thd, bool all) // Here, the call will not commit inside InnoDB. It is only working // around closing thd->transaction.stmt open by TR_table::open(). if (all) - commit_one_phase_2(thd, false, &thd->transaction.stmt, false, false); + commit_one_phase_2(thd, false, &thd->transaction.stmt, false); } } #endif @@ -1552,7 +1583,7 @@ int ha_commit_trans(THD *thd, bool all) goto wsrep_err; } #endif /* WITH_WSREP */ - error= ha_commit_one_phase(thd, all, rw_trans); + error= ha_commit_one_phase(thd, all); #ifdef WITH_WSREP if (run_wsrep_hooks) error= error || wsrep_after_commit(thd, all); @@ -1604,7 +1635,7 @@ int ha_commit_trans(THD *thd, bool all) if (!is_real_trans) { - error= commit_one_phase_2(thd, all, trans, is_real_trans, rw_trans); + error= commit_one_phase_2(thd, all, trans, is_real_trans); goto done; } #ifdef WITH_WSREP @@ -1622,7 +1653,7 @@ int ha_commit_trans(THD *thd, bool all) DEBUG_SYNC(thd, "ha_commit_trans_after_log_and_order"); DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_SUICIDE();); - error= commit_one_phase_2(thd, all, trans, is_real_trans, rw_trans) ? 2 : 0; + error= commit_one_phase_2(thd, all, trans, is_real_trans) ? 2 : 0; #ifdef WITH_WSREP if (run_wsrep_hooks && (error || (error = wsrep_after_commit(thd, all)))) { @@ -1685,6 +1716,17 @@ err: thd->rgi_slave->is_parallel_exec); } end: + if (mdl_backup.ticket) + { + /* + We do not always immediately release transactional locks + after ha_commit_trans() (see uses of ha_enable_transaction()), + thus we release the commit blocker lock as soon as it's + not needed. + */ + thd->mdl_context.release_lock(mdl_backup.ticket); + } + thd->backup_commit_lock= 0; #ifdef WITH_WSREP if (wsrep_is_active(thd) && is_real_trans && !error && (rw_ha_count == 0 || all) && @@ -1699,8 +1741,8 @@ end: /** @note - This function does not care about global read lock. A caller should. - However backup locks are handled in commit_one_phase_2. + This function does not care about global read lock or backup locks, + the caller should. @param[in] all Is set in case of explicit commit (COMMIT statement), or implicit commit @@ -1709,7 +1751,7 @@ end: autocommit=1. */ -int ha_commit_one_phase(THD *thd, bool all, bool rw_trans) +int ha_commit_one_phase(THD *thd, bool all) { THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; /* @@ -1735,50 +1777,21 @@ int ha_commit_one_phase(THD *thd, bool all, bool rw_trans) if ((res= thd->wait_for_prior_commit())) DBUG_RETURN(res); } - res= commit_one_phase_2(thd, all, trans, is_real_trans, rw_trans); + res= commit_one_phase_2(thd, all, trans, is_real_trans); DBUG_RETURN(res); } static int -commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans, - bool rw_trans) +commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) { int error= 0; uint count= 0; Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; - MDL_request mdl_request; DBUG_ENTER("commit_one_phase_2"); if (is_real_trans) DEBUG_SYNC(thd, "commit_one_phase_2"); - if (rw_trans) - { - /* - Acquire a metadata lock which will ensure that COMMIT is blocked - by an active FLUSH TABLES WITH READ LOCK (and vice versa: - COMMIT in progress blocks FTWRL). - - We allow the owner of FTWRL to COMMIT; we assume that it knows - what it does. - */ - mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT); - - if (!WSREP(thd) && - thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) - { - my_error(ER_ERROR_DURING_COMMIT, MYF(0), 1); - ha_rollback_trans(thd, all); - DBUG_RETURN(1); - } - DEBUG_SYNC(thd, "ha_commit_trans_after_acquire_commit_lock"); - } - -#if defined(WITH_ARIA_STORAGE_ENGINE) && MYSQL_VERSION_ID < 100500 - ha_maria::implicit_commit(thd, TRUE); -#endif - if (ha_info) { for (; ha_info; ha_info= ha_info_next) @@ -1807,16 +1820,6 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans, #endif } } - if (mdl_request.ticket) - { - /* - We do not always immediately release transactional locks - after ha_commit_trans() (see uses of ha_enable_transaction()), - thus we release the commit blocker lock as soon as it's - not needed. - */ - thd->mdl_context.release_lock(mdl_request.ticket); - } /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) diff --git a/sql/handler.h b/sql/handler.h index 80d0f1b59d8..3b0cedfcd96 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -5024,7 +5024,7 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); /* transactions: interface to handlerton functions */ int ha_start_consistent_snapshot(THD *thd); int ha_commit_or_rollback_by_xid(XID *xid, bool commit); -int ha_commit_one_phase(THD *thd, bool all, bool rw_trans); +int ha_commit_one_phase(THD *thd, bool all); int ha_commit_trans(THD *thd, bool all); int ha_rollback_trans(THD *thd, bool all); int ha_prepare(THD *thd); diff --git a/sql/log.cc b/sql/log.cc index eaa49bcb58c..bfa77fbd88e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6380,11 +6380,25 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) if (direct) { + /* We come here only for incident events */ int res; uint64 commit_id= 0; + MDL_request mdl_request; DBUG_PRINT("info", ("direct is set")); + DBUG_ASSERT(!thd->backup_commit_lock); + + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT); + thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout); + thd->backup_commit_lock= &mdl_request; + if ((res= thd->wait_for_prior_commit())) + { + if (mdl_request.ticket) + thd->mdl_context.release_lock(mdl_request.ticket); + thd->backup_commit_lock= 0; DBUG_RETURN(res); + } file= &log_file; my_org_b_tell= my_b_tell(file); mysql_mutex_lock(&LOCK_log); @@ -6399,7 +6413,11 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) commit_name.length); commit_id= entry->val_int(&null_value); }); - if (write_gtid_event(thd, true, using_trans, commit_id)) + res= write_gtid_event(thd, true, using_trans, commit_id); + if (mdl_request.ticket) + thd->mdl_context.release_lock(mdl_request.ticket); + thd->backup_commit_lock= 0; + if (res) goto err; } else @@ -7461,7 +7479,11 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) group_commit_entry *entry, *orig_queue, *last; wait_for_commit *cur; wait_for_commit *wfc; + bool backup_lock_released= 0; + int result= 0; + THD *thd= orig_entry->thd; DBUG_ENTER("MYSQL_BIN_LOG::queue_for_group_commit"); + DBUG_ASSERT(thd == current_thd); /* Check if we need to wait for another transaction to commit before us. @@ -7493,6 +7515,21 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) { PSI_stage_info old_stage; + /* + Release MDL_BACKUP_COMMIT LOCK while waiting for other threads to + commit. + This is needed to avoid deadlock between the other threads (which not + yet have the MDL_BACKUP_COMMIT_LOCK) and any threads using + BACKUP LOCK BLOCK_COMMIT. + */ + if (thd->backup_commit_lock && thd->backup_commit_lock->ticket && + !backup_lock_released) + { + backup_lock_released= 1; + thd->mdl_context.release_lock(thd->backup_commit_lock->ticket); + thd->backup_commit_lock->ticket= 0; + } + /* By setting wfc->opaque_pointer to our own entry, we mark that we are ready to commit, but waiting for another transaction to commit before @@ -7553,7 +7590,8 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) wfc->wakeup_error= ER_QUERY_INTERRUPTED; my_message(wfc->wakeup_error, ER_THD(orig_entry->thd, wfc->wakeup_error), MYF(0)); - DBUG_RETURN(-1); + result= -1; + goto end; } } orig_entry->thd->EXIT_COND(&old_stage); @@ -7567,12 +7605,13 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) then there is nothing else to do. */ if (orig_entry->queued_by_other) - DBUG_RETURN(0); + goto end; if (wfc && wfc->wakeup_error) { my_error(ER_PRIOR_COMMIT_FAILED, MYF(0)); - DBUG_RETURN(-1); + result= -1; + goto end; } /* Now enqueue ourselves in the group commit queue. */ @@ -7733,7 +7772,13 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) DBUG_PRINT("info", ("Queued for group commit as %s", (orig_queue == NULL) ? "leader" : "participant")); - DBUG_RETURN(orig_queue == NULL); + result= orig_queue == NULL; + +end: + if (backup_lock_released) + thd->mdl_context.acquire_lock(thd->backup_commit_lock, + thd->variables.lock_wait_timeout); + DBUG_RETURN(result); } bool diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8f6356b15c7..4986889b3c8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1271,6 +1271,7 @@ void THD::init() first_successful_insert_id_in_prev_stmt_for_binlog= 0; first_successful_insert_id_in_cur_stmt= 0; current_backup_stage= BACKUP_FINISHED; + backup_commit_lock= 0; #ifdef WITH_WSREP wsrep_last_query_id= 0; wsrep_xid.null(); @@ -1383,7 +1384,7 @@ void THD::init_for_queries() set_time(); /* We don't need to call ha_enable_transaction() as we can't have - any active transactions that has to be commited + any active transactions that has to be committed */ transaction.on= TRUE; @@ -7386,16 +7387,33 @@ wait_for_commit::register_wait_for_prior_commit(wait_for_commit *waitee) } -/* - Wait for commit of another transaction to complete, as already registered +/** + Waits for commit of another transaction to complete, as already registered with register_wait_for_prior_commit(). If the commit already completed, returns immediately. + + If thd->backup_commit_lock is set, release it while waiting for other threads */ + int wait_for_commit::wait_for_prior_commit2(THD *thd) { PSI_stage_info old_stage; wait_for_commit *loc_waitee; + bool backup_lock_released= 0; + + /* + Release MDL_BACKUP_COMMIT LOCK while waiting for other threads to commit + This is needed to avoid deadlock between the other threads (which not + yet have the MDL_BACKUP_COMMIT_LOCK) and any threads using + BACKUP LOCK BLOCK_COMMIT. + */ + if (thd->backup_commit_lock && thd->backup_commit_lock->ticket) + { + backup_lock_released= 1; + thd->mdl_context.release_lock(thd->backup_commit_lock->ticket); + thd->backup_commit_lock->ticket= 0; + } mysql_mutex_lock(&LOCK_wait_commit); DEBUG_SYNC(thd, "wait_for_prior_commit_waiting"); @@ -7445,10 +7463,16 @@ wait_for_commit::wait_for_prior_commit2(THD *thd) use within enter_cond/exit_cond. */ DEBUG_SYNC(thd, "wait_for_prior_commit_killed"); + if (backup_lock_released) + thd->mdl_context.acquire_lock(thd->backup_commit_lock, + thd->variables.lock_wait_timeout); return wakeup_error; end: thd->EXIT_COND(&old_stage); + if (backup_lock_released) + thd->mdl_context.acquire_lock(thd->backup_commit_lock, + thd->variables.lock_wait_timeout); return wakeup_error; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 7cacfe25ce4..0c2d03a516a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2200,7 +2200,10 @@ public: rpl_io_thread_info *rpl_io_info; rpl_sql_thread_info *rpl_sql_info; } system_thread_info; + /* Used for BACKUP LOCK */ MDL_ticket *mdl_backup_ticket, *mdl_backup_lock; + /* Used to register that thread has a MDL_BACKUP_WAIT_COMMIT lock */ + MDL_request *backup_commit_lock; void reset_for_next_command(bool do_clear_errors= 1); /* diff --git a/sql/xa.cc b/sql/xa.cc index 15116ba9366..b08ab973cc5 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -582,7 +582,7 @@ bool trans_xa_commit(THD *thd) { DEBUG_SYNC(thd, "trans_xa_commit_after_acquire_commit_lock"); - res= MY_TEST(ha_commit_one_phase(thd, 1, 1)); + res= MY_TEST(ha_commit_one_phase(thd, 1)); if (res) my_error(ER_XAER_RMERR, MYF(0)); } From 895e9950b2a361a7cf428f60a32e7e3ddc49f833 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 15 Sep 2020 16:13:37 +0300 Subject: [PATCH 23/37] Fix for timeout in rpl.rpl_parallel_retry MDEV-17109 rpl.rpl_parallel_retry fails in buildbot with timeout I was not able to prove that this fix works, but at least it simplifies the problem as it removes some possible timing issues. --- mysql-test/suite/rpl/r/rpl_parallel_retry.result | 2 +- mysql-test/suite/rpl/t/rpl_parallel_retry.test | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_retry.result b/mysql-test/suite/rpl/r/rpl_parallel_retry.result index 66428c94086..b43556815d1 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_retry.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_retry.result @@ -372,7 +372,7 @@ connection server_2; SET @old_dbug= @@GLOBAL.debug_dbug; SET @@GLOBAL.debug_dbug="+d,rpl_parallel_simulate_wait_at_retry"; include/start_slave.inc -# Make sure the 2nd seqno_1001 worker has gotten to waiting +# Make sure both workers are waiting at their sync points # Signal to the 1st to proceed after it has reached termination state SET @@DEBUG_SYNC='now SIGNAL proceed_by_1000'; connection spoiler_21; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry.test b/mysql-test/suite/rpl/t/rpl_parallel_retry.test index 96863f9021d..55da54e3c8c 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_retry.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_retry.test @@ -426,8 +426,8 @@ SET @old_dbug= @@GLOBAL.debug_dbug; SET @@GLOBAL.debug_dbug="+d,rpl_parallel_simulate_wait_at_retry"; --source include/start_slave.inc ---echo # Make sure the 2nd seqno_1001 worker has gotten to waiting ---let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE '%debug sync point: now%'; +--echo # Make sure both workers are waiting at their sync points +--let $wait_condition= SELECT count(*)=2 FROM information_schema.processlist WHERE state LIKE '%debug sync point%'; --source include/wait_condition.inc From 0b73ef0688b320c2ff7fe678b28041f3e7505e97 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 16 Sep 2020 18:29:11 +0300 Subject: [PATCH 24/37] MDEV-21470 ASAN heap-use-after-free in my_hash_sort_bin The problem was that the server was calling virtual functions on a record that was not initialized with new data. This happened when fill_record() was aborted in the middle because an error in save_val() or save_in_field() --- mysql-test/main/type_blob.result | 15 +++++++++++++++ mysql-test/main/type_blob.test | 20 ++++++++++++++++++++ sql/sql_base.cc | 19 +++++++++++-------- sql/table.cc | 24 +++++++++++++++++------- 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/mysql-test/main/type_blob.result b/mysql-test/main/type_blob.result index 967fb37b230..a0a5f82a656 100644 --- a/mysql-test/main/type_blob.result +++ b/mysql-test/main/type_blob.result @@ -1125,5 +1125,20 @@ LENGTH(a) LENGTH(DEFAULT(a)) 256 256 DROP TABLE t1; # +# ASAN heap-use-after-free in my_hash_sort_bin or ER_KEY_NOT_FOUND +# upon INSERT into table with long unique blob +# +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE='STRICT_ALL_TABLES'; +CREATE TABLE t1 (a INT, b BLOB) ENGINE=innodb; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +CREATE TABLE t2 (c BIT, d BLOB, UNIQUE(d)) ENGINE=innodb; +INSERT INTO t2 SELECT * FROM t1; +ERROR 22001: Data too long for column 'c' at row 2 +select * from t2; +c d +DROP TABLE t1, t2; +SET @@sql_mode=@save_sql_mode; +# # End of 10.4 test # diff --git a/mysql-test/main/type_blob.test b/mysql-test/main/type_blob.test index 7801280a8d2..a9b044b5318 100644 --- a/mysql-test/main/type_blob.test +++ b/mysql-test/main/type_blob.test @@ -1,6 +1,7 @@ # This test can't be run with running server (--extern) as this uses # load_file() on a file in the tree. # +--source include/have_innodb.inc # # Basic cleanup @@ -735,6 +736,25 @@ INSERT INTO t1 VALUES (); SELECT LENGTH(a), LENGTH(DEFAULT(a)) FROM t1; DROP TABLE t1; +--echo # +--echo # ASAN heap-use-after-free in my_hash_sort_bin or ER_KEY_NOT_FOUND +--echo # upon INSERT into table with long unique blob +--echo # + +# Note that this test worked with myisam as it caches blobs differently than +# InnoDB + +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE='STRICT_ALL_TABLES'; + +CREATE TABLE t1 (a INT, b BLOB) ENGINE=innodb; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +CREATE TABLE t2 (c BIT, d BLOB, UNIQUE(d)) ENGINE=innodb; +--error ER_DATA_TOO_LONG +INSERT INTO t2 SELECT * FROM t1; +select * from t2; +DROP TABLE t1, t2; +SET @@sql_mode=@save_sql_mode; --echo # --echo # End of 10.4 test diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 75427f106a4..9f9bee0ad17 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8813,14 +8813,17 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List &values, goto err; field->set_has_explicit_value(); } - /* Update virtual fields */ - thd->abort_on_warning= FALSE; - if (table->versioned()) - table->vers_update_fields(); - if (table->vfield && - table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE)) - goto err; - thd->abort_on_warning= abort_on_warning_saved; + /* Update virtual fields if there wasn't any errors */ + if (!thd->is_error()) + { + thd->abort_on_warning= FALSE; + if (table->versioned()) + table->vers_update_fields(); + if (table->vfield && + table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_WRITE)) + goto err; + thd->abort_on_warning= abort_on_warning_saved; + } DBUG_RETURN(thd->is_error()); err: diff --git a/sql/table.cc b/sql/table.cc index 6fa2ef51f89..5d465cf80b5 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8268,28 +8268,39 @@ public: @details The function computes the values of the virtual columns of the table and stores them in the table record buffer. + This will be done even if is_error() is set either when function was called + or by calculating the virtual function, as most calls to this + function doesn't check the result. We also want to ensure that as many + fields as possible has the right value so that we can optionally + return the partly-faulty-row from a storage engine with a virtual + field that gives an error on storage for an existing row. + + @todo + Ensure that all caller checks the value of this function and + either properly ignores it (and resets the error) or sends the + error forward to the caller. @retval 0 Success @retval - >0 Error occurred when storing a virtual field value + >0 Error occurred when storing a virtual field value or potentially + is_error() was set when function was called. */ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) { DBUG_ENTER("TABLE::update_virtual_fields"); - DBUG_PRINT("enter", ("update_mode: %d", update_mode)); + DBUG_PRINT("enter", ("update_mode: %d is_error: %d", update_mode, + in_use->is_error())); Field **vfield_ptr, *vf; Query_arena backup_arena; Turn_errors_to_warnings_handler Suppress_errors; - int error; bool handler_pushed= 0, update_all_columns= 1; DBUG_ASSERT(vfield); if (h->keyread_enabled()) DBUG_RETURN(0); - error= 0; in_use->set_n_backup_active_arena(expr_arena, &backup_arena); /* When reading or deleting row, ignore errors from virtual columns */ @@ -8312,7 +8323,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) } /* Iterate over virtual fields in the table */ - for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) + for (vfield_ptr= vfield; *vfield_ptr ; vfield_ptr++) { vf= (*vfield_ptr); Virtual_column_info *vcol_info= vf->vcol_info; @@ -8363,8 +8374,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) int field_error __attribute__((unused)) = 0; /* Compute the actual value of the virtual fields */ DBUG_FIX_WRITE_SET(vf); - if (vcol_info->expr->save_in_field(vf, 0)) - field_error= error= 1; + field_error= vcol_info->expr->save_in_field(vf, 0); DBUG_RESTORE_WRITE_SET(vf); DBUG_PRINT("info", ("field '%s' - updated error: %d", vf->field_name.str, field_error)); From 8819b5eea5640dc99a96c76a428f739236600ad8 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 17 Sep 2020 16:06:16 +0300 Subject: [PATCH 25/37] MDEV-23318 Assertion `cache_empty(keycache)' failed in prepare_resize_simple_key_cache The reason was that during MyISAM parallel repair two threads used the same changed TABLE object to compute virtual columns Fixed by adding a mutex in compute_vcols() --- mysql-test/main/myisam_repair.result | 51 +++++++++++++++++++++++++ mysql-test/main/myisam_repair.test | 57 ++++++++++++++++++++++++++++ storage/myisam/ha_myisam.cc | 14 +++++-- 3 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 mysql-test/main/myisam_repair.result create mode 100644 mysql-test/main/myisam_repair.test diff --git a/mysql-test/main/myisam_repair.result b/mysql-test/main/myisam_repair.result new file mode 100644 index 00000000000..50a9695c8c7 --- /dev/null +++ b/mysql-test/main/myisam_repair.result @@ -0,0 +1,51 @@ +# +# MDEV-23318 Assertion `cache_empty(keycache)' failed in +# prepare_resize_simple_key_cache +# +SET @buffer_size.save= @@key_buffer_size; +SET GLOBAL key_buffer_size= 134217728; +SET myisam_repair_threads= 6; +CREATE TABLE t1 ( +pk INT AUTO_INCREMENT, +a INTEGER, +b DATE, +c VARCHAR(1), +d BLOB, +PRIMARY KEY (pk), +KEY (a), +KEY (b), +KEY (c, a), +UNIQUE (d) +) ENGINE=MyISAM; +INSERT INTO t1 (a,b,c) SELECT seq, '2020-12-12', 'x' FROM seq_1_to_20; +ALTER TABLE t1 DISABLE KEYS; +SET GLOBAL c.key_buffer_size= 13700864; +Warnings: +Warning 1292 Truncated incorrect key_buffer_size value: '13700864' +INSERT INTO t1 SELECT 1; +ERROR 21S01: Column count doesn't match value count at row 1 +SET GLOBAL c.key_buffer_size= 0; +DROP TABLE t1; +SET GLOBAL key_buffer_size= 134217728; +CREATE TABLE t1 ( +pk INT AUTO_INCREMENT, +a INTEGER, +b DATE, +c VARCHAR(1), +d VARBINARY(40982), +PRIMARY KEY (pk), +KEY (a), +KEY (b), +KEY (c, a), +UNIQUE (d) +) ENGINE=MyISAM; +INSERT INTO t1 (a,b,c) SELECT seq, '2020-12-12', 'x' FROM seq_1_to_20; +ALTER TABLE t1 DISABLE KEYS; +SET GLOBAL c.key_buffer_size= 13700864; +Warnings: +Warning 1292 Truncated incorrect key_buffer_size value: '13700864' +INSERT INTO t1 SELECT 1; +ERROR 21S01: Column count doesn't match value count at row 1 +SET GLOBAL c.key_buffer_size= 0; +DROP TABLE t1; +SET GLOBAL key_buffer_size= @buffer_size.save; diff --git a/mysql-test/main/myisam_repair.test b/mysql-test/main/myisam_repair.test new file mode 100644 index 00000000000..bcb69d59e2c --- /dev/null +++ b/mysql-test/main/myisam_repair.test @@ -0,0 +1,57 @@ +--source include/have_sequence.inc + + +--echo # +--echo # MDEV-23318 Assertion `cache_empty(keycache)' failed in +--echo # prepare_resize_simple_key_cache +--echo # + +SET @buffer_size.save= @@key_buffer_size; +SET GLOBAL key_buffer_size= 134217728; +SET myisam_repair_threads= 6; + +CREATE TABLE t1 ( + pk INT AUTO_INCREMENT, + a INTEGER, + b DATE, + c VARCHAR(1), + d BLOB, + PRIMARY KEY (pk), + KEY (a), + KEY (b), + KEY (c, a), + UNIQUE (d) +) ENGINE=MyISAM; + +INSERT INTO t1 (a,b,c) SELECT seq, '2020-12-12', 'x' FROM seq_1_to_20; + +ALTER TABLE t1 DISABLE KEYS; +SET GLOBAL c.key_buffer_size= 13700864; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT 1; +SET GLOBAL c.key_buffer_size= 0; +DROP TABLE t1; + +SET GLOBAL key_buffer_size= 134217728; + +CREATE TABLE t1 ( + pk INT AUTO_INCREMENT, + a INTEGER, + b DATE, + c VARCHAR(1), + d VARBINARY(40982), + PRIMARY KEY (pk), + KEY (a), + KEY (b), + KEY (c, a), + UNIQUE (d) +) ENGINE=MyISAM; +INSERT INTO t1 (a,b,c) SELECT seq, '2020-12-12', 'x' FROM seq_1_to_20; +ALTER TABLE t1 DISABLE KEYS; +SET GLOBAL c.key_buffer_size= 13700864; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT 1; +SET GLOBAL c.key_buffer_size= 0; + +DROP TABLE t1; +SET GLOBAL key_buffer_size= @buffer_size.save; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 1cc396fe2cd..1b994210ddf 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -688,6 +688,8 @@ my_bool mi_killed_in_mariadb(MI_INFO *info) static int compute_vcols(MI_INFO *info, uchar *record, int keynum) { + /* This mutex is needed for parallel repair */ + mysql_mutex_lock(&info->s->intern_lock); TABLE *table= (TABLE*)(info->external_ref); table->move_fields(table->field, record, table->field[0]->record_ptr()); if (keynum == -1) // update all vcols @@ -695,6 +697,7 @@ static int compute_vcols(MI_INFO *info, uchar *record, int keynum) int error= table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ); if (table->update_virtual_fields(table->file, VCOL_UPDATE_INDEXED)) error= 1; + mysql_mutex_unlock(&info->s->intern_lock); return error; } // update only one key @@ -703,9 +706,10 @@ static int compute_vcols(MI_INFO *info, uchar *record, int keynum) for (; kp < end; kp++) { Field *f= table->field[kp->fieldnr - 1]; - if (f->vcol_info) + if (f->vcol_info && !f->vcol_info->stored_in_db) table->update_virtual_field(f); } + mysql_mutex_unlock(&info->s->intern_lock); return 0; } @@ -956,7 +960,7 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) if (!table->vfield) return; - if (file->s->base.reclength == file->s->vreclength) + if (file->s->base.reclength == file->s->vreclength) { bool indexed_vcols= false; ulong new_vreclength= file->s->vreclength; @@ -964,7 +968,8 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) { if (!(*vf)->stored_in_db()) { - uint vf_end= (*vf)->offset(table->record[0]) + (*vf)->pack_length_in_rec(); + uint vf_end= ((*vf)->offset(table->record[0]) + + (*vf)->pack_length_in_rec()); set_if_bigger(new_vreclength, vf_end); indexed_vcols|= ((*vf)->flags & PART_KEY_FLAG) != 0; } @@ -982,7 +987,8 @@ void ha_myisam::restore_vcos_after_repair() { if (file->s->base.reclength < file->s->vreclength) { - table->move_fields(table->field, table->record[0], table->field[0]->record_ptr()); + table->move_fields(table->field, table->record[0], + table->field[0]->record_ptr()); table->default_column_bitmaps(); } } From 92b5a8bb65991815e44290de8b9a0a96fa815b7a Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 17 Sep 2020 17:59:59 +0300 Subject: [PATCH 26/37] MDEV-17665 Assertion `!share and other errors on concurrent Aria operations Fixes also: MDEV-22674 Server crash in compare_bin ... restore_table_state_after_repair The bug was that the 'can_enable_index' variable in MyISAM and Aria was not properly set and reset for bulk insert. Because of this, insert...select was trying to recreate indexes while another thread was using it, causing crashes in page cache. --- mysql-test/suite/maria/alter.result | 60 +++++++++++++ mysql-test/suite/maria/alter.test | 84 +++++++++++++++++++ .../suite/maria/maria-no-logging.result | 6 ++ mysql-test/suite/maria/maria-no-logging.test | 2 + sql/sql_table.cc | 8 +- storage/maria/ha_maria.cc | 8 +- storage/myisam/ha_myisam.cc | 9 +- 7 files changed, 173 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/maria/alter.result b/mysql-test/suite/maria/alter.result index 4e6f21b70a7..c79c86e8ba0 100644 --- a/mysql-test/suite/maria/alter.result +++ b/mysql-test/suite/maria/alter.result @@ -104,3 +104,63 @@ DROP TABLE t1; # # End of 10.2 test # +# +# MDEV-17665 Assertion `!share || share->page_type == PAGECACHE_LSN_PAGE', +# `type != PAGECACHE_READ_UNKNOWN_PAGE' and similar ones upon concurrent +# Aria operations +# +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; +connect con1,localhost,root,,test; +connect con2,localhost,root,,test; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; +connection con1; +FLUSH TABLES; +connection default; +INSERT INTO t1 SELECT 1; +ERROR 21S01: Column count doesn't match value count at row 1 +connection con2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +disconnect con2; +connection con1; +disconnect con1; +connection default; +DROP TABLE t1; +# +# MDEV-22674 Server crash in compare_bin, ASAN heap-buffer-overflow in +# _ma_dpointer, Assertion `!info->s->have_versioning || +# info->s->lock_key_trees' failed in restore_table_state_after_repair +# +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +connect con1,localhost,root,,test; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (id) SELECT b FROM t2; +connection default; +INSERT INTO t1 SELECT a FROM t2; +ERROR 21S01: Column count doesn't match value count at row 1 +connection con1; +ERROR 42S22: Unknown column 'b' in 'field list' +disconnect con1; +connection default; +drop table t1, t2; +# This is also in MDEV-22674 +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (id) SELECT b FROM t2; +ERROR 42S22: Unknown column 'b' in 'field list' +INSERT INTO t1 SELECT a FROM t2; +ERROR 21S01: Column count doesn't match value count at row 1 +SELECT COUNT(*) FROM t1; +COUNT(*) +500 +DROP TABLE t1,t2; +# +# End of 10.4 test +# diff --git a/mysql-test/suite/maria/alter.test b/mysql-test/suite/maria/alter.test index 31eeac1df87..17a270f2a90 100644 --- a/mysql-test/suite/maria/alter.test +++ b/mysql-test/suite/maria/alter.test @@ -1,6 +1,8 @@ # Testing of potential problems in Aria and alter table -- source include/have_maria.inc +-- source include/have_innodb.inc +-- source include/have_sequence.inc drop table if exists t1; @@ -90,3 +92,85 @@ DROP TABLE t1; --echo # --echo # End of 10.2 test --echo # + +--echo # +--echo # MDEV-17665 Assertion `!share || share->page_type == PAGECACHE_LSN_PAGE', +--echo # `type != PAGECACHE_READ_UNKNOWN_PAGE' and similar ones upon concurrent +--echo # Aria operations +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT, KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; + +--connect (con1,localhost,root,,test) +--connect (con2,localhost,root,,test) +--send + INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; + +--connection con1 +--send + FLUSH TABLES; + +--connection default +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT 1; + +# Cleanup +--connection con2 +--error ER_DUP_ENTRY +--reap +--disconnect con2 +--connection con1 +--reap +--disconnect con1 +--connection default +DROP TABLE t1; + +--echo # +--echo # MDEV-22674 Server crash in compare_bin, ASAN heap-buffer-overflow in +--echo # _ma_dpointer, Assertion `!info->s->have_versioning || +--echo # info->s->lock_key_trees' failed in restore_table_state_after_repair +--echo # + +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; + +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); + +--connect (con1,localhost,root,,test) +ALTER TABLE t1 DISABLE KEYS; +--send + INSERT INTO t1 (id) SELECT b FROM t2; + +--connection default +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT a FROM t2; + +# Cleanup +--connection con1 +--error ER_BAD_FIELD_ERROR +--reap +--disconnect con1 + +--connection default +drop table t1, t2; + +--echo # This is also in MDEV-22674 + +CREATE TABLE t1 (id INT, d DATETIME, PRIMARY KEY(d,id),INDEX(d)) ENGINE=Aria; +INSERT INTO t1 SELECT seq, NOW() FROM seq_1_to_500; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +ALTER TABLE t1 DISABLE KEYS; +--error ER_BAD_FIELD_ERROR +INSERT INTO t1 (id) SELECT b FROM t2; +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 SELECT a FROM t2; +SELECT COUNT(*) FROM t1; +DROP TABLE t1,t2; + +--echo # +--echo # End of 10.4 test +--echo # diff --git a/mysql-test/suite/maria/maria-no-logging.result b/mysql-test/suite/maria/maria-no-logging.result index fb175d0e326..e79686c4731 100644 --- a/mysql-test/suite/maria/maria-no-logging.result +++ b/mysql-test/suite/maria/maria-no-logging.result @@ -31,6 +31,9 @@ insert into t1 select * from t2; show engine aria logs; Type Name Status Aria Size 24576 aria_log.00000001 unknown +select count(*) from t1; +count(*) +65 connection default; connection admin; * shut down mysqld, removed logs, restarted it @@ -40,6 +43,9 @@ insert into t1 select * from t2; show engine aria logs; Type Name Status Aria Size 16384 aria_log.00000001 unknown +select count(*) from t1; +count(*) +64 drop table t1; connection default; connection admin; diff --git a/mysql-test/suite/maria/maria-no-logging.test b/mysql-test/suite/maria/maria-no-logging.test index fb2f34f7708..5d8029156ed 100644 --- a/mysql-test/suite/maria/maria-no-logging.test +++ b/mysql-test/suite/maria/maria-no-logging.test @@ -48,6 +48,7 @@ insert into t1 values('a'); insert into t1 select * from t2; --replace_regex /; .+aria_log/aria_log/ show engine aria logs; +select count(*) from t1; # optimization because table is empty -- source include/maria_empty_logs.inc @@ -55,6 +56,7 @@ truncate table t1; insert into t1 select * from t2; --replace_regex /; .+aria_log/aria_log/ show engine aria logs; +select count(*) from t1; drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3831bd03802..c90387cf1c3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10614,6 +10614,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool make_versioned= !from->versioned() && to->versioned(); bool make_unversioned= from->versioned() && !to->versioned(); bool keep_versioned= from->versioned() && to->versioned(); + bool bulk_insert_started= 0; Field *to_row_start= NULL, *to_row_end= NULL, *from_row_end= NULL; MYSQL_TIME query_start; DBUG_ENTER("copy_data_between_tables"); @@ -10652,6 +10653,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE); to->file->ha_start_bulk_insert(from->file->stats.records, ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT); + bulk_insert_started= 1; List_iterator it(create); Create_field *def; copy_end=copy; @@ -10914,6 +10916,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, to->file->print_error(my_errno,MYF(0)); error= 1; } + bulk_insert_started= 0; if (!ignore) to->file->extra(HA_EXTRA_END_ALTER_COPY); @@ -10927,7 +10930,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, error= 1; err: - /* Free resources */ + if (bulk_insert_started) + (void) to->file->ha_end_bulk_insert(); + +/* Free resources */ if (init_read_record_done) end_read_record(&info); delete [] copy; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 013c740582b..aa99bc157c9 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1025,7 +1025,7 @@ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_EXPORT | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_TABLES_WITHOUT_ROLLBACK), -can_enable_indexes(1), bulk_insert_single_undo(BULK_INSERT_NONE) +can_enable_indexes(0), bulk_insert_single_undo(BULK_INSERT_NONE) {} @@ -2089,6 +2089,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) DBUG_ENTER("ha_maria::start_bulk_insert"); THD *thd= table->in_use; MARIA_SHARE *share= file->s; + bool index_disabled= 0; DBUG_PRINT("info", ("start_bulk_insert: rows %lu", (ulong) rows)); /* don't enable row cache if too few rows */ @@ -2152,6 +2153,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) { /* Internal table; If we get a duplicate something is very wrong */ file->update|= HA_STATE_CHANGED; + index_disabled= share->base.keys > 0; maria_clear_all_keys_active(file->s->state.key_map); } else @@ -2179,6 +2181,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH) { maria_clear_key_active(share->state.key_map, i); + index_disabled= 1; file->update|= HA_STATE_CHANGED; file->create_unique_index_by_sort= all_keys; } @@ -2208,6 +2211,7 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) rows); } } + can_enable_indexes= index_disabled; DBUG_VOID_RETURN; } @@ -2246,7 +2250,6 @@ int ha_maria::end_bulk_insert() if (bulk_insert_single_undo != BULK_INSERT_NONE) { - DBUG_ASSERT(can_enable_indexes); /* Table was transactional just before start_bulk_insert(). No need to flush pages if we did a repair (which already flushed). @@ -2257,6 +2260,7 @@ int ha_maria::end_bulk_insert() first_error= first_error ? first_error : error; bulk_insert_single_undo= BULK_INSERT_NONE; // Safety } + can_enable_indexes= 0; DBUG_RETURN(first_error); } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 1b994210ddf..f0df75aa578 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -726,7 +726,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR | HA_CAN_TABLES_WITHOUT_ROLLBACK), - can_enable_indexes(1) + can_enable_indexes(0) {} handler *ha_myisam::clone(const char *name __attribute__((unused)), @@ -1729,6 +1729,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) THD *thd= table->in_use; ulong size= MY_MIN(thd->variables.read_buff_size, (ulong) (table->s->avg_row_length*rows)); + bool index_disabled= 0; DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu", (ulong) rows, size)); @@ -1752,6 +1753,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) if (file->open_flag & HA_OPEN_INTERNAL_TABLE) { file->update|= HA_STATE_CHANGED; + index_disabled= file->s->base.keys > 0; mi_clear_all_keys_active(file->s->state.key_map); } else @@ -1782,6 +1784,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH) { mi_clear_key_active(share->state.key_map, i); + index_disabled= 1; file->update|= HA_STATE_CHANGED; file->create_unique_index_by_sort= all_keys; } @@ -1789,12 +1792,15 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) } } else + { if (!file->bulk_insert && (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT)) { mi_init_bulk_insert(file, (size_t) thd->variables.bulk_insert_buff_size, rows); } + } + can_enable_indexes= index_disabled; DBUG_VOID_RETURN; } @@ -1846,6 +1852,7 @@ int ha_myisam::end_bulk_insert() file->s->state.changed&= ~(STATE_CRASHED|STATE_CRASHED_ON_REPAIR); } } + can_enable_indexes= 0; } DBUG_PRINT("exit", ("first_error: %d", first_error)); DBUG_RETURN(first_error); From bb2c958132a12a049163564b7a6e6d4da8e2851a Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 17 Sep 2020 18:54:11 +0300 Subject: [PATCH 27/37] MDEV-23296 Assertion `block->type == PAGECACHE_EMPTY_PAGE.. with aria_max_sort_file_size=0 When maria_drop_all_indexes() reset the key files, it didn't flush the page cache. This confused the cache as there where old key blocks marked with LSN in it and repair tried to overwrite these with PLAIN blocks which is not allowed. --- mysql-test/suite/maria/alter.result | 20 ++++++++++++++++++++ mysql-test/suite/maria/alter.test | 18 ++++++++++++++++++ storage/maria/ma_check.c | 3 +++ 3 files changed, 41 insertions(+) diff --git a/mysql-test/suite/maria/alter.result b/mysql-test/suite/maria/alter.result index c79c86e8ba0..e1a57ed654f 100644 --- a/mysql-test/suite/maria/alter.result +++ b/mysql-test/suite/maria/alter.result @@ -162,5 +162,25 @@ COUNT(*) 500 DROP TABLE t1,t2; # +# MDEV-23296 Assertion `block->type == PAGECACHE_EMPTY_PAGE || +# block->type == PAGECACHE_READ_UNKNOWN_PAGE || block->type == type || +# (block->type == PAGECACHE_PLAIN_PAGE && type == PAGECACHE_LSN_PAGE)' +# with aria_max_sort_file_size +# +SET @max_size.save= @@aria_max_sort_file_size; +SET GLOBAL aria_max_sort_file_size= 0; +CREATE TABLE t1 (pk INT PRIMARY KEY, a CHAR(255), KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ALTER TABLE t1 ENABLE KEYS; +INSERT INTO t1 VALUES (3,'nice try'); +SELECT * FROM t1; +pk a +1 foo +2 bar +3 nice try +DROP TABLE t1; +SET GLOBAL aria_max_sort_file_size= @max_size.save; +# # End of 10.4 test # diff --git a/mysql-test/suite/maria/alter.test b/mysql-test/suite/maria/alter.test index 17a270f2a90..f2950f0a6d3 100644 --- a/mysql-test/suite/maria/alter.test +++ b/mysql-test/suite/maria/alter.test @@ -171,6 +171,24 @@ INSERT INTO t1 SELECT a FROM t2; SELECT COUNT(*) FROM t1; DROP TABLE t1,t2; +--echo # +--echo # MDEV-23296 Assertion `block->type == PAGECACHE_EMPTY_PAGE || +--echo # block->type == PAGECACHE_READ_UNKNOWN_PAGE || block->type == type || +--echo # (block->type == PAGECACHE_PLAIN_PAGE && type == PAGECACHE_LSN_PAGE)' +--echo # with aria_max_sort_file_size +--echo # + +SET @max_size.save= @@aria_max_sort_file_size; +SET GLOBAL aria_max_sort_file_size= 0; +CREATE TABLE t1 (pk INT PRIMARY KEY, a CHAR(255), KEY(a)) ENGINE=Aria; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ALTER TABLE t1 ENABLE KEYS; +INSERT INTO t1 VALUES (3,'nice try'); +SELECT * FROM t1; +DROP TABLE t1; +SET GLOBAL aria_max_sort_file_size= @max_size.save; + --echo # --echo # End of 10.4 test --echo # diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 37c2712b143..9670daa9104 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -2550,6 +2550,9 @@ static int maria_drop_all_indexes(HA_CHECK *param, MARIA_HA *info, DBUG_PRINT("repair", ("declared all indexes disabled")); } + /* Flush obsolete index data from key cache */ + _ma_flush_table_files(info, MARIA_FLUSH_INDEX, + FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED); /* Clear index root block pointers. */ for (i= 0; i < share->base.keys; i++) state->key_root[i]= HA_OFFSET_ERROR; From 71a7b79bcbfe90c3118e3d4379ad734dc72c9f39 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 25 Sep 2020 13:38:48 +0300 Subject: [PATCH 28/37] Added asssert to init_of_queries() to make it more safe Part of review of 10.4 code by Sergei. Other things: - Changed return type if is_active() from my_bool to bool as this is only used by C++ code. --- sql/sql_class.cc | 1 + sql/sql_class.h | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4986889b3c8..e57196ee056 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1386,6 +1386,7 @@ void THD::init_for_queries() We don't need to call ha_enable_transaction() as we can't have any active transactions that has to be committed */ + DBUG_ASSERT(transaction.is_empty()); transaction.on= TRUE; reset_root_defaults(mem_root, variables.query_alloc_block_size, diff --git a/sql/sql_class.h b/sql/sql_class.h index 0c2d03a516a..64cd1ed6ba3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2630,10 +2630,14 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_VOID_RETURN; } - my_bool is_active() + bool is_active() { return (all.ha_list != NULL); } + bool is_empty() + { + return all.is_empty() && stmt.is_empty(); + } st_transactions() { bzero((char*)this, sizeof(*this)); From 6a1376252d7997f6fa1268c08bed5f93b32922f8 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 25 Sep 2020 15:58:08 +0300 Subject: [PATCH 29/37] Reverted wrong patch for mysql_upgrade The original code was correct. mysql_upgrade calls the mysql client to talk with MariaDB. It doesn't call itself! --- client/mysql_upgrade.c | 2 +- mysql-test/main/mysql_upgrade.result | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 4872d187a72..4f3f1ff86da 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1173,7 +1173,7 @@ static int check_version_match(void) extract_variable_from_show(&ds_version, version_str)) { print_error("Version check failed. Got the following error when calling " - "the 'mysql_upgrade' command line client", &ds_version); + "the 'mysql' command line client", &ds_version); dynstr_free(&ds_version); return 1; /* Query failed */ } diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 84628e6d504..7be0be6ccc3 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -145,7 +145,7 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK DROP USER mysqltest1@'%'; -Version check failed. Got the following error when calling the 'mysql_upgrade' command line client +Version check failed. Got the following error when calling the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'mysqltest1'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed Run mysql_upgrade with a non existing server socket @@ -412,7 +412,7 @@ OK # Bug #21489398: MYSQL_UPGRADE: FATAL ERROR: UPGRADE FAILED - IMPROVE ERROR # Run mysql_upgrade with unauthorized access -Version check failed. Got the following error when calling the 'mysql_upgrade' command line client +Version check failed. Got the following error when calling the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed # From e8b05ce503dffc2d95d1583b7c89403d320e263c Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 8 Sep 2020 17:24:08 +0530 Subject: [PATCH 30/37] MDEV-23675 Assertion `pos < table->n_def' fails in dict_table_get_nth_col - During insertion of clustered inde, InnoDB does the check for foreign key constraints. It rebuild the tuple based on foreign column names when there is no foreign index. While rebuilding, InnoDB should ignore the dropped columns. --- mysql-test/suite/innodb/r/foreign_key.result | 13 +++++++++++++ mysql-test/suite/innodb/t/foreign_key.test | 14 ++++++++++++++ storage/innobase/row/row0ins.cc | 10 ++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index bd40f98ef65..2facbccc466 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -755,4 +755,17 @@ DROP TABLE t1; CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +# +# MDEV-23675 Assertion `pos < table->n_def' in dict_table_get_nth_col +# +CREATE TABLE t1 (pk int PRIMARY KEY, a INT, b INT, c INT, KEY(c), +FOREIGN KEY fx (b) REFERENCES t1 (c)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0,10,10); +ALTER TABLE t1 DROP a, ALGORITHM=INSTANT; +SET FOREIGN_KEY_CHECKS= 0; +DROP INDEX fx ON t1; +INSERT INTO t1 VALUES (2,11,11); +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 9207fce6525..dab0736f712 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -741,6 +741,20 @@ DROP TABLE t1; CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; +--echo # +--echo # MDEV-23675 Assertion `pos < table->n_def' in dict_table_get_nth_col +--echo # +CREATE TABLE t1 (pk int PRIMARY KEY, a INT, b INT, c INT, KEY(c), +FOREIGN KEY fx (b) REFERENCES t1 (c)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0,10,10); +ALTER TABLE t1 DROP a, ALGORITHM=INSTANT; +SET FOREIGN_KEY_CHECKS= 0; +DROP INDEX fx ON t1; +INSERT INTO t1 VALUES (2,11,11); +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; + -- echo # End of 10.4 tests --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 9c913b0c9f2..a28489062b0 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1908,8 +1908,14 @@ bool row_ins_foreign_index_entry(dict_foreign_t *foreign, { for (ulint j= 0; j < index->n_fields; j++) { - const char *col_name= dict_table_get_col_name( - index->table, dict_index_get_nth_col_no(index, j)); + const dict_col_t *col= dict_index_get_nth_col(index, j); + + /* A clustered index may contain instantly dropped columns, + which must be skipped. */ + if (col->is_dropped()) + continue; + + const char *col_name= dict_table_get_col_name(index->table, col->ind); if (0 == innobase_strcasecmp(col_name, foreign->foreign_col_names[i])) { dfield_copy(&ref_entry->fields[i], &entry->fields[j]); From e0f5e7bc9ef306a76c5bf4e067ee5c1a9a7b6187 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 25 Sep 2020 15:58:08 +0300 Subject: [PATCH 31/37] Reverted wrong patch for mysql_upgrade The original code was correct. mysql_upgrade calls the mysql client to talk with MariaDB. It doesn't call itself! --- client/mysql_upgrade.c | 2 +- mysql-test/r/mysql_upgrade.result | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 9cc12c8d7e7..d18dc97c9b8 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1108,7 +1108,7 @@ static int check_version_match(void) extract_variable_from_show(&ds_version, version_str)) { print_error("Version check failed. Got the following error when calling " - "the 'mysql_upgrade' command line client", &ds_version); + "the 'mysql' command line client", &ds_version); dynstr_free(&ds_version); return 1; /* Query failed */ } diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index a1464bb4853..69637f4078f 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -142,7 +142,7 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK DROP USER mysqltest1@'%'; -Version check failed. Got the following error when calling the 'mysql_upgrade' command line client +Version check failed. Got the following error when calling the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'mysqltest1'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed Run mysql_upgrade with a non existing server socket @@ -405,7 +405,7 @@ OK # Bug #21489398: MYSQL_UPGRADE: FATAL ERROR: UPGRADE FAILED - IMPROVE ERROR # Run mysql_upgrade with unauthorized access -Version check failed. Got the following error when calling the 'mysql_upgrade' command line client +Version check failed. Got the following error when calling the 'mysql' command line client ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) FATAL ERROR: Upgrade failed # From 15cd9195353282e54e109962d46e1900c9eff3d4 Mon Sep 17 00:00:00 2001 From: Sujatha Date: Thu, 24 Sep 2020 15:07:42 +0530 Subject: [PATCH 32/37] MDEV-22330: mysqlbinlog stops with an error Don't know how to handle column type: 255 meta: 4 (0004) Analysis: ======== "mysqlbinlog -v" option will reconstruct row events and display them as commented SQL statements. If this option is given twice, the output includes comments to indicate column data types and some metadata. `log_event_print_value` is the function reponsible for printing values and their types. This function doesn't handle GEOMETRY type. Hence the above error gets printed. Fix: === Add support for GEOMETRY datatype. --- .../binlog/r/binlog_mysqlbinlog_row.result | 56 ++++++++++++++++++- .../binlog/t/binlog_mysqlbinlog_row.test | 14 ++++- sql/log_event.cc | 17 ++++-- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result index 9a3f4751165..0b05c4f449f 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_row.result @@ -339,7 +339,11 @@ a 123.47 999.99 DROP TABLE t1dec102; -flush logs; +CREATE TABLE t1 (a GEOMETRY DEFAULT NULL); +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (POINT(10,10)); +DROP TABLE t1; +FLUSH LOGS; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; @@ -4623,6 +4627,56 @@ SET TIMESTAMP=1000000000/*!*/; DROP TABLE `t1dec102` /* generated by server */ /*!*/; # at # +#010909 4:46:40 server id 1 end_log_pos # GTID 0-1-321 ddl +/*!100001 SET @@session.gtid_seq_no=321*//*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +CREATE TABLE t1 (a GEOMETRY DEFAULT NULL) +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # GTID 0-1-322 +/*!100001 SET @@session.gtid_seq_no=322*//*!*/; +BEGIN +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1=NULL /* GEOMETRY meta=4 nullable=1 is_null=1 */ +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # GTID 0-1-323 +/*!100001 SET @@session.gtid_seq_no=323*//*!*/; +BEGIN +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number # +# at # +#010909 4:46:40 server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1='\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00$@\x00\x00\x00\x00\x00\x00$@' /* GEOMETRY meta=4 nullable=1 is_null=0 */ +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +COMMIT +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # GTID 0-1-324 ddl +/*!100001 SET @@session.gtid_seq_no=324*//*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +DROP TABLE `t1` /* generated by server */ +/*!*/; +# at # #010909 4:46:40 server id 1 end_log_pos # Rotate to master-bin.000002 pos: 4 DELIMITER ; # End of log file diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test index 0c94d968338..93c26cc57a2 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_row.test @@ -450,7 +450,19 @@ INSERT INTO t1dec102 VALUES (999.99); SELECT * FROM t1dec102 ORDER BY a; DROP TABLE t1dec102; -flush logs; + +# +# MDEV-22330: mysqlbinlog stops with an error Don't know how to handle column +# type: 255 meta: 4 (0004) +# Check support for GEOMETRY type with verbose mode. +# +CREATE TABLE t1 (a GEOMETRY DEFAULT NULL); + +INSERT INTO t1 VALUES (NULL); +INSERT INTO t1 VALUES (POINT(10,10)); +DROP TABLE t1; + +FLUSH LOGS; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /(@[0-9]*=[0-9]*[.][0-9]{1,3})[0-9e+-]*[^ ]*(.*(FLOAT|DOUBLE).*[*].)/\1...\2/ diff --git a/sql/log_event.cc b/sql/log_event.cc index 4d7bb1726ed..3d28c249e21 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2575,13 +2575,20 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, "Not enough metadata to display the value. "); break; + case MYSQL_TYPE_GEOMETRY: + strmake(typestr, "GEOMETRY", typestr_length); + if (!ptr) + goto return_null; + + length= uint4korr(ptr); + my_b_write_quoted(file, ptr + meta, length); + return length + meta; + default: { - char tmp[5]; - my_snprintf(tmp, sizeof(tmp), "%04x", meta); - my_b_printf(file, - "!! Don't know how to handle column type=%d meta=%d (%s)", - type, meta, tmp); + fprintf(stderr, + "\nError: Don't know how to handle column type: %d meta: %d (%04x)\n", + type, meta, meta); } break; } From a6987d9fb921a6638bb1a2397b89ca606fad6f49 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 28 Sep 2020 09:49:46 +0200 Subject: [PATCH 33/37] MDEV-23823 Crash in SELECT NEXT VALUE on locked view Make open_table() fail if sequence should be opened, but it turns out to be locked view. --- mysql-test/suite/sql_sequence/next.result | 9 +++++++++ mysql-test/suite/sql_sequence/next.test | 10 ++++++++++ sql/sql_base.cc | 7 +++++++ 3 files changed, 26 insertions(+) diff --git a/mysql-test/suite/sql_sequence/next.result b/mysql-test/suite/sql_sequence/next.result index b1b1bb69306..fe761baa032 100644 --- a/mysql-test/suite/sql_sequence/next.result +++ b/mysql-test/suite/sql_sequence/next.result @@ -534,3 +534,12 @@ select next value for s; next value for s -999 drop sequence s; +# +# MDEV-23823 NEXT VALUE crash on locked view +# +CREATE VIEW v AS SELECT 1; +LOCK TABLE v READ; +SELECT NEXT VALUE FOR v; +ERROR 42S02: 'test.v' is not a SEQUENCE +UNLOCK TABLES; +DROP VIEW v; diff --git a/mysql-test/suite/sql_sequence/next.test b/mysql-test/suite/sql_sequence/next.test index a1f91bd7823..5eac3b668ba 100644 --- a/mysql-test/suite/sql_sequence/next.test +++ b/mysql-test/suite/sql_sequence/next.test @@ -280,3 +280,13 @@ select next value for s; flush tables; select next value for s; drop sequence s; + +--echo # +--echo # MDEV-23823 NEXT VALUE crash on locked view +--echo # +CREATE VIEW v AS SELECT 1; +LOCK TABLE v READ; +--error ER_NOT_SEQUENCE +SELECT NEXT VALUE FOR v; +UNLOCK TABLES; +DROP VIEW v; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 73ed7a855a2..00e1198df0e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1724,7 +1724,14 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) } if (is_locked_view(thd, table_list)) + { + if (table_list->sequence) + { + my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db.str, table_list->alias.str); + DBUG_RETURN(true); + } DBUG_RETURN(FALSE); // VIEW + } /* No table in the locked tables list. In case of explicit LOCK TABLES From c078f55f47eba8660f6daed6d0c2000694159a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 28 Sep 2020 11:05:09 +0300 Subject: [PATCH 34/37] MDEV-23659 : Update Galera disabled.def file This will update galera_3nodes/disabled.def. --- mysql-test/suite/galera_3nodes/disabled.def | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 0e2706f2dc3..80cfa7a920f 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -10,7 +10,13 @@ # ############################################################################## + galera_gtid_2_cluster : MDEV-23775 Galera test failure on galera_3nodes.galera_gtid_2_cluster +galera_ipv6_mariabackup.test : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails +galera_ipv6_mariabackup_section.test : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails +galera_ipv6_mysqldump.test : MDEV-23576 galera_3nodes.galera_ipv6_mysqldump MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken +galera_ipv6_rsync.test : MDEV-23581 galera_3nodes.galera_ipv6_rsync MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken +galera_ipv6_rsync_section.test : MDEV-23580 galera_3nodes.galera_ipv6_rsync_section MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken galera_ist_gcache_rollover : MDEV-23578 WSREP: exception caused by message: {v=0,t=1,ut=255,o=4,s=0,sr=0,as=1,f=6,src=50524cfe,srcvid=view_id(REG,50524cfe,4),insvid=view_id(UNKNOWN,00000000,0),ru=00000000,r=[-1,-1],fs=75,nl=(} galera_slave_options_do :MDEV-8798 galera_slave_options_ignore : MDEV-8798 From 7edfb72efff18b7de7f22cd6dfd90b553e27c286 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Fri, 25 Sep 2020 14:08:35 +0200 Subject: [PATCH 35/37] Fix MTR test wsrep.variables Require galera_have_debug_sync.inc and re-record to include new variables exposed by latest galera library. --- mysql-test/suite/wsrep/r/variables.result | 6 ++++++ mysql-test/suite/wsrep/t/variables.test | 1 + 2 files changed, 7 insertions(+) diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index 1ff221f1459..87a385ec9a6 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -48,6 +48,8 @@ wsrep_flow_control_paused_ns # wsrep_flow_control_paused # wsrep_flow_control_sent # wsrep_flow_control_recv # +wsrep_flow_control_active # +wsrep_flow_control_requested # wsrep_cert_deps_distance # wsrep_apply_oooe # wsrep_apply_oool # @@ -63,6 +65,7 @@ wsrep_cert_interval # wsrep_open_transactions # wsrep_open_connections # wsrep_incoming_addresses # +wsrep_debug_sync_waiters # wsrep_applier_thread_count # wsrep_cluster_capabilities # wsrep_cluster_conf_id # @@ -109,6 +112,8 @@ wsrep_flow_control_paused_ns # wsrep_flow_control_paused # wsrep_flow_control_sent # wsrep_flow_control_recv # +wsrep_flow_control_active # +wsrep_flow_control_requested # wsrep_cert_deps_distance # wsrep_apply_oooe # wsrep_apply_oool # @@ -124,6 +129,7 @@ wsrep_cert_interval # wsrep_open_transactions # wsrep_open_connections # wsrep_incoming_addresses # +wsrep_debug_sync_waiters # wsrep_applier_thread_count # wsrep_cluster_capabilities # wsrep_cluster_conf_id # diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 89b1ff99012..93aa31b9c93 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -1,6 +1,7 @@ --source include/have_wsrep.inc --source include/force_restart.inc --source include/have_innodb.inc +--source include/galera_have_debug_sync.inc SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; SET @wsrep_cluster_address_saved= @@global.wsrep_cluster_address; From 842616532a76cd078ba1d526ae4b85d3ad4be069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 28 Sep 2020 14:39:24 +0300 Subject: [PATCH 36/37] MDEV-23659 : Update Galera disabled.def file Fix typo. --- mysql-test/suite/galera_3nodes/disabled.def | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 80cfa7a920f..ff7262947a0 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -10,13 +10,12 @@ # ############################################################################## - galera_gtid_2_cluster : MDEV-23775 Galera test failure on galera_3nodes.galera_gtid_2_cluster -galera_ipv6_mariabackup.test : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails -galera_ipv6_mariabackup_section.test : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails -galera_ipv6_mysqldump.test : MDEV-23576 galera_3nodes.galera_ipv6_mysqldump MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken -galera_ipv6_rsync.test : MDEV-23581 galera_3nodes.galera_ipv6_rsync MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken -galera_ipv6_rsync_section.test : MDEV-23580 galera_3nodes.galera_ipv6_rsync_section MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken +galera_ipv6_mariabackup : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails +galera_ipv6_mariabackup_section : MDEV-21770 galera_3nodes.galera_ipv6_mariabackup fails +galera_ipv6_mysqldump : MDEV-23576 galera_3nodes.galera_ipv6_mysqldump MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken +galera_ipv6_rsync : MDEV-23581 galera_3nodes.galera_ipv6_rsync MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken +galera_ipv6_rsync_section : MDEV-23580 galera_3nodes.galera_ipv6_rsync_section MTR failed: WSREP_SST: [ERROR] rsync daemon port '16008' has been taken galera_ist_gcache_rollover : MDEV-23578 WSREP: exception caused by message: {v=0,t=1,ut=255,o=4,s=0,sr=0,as=1,f=6,src=50524cfe,srcvid=view_id(REG,50524cfe,4),insvid=view_id(UNKNOWN,00000000,0),ru=00000000,r=[-1,-1],fs=75,nl=(} galera_slave_options_do :MDEV-8798 galera_slave_options_ignore : MDEV-8798 From 79e32e47a11150839ac4ab44ac02d4019c0e0019 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 26 Sep 2020 10:07:28 -0700 Subject: [PATCH 37/37] MDEV-23778 Derived table handler looses data on conversion from HEAP to Aria This bug happened when the HEAP temporary table used for the derived table created for a derived handler of a remote engine of the federated type became full and was converted to an Area table. For this conversion the tmp_table_param parameter must be always taken from the select_unit object created for the result of the derived table. --- .../federatedx_create_handlers.result | 44 ++++++++++++++ .../federated/federatedx_create_handlers.test | 57 +++++++++++++++++++ sql/derived_handler.cc | 4 +- 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index 63e56bff425..b115cc73b87 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -376,6 +376,50 @@ DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4; connection slave; DROP TABLE federated.t1, federated.t2; connection default; +# +# MDEV-23778: Derived handler used for big derived tables +# +connection slave; +CREATE TABLE federated.t1 ( +a varchar(100) NOT NULL default '123' +) +DEFAULT CHARSET=latin1; +CREATE TABLE federated.t2 LIKE federated.t1; +BEGIN NOT ATOMIC +DECLARE i INT DEFAULT 0; +START TRANSACTION; +WHILE i < 70000 DO +INSERT INTO federated.t1 VALUES (i); +SET i = i + 1; +END WHILE; +COMMIT; +END +$$ +connection master; +CREATE TABLE federated.t1 ( +a varchar(100) NOT NULL default '123' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +CREATE TABLE federated.t2 ( +a varchar(100) NOT NULL default '123' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2'; +SELECT COUNT(DISTINCT a) FROM federated.t1; +COUNT(DISTINCT a) +70000 +INSERT INTO federated.t2 +SELECT * FROM (SELECT * FROM federated.t1 LIMIT 100) dt; +SELECT COUNT(DISTINCT a) FROM federated.t2; +COUNT(DISTINCT a) +100 +TRUNCATE TABLE federated.t2; +INSERT INTO federated.t2 +SELECT * FROM (SELECT * FROM federated.t1 LIMIT 70000) dt; +SELECT COUNT(DISTINCT a) FROM federated.t2; +COUNT(DISTINCT a) +70000 set global federated_pushdown=0; connection master; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index d765588b79b..4b5789e1d96 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -208,6 +208,63 @@ DROP TABLE federated.t1, federated.t2; connection default; +--echo # +--echo # MDEV-23778: Derived handler used for big derived tables +--echo # + +connection slave; + +CREATE TABLE federated.t1 ( + a varchar(100) NOT NULL default '123' +) +DEFAULT CHARSET=latin1; + +CREATE TABLE federated.t2 LIKE federated.t1; + +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE i INT DEFAULT 0; + START TRANSACTION; + WHILE i < 70000 DO + INSERT INTO federated.t1 VALUES (i); + SET i = i + 1; + END WHILE; + COMMIT; +END +$$ + +DELIMITER ;$$ + +connection master; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t1 ( + a varchar(100) NOT NULL default '123' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t2 ( + a varchar(100) NOT NULL default '123' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2'; + +SELECT COUNT(DISTINCT a) FROM federated.t1; + +INSERT INTO federated.t2 + SELECT * FROM (SELECT * FROM federated.t1 LIMIT 100) dt; +SELECT COUNT(DISTINCT a) FROM federated.t2; + +TRUNCATE TABLE federated.t2; +INSERT INTO federated.t2 + SELECT * FROM (SELECT * FROM federated.t1 LIMIT 70000) dt; +SELECT COUNT(DISTINCT a) FROM federated.t2; + set global federated_pushdown=0; source include/federated_cleanup.inc; diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc index 76fd736de2b..f48b95cbf76 100644 --- a/sql/derived_handler.cc +++ b/sql/derived_handler.cc @@ -120,8 +120,6 @@ void derived_handler::set_derived(TABLE_LIST *tbl) table= tbl->table; unit= tbl->derived; select= unit->first_select(); - tmp_table_param= select->next_select() ? - ((select_unit *)(unit->result))->get_tmp_table_param() : - &select->join->tmp_table_param; + tmp_table_param= ((select_unit *)(unit->result))->get_tmp_table_param(); }