diff options
author | Alexander Nozdrin <alik@sun.com> | 2010-02-02 16:38:44 +0300 |
---|---|---|
committer | Alexander Nozdrin <alik@sun.com> | 2010-02-02 16:38:44 +0300 |
commit | 59f1be1b636e360c410c81de1c41a8c4a254077d (patch) | |
tree | f9c8abdf7dad923c0137a358559ba46ba23e2c61 /sql | |
parent | 2db684572ea716de462bf8d79f398dfcc130a8ff (diff) | |
download | mariadb-git-59f1be1b636e360c410c81de1c41a8c4a254077d.tar.gz |
Revert a patch for Bug#48231, which introduced valgrind warnings.
Original revision:
------------------------------------------------------------
revision-id: li-bing.song@sun.com-20100130124925-o6sfex42b6noyc6x
parent: joro@sun.com-20100129145427-0n79l9hnk0q43ajk
committer: <Li-Bing.Song@sun.com>
branch nick: mysql-5.1-bugteam
timestamp: Sat 2010-01-30 20:49:25 +0800
message:
Bug #48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER;
REVOKE/GRANT; ALTER EVENT.
The following statements support the CURRENT_USER() where a user is needed.
DROP USER
RENAME USER CURRENT_USER() ...
GRANT ... TO CURRENT_USER()
REVOKE ... FROM CURRENT_USER()
ALTER DEFINER = CURRENT_USER() EVENT
but, When these statements are binlogged, CURRENT_USER() just is binlogged
as 'CURRENT_USER()', it is not expanded to the real user name. When slave
executes the log event, 'CURRENT_USER()' is expand to the user of slave
SQL thread, but SQL thread's user name always NULL. This breaks the replication.
After this patch, All above statements are rewritten when they are binlogged.
The CURRENT_USER() is expanded to the real user's name and host.
------------------------------------------------------------
Diffstat (limited to 'sql')
-rw-r--r-- | sql/events.cc | 79 | ||||
-rw-r--r-- | sql/sql_acl.cc | 124 | ||||
-rw-r--r-- | sql/sql_lex.h | 25 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 36 |
4 files changed, 59 insertions, 205 deletions
diff --git a/sql/events.cc b/sql/events.cc index 6c8bdb1ea0f..4c6dd0f35d1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -341,48 +341,31 @@ common_1_lev_code: } -/* - Binlog '{CREATE|ALTER} EVENT' statements. - Definer part is always rewritten, for definer can be CURRENT_USER() function. - +/** + Create a new query string for removing executable comments + for avoiding leak and keeping consistency of the execution + on master and slave. + @param[in] thd Thread handler - @param[in] create CREATE or ALTER statement + @param[in] buf Query string @return - FASE ok - TRUE error + 0 ok + 1 error */ -static bool event_write_bin_log(THD *thd, bool create) +static int +create_query_string(THD *thd, String *buf) { - String log_query; - if (create) - { - /* Append the "CREATE" part of the query */ - if (log_query.append(STRING_WITH_LEN("CREATE "))) - return TRUE; - } - else - { - /* Append the "ALETR " part of the query */ - if (log_query.append(STRING_WITH_LEN("ALTER "))) - return TRUE; - } - - /* Append definer - If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER - will be written into the binary log as the definer for the SQL thread. - */ - append_definer(thd, &log_query, &(thd->lex->definer->user), - &(thd->lex->definer->host)); - + /* Append the "CREATE" part of the query */ + if (buf->append(STRING_WITH_LEN("CREATE "))) + return 1; + /* Append definer */ + append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); /* Append the left part of thd->query after "DEFINER" part */ - if (log_query.append(thd->lex->stmt_definition_begin, - thd->lex->stmt_definition_end - - thd->lex->stmt_definition_begin)) - return TRUE; - - return write_bin_log(thd, TRUE, log_query.c_ptr_safe(), log_query.length()) - != 0; + if (buf->append(thd->lex->stmt_definition_begin)) + return 1; + + return 0; } /** @@ -397,7 +380,8 @@ static bool event_write_bin_log(THD *thd, bool create) @sa Events::drop_event for the notes about locking, pre-locking and Events DDL. - @retval FALSE OK @retval TRUE Error (reported) + @retval FALSE OK + @retval TRUE Error (reported) */ bool @@ -481,7 +465,22 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, binlog the create event unless it's been successfully dropped */ if (!dropped) - ret= event_write_bin_log(thd, TRUE); + { + /* Binlog the create event. */ + DBUG_ASSERT(thd->query() && thd->query_length()); + String log_query; + if (create_query_string(thd, &log_query)) + { + sql_print_error("Event Error: An error occurred while creating query string, " + "before writing it into binary log."); + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_RETURN(TRUE); + } + /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. */ + ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); + } } pthread_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ @@ -603,7 +602,9 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (event_queue) event_queue->update_event(thd, parse_data->dbname, parse_data->name, new_element); - ret= event_write_bin_log(thd, FALSE); + /* Binlog the alter event. */ + DBUG_ASSERT(thd->query() && thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } pthread_mutex_unlock(&LOCK_event_metadata); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 70983f69746..a8828d15cae 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -194,7 +194,6 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); -static bool acl_write_bin_log(THD *thd, List <LEX_USER> &list, bool clear_error); /* Convert scrambled password to binary form, according to scramble type, @@ -3226,8 +3225,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - if (acl_write_bin_log(thd, user_list, TRUE)) - result= -1; + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3403,7 +3401,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - result|= acl_write_bin_log(thd, user_list, FALSE); + if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + result= TRUE; } rw_unlock(&LOCK_grant); @@ -3532,7 +3531,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, if (!result) { - result= acl_write_bin_log(thd, list, TRUE); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -5664,9 +5663,9 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } -static void append_user(String *str, LEX_USER *user, bool comma= TRUE) +static void append_user(String *str, LEX_USER *user) { - if (comma && str->length()) + if (str->length()) str->append(','); str->append('\''); str->append(user->user.str); @@ -5675,65 +5674,6 @@ static void append_user(String *str, LEX_USER *user, bool comma= TRUE) str->append('\''); } -/* - The operations(DROP, RENAME, REVOKE, GRANT) will cause inconsistency between - master and slave, when CURRENT_USER() is used. To solve this problem, we - construct a new binlog statement in which CURRENT_USER() is replaced by - the real user name and host name. - */ -static bool acl_write_bin_log(THD *thd, List <LEX_USER> &list, bool clear_error) -{ - String log_query; - LEX *lex= thd->lex; - List_iterator <LEX_USER> user_list(list); - LEX_USER *user, *tmp_user; - - if (!mysql_bin_log.is_open()) - return FALSE; - - if (log_query.append(lex->stmt_begin, lex->stmt_user_begin - lex->stmt_begin)) - return TRUE; - while ((tmp_user= user_list++)) - { - if (!(user= get_current_user(thd, tmp_user))) - continue; - - /* - No User, but a password? - They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... ! - Get the current user, and shallow-copy the new password to them! - */ - if (!tmp_user->user.str && tmp_user->password.str) - user->password= tmp_user->password; - - if (log_query.append(" ", 1)) - return TRUE; - append_user(&log_query, user, FALSE); - /* Only 'GRANT' have password */ - if (user->password.str) - { - if (log_query.append(STRING_WITH_LEN(" IDENTIFIED BY ")) || - log_query.append(STRING_WITH_LEN("PASSWORD ")) || - log_query.append("'", 1) || - log_query.append(user->password.str, - user->password.length) || - log_query.append("'", 1)) - return TRUE; - } - if (log_query.append(",", 1)) - return TRUE; - } - /* It is binlogged only when at least one user is in the query */ - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - if (log_query.append(lex->stmt_user_end, lex->stmt_end - lex->stmt_user_end)) - return TRUE; - return write_bin_log(thd, clear_error, log_query.c_ptr_safe(), - log_query.length()) != 0; - } - return FALSE; -} /* Create a list of users. @@ -5840,7 +5780,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) { int result; String wrong_users; - String log_query; LEX_USER *user_name, *tmp_user_name; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; @@ -5870,7 +5809,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - log_query.append(STRING_WITH_LEN("DROP USER")); while ((tmp_user_name= user_list++)) { if (!(user_name= get_current_user(thd, tmp_user_name))) @@ -5878,17 +5816,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) result= TRUE; continue; } - - /* - The operation will cause inconsistency between master and slave, when - CURRENT_USER() is used. To solve this problem, we construct a new - binlog statement in which CURRENT_USER() is replaced by the real user - name and host name. - */ - log_query.append(STRING_WITH_LEN(" ")); - append_user(&log_query, user_name, FALSE); - log_query.append(STRING_WITH_LEN(",")); - if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5907,13 +5834,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - { - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); - } - } + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5941,7 +5862,6 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) { int result; String wrong_users; - String log_query; LEX_USER *user_from, *tmp_user_from; LEX_USER *user_to, *tmp_user_to; List_iterator <LEX_USER> user_list(list); @@ -5969,7 +5889,6 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - log_query.append(STRING_WITH_LEN("RENAME USER")); while ((tmp_user_from= user_list++)) { if (!(user_from= get_current_user(thd, tmp_user_from))) @@ -5986,18 +5905,6 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ /* - The operation will cause inconsistency between master and slave, when - CURRENT_USER() is used. To solve this problem, we construct a new - binlog statement in which CURRENT_USER() is replaced by the real user - name and host name. - */ - log_query.append(STRING_WITH_LEN(" ")); - append_user(&log_query, user_from, FALSE); - log_query.append(STRING_WITH_LEN(" TO ")); - append_user(&log_query, user_to, FALSE); - log_query.append(STRING_WITH_LEN(",")); - - /* Search all in-memory structures and grant tables for a mention of the new user name. */ @@ -6018,15 +5925,9 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) if (result) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); - - if (some_users_renamed) - { - if (log_query.c_ptr()[log_query.length()-1] == ',') - { - log_query.length(log_query.length()-1); - result|= write_bin_log(thd, FALSE, log_query.c_ptr_safe(), log_query.length()); - } - } + + if (some_users_renamed && mysql_bin_log.is_open()) + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6216,9 +6117,8 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - int binlog_error= 0; - if (acl_write_bin_log(thd, list, FALSE)) - binlog_error= 1; + int binlog_error= + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 99f5257eb5e..4e4794ef2cf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1727,8 +1727,6 @@ typedef struct st_lex : public Query_tables_list - CREATE TRIGGER (points to "TRIGGER"); - CREATE PROCEDURE (points to "PROCEDURE"); - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE"); - - CREATE VIEW(points to "VIEW"); - - CREATE EVENT(points to "EVENT"); This pointer is required to add possibly omitted DEFINER-clause to the DDL-statement before dumping it to the binlog. @@ -1737,29 +1735,6 @@ typedef struct st_lex : public Query_tables_list const char *stmt_definition_end; - /* - stmt_begin is intended to point to the begin of every statement. - It is now used in the following statements: - - GRANT ALL PRIVELEGES ON *.* (points to "GRANT"); - - REVOKE ALL PRIVELEGES ON *.* (points to "REVOKE"); - */ - const char *stmt_begin; - const char *stmt_end; - - /* - stmt_user_begin is intended to point to the begin of the user list in - the following statements: - - GRANT ALL PRIVELEGES ON *.* TO 'username'@'hostname' - (points to "'username'"); - - REVOKE ALL PRIVELEGES ON *.* FROM 'username'@'hostname' - (points to "'username'"); - - these pointers are required to replace the CURRENT_USER() - function by the real user before dumping it to the binlog. - */ - const char *stmt_user_begin; - const char *stmt_user_end; - /** During name resolution search only in the table list given by Name_resolution_context::first_name_resolution_table and diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 92c4de5b462..8dc08f8425f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1562,11 +1562,7 @@ opt_end_of_input: ; verb_clause: - remember_name statement remember_end - { - Lex->stmt_begin= $1; - Lex->stmt_end= $3; - } + statement | begin ; @@ -5747,7 +5743,7 @@ alter: } view_tail {} - | ALTER definer_opt remember_name EVENT_SYM sp_name + | ALTER definer_opt EVENT_SYM sp_name { /* It is safe to use Lex->spname because @@ -5759,8 +5755,7 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) MYSQL_YYABORT; - Lex->event_parse_data->identifier= $5; - Lex->stmt_definition_begin= $3; + Lex->event_parse_data->identifier= $4; Lex->sql_command= SQLCOM_ALTER_EVENT; } @@ -5770,7 +5765,7 @@ alter: opt_ev_comment opt_ev_sql_stmt { - if (!($7 || $8 || $9 || $10 || $11)) + if (!($6 || $7 || $8 || $9 || $10)) { my_parse_error(ER(ER_SYNTAX_ERROR)); MYSQL_YYABORT; @@ -5831,16 +5826,7 @@ opt_ev_rename_to: ; opt_ev_sql_stmt: - /* empty*/ - { - $$= 0; - /* - Lex->sp_head is not initialized when event body is empty. - So we can not use Lex->sp_head->set_stmt_end() to set - stmt_definition_end. - */ - Lex->stmt_definition_end= (char*) YYLIP->get_cpp_tok_end(); - } + /* empty*/ { $$= 0;} | DO_SYM ev_sql_stmt { $$= 1; } ; @@ -11530,7 +11516,6 @@ user: $$->user = $1; $$->host.str= (char *) "%"; $$->host.length= 1; - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11543,7 +11528,6 @@ user: if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (check_string_char_length(&$$->user, ER(ER_USERNAME), USERNAME_CHAR_LENGTH, @@ -11553,7 +11537,6 @@ user: } | CURRENT_USER optional_braces { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; /* @@ -12744,10 +12727,9 @@ user_list: ; grant_list: - { Lex->stmt_user_begin= YYLIP->get_cpp_ptr(); } grant_user { - if (Lex->users_list.push_back($2)) + if (Lex->users_list.push_back($1)) MYSQL_YYABORT; } | grant_list ',' grant_user @@ -12760,7 +12742,6 @@ grant_list: grant_user: user IDENTIFIED_SYM BY TEXT_STRING { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); $$=$1; $1->password=$4; if ($4.length) { @@ -12787,10 +12768,7 @@ grant_user: } } | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING - { - Lex->stmt_user_end= YYLIP->get_cpp_ptr(); - $$= $1; $1->password= $5; - } + { $$= $1; $1->password= $5; } | user { $$= $1; $1->password= null_lex_str; } ; |