diff options
author | cmiller@zippy.cornsilk.net <> | 2006-10-03 13:38:25 -0400 |
---|---|---|
committer | cmiller@zippy.cornsilk.net <> | 2006-10-03 13:38:25 -0400 |
commit | 5512100c6aa1cfc49cbfb369c6ddf4079b47238c (patch) | |
tree | d5a05af2d246695f683a48051134ed0526ea254e | |
parent | 46b3997c514fac4b991209d8679b12698bf5103f (diff) | |
download | mariadb-git-5512100c6aa1cfc49cbfb369c6ddf4079b47238c.tar.gz |
Bug #14262: SP: DROP PROCEDURE|VIEW (maybe more) write to binlog too late \
(race cond)
It was possible for one thread to interrupt a Data Definition Language
statement and thereby get messages to the binlog out of order. Consider:
Connection 1: Drop Foo x
Connection 2: Create or replace Foo x
Connection 2: Log "Create or replace Foo x"
Connection 1: Log "Drop Foo x"
Local end would have Foo x, but the replicated slaves would not.
The fix for this is to wrap all DDL and logging of a kind in the same mutex.
Since we already use mutexes for the various parts of altering the server,
this only entails moving the logging events down close to the action, inside
the mutex protection.
-rw-r--r-- | BitKeeper/etc/collapsed | 5 | ||||
-rw-r--r-- | sql/sp.cc | 23 | ||||
-rw-r--r-- | sql/sql_acl.cc | 67 | ||||
-rw-r--r-- | sql/sql_db.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 118 | ||||
-rw-r--r-- | sql/sql_table.cc | 15 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 8 | ||||
-rw-r--r-- | sql/sql_view.cc | 47 | ||||
-rw-r--r-- | sql/sql_view.h | 2 |
9 files changed, 182 insertions, 108 deletions
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed new file mode 100644 index 00000000000..d831276ffd3 --- /dev/null +++ b/BitKeeper/etc/collapsed @@ -0,0 +1,5 @@ +45143312u0Tz4r0wPXCbUKwdHa2jWA +45143b90ewOQuTW8-jrB3ZSAQvMRJw +45184588w9U72A6KX1hUFeAC4shSHA +45185df8mZbxfp85FbA0VxUXkmDewA +451b110a3ZV6MITl93ehXk2wxrbW7g diff --git a/sql/sp.cc b/sql/sp.cc index a7078da2f50..861ba351160 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -660,6 +660,17 @@ db_drop_routine(THD *thd, int type, sp_name *name) if (table->file->delete_row(table->record[0])) ret= SP_DELETE_ROW_FAILED; } + + if (ret == SP_OK) + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + } + close_thread_tables(thd); DBUG_RETURN(ret); } @@ -695,6 +706,17 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if ((table->file->update_row(table->record[1],table->record[0]))) ret= SP_WRITE_ROW_FAILED; } + + if (ret == SP_OK) + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + } + close_thread_tables(thd); DBUG_RETURN(ret); } @@ -773,6 +795,7 @@ print_field_values(THD *thd, TABLE *table, return SP_INTERNAL_ERROR; } } + return SP_OK; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ae5ea210a47..d54d9910820 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3005,9 +3005,22 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, grant_option=TRUE; thd->mem_root= old_root; pthread_mutex_unlock(&acl_cache->lock); + + if (!result) /* success */ + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + } + rw_unlock(&LOCK_grant); - if (!result) + + if (!result) /* success */ send_ok(thd); + /* Tables are automatically closed */ DBUG_RETURN(result); } @@ -3168,9 +3181,21 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, grant_option=TRUE; thd->mem_root= old_root; pthread_mutex_unlock(&acl_cache->lock); + if (!result && !no_error) + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + } + rw_unlock(&LOCK_grant); + if (!result && !no_error) send_ok(thd); + /* Tables are automatically closed */ DBUG_RETURN(result); } @@ -3276,11 +3301,23 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } } VOID(pthread_mutex_unlock(&acl_cache->lock)); + + if (!result) + { + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + } + rw_unlock(&LOCK_grant); close_thread_tables(thd); if (!result) send_ok(thd); + DBUG_RETURN(result); } @@ -5241,6 +5278,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) } VOID(pthread_mutex_unlock(&acl_cache->lock)); + + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + rw_unlock(&LOCK_grant); close_thread_tables(thd); if (result) @@ -5297,6 +5341,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) rebuild_check_host(); VOID(pthread_mutex_unlock(&acl_cache->lock)); + + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + rw_unlock(&LOCK_grant); close_thread_tables(thd); if (result) @@ -5366,6 +5417,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) rebuild_check_host(); VOID(pthread_mutex_unlock(&acl_cache->lock)); + + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + rw_unlock(&LOCK_grant); close_thread_tables(thd); if (result) @@ -5541,6 +5599,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) } VOID(pthread_mutex_unlock(&acl_cache->lock)); + + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + rw_unlock(&LOCK_grant); close_thread_tables(thd); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 902539dfdec..05526704eb1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -542,6 +542,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, qinfo.db = db; qinfo.db_len = strlen(db); + /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -613,6 +614,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db_len = strlen(db); thd->clear_error(); + /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -736,6 +738,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) qinfo.db_len = strlen(db); thd->clear_error(); + /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } thd->server_status|= SERVER_STATUS_DB_DROPPED; @@ -762,6 +765,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) tbl_name_len= strlen(tbl->table_name) + 3; if (query_pos + tbl_name_len + 1 >= query_end) { + /* These DDL methods and logging protected with LOCK_mysql_create_db */ write_to_binlog(thd, query, query_pos -1 - query, db, db_len); query_pos= query_data_start; } @@ -774,6 +778,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos != query_data_start) { + /* These DDL methods and logging protected with LOCK_mysql_create_db */ write_to_binlog(thd, query, query_pos -1 - query, db, db_len); } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 28ed3e25d57..bee537a5a19 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3195,6 +3195,7 @@ end_with_restore_list: /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + /* Presumably, REPAIR and binlog writing doesn't require synchronization */ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -3229,6 +3230,7 @@ end_with_restore_list: /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + /* Presumably, ANALYZE and binlog writing doesn't require synchronization */ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -3254,6 +3256,7 @@ end_with_restore_list: /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */ if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -3542,6 +3545,7 @@ end_with_restore_list: /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; } + /* DDL and binlog write order protected by LOCK_open */ res= mysql_rm_table(thd, first_table, lex->drop_if_exists, lex->drop_temporary); } @@ -3830,15 +3834,9 @@ end_with_restore_list: break; if (end_active_trans(thd)) goto error; + /* Conditionally writes to binlog */ if (!(res= mysql_create_user(thd, lex->users_list))) - { - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); - } break; } case SQLCOM_DROP_USER: @@ -3848,15 +3846,9 @@ end_with_restore_list: break; if (end_active_trans(thd)) goto error; + /* Conditionally writes to binlog */ if (!(res= mysql_drop_user(thd, lex->users_list))) - { - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); - } break; } case SQLCOM_RENAME_USER: @@ -3866,15 +3858,9 @@ end_with_restore_list: break; if (end_active_trans(thd)) goto error; + /* Conditionally writes to binlog */ if (!(res= mysql_rename_user(thd, lex->users_list))) - { - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); - } break; } case SQLCOM_REVOKE_ALL: @@ -3882,15 +3868,9 @@ end_with_restore_list: if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; + /* Conditionally writes to binlog */ if (!(res = mysql_revoke_all(thd, lex->users_list))) - { - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); - } break; } case SQLCOM_REVOKE: @@ -3949,6 +3929,7 @@ end_with_restore_list: check_grant_routine(thd, grants | GRANT_ACL, all_tables, lex->type == TYPE_ENUM_PROCEDURE, 0)) goto error; + /* Conditionally writes to binlog */ res= mysql_routine_grant(thd, all_tables, lex->type == TYPE_ENUM_PROCEDURE, lex->users_list, grants, @@ -3961,16 +3942,11 @@ end_with_restore_list: GRANT_ACL), all_tables, 0, UINT_MAX, 0)) goto error; + /* Conditionally writes to binlog */ res= mysql_table_grant(thd, all_tables, lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE); } - if (!res && mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } } else { @@ -3981,16 +3957,11 @@ end_with_restore_list: goto error; } else + /* Conditionally writes to binlog */ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, lex->sql_command == SQLCOM_REVOKE); if (!res) { - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } if (lex->sql_command == SQLCOM_GRANT) { List_iterator <LEX_USER> str_list(lex->users_list); @@ -4028,6 +3999,7 @@ end_with_restore_list: We WANT to write and we CAN write. ! we write after unlocking the table. */ + /* Presumably, RESET and binlog writing doesn't require synchronization */ if (!lex->no_write_to_binlog && write_to_binlog) { if (mysql_bin_log.is_open()) @@ -4564,20 +4536,16 @@ end_with_restore_list: already puts on CREATE FUNCTION. */ if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) + /* Conditionally writes to binlog */ result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); else + /* Conditionally writes to binlog */ result= sp_update_function(thd, lex->spname, &lex->sp_chistics); } } switch (result) { case SP_OK: - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); break; case SP_KEY_NOT_FOUND: @@ -4622,9 +4590,11 @@ end_with_restore_list: } #endif if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - result= sp_drop_procedure(thd, lex->spname); + /* Conditionally writes to binlog */ + result= sp_drop_procedure(thd, lex->spname); /* Conditionally writes to binlog */ else - result= sp_drop_function(thd, lex->spname); + /* Conditionally writes to binlog */ + result= sp_drop_function(thd, lex->spname); /* Conditionally writes to binlog */ } else { @@ -4637,6 +4607,8 @@ end_with_restore_list: { if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) goto error; + + /* Does NOT write to binlog */ if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) { send_ok(thd); @@ -4657,12 +4629,6 @@ end_with_restore_list: switch (result) { case SP_OK: - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } send_ok(thd); break; case SP_KEY_NOT_FOUND: @@ -4758,37 +4724,8 @@ end_with_restore_list: { if (end_active_trans(thd)) goto error; - - if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) && - mysql_bin_log.is_open()) - { - String buff; - const LEX_STRING command[3]= - {{(char *)STRING_WITH_LEN("CREATE ")}, - {(char *)STRING_WITH_LEN("ALTER ")}, - {(char *)STRING_WITH_LEN("CREATE OR REPLACE ")}}; - thd->clear_error(); - - buff.append(command[thd->lex->create_view_mode].str, - command[thd->lex->create_view_mode].length); - view_store_options(thd, first_table, &buff); - buff.append(STRING_WITH_LEN("VIEW ")); - /* Test if user supplied a db (ie: we did not use thd->db) */ - if (first_table->db && first_table->db[0] && - (thd->db == NULL || strcmp(first_table->db, thd->db))) - { - append_identifier(thd, &buff, first_table->db, - first_table->db_length); - buff.append('.'); - } - append_identifier(thd, &buff, first_table->table_name, - first_table->table_name_length); - buff.append(STRING_WITH_LEN(" AS ")); - buff.append(first_table->source.str, first_table->source.length); - - Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); - mysql_bin_log.write(&qinfo); - } + /* Conditionally writes to binlog. */ + res= mysql_create_view(thd, first_table, thd->lex->create_view_mode); break; } case SQLCOM_DROP_VIEW: @@ -4796,13 +4733,8 @@ end_with_restore_list: if (check_table_access(thd, DROP_ACL, all_tables, 0) || end_active_trans(thd)) goto error; - if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) && - mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } + /* Conditionally writes to binlog. */ + res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); break; } case SQLCOM_CREATE_TRIGGER: @@ -4810,6 +4742,7 @@ end_with_restore_list: if (end_active_trans(thd)) goto error; + /* Conditionally writes to binlog. */ res= mysql_create_or_drop_trigger(thd, all_tables, 1); /* We don't care about trigger body after this point */ @@ -4822,6 +4755,7 @@ end_with_restore_list: if (end_active_trans(thd)) goto error; + /* Conditionally writes to binlog. */ res= mysql_create_or_drop_trigger(thd, all_tables, 0); break; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4772d64ad0a..403c5c8833e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3168,6 +3168,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ if (alter_info->tablespace_op != NO_TABLESPACE_OP) + /* Conditionally writes to binlog. */ DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list, alter_info->tablespace_op)); if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) @@ -3249,10 +3250,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, !table->s->tmp_table) // no need to touch frm { error=0; + VOID(pthread_mutex_lock(&LOCK_open)); if (new_name != table_name || new_db != db) { thd->proc_info="rename"; - VOID(pthread_mutex_lock(&LOCK_open)); /* Then do a 'simple' rename of the table */ error=0; if (!access(new_name_buff,F_OK)) @@ -3274,7 +3275,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error= -1; } } - VOID(pthread_mutex_unlock(&LOCK_open)); } if (!error) @@ -3283,16 +3283,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, case LEAVE_AS_IS: break; case ENABLE: - VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: - VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; @@ -3322,6 +3318,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, table->file->print_error(error, MYF(0)); error= -1; } + VOID(pthread_mutex_unlock(&LOCK_open)); table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); @@ -3768,6 +3765,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, my_free((gptr) new_table,MYF(0)); goto err; } + /* + Writing to the binlog does not need to be synchronized for temporary tables, + which are thread-specific. + */ if (mysql_bin_log.is_open()) { thd->clear_error(); @@ -3950,7 +3951,7 @@ end_temporary: thd->some_tables_deleted=0; DBUG_RETURN(FALSE); - err: +err: DBUG_RETURN(TRUE); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 66a16f16d8c..6ff8a0620f4 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -268,8 +268,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) table->triggers->drop_trigger(thd, tables)); end: - VOID(pthread_mutex_unlock(&LOCK_open)); - start_waiting_global_read_lock(thd); if (!result) { @@ -302,9 +300,13 @@ end: Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), 0, FALSE); mysql_bin_log.write(&qinfo); } + } + + VOID(pthread_mutex_unlock(&LOCK_open)); + start_waiting_global_read_lock(thd); + if (!result) send_ok(thd); - } DBUG_RETURN(result); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1561ade78af..a755a536b64 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -162,6 +162,7 @@ err: SYNOPSIS mysql_create_view() thd - thread handler + views - views to create mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE RETURN VALUE @@ -169,7 +170,7 @@ err: TRUE Error */ -bool mysql_create_view(THD *thd, +bool mysql_create_view(THD *thd, TABLE_LIST *views, enum_view_create_mode mode) { LEX *lex= thd->lex; @@ -490,6 +491,37 @@ bool mysql_create_view(THD *thd, } VOID(pthread_mutex_lock(&LOCK_open)); res= mysql_register_view(thd, view, mode); + + if (mysql_bin_log.is_open()) + { + String buff; + const LEX_STRING command[3]= + {{(char *)STRING_WITH_LEN("CREATE ")}, + {(char *)STRING_WITH_LEN("ALTER ")}, + {(char *)STRING_WITH_LEN("CREATE OR REPLACE ")}}; + + buff.append(command[thd->lex->create_view_mode].str, + command[thd->lex->create_view_mode].length); + view_store_options(thd, views, &buff); + buff.append(STRING_WITH_LEN("VIEW ")); + + /* Test if user supplied a db (ie: we did not use thd->db) */ + if (views->db && views->db[0] && + (thd->db == NULL || strcmp(views->db, thd->db))) + { + append_identifier(thd, &buff, views->db, + views->db_length); + buff.append('.'); + } + append_identifier(thd, &buff, views->table_name, + views->table_name_length); + buff.append(STRING_WITH_LEN(" AS ")); + buff.append(views->source.str, views->source.length); + + Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); + mysql_bin_log.write(&qinfo); + } + VOID(pthread_mutex_unlock(&LOCK_open)); if (view->revision != 1) query_cache_invalidate3(thd, view, 0); @@ -1229,12 +1261,12 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) bool type= 0; db_type not_used; + VOID(pthread_mutex_lock(&LOCK_open)); for (view= views; view; view= view->next_local) { strxnmov(path, FN_REFLEN, mysql_data_home, "/", view->db, "/", view->table_name, reg_ext, NullS); (void) unpack_filename(path, path); - VOID(pthread_mutex_lock(&LOCK_open)); if (access(path, F_OK) || (type= (mysql_frm_type(thd, path, ¬_used) != FRMTYPE_VIEW))) { @@ -1245,7 +1277,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), name); - VOID(pthread_mutex_unlock(&LOCK_open)); continue; } if (type) @@ -1258,8 +1289,16 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) goto err; query_cache_invalidate3(thd, view, 0); sp_cache_invalidate(); - VOID(pthread_mutex_unlock(&LOCK_open)); } + + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + + VOID(pthread_mutex_unlock(&LOCK_open)); send_ok(thd); DBUG_RETURN(FALSE); diff --git a/sql/sql_view.h b/sql/sql_view.h index cd61d7e9e71..9b6856b8c8a 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -bool mysql_create_view(THD *thd, +bool mysql_create_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode); bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table); |