From f3e2b3df18918550ee49021d0e16ea8cb5272085 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 5 Oct 2010 14:57:51 +0200 Subject: Bug#55091: Server crashes on ADD PARTITION after a failed attempt In case of failure in ALTER ... PARTITION under LOCK TABLE the server could crash, due to it had modified the locked table object, which was not reverted in case of failure, resulting in a bad table definition used after the failed command. Solved by always closing the LOCKED TABLE, even in case of error. Note: this is a 5.1-only fix, bug#56172 fixed it in 5.5+ --- sql/sql_partition.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 76caa2b0c8d..7b0c47865d8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5934,6 +5934,12 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) int err; if (lpt->thd->locked_tables) { + /* + Close the table if open, to remove/destroy the already altered + table->part_info object, so that it is not reused. + */ + if (lpt->table->db_stat) + abort_and_upgrade_lock_and_close_table(lpt); /* When we have the table locked, it is necessary to reopen the table since all table objects were closed and removed as part of the @@ -6436,7 +6442,20 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, table, table_list, FALSE, NULL, written_bin_log)); err: - close_thread_tables(thd); + if (thd->locked_tables) + { + /* + table->part_info was altered in prep_alter_part_table and must be + destroyed and recreated, since otherwise it will be reused, since + we are under LOCK TABLE. + */ + alter_partition_lock_handling(lpt); + } + else + { + /* Force the table to be closed to avoid reuse of the table->part_info */ + close_thread_tables(thd); + } DBUG_RETURN(TRUE); } #endif -- cgit v1.2.1 From 97e295cc2242a27550a6dafe86b184d4c559fa3b Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Fri, 29 Oct 2010 16:10:53 +0200 Subject: Bug #57659 Segfault in Query_cache::invalidate_data for TRUNCATE TABLE This crash could happen if TRUNCATE TABLE indirectly failed to open a merge table due to failures to open underlying tables. Even if opening failed, the TRUNCATE TABLE code would try to invalidate the table in the query cache. Since this table had been closed and memory released, this could lead to a crash. This bug was introduced by a combination of the changes introduced by the patch for Bug#52044, where failing to open a table will cause opened tables to be closed. And the changes in patch for Bug#49938, where TRUNCATE TABLE uses the standard open tables function. This patch fixes the problem by setting the TABLE pointer to NULL before invalidating the query cache. Test case added to truncate_coverage.test. --- sql/sql_truncate.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 0cff2875ac8..909c6a08b67 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -472,6 +472,13 @@ bool Truncate_statement::truncate_table(THD *thd, TABLE_LIST *table_ref) binlog_stmt= !error || error != HA_ERR_WRONG_COMMAND; } + /* + If we tried to open a MERGE table and failed due to problems with the + children tables, the table will have been closed and table_ref->table + will be invalid. Reset the pointer here in any case as + query_cache_invalidate does not need a valid TABLE object. + */ + table_ref->table= NULL; query_cache_invalidate3(thd, table_ref, FALSE); } -- cgit v1.2.1 From 0fb0d9a9a2484d1ccdf2e2340ac7a36ee3bb070c Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Wed, 3 Nov 2010 16:47:32 +0100 Subject: Bug #57130 crash in Item_field::print during SHOW CREATE TABLE or VIEW This crash could happen if SHOW CREATE VIEW indirectly failed to open a view due to failures to open underlying tables (or functions). Several such errors were hidden and converted to ER_VIEW_INVALID warnings to prevent exposing details of underlying tables for which the user have no privileges. However, with the changes introduced by the patch for Bug#52044, failing to open a view will cause opened tables, views and functions to be closed. Since the errors causing these failures were converted to warnings, SHOW CREATE VIEW would try to continue. This made it possible to try to access memory that had been freed, causing a crash. This patch fixes the problem by not closing opened tables, views and functions in these cases. This allows SHOW CREATE VIEW to continue and also prevents it from accessing freed memory. Test case added to lock_sync.test. --- sql/sql_show.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index be3dd8a0ca2..fa9c0e85c27 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -29,6 +29,8 @@ #include "repl_failsafe.h" #include "sql_parse.h" // check_access, check_table_access #include "sql_partition.h" // partition_element +#include "sql_derived.h" // mysql_derived_prepare, + // mysql_handle_derived, #include "sql_db.h" // check_db_dir_existence, load_db_opt_by_name #include "sql_time.h" // interval_type_to_name #include "tztime.h" // struct Time_zone @@ -683,11 +685,18 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->lex->view_prepare_mode= TRUE; { + /* + Use open_tables() directly rather than open_normal_and_derived_tables(). + This ensures that close_thread_tables() is not called if open tables fails + and the error is ignored. This allows us to handle broken views nicely. + */ + uint counter; Show_create_error_handler view_error_suppressor(thd, table_list); thd->push_internal_handler(&view_error_suppressor); bool open_error= - open_normal_and_derived_tables(thd, table_list, - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL); + open_tables(thd, &table_list, &counter, + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) || + mysql_handle_derived(thd->lex, &mysql_derived_prepare); thd->pop_internal_handler(); if (open_error && (thd->killed || thd->is_error())) goto exit; -- cgit v1.2.1 From ccbf81d5ff87c10e423abbcab385552c7dca7403 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Thu, 4 Nov 2010 16:18:27 +0300 Subject: Bug#57278: Crash on min/max + with date out of range. MySQL officially supports DATE values starting from 1000-01-01. This is enforced for int values, but not for string values, thus one could easily insert '0001-01-01' value. Int values are checked by number_to_datetime function and Item_cache_datetime::val_str uses it to fill MYSQL_TIME struct out of cached int value. This leads to the scenario where Item_cache_datetime caches a non-null datetime value and when it tries to convert it from int to string number_to_datetime function treats the value as out-of-range and returns an error and Item_cache_datetime::val_str returns NULL for a non-null value. Due to this inconsistency server crashes. Now number_to_datetime allows DATE values below 1000-01-01 if the TIME_FUZZY_DATE flag is set. Better NULL handling for Item_cache_datetime. Added the Item_cache_datetime::store function to reset str_value_cached flag when an item is stored. --- sql/item.cc | 19 ++++++++++++++++--- sql/item.h | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index b166f3e645f..7efbdf162a7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7493,9 +7493,19 @@ void Item_cache_datetime::store(Item *item, longlong val_arg) } +void Item_cache_datetime::store(Item *item) +{ + Item_cache::store(item); + str_value_cached= FALSE; +} + String *Item_cache_datetime::val_str(String *str) { DBUG_ASSERT(fixed == 1); + + if ((value_cached || str_value_cached) && null_value) + return NULL; + if (!str_value_cached) { /* @@ -7509,6 +7519,8 @@ String *Item_cache_datetime::val_str(String *str) if (value_cached) { MYSQL_TIME ltime; + /* Return NULL in case of OOM/conversion error. */ + null_value= TRUE; if (str_value.alloc(MAX_DATE_STRING_REP_LENGTH)) return NULL; if (cached_field_type == MYSQL_TYPE_TIME) @@ -7531,13 +7543,14 @@ String *Item_cache_datetime::val_str(String *str) { int was_cut; longlong res; - res= number_to_datetime(val_int(), <ime, TIME_FUZZY_DATE, &was_cut); + res= number_to_datetime(int_value, <ime, TIME_FUZZY_DATE, &was_cut); if (res == -1) return NULL; } str_value.length(my_TIME_to_str(<ime, const_cast(str_value.ptr()))); str_value_cached= TRUE; + null_value= FALSE; } else if (!cache_value()) return NULL; @@ -7558,7 +7571,7 @@ my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val) double Item_cache_datetime::val_real() { DBUG_ASSERT(fixed == 1); - if (!value_cached && !cache_value_int()) + if ((!value_cached && !cache_value_int()) || null_value) return 0.0; return (double) int_value; } @@ -7566,7 +7579,7 @@ double Item_cache_datetime::val_real() longlong Item_cache_datetime::val_int() { DBUG_ASSERT(fixed == 1); - if (!value_cached && !cache_value_int()) + if ((!value_cached && !cache_value_int()) || null_value) return 0; return int_value; } diff --git a/sql/item.h b/sql/item.h index 8e8199ecac8..b46f78853b7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3451,8 +3451,8 @@ public: cmp_context= STRING_RESULT; } - virtual void store(Item *item) { Item_cache::store(item); } void store(Item *item, longlong val_arg); + void store(Item *item); double val_real(); longlong val_int(); String* val_str(String *str); -- cgit v1.2.1 From 0c4e115c952c8c6a429c81d844b5767cd80ad479 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 11 Nov 2010 11:08:53 +0300 Subject: Bug#57687 crash when reporting duplicate group_key error and utf8 Fixing DoS regression problem. Using "key_part->fieldnr - 1" to access the desired field is only correct in real INSERT queries. In case of inserting records into a temporary table when performing GROUP BY queries this expression does not work. Fix: Instead of accessing field_length and comparing it to key_part->length, there is an easier way to check if we're dealing with a prefix key: check key_part_flag against HA_PART_KEY_SEG flag. --- sql/key.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/key.cc b/sql/key.cc index e28e0803986..288afd034a9 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -364,9 +364,7 @@ void key_unpack(String *to,TABLE *table,uint idx) while (tmp_end > tmp.ptr() && !*--tmp_end) ; tmp.length(tmp_end - tmp.ptr() + 1); } - if (cs->mbmaxlen > 1 && - table->field[key_part->fieldnr - 1]->field_length != - key_part->length) + if (cs->mbmaxlen > 1 && (key_part->key_part_flag & HA_PART_KEY_SEG)) { /* Prefix key, multi-byte charset. -- cgit v1.2.1 From 771137b50e9ae9a5fcbb8d2665f985d394434036 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 11 Nov 2010 13:25:23 +0300 Subject: Bug#57257 Replace(ExtractValue(...)) causes MySQL crash Bug#57820 extractvalue crashes Problem: ExtractValue and Replace crashed in some cases due to invalid handling of empty and NULL arguments. Per file comments: @mysql-test/r/ctype_ujis.result @mysql-test/r/xml.result @mysql-test/t/ctype_ujis.test @mysql-test/t/xml.test Adding tests @sql/item_strfunc.cc Make sure Item_func_replace::val_str safely handles empty strings. @sql/item_xmlfunc.cc set null_value if nodeset_func returned NULL, which is possible when the second argument is an unset user variable. --- sql/item_strfunc.cc | 8 +++++++- sql/item_xmlfunc.cc | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8fda281bd9e..fd5c47d25cb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -904,9 +904,15 @@ String *Item_func_replace::val_str(String *str) search=res2->ptr(); search_end=search+from_length; redo: + DBUG_ASSERT(res->ptr() || !offset); ptr=res->ptr()+offset; strend=res->ptr()+res->length(); - end=strend-from_length+1; + /* + In some cases val_str() can return empty string + with ptr() == NULL and length() == 0. + Let's check strend to avoid overflow. + */ + end= strend ? strend - from_length + 1 : NULL; while (ptr < end) { if (*ptr == *search) diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 3e20b90e68e..364311877e0 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -2790,12 +2790,12 @@ String *Item_func_xml_extractvalue::val_str(String *str) null_value= 0; if (!nodeset_func || !(res= args[0]->val_str(str)) || - !parse_xml(res, &pxml)) + !parse_xml(res, &pxml) || + !(res= nodeset_func->val_str(&tmp_value))) { null_value= 1; return 0; } - res= nodeset_func->val_str(&tmp_value); return res; } -- cgit v1.2.1 From 0e1c167e168a69bedf20b048ae1adf37a7d2dbb1 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 12 Nov 2010 13:12:15 +0300 Subject: Bug#58005 utf8 + get_format causes failed assertion: !str || str != Ptr' Problem: When GET_FORMAT() is called two times from the upper level function (e.g. LEAST in the bug report), on the second call "res= args[0]->val_str(...)" and str point to the same String object. 1. Fix: changing the order from - get val_str into tmp_value then convert to str to - get val_str into str then convert to tmp_value The new order is more correct: the purpose of "str" parameter is exactly to call val_str() for arguments. The purpose of String class members (like tmp_value) is to do further actions on the result. Doing it in the other way around give unexpected surprises. 2. Using str_value instead of str to do padding, for the same reason. --- sql/item_timefunc.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 103bd96efd4..6335199b8de 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2456,14 +2456,14 @@ String *Item_char_typecast::val_str(String *str) { // Convert character set if differ uint dummy_errors; - if (!(res= args[0]->val_str(&tmp_value)) || - str->copy(res->ptr(), res->length(), from_cs, - cast_cs, &dummy_errors)) + if (!(res= args[0]->val_str(str)) || + tmp_value.copy(res->ptr(), res->length(), from_cs, + cast_cs, &dummy_errors)) { null_value= 1; return 0; } - res= str; + res= &tmp_value; } res->set_charset(cast_cs); @@ -2497,9 +2497,9 @@ String *Item_char_typecast::val_str(String *str) { if (res->alloced_length() < (uint) cast_length) { - str->alloc(cast_length); - str->copy(*res); - res= str; + str_value.alloc(cast_length); + str_value.copy(*res); + res= &str_value; } bzero((char*) res->ptr() + res->length(), (uint) cast_length - res->length()); -- cgit v1.2.1 From 594a599247489df21747526c523f436c41511dfe Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 18 Nov 2010 11:53:08 +0300 Subject: Bug#58022 ... like ... escape export_set ( ... ) crashes when export_set returns warnings ESCAPE argument might be empty string. It leads to server crash under some circumstances. The fix: -added check if ESCAPE argument result is not empty string --- sql/item_cmpfunc.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6987dd9e053..5302406e270 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4692,6 +4692,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) String *escape_str= escape_item->val_str(&cmp.value1); if (escape_str) { + const char *escape_str_ptr= escape_str->ptr(); if (escape_used_in_parsing && ( (((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) && escape_str->numchars() != 1) || @@ -4706,9 +4707,9 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) CHARSET_INFO *cs= escape_str->charset(); my_wc_t wc; int rc= cs->cset->mb_wc(cs, &wc, - (const uchar*) escape_str->ptr(), - (const uchar*) escape_str->ptr() + - escape_str->length()); + (const uchar*) escape_str_ptr, + (const uchar*) escape_str_ptr + + escape_str->length()); escape= (int) (rc > 0 ? wc : '\\'); } else @@ -4725,13 +4726,13 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) { char ch; uint errors; - uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(), + uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str_ptr, escape_str->length(), escape_str->charset(), &errors); escape= cnvlen ? ch : '\\'; } else - escape= *(escape_str->ptr()); + escape= escape_str_ptr ? *escape_str_ptr : '\\'; } } else -- cgit v1.2.1 From efb1f6407361ba7978aa092cfea102b700359333 Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Wed, 24 Nov 2010 18:08:27 +0300 Subject: Bug#45445: cannot execute procedures with thread_stack set to 128k. Reverting the patch. --- sql/sp.cc | 6 ------ sql/sp_head.cc | 11 ++++------- sql/sql_parse.cc | 3 --- 3 files changed, 4 insertions(+), 16 deletions(-) (limited to 'sql') diff --git a/sql/sp.cc b/sql/sp.cc index 5d424564317..71a5afb437c 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -779,9 +779,6 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, int ret= 0; - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&ret)) - return TRUE; - thd->lex= &newlex; newlex.current_select= NULL; @@ -1611,9 +1608,6 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, (int) name->m_name.length, name->m_name.str, type, cache_only)); - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&depth)) - return NULL; - if ((sp= sp_cache_lookup(cp, name))) { ulong level; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 2f165310c28..54e32b67c65 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1240,8 +1240,11 @@ sp_head::execute(THD *thd, bool merge_da_on_success) The same with db_load_routine() required circa 7k bytes and 14k bytes accordingly. Hence, here we book the stack with some reasonable margin. + + Reverting back to 8 * STACK_MIN_SIZE until further fix. + 8 * STACK_MIN_SIZE is required on some exotic platforms. */ - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&old_packet)) + if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (uchar*)&old_packet)) DBUG_RETURN(TRUE); /* init per-instruction memroot */ @@ -2915,9 +2918,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, It's merged with the saved parent's value at the exit of this func. */ bool parent_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&parent_modified_non_trans_table)) - DBUG_RETURN(TRUE); - thd->transaction.stmt.modified_non_trans_table= FALSE; DBUG_ASSERT(!thd->derived_tables); DBUG_ASSERT(thd->change_list.is_empty()); @@ -3073,9 +3073,6 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_ENTER("sp_instr_stmt::execute"); DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command())); - if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res)) - DBUG_RETURN(TRUE); - const CSET_STRING query_backup= thd->query_string; #if defined(ENABLED_PROFILING) /* This s-p instr is profilable and will be captured. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 40cecb75b69..cb641b5ff68 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7209,9 +7209,6 @@ bool parse_sql(THD *thd, Object_creation_ctx *backup_ctx= NULL; - if (check_stack_overrun(thd, 2 * STACK_MIN_SIZE, (uchar*)&backup_ctx)) - return TRUE; - if (creation_ctx) backup_ctx= creation_ctx->set_n_backup(thd); -- cgit v1.2.1 From a186085a077c3f22827496a86c4029c8fd1384af Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 30 Nov 2010 18:52:38 +0100 Subject: Bug #58414 mysql_upgrade fails on dump upgrade between 5.1.53 -> 5.5.8 The problem was that mysql_upgrade failed because DROP DATABASE refused to drop the 'performance_schema' database when the mysql.proc table definition was made temporarily invalid by dump import. This patch fixes the problem by adding the error resulting from opening a damaged mysq.proc table (ER_CANNOT_LOAD_FROM_TABLE), to the list of errors DROP DATABASE will ignore when trying to lock stored procedures and functions before deletion. This problem was a regression introduced by the patch for Bug#57663. Test case added to sp-destruct.test. --- sql/sp.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql') diff --git a/sql/sp.cc b/sql/sp.cc index 71a5afb437c..ae11c2ad14c 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1372,6 +1372,8 @@ public: MYSQL_ERROR ** cond_hdl) { if (sql_errno == ER_NO_SUCH_TABLE || + sql_errno == ER_CANNOT_LOAD_FROM_TABLE || + sql_errno == ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE || sql_errno == ER_COL_COUNT_DOESNT_MATCH_CORRUPTED) return true; return false; -- cgit v1.2.1 From 93efc7e2c4bc8cffa235f2406db3bdaf4180189d Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 3 Dec 2010 20:49:08 +0300 Subject: Fix for bug #58669: read_only not enforced on 5.5.x Problem: "read-only" option ignored if it's enabled in the command line (or in the config file). Fix: sync opt_readonly (which is used for checks) with read_only (global var) when all server options are handled. --- sql/mysqld.cc | 5 ++++- sql/mysqld.h | 3 ++- sql/sys_vars.cc | 11 ++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7fec30520d0..09c17d600a8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -410,7 +410,8 @@ handlerton *heap_hton; handlerton *myisam_hton; handlerton *partition_hton; -my_bool opt_readonly= 0, use_temp_pool, relay_log_purge; +my_bool read_only= 0, opt_readonly= 0; +my_bool use_temp_pool, relay_log_purge; my_bool relay_log_recovery; my_bool opt_sync_frm, opt_allow_suspicious_udfs; my_bool opt_secure_auth= 0; @@ -7342,6 +7343,8 @@ static int get_options(int *argc_ptr, char ***argv_ptr) test(global_system_variables.optimizer_switch & OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN); + opt_readonly= read_only; + return 0; } diff --git a/sql/mysqld.h b/sql/mysqld.h index 376d8440619..7fe4dc7258a 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -107,7 +107,8 @@ extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern ulong slave_exec_mode_options; extern ulonglong slave_type_conversions_options; -extern my_bool opt_readonly, lower_case_file_system; +extern my_bool read_only, opt_readonly; +extern my_bool lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern char* opt_secure_file_priv; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5c9df82ddac..9ca97b5dded 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1436,7 +1436,6 @@ static Sys_var_ulong Sys_read_buff_size( VALID_RANGE(IO_SIZE*2, INT_MAX32), DEFAULT(128*1024), BLOCK_SIZE(IO_SIZE)); -static my_bool read_only; static bool check_read_only(sys_var *self, THD *thd, set_var *var) { /* Prevent self dead-lock */ @@ -1520,6 +1519,16 @@ static bool fix_read_only(sys_var *self, THD *thd, enum_var_type type) read_only= opt_readonly; DBUG_RETURN(result); } + + +/** + The read_only boolean is always equal to the opt_readonly boolean except + during fix_read_only(); when that function is entered, opt_readonly is + the pre-update value and read_only is the post-update value. + fix_read_only() compares them and runs needed operations for the + transition (especially when transitioning from false to true) and + synchronizes both booleans in the end. +*/ static Sys_var_mybool Sys_readonly( "read_only", "Make all non-temporary tables read-only, with the exception for " -- cgit v1.2.1