diff options
author | istruewing@stella.local <> | 2008-02-14 16:53:03 +0100 |
---|---|---|
committer | istruewing@stella.local <> | 2008-02-14 16:53:03 +0100 |
commit | 9a4d57e31964634785c6f941c3714ce5a46d7bd4 (patch) | |
tree | a49c7a5dd76561facfd53b760feaadf0369e787b /sql | |
parent | fb20c9dd5e3f7fb5c45d649c30a2932d337bc35f (diff) | |
parent | 301ab0d8b72bea5a924cd996f0a0378b3175e9db (diff) | |
download | mariadb-git-9a4d57e31964634785c6f941c3714ce5a46d7bd4.tar.gz |
Merge stella.local:/home2/mydev/mysql-5.1-amain
into stella.local:/home2/mydev/mysql-5.1-axmrg
Diffstat (limited to 'sql')
-rw-r--r-- | sql/event_db_repository.cc | 69 | ||||
-rw-r--r-- | sql/item.cc | 3 | ||||
-rw-r--r-- | sql/log.cc | 23 | ||||
-rw-r--r-- | sql/mysql_priv.h | 4 | ||||
-rw-r--r-- | sql/mysqld.cc | 34 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 5 | ||||
-rw-r--r-- | sql/rpl_rli.h | 4 | ||||
-rw-r--r-- | sql/set_var.cc | 2 | ||||
-rw-r--r-- | sql/slave.cc | 24 | ||||
-rw-r--r-- | sql/sp.cc | 43 | ||||
-rw-r--r-- | sql/sp_head.cc | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 9 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 | ||||
-rw-r--r-- | sql/sql_binlog.cc | 3 | ||||
-rw-r--r-- | sql/sql_bitmap.h | 2 | ||||
-rw-r--r-- | sql/sql_cache.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 75 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 8 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 2 | ||||
-rw-r--r-- | sql/sql_view.cc | 6 | ||||
-rw-r--r-- | sql/stacktrace.c | 64 | ||||
-rw-r--r-- | sql/stacktrace.h | 8 |
25 files changed, 306 insertions, 102 deletions
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 9a33b33d8c9..401f76f5d26 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -111,7 +111,7 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES'," "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," - "'HIGH_NOT_PRECEDENCE')") }, + "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") }, {NULL, 0} }, { @@ -172,11 +172,13 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, sp_head *sp, + ulong sql_mode, my_bool is_update) { CHARSET_INFO *scs= system_charset_info; enum enum_events_table_field f_num; Field **fields= table->field; + int rs= FALSE; DBUG_ENTER("mysql_event_fill_row"); @@ -205,12 +207,9 @@ mysql_event_fill_row(THD *thd, goto err_truncate; /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/ - fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE); - - fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE); - - fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE); - + rs|= fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE); + rs|= fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE); + rs|= fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE); /* Change the SQL_MODE only if body was present in an ALTER EVENT and of course @@ -220,7 +219,7 @@ mysql_event_fill_row(THD *thd, { DBUG_ASSERT(sp->m_body.str); - fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE); + rs|= fields[ET_FIELD_SQL_MODE]->store((longlong)sql_mode, TRUE); if (fields[f_num= ET_FIELD_BODY]->store(sp->m_body.str, sp->m_body.length, @@ -236,16 +235,16 @@ mysql_event_fill_row(THD *thd, if (!is_update || !et->starts_null) { fields[ET_FIELD_TIME_ZONE]->set_notnull(); - fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(), - tz_name->charset()); + rs|= fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(), + tz_name->charset()); } fields[ET_FIELD_INTERVAL_EXPR]->set_notnull(); - fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE); + rs|= fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE); fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull(); - fields[ET_FIELD_TRANSIENT_INTERVAL]-> + rs|= fields[ET_FIELD_TRANSIENT_INTERVAL]-> store(interval_type_to_name[et->interval].str, interval_type_to_name[et->interval].length, scs); @@ -274,8 +273,8 @@ mysql_event_fill_row(THD *thd, { const String *tz_name= thd->variables.time_zone->get_name(); fields[ET_FIELD_TIME_ZONE]->set_notnull(); - fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(), - tz_name->charset()); + rs|= fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(), + tz_name->charset()); fields[ET_FIELD_INTERVAL_EXPR]->set_null(); fields[ET_FIELD_TRANSIENT_INTERVAL]->set_null(); @@ -308,13 +307,13 @@ mysql_event_fill_row(THD *thd, } fields[ET_FIELD_CHARACTER_SET_CLIENT]->set_notnull(); - fields[ET_FIELD_CHARACTER_SET_CLIENT]->store( + rs|= fields[ET_FIELD_CHARACTER_SET_CLIENT]->store( thd->variables.character_set_client->csname, strlen(thd->variables.character_set_client->csname), system_charset_info); fields[ET_FIELD_COLLATION_CONNECTION]->set_notnull(); - fields[ET_FIELD_COLLATION_CONNECTION]->store( + rs|= fields[ET_FIELD_COLLATION_CONNECTION]->store( thd->variables.collation_connection->name, strlen(thd->variables.collation_connection->name), system_charset_info); @@ -323,15 +322,23 @@ mysql_event_fill_row(THD *thd, CHARSET_INFO *db_cl= get_default_db_collation(thd, et->dbname.str); fields[ET_FIELD_DB_COLLATION]->set_notnull(); - fields[ET_FIELD_DB_COLLATION]->store( - db_cl->name, strlen(db_cl->name), system_charset_info); + rs|= fields[ET_FIELD_DB_COLLATION]->store(db_cl->name, + strlen(db_cl->name), + system_charset_info); } if (et->body_changed) { fields[ET_FIELD_BODY_UTF8]->set_notnull(); - fields[ET_FIELD_BODY_UTF8]->store( - sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info); + rs|= fields[ET_FIELD_BODY_UTF8]->store(sp->m_body_utf8.str, + sp->m_body_utf8.length, + system_charset_info); + } + + if (rs) + { + my_error(ER_EVENT_STORE_FAILED, MYF(0), fields[f_num]->field_name, rs); + DBUG_RETURN(TRUE); } DBUG_RETURN(FALSE); @@ -585,12 +592,16 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, int ret= 1; TABLE *table= NULL; sp_head *sp= thd->lex->sphead; + ulong saved_mode= thd->variables.sql_mode; DBUG_ENTER("Event_db_repository::create_event"); DBUG_PRINT("info", ("open mysql.event for update")); DBUG_ASSERT(sp); + /* Reset sql_mode during data dictionary operations. */ + thd->variables.sql_mode= 0; + if (open_event_table(thd, TL_WRITE, &table)) goto end; @@ -646,7 +657,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, mysql_event_fill_row() calls my_error() in case of error so no need to handle it here */ - if (mysql_event_fill_row(thd, table, parse_data, sp, FALSE)) + if (mysql_event_fill_row(thd, table, parse_data, sp, saved_mode, FALSE)) goto end; table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE); @@ -661,6 +672,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data, end: if (table) close_thread_tables(thd); + thd->variables.sql_mode= saved_mode; DBUG_RETURN(test(ret)); } @@ -691,6 +703,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, CHARSET_INFO *scs= system_charset_info; TABLE *table= NULL; sp_head *sp= thd->lex->sphead; + ulong saved_mode= thd->variables.sql_mode; int ret= 1; DBUG_ENTER("Event_db_repository::update_event"); @@ -698,6 +711,9 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, /* None or both must be set */ DBUG_ASSERT(new_dbname && new_name || new_dbname == new_name); + /* Reset sql_mode during data dictionary operations. */ + thd->variables.sql_mode= 0; + if (open_event_table(thd, TL_WRITE, &table)) goto end; @@ -736,7 +752,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, mysql_event_fill_row() calls my_error() in case of error so no need to handle it here */ - if (mysql_event_fill_row(thd, table, parse_data, sp, TRUE)) + if (mysql_event_fill_row(thd, table, parse_data, sp, saved_mode, TRUE)) goto end; if (new_dbname) @@ -755,6 +771,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, end: if (table) close_thread_tables(thd); + thd->variables.sql_mode= saved_mode; DBUG_RETURN(test(ret)); } @@ -950,13 +967,17 @@ bool Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *etn) { - TABLE *table= NULL; bool ret; + TABLE *table= NULL; + ulong saved_mode= thd->variables.sql_mode; DBUG_ENTER("Event_db_repository::load_named_event"); DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, (int) name.length, name.str)); + /* Reset sql_mode during data dictionary operations. */ + thd->variables.sql_mode= 0; + if (!(ret= open_event_table(thd, TL_READ, &table))) { if ((ret= find_named_event(dbname, name, table))) @@ -967,7 +988,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, close_thread_tables(thd); } - + thd->variables.sql_mode= saved_mode; DBUG_RETURN(ret); } diff --git a/sql/item.cc b/sql/item.cc index c546badd8e7..ab9243fcaf5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2628,6 +2628,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) if (entry && entry->value) { item_result_type= entry->type; + unsigned_flag= entry->unsigned_flag; if (strict_type && required_result_type != item_result_type) DBUG_RETURN(1); switch (item_result_type) { @@ -2925,7 +2926,7 @@ const String *Item_param::query_val_str(String* str) const { switch (state) { case INT_VALUE: - str->set(value.integer, &my_charset_bin); + str->set_int(value.integer, unsigned_flag, &my_charset_bin); break; case REAL_VALUE: str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin); diff --git a/sql/log.cc b/sql/log.cc index fce1eb076db..9b5b2ae5a6c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -73,23 +73,28 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all); */ class Silence_log_table_errors : public Internal_error_handler { + char m_message[MYSQL_ERRMSG_SIZE]; public: Silence_log_table_errors() - {} + { + m_message[0]= '\0'; + } virtual ~Silence_log_table_errors() {} virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); + const char *message() const { return m_message; } }; bool Silence_log_table_errors::handle_error(uint /* sql_errno */, - const char * /* message */, + const char *message_arg, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { + strmake(m_message, message_arg, sizeof(m_message)-1); return TRUE; } @@ -436,8 +441,9 @@ bool Log_to_csv_event_handler:: result= FALSE; err: - if (result) - sql_print_error("Failed to write to mysql.general_log"); + if (result && !thd->killed) + sql_print_error("Failed to write to mysql.general_log: %s", + error_handler.message()); if (need_rnd_end) { @@ -495,11 +501,13 @@ bool Log_to_csv_event_handler:: bool result= TRUE; bool need_close= FALSE; bool need_rnd_end= FALSE; + Silence_log_table_errors error_handler; Open_tables_state open_tables_backup; CHARSET_INFO *client_cs= thd->variables.character_set_client; bool save_time_zone_used; DBUG_ENTER("Log_to_csv_event_handler::log_slow"); + thd->push_internal_handler(& error_handler); /* CSV uses TIME_to_timestamp() internally if table needs to be repaired which will set thd->time_zone_used @@ -629,8 +637,11 @@ bool Log_to_csv_event_handler:: result= FALSE; err: - if (result) - sql_print_error("Failed to write to mysql.slow_log"); + thd->pop_internal_handler(); + + if (result && !thd->killed) + sql_print_error("Failed to write to mysql.slow_log: %s", + error_handler.message()); if (need_rnd_end) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1d6990b36f1..ea7482ca067 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1034,7 +1034,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool no_grant, bool no_errors, bool schema_db); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, - bool no_errors); + uint number, bool no_errors); bool check_global_access(THD *thd, ulong want_access); #else inline bool check_access(THD *thd, ulong access, const char *db, @@ -1046,7 +1046,7 @@ inline bool check_access(THD *thd, ulong access, const char *db, return false; } inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, - bool no_errors) + uint number, bool no_errors) { return false; } inline bool check_global_access(THD *thd, ulong want_access) { return false; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 61f3735fe62..08ecc025332 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -221,6 +221,11 @@ extern "C" int gethostname(char *name, int namelen); /* Constants */ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; +/* + WARNING: When adding new SQL modes don't forget to update the + tables definitions that stores it's value. + (ie: mysql.event, mysql.proc) +*/ static const char *sql_mode_names[]= { "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", @@ -2179,6 +2184,16 @@ static void check_data_home(const char *path) #define UNSAFE_DEFAULT_LINUX_THREADS 200 #endif + +#if BACKTRACE_DEMANGLE +#include <cxxabi.h> +extern "C" char *my_demangle(const char *mangled_name, int *status) +{ + return abi::__cxa_demangle(mangled_name, NULL, NULL, status); +} +#endif + + extern "C" sig_handler handle_segfault(int sig) { time_t curr_time; @@ -2250,10 +2265,29 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n", } if (thd) { + const char *kreason= "UNKNOWN"; + switch (thd->killed) { + case THD::NOT_KILLED: + kreason= "NOT_KILLED"; + break; + case THD::KILL_BAD_DATA: + kreason= "KILL_BAD_DATA"; + break; + case THD::KILL_CONNECTION: + kreason= "KILL_CONNECTION"; + break; + case THD::KILL_QUERY: + kreason= "KILL_QUERY"; + break; + case THD::KILLED_NO_VALUE: + kreason= "KILLED_NO_VALUE"; + break; + } fprintf(stderr, "Trying to get some variables.\n\ Some pointers may be invalid and cause the dump to abort...\n"); safe_print_str("thd->query", thd->query, 1024); fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id); + fprintf(stderr, "thd->killed=%s\n", kreason); } fprintf(stderr, "\ The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains\n\ diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 3e9a484126a..03f790b934f 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -33,7 +33,10 @@ Relay_log_info::Relay_log_info() :Slave_reporting_capability("SQL"), no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), - group_relay_log_pos(0), + group_relay_log_pos(0), event_relay_log_pos(0), +#if HAVE_purify + is_fake(FALSE), +#endif cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0), abort_pos_wait(0), slave_run_id(0), sql_thd(0), diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index a3a57ad4ce9..36daffae1af 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -154,6 +154,10 @@ public: ulonglong event_relay_log_pos; ulonglong future_event_relay_log_pos; +#ifdef HAVE_purify + bool is_fake; /* Mark that this is a fake relay log info structure */ +#endif + /* Original log name and position of the group we're currently executing (whose coordinates are group_relay_log_name/pos in the relay log) diff --git a/sql/set_var.cc b/sql/set_var.cc index 410608f154f..4c77cbfff82 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1021,7 +1021,7 @@ bool sys_var_set::update(THD *thd, set_var *var) { *value= var->save_result.ulong_value; return 0; -}; +} uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) diff --git a/sql/slave.cc b/sql/slave.cc index 4ffc2023e85..9dd52c60dad 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1892,14 +1892,21 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, if (exec_res == 0) { int error= ev->update_pos(rli); - char buf[22]; - DBUG_PRINT("info", ("update_pos error = %d", error)); - DBUG_PRINT("info", ("group %s %s", - llstr(rli->group_relay_log_pos, buf), - rli->group_relay_log_name)); - DBUG_PRINT("info", ("event %s %s", - llstr(rli->event_relay_log_pos, buf), - rli->event_relay_log_name)); +#ifdef HAVE_purify + if (!rli->is_fake) +#endif + { +#ifndef DBUG_OFF + char buf[22]; +#endif + DBUG_PRINT("info", ("update_pos error = %d", error)); + DBUG_PRINT("info", ("group %s %s", + llstr(rli->group_relay_log_pos, buf), + rli->group_relay_log_name)); + DBUG_PRINT("info", ("event %s %s", + llstr(rli->event_relay_log_pos, buf), + rli->event_relay_log_name)); + } /* The update should not fail, so print an error message and return an error code. @@ -1909,6 +1916,7 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli, */ if (error) { + char buf[22]; rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR, "It was not possible to update the positions" " of the relay log information: the slave may" diff --git a/sql/sp.cc b/sql/sp.cc index 99ffc18deea..83995e9b753 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -388,7 +388,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) uint length; char buff[65]; String str(buff, sizeof(buff), &my_charset_bin); - ulong sql_mode; + ulong sql_mode, saved_mode= thd->variables.sql_mode; Open_tables_state open_tables_state_backup; Stored_program_creation_ctx *creation_ctx; @@ -400,6 +400,9 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); + /* Reset sql_mode during data dictionary operations. */ + thd->variables.sql_mode= 0; + if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK) goto done; @@ -503,10 +506,36 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) done: if (table) close_system_tables(thd, &open_tables_state_backup); + thd->variables.sql_mode= saved_mode; DBUG_RETURN(ret); } +/** + Silence DEPRECATED SYNTAX warnings when loading a stored procedure + into the cache. +*/ +struct Silence_deprecated_warning : public Internal_error_handler +{ +public: + virtual bool handle_error(uint sql_errno, const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd); +}; + +bool +Silence_deprecated_warning::handle_error(uint sql_errno, const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd) +{ + if (sql_errno == ER_WARN_DEPRECATED_SYNTAX && + level == MYSQL_ERROR::WARN_LEVEL_WARN) + return TRUE; + + return FALSE; +} + + static int db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ulong sql_mode, const char *params, const char *returns, @@ -523,7 +552,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ulong old_sql_mode= thd->variables.sql_mode; ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; - + Silence_deprecated_warning warning_handler; + char definer_user_name_holder[USERNAME_LENGTH + 1]; LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH }; @@ -583,7 +613,9 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, lex_start(thd); + thd->push_internal_handler(&warning_handler); ret= parse_sql(thd, &lip, creation_ctx) || newlex.sphead == NULL; + thd->pop_internal_handler(); /* Force switching back to the saved current database (if changed), @@ -675,6 +707,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) int ret; TABLE *table; char definer[USER_HOST_BUFF_SIZE]; + ulong saved_mode= thd->variables.sql_mode; CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str); @@ -689,6 +722,9 @@ sp_create_routine(THD *thd, int type, sp_head *sp) DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || type == TYPE_ENUM_FUNCTION); + /* Reset sql_mode during data dictionary operations. */ + thd->variables.sql_mode= 0; + /* This statement will be replicated as a statement, even when using row-based replication. The flag will be reset at the end of the @@ -790,7 +826,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) store_failed= store_failed || table->field[MYSQL_PROC_FIELD_SQL_MODE]-> - store((longlong)thd->variables.sql_mode, TRUE); + store((longlong)saved_mode, TRUE); if (sp->m_chistics->comment.str) { @@ -890,6 +926,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) done: thd->count_cuted_fields= saved_count_cuted_fields; + thd->variables.sql_mode= saved_mode; close_thread_tables(thd); DBUG_RETURN(ret); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0edb566ed9f..8e6f5a96640 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2309,7 +2309,7 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) bzero((char*) &tables,sizeof(tables)); tables.db= (char*) "mysql"; tables.table_name= tables.alias= (char*) "proc"; - *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1) || + *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) || (!strcmp(sp->m_definer_user.str, thd->security_ctx->priv_user) && !strcmp(sp->m_definer_host.str, @@ -2753,7 +2753,7 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables) Check whenever we have access to tables for this statement and open and lock them before executing instructions core function. */ - if (check_table_access(thd, SELECT_ACL, tables, 0) + if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE) || open_and_lock_tables(thd, tables)) result= -1; else diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0d563ab9051..b04f624f746 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3041,6 +3041,12 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, } #endif + /* + The lock api is depending on the thd->lex variable which needs to be + re-initialized. + */ + Query_tables_list backup; + thd->lex->reset_n_backup_query_tables_list(&backup); if (simple_open_n_lock_tables(thd,tables)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ @@ -3173,6 +3179,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, send_ok(thd); /* Tables are automatically closed */ + thd->lex->restore_backup_query_tables_list(&backup); DBUG_RETURN(result); } @@ -3862,7 +3869,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, of other queries). For simple queries first_not_own_table is 0. */ for (i= 0, table= tables; - table != first_not_own_table && i < number; + i < number && table != first_not_own_table; table= table->next_global, i++) { /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 799cb673a0e..e5a5b51fcf6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -799,7 +799,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) table_list.table_name= share->table_name.str; table_list.grant.privilege=0; - if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1)) + if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list, 1, TRUE)) continue; /* need to check if we haven't already listed it */ for (table= open_list ; table ; table=table->next) diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 04f408453ea..f1fbe6eb4b7 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -56,6 +56,9 @@ void mysql_client_binlog_statement(THD* thd) if (!thd->rli_fake) { thd->rli_fake= new Relay_log_info; +#ifdef HAVE_purify + thd->rli_fake->is_fake= TRUE; +#endif have_fd_event= FALSE; } if (thd->rli_fake && !thd->rli_fake->relay_log.description_event_for_exec) diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index 9a765120895..97accefe8aa 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -65,7 +65,7 @@ public: my_bool is_clear_all() const { return bitmap_is_clear_all(&map); } my_bool is_set_all() const { return bitmap_is_set_all(&map); } my_bool is_subset(const Bitmap& map2) const { return bitmap_is_subset(&map, &map2.map); } - my_bool is_overlapping(const Bitmap& map2) const { return bitmap_is_overlapping(&map, map2.map); } + my_bool is_overlapping(const Bitmap& map2) const { return bitmap_is_overlapping(&map, &map2.map); } my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); } char *print(char *buf) const { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7e54f87fe14..ae6765c7934 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1384,7 +1384,7 @@ def_week_frmt: %lu", table_list.db = table->db(); table_list.alias= table_list.table_name= table->table(); #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_table_access(thd,SELECT_ACL,&table_list,1)) + if (check_table_access(thd,SELECT_ACL,&table_list, 1, TRUE)) { DBUG_PRINT("qcache", ("probably no SELECT access to %s.%s => return to normal processing", diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 75376c53f68..5180cafc774 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -406,7 +406,7 @@ Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg, m_affected_rows= affected_rows_arg; m_last_insert_id= last_insert_id_arg; if (message_arg) - strmake(m_message, message_arg, sizeof(m_message)); + strmake(m_message, message_arg, sizeof(m_message) - 1); else m_message[0]= '\0'; m_status= DA_OK; @@ -456,7 +456,7 @@ Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg, DBUG_ASSERT(! is_set() || can_overwrite_status); m_sql_errno= sql_errno_arg; - strmake(m_message, message_arg, sizeof(m_message)); + strmake(m_message, message_arg, sizeof(m_message) - 1); m_status= DA_ERROR; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c535d6a714b..031ceddde9a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -503,7 +503,7 @@ static bool check_merge_table_access(THD *thd, char *db, tlist->db= db; /* purecov: inspected */ } error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, - table_list,0); + table_list, UINT_MAX, FALSE); } return error; } @@ -2046,7 +2046,7 @@ mysql_execute_command(THD *thd) res= check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, - all_tables, 0); + all_tables, UINT_MAX, FALSE); } else res= check_access(thd, @@ -2071,7 +2071,7 @@ mysql_execute_command(THD *thd) break; } case SQLCOM_DO: - if (check_table_access(thd, SELECT_ACL, all_tables, 0) || + if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) || open_and_lock_tables(thd, all_tables)) goto error; @@ -2181,7 +2181,7 @@ mysql_execute_command(THD *thd) case SQLCOM_BACKUP_TABLE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL, all_tables, 0) || + if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) || check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; @@ -2193,7 +2193,7 @@ mysql_execute_command(THD *thd) case SQLCOM_RESTORE_TABLE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, INSERT_ACL, all_tables, 0) || + if (check_table_access(thd, INSERT_ACL, all_tables, UINT_MAX, FALSE) || check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; @@ -2270,14 +2270,14 @@ mysql_execute_command(THD *thd) #endif /* HAVE_REPLICATION */ case SQLCOM_SHOW_ENGINE_STATUS: { - if (check_global_access(thd, SUPER_ACL)) + if (check_global_access(thd, PROCESS_ACL)) goto error; res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS); break; } case SQLCOM_SHOW_ENGINE_MUTEX: { - if (check_global_access(thd, SUPER_ACL)) + if (check_global_access(thd, PROCESS_ACL)) goto error; res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX); break; @@ -2734,7 +2734,8 @@ end_with_restore_list: case SQLCOM_CHECKSUM: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0)) + if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, + UINT_MAX, FALSE)) goto error; /* purecov: inspected */ res = mysql_checksum_table(thd, first_table, &lex->check_opt); break; @@ -2742,7 +2743,8 @@ end_with_restore_list: case SQLCOM_REPAIR: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, + UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_repair_table(thd, first_table, &lex->check_opt); @@ -2761,7 +2763,8 @@ end_with_restore_list: case SQLCOM_CHECK: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0)) + if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, + UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_check_table(thd, first_table, &lex->check_opt); @@ -2772,7 +2775,8 @@ end_with_restore_list: case SQLCOM_ANALYZE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, + UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_analyze_table(thd, first_table, &lex->check_opt); @@ -2792,7 +2796,8 @@ end_with_restore_list: case SQLCOM_OPTIMIZE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, + UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? @@ -3121,7 +3126,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (!lex->drop_temporary) { - if (check_table_access(thd, DROP_ACL, all_tables, 0)) + if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ if (end_active_trans(thd)) goto error; @@ -3225,7 +3230,7 @@ end_with_restore_list: if (lex->autocommit && end_active_trans(thd)) goto error; - if ((check_table_access(thd, SELECT_ACL, all_tables, 0) || + if ((check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) || open_and_lock_tables(thd, all_tables))) goto error; if (lex->one_shot_set && not_all_support_one_shot(lex_var_list)) @@ -3267,7 +3272,8 @@ end_with_restore_list: /* we must end the trasaction first, regardless of anything */ if (end_active_trans(thd)) goto error; - if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0)) + if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, + UINT_MAX, FALSE)) goto error; thd->in_lock_tables=1; thd->options|= OPTION_TABLE_LOCK; @@ -3761,7 +3767,7 @@ end_with_restore_list: #endif case SQLCOM_HA_OPEN: DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL, all_tables, 0)) + if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)) goto error; res= mysql_ha_open(thd, first_table, 0); break; @@ -4009,7 +4015,7 @@ create_sp_error: This will cache all SP and SF and open and lock all tables required for execution. */ - if (check_table_access(thd, SELECT_ACL, all_tables, 0) || + if (check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE) || open_and_lock_tables(thd, all_tables)) goto error; @@ -4356,7 +4362,7 @@ create_sp_error: } case SQLCOM_DROP_VIEW: { - if (check_table_access(thd, DROP_ACL, all_tables, 0) || + if (check_table_access(thd, DROP_ACL, all_tables, UINT_MAX, FALSE) || end_active_trans(thd)) goto error; /* Conditionally writes to binlog. */ @@ -4832,7 +4838,7 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) subselects_tables= subselects_tables->next_global; } if (subselects_tables && - (check_table_access(thd, SELECT_ACL, subselects_tables, 0))) + (check_table_access(thd, SELECT_ACL, subselects_tables, UINT_MAX, FALSE))) return 1; } return 0; @@ -5066,11 +5072,12 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) /** Check the privilege for all used tables. - @param thd Thread context - @param want_access Privileges requested - @param tables List of tables to be checked - @param no_errors FALSE/TRUE - report/don't report error to - the client (using my_error() call). + @param thd Thread context + @param want_access Privileges requested + @param tables List of tables to be checked + @param number Check at most this number of tables. + @param no_errors FALSE/TRUE - report/don't report error to + the client (using my_error() call). @note Table privileges are cached in the table list for GRANT checking. @@ -5079,25 +5086,25 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) (the latter should be either 0 or point to next_global member of one of elements of this table list). - @retval - FALSE OK - @retval - TRUE Access denied + @retval FALSE OK + @retval TRUE Access denied */ bool check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, - bool no_errors) + uint number, bool no_errors) { TABLE_LIST *org_tables= tables; TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); + uint i= 0; Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; /* The check that first_not_own_table is not reached is for the case when the given table list refers to the list for prelocking (contains tables of other queries). For simple queries first_not_own_table is 0. */ - for (; tables != first_not_own_table; tables= tables->next_global) + for (; i < number && tables != first_not_own_table; + tables= tables->next_global, i++) { if (tables->security_ctx) sctx= tables->security_ctx; @@ -5147,7 +5154,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, } thd->security_ctx= backup_ctx; return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, - test(want_access & EXTRA_ACL), UINT_MAX, no_errors); + test(want_access & EXTRA_ACL), number, no_errors); deny: thd->security_ctx= backup_ctx; return TRUE; @@ -6876,7 +6883,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) /* sql_yacc guarantees that tables and aux_tables are not zero */ DBUG_ASSERT(aux_tables != 0); - if (check_table_access(thd, SELECT_ACL, tables, 0)) + if (check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) DBUG_RETURN(TRUE); /* @@ -6885,7 +6892,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) call check_table_access() safely. */ thd->lex->query_tables_own_last= 0; - if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) + if (check_table_access(thd, DELETE_ACL, aux_tables, UINT_MAX, FALSE)) { thd->lex->query_tables_own_last= save_query_tables_own_last; DBUG_RETURN(TRUE); @@ -7124,7 +7131,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, } } #endif - if (tables && check_table_access(thd, SELECT_ACL, tables,0)) + if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) goto err; } else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index bae4a85fd8a..74c99b5773d 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1638,7 +1638,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl bzero(&tables, sizeof(tables)); tables.db= (char *)"mysql"; tables.table_name= tables.alias= (char *)"plugin"; - if (check_table_access(thd, INSERT_ACL, &tables, 0)) + if (check_table_access(thd, INSERT_ACL, &tables, 1, FALSE)) DBUG_RETURN(TRUE); /* need to open before acquiring LOCK_plugin or it will deadlock */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c0178a231c9..5a903a4fe1c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1280,7 +1280,7 @@ static int mysql_test_select(Prepared_statement *stmt, ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; if (tables) { - if (check_table_access(thd, privilege, tables,0)) + if (check_table_access(thd, privilege, tables, UINT_MAX, FALSE)) goto error; } else if (check_access(thd, privilege, any_db,0,0,0,0)) @@ -1349,7 +1349,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, THD *thd= stmt->thd; DBUG_ENTER("mysql_test_do_fields"); - if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) + if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) DBUG_RETURN(TRUE); if (open_normal_and_derived_tables(thd, tables, 0)) @@ -1380,7 +1380,7 @@ static bool mysql_test_set_fields(Prepared_statement *stmt, THD *thd= stmt->thd; set_var_base *var; - if (tables && check_table_access(thd, SELECT_ACL, tables, 0) || + if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE) || open_normal_and_derived_tables(thd, tables, 0)) goto error; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ee0a6d3c2ab..6d817cb0620 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4059,7 +4059,7 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) proc_tables.table_name= proc_tables.alias= (char*) "proc"; proc_tables.table_name_length= 4; proc_tables.lock_type= TL_READ; - full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1); + full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1, TRUE); if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup))) { DBUG_RETURN(1); @@ -4447,10 +4447,8 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables, Table_triggers_list *triggers= tables->table->triggers; int event, timing; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_table_access(thd, TRIGGER_ACL, tables, 1)) + if (check_table_access(thd, TRIGGER_ACL, tables, 1, TRUE)) goto ret; -#endif for (event= 0; event < (int)TRG_EVENT_MAX; event++) { @@ -4488,9 +4486,7 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables, } } } -#ifndef NO_EMBEDDED_ACCESS_CHECKS ret: -#endif DBUG_RETURN(0); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 4bf23dc52f9..4cd1d542375 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -422,7 +422,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; thd->lex->query_tables_own_last= 0; - err_status= check_table_access(thd, TRIGGER_ACL, tables, 0); + err_status= check_table_access(thd, TRIGGER_ACL, tables, 1, FALSE); thd->lex->query_tables_own_last= save_query_tables_own_last; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index da301b37484..1a4d7d515a8 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1123,8 +1123,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if (!table->prelocking_placeholder && (old_lex->sql_command == SQLCOM_SELECT && old_lex->describe)) { - if (check_table_access(thd, SELECT_ACL, view_tables, 1) && - check_table_access(thd, SHOW_VIEW_ACL, table, 1)) + if (check_table_access(thd, SELECT_ACL, view_tables, UINT_MAX, TRUE) && + check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, TRUE)) { my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0)); goto err; @@ -1134,7 +1134,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, (old_lex->sql_command == SQLCOM_SHOW_CREATE) && !table->belong_to_view) { - if (check_table_access(thd, SHOW_VIEW_ACL, table, 0)) + if (check_table_access(thd, SHOW_VIEW_ACL, table, UINT_MAX, FALSE)) goto err; } diff --git a/sql/stacktrace.c b/sql/stacktrace.c index b1267e20774..3d718dfd9d2 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -17,11 +17,16 @@ #include "stacktrace.h" #include <signal.h> #include <my_pthread.h> +#include <m_string.h> #ifdef HAVE_STACKTRACE #include <unistd.h> #include <strings.h> +#if HAVE_EXECINFO_H +#include <execinfo.h> +#endif + #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) char *heap_start; @@ -93,9 +98,68 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) } #endif /* defined(__alpha__) && defined(__GNUC__) */ +#if BACKTRACE_DEMANGLE +static void my_demangle_symbols(char **addrs, int n) +{ + int status, i; + char *begin, *end, *demangled; + + for (i= 0; i < n; i++) + { + demangled= NULL; + begin= strchr(addrs[i], '('); + end= begin ? strchr(begin, '+') : NULL; + + if (begin && end) + { + *begin++= *end++= '\0'; + demangled= my_demangle(begin, &status); + if (!demangled || status) + { + demangled= NULL; + begin[-1]= '('; + end[-1]= '+'; + } + } + + if (demangled) + fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end); + else + fprintf(stderr, "%s\n", addrs[i]); + } +} +#endif + + +#if HAVE_BACKTRACE +static void backtrace_current_thread(void) +{ + void *addrs[128]; + char **strings= NULL; + int n = backtrace(addrs, array_elements(addrs)); +#if BACKTRACE_DEMANGLE + if ((strings= backtrace_symbols(addrs, n))) + { + my_demangle_symbols(strings, n); + free(strings); + } +#endif +#if HAVE_BACKTRACE_SYMBOLS_FD + if (!strings) + { + backtrace_symbols_fd(addrs, n, fileno(stderr)); + } +#endif +} +#endif + void print_stacktrace(uchar* stack_bottom, ulong thread_stack) { +#if HAVE_BACKTRACE + backtrace_current_thread(); + return; +#endif uchar** fp; uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) diff --git a/sql/stacktrace.h b/sql/stacktrace.h index 1a0b80c88d3..96c09a21ad6 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -17,6 +17,14 @@ extern "C" { #endif +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS && HAVE_CXXABI_H && HAVE_ABI_CXA_DEMANGLE +#define BACKTRACE_DEMANGLE 1 +#endif + +#if BACKTRACE_DEMANGLE +char *my_demangle(const char *mangled_name, int *status); +#endif + #ifdef TARGET_OS_LINUX #if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE |