diff options
Diffstat (limited to 'sql')
51 files changed, 455 insertions, 220 deletions
diff --git a/sql/events.cc b/sql/events.cc index 2bb112867bf..abc798b659a 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -80,7 +80,8 @@ Event_queue *Events::event_queue; Event_scheduler *Events::scheduler; Event_db_repository *Events::db_repository; ulong Events::opt_event_scheduler= Events::EVENTS_OFF; -bool Events::check_system_tables_error= FALSE; +ulong Events::startup_state= Events::EVENTS_OFF; +ulong Events::inited; /* @@ -114,7 +115,7 @@ bool Events::check_if_system_tables_error() { DBUG_ENTER("Events::check_if_system_tables_error"); - if (check_system_tables_error) + if (!inited) { my_error(ER_EVENTS_DB_ERROR, MYF(0)); DBUG_RETURN(TRUE); @@ -257,10 +258,10 @@ common_1_lev_code: /** - Create a new query string for removing executable comments - for avoiding leak and keeping consistency of the execution + 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] buf Query string @@ -287,7 +288,7 @@ create_query_string(THD *thd, String *buf) thd->lex->stmt_definition_end - thd->lex->stmt_definition_begin)) return 1; - + return 0; } @@ -340,8 +341,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) if (parse_data->do_not_create) DBUG_RETURN(FALSE); - /* - Turn off row binlogging of this statement and use statement-based + /* + Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -392,8 +393,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) String log_query(buffer, sizeof(buffer), &my_charset_bin); 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."); + my_message_sql(ER_STARTUP, + "Event Error: An error occurred while creating query " + "string, before writing it into binary log.", + MYF(ME_NOREFRESH)); ret= true; } else @@ -481,8 +484,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, } } - /* - Turn off row binlogging of this statement and use statement-based + /* + Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -769,6 +772,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) int ret; DBUG_ENTER("Events::fill_schema_events"); + /* + If we didn't start events because of --skip-grant-tables, return an + empty set + */ + if (opt_noacl) + DBUG_RETURN(0); + if (check_if_system_tables_error()) DBUG_RETURN(1); @@ -797,6 +807,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) /** Initializes the scheduler's structures. + @param THD or null (if called by init) @param opt_noacl_or_bootstrap TRUE if there is --skip-grant-tables or --bootstrap option. In that case we disable the event scheduler. @@ -804,44 +815,56 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) @note This function is not synchronized. @retval FALSE Perhaps there was an error, and the event scheduler - is disabled. But the error is not fatal and the + is disabled. But the error is not fatal and the server start up can continue. @retval TRUE Fatal error. Startup must terminate (call unireg_abort()). */ bool -Events::init(bool opt_noacl_or_bootstrap) +Events::init(THD *thd, bool opt_noacl_or_bootstrap) { - - THD *thd; int err_no; bool res= FALSE; - + bool had_thd= thd != 0; DBUG_ENTER("Events::init"); + DBUG_ASSERT(inited == 0); + + /* + Was disabled explicitly from the command line + */ + if (opt_event_scheduler == Events::EVENTS_DISABLED || + opt_noacl_or_bootstrap) + DBUG_RETURN(FALSE); + /* We need a temporary THD during boot */ - if (!(thd= new THD())) + if (!thd) { - res= TRUE; - goto end; + + if (!(thd= new THD())) + { + res= TRUE; + goto end; + } + /* + The thread stack does not start from this function but we cannot + guess the real value. So better some value that doesn't assert than + no value. + */ + thd->thread_stack= (char*) &thd; + thd->store_globals(); + /* + Set current time for the thread that handles events. + Current time is stored in data member start_time of THD class. + Subsequently, this value is used to check whether event was expired + when make loading events from storage. Check for event expiration time + is done at Event_queue_element::compute_next_execution_time() where + event's status set to Event_parse_data::DISABLED and dropped flag set + to true if event was expired. + */ + thd->set_time(); } - /* - The thread stack does not start from this function but we cannot - guess the real value. So better some value that doesn't assert than - no value. - */ - thd->thread_stack= (char*) &thd; - thd->store_globals(); - /* - Set current time for the thread that handles events. - Current time is stored in data member start_time of THD class. - Subsequently, this value is used to check whether event was expired - when make loading events from storage. Check for event expiration time - is done at Event_queue_element::compute_next_execution_time() where - event's status set to Event_parse_data::DISABLED and dropped flag set - to true if event was expired. - */ - thd->set_time(); + /* We will need Event_db_repository anyway, even if the scheduler is disabled - to perform events DDL. @@ -861,28 +884,19 @@ Events::init(bool opt_noacl_or_bootstrap) are most likely not there and we're going to disable the event scheduler anyway. */ - if (opt_noacl_or_bootstrap || Event_db_repository::check_system_tables(thd)) + if (Event_db_repository::check_system_tables(thd)) { - if (! opt_noacl_or_bootstrap) - { - sql_print_error("Event Scheduler: An error occurred when initializing " - "system tables. Disabling the Event Scheduler."); - check_system_tables_error= TRUE; - } - + delete db_repository; + db_repository= 0; + my_message(ER_STARTUP, + "Event Scheduler: An error occurred when initializing " + "system tables. Disabling the Event Scheduler.", + MYF(ME_NOREFRESH)); /* Disable the scheduler since the system tables are not up to date */ - opt_event_scheduler= EVENTS_DISABLED; + opt_event_scheduler= EVENTS_OFF; goto end; } - /* - Was disabled explicitly from the command line, or because we're running - with --skip-grant-tables, or --bootstrap, or because we have no system - tables. - */ - if (opt_event_scheduler == Events::EVENTS_DISABLED) - goto end; - DBUG_ASSERT(opt_event_scheduler == Events::EVENTS_ON || opt_event_scheduler == Events::EVENTS_OFF); @@ -897,20 +911,20 @@ Events::init(bool opt_noacl_or_bootstrap) if (event_queue->init_queue(thd) || load_events_from_db(thd) || (opt_event_scheduler == EVENTS_ON && scheduler->start(&err_no))) { - sql_print_error("Event Scheduler: Error while loading from disk."); + my_message_sql(ER_STARTUP, + "Event Scheduler: Error while loading from mysql.event table.", + MYF(ME_NOREFRESH)); res= TRUE; /* fatal error: request unireg_abort */ goto end; } Event_worker_thread::init(db_repository); + inited= 1; end: if (res) - { - delete db_repository; - delete event_queue; - delete scheduler; - } - delete thd; + deinit(); + if (!had_thd) + delete thd; DBUG_RETURN(res); } @@ -930,17 +944,14 @@ Events::deinit() { DBUG_ENTER("Events::deinit"); - if (opt_event_scheduler != EVENTS_DISABLED) - { - delete scheduler; - scheduler= NULL; /* safety */ - delete event_queue; - event_queue= NULL; /* safety */ - } - + delete scheduler; + scheduler= NULL; /* For restart */ + delete event_queue; + event_queue= NULL; /* For restart */ delete db_repository; - db_repository= NULL; /* safety */ + db_repository= NULL; /* For restart */ + inited= 0; DBUG_VOID_RETURN; } @@ -1043,7 +1054,7 @@ Events::dump_internal_status() holding LOCK_global_system_variables. */ mysql_mutex_lock(&LOCK_global_system_variables); - if (opt_event_scheduler == EVENTS_DISABLED) + if (!inited) puts("The Event Scheduler is disabled"); else { @@ -1057,11 +1068,13 @@ Events::dump_internal_status() bool Events::start(int *err_no) { + DBUG_ASSERT(inited); return scheduler->start(err_no); } bool Events::stop() { + DBUG_ASSERT(inited); return scheduler->stop(); } @@ -1091,7 +1104,6 @@ Events::load_events_from_db(THD *thd) bool ret= TRUE; uint count= 0; ulong saved_master_access; - DBUG_ENTER("Events::load_events_from_db"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); @@ -1116,7 +1128,9 @@ Events::load_events_from_db(THD *thd) if (ret) { - sql_print_error("Event Scheduler: Failed to open table mysql.event"); + my_message_sql(ER_STARTUP, + "Event Scheduler: Failed to open table mysql.event", + MYF(ME_NOREFRESH)); DBUG_RETURN(TRUE); } @@ -1138,9 +1152,11 @@ Events::load_events_from_db(THD *thd) if (et->load_from_row(thd, table)) { - sql_print_error("Event Scheduler: " - "Error while loading events from mysql.event. " - "The table probably contains bad data or is corrupted"); + my_message(ER_STARTUP, + "Event Scheduler: " + "Error while loading events from mysql.event. " + "The table probably contains bad data or is corrupted", + MYF(ME_NOREFRESH)); delete et; goto end; } @@ -1177,9 +1193,12 @@ Events::load_events_from_db(THD *thd) } } } - if (global_system_variables.log_warnings) - sql_print_information("Event Scheduler: Loaded %d event%s", - count, (count == 1) ? "" : "s"); + my_printf_error(ER_STARTUP, + "Event Scheduler: Loaded %d event%s", + MYF(ME_NOREFRESH | + (global_system_variables.log_warnings) ? + ME_JUST_INFO: 0), + count, (count == 1) ? "" : "s"); ret= FALSE; end: diff --git a/sql/events.h b/sql/events.h index bc2af1fb4de..368aa9a05d5 100644 --- a/sql/events.h +++ b/sql/events.h @@ -79,9 +79,11 @@ public: and the @@global.event_scheduler SQL variable. See sys_var.cc */ - enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED }; + enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED, + EVENTS_ORIGINAL }; /* Protected using LOCK_global_system_variables only. */ - static ulong opt_event_scheduler; + static ulong opt_event_scheduler, startup_state; + static ulong inited; static bool check_if_system_tables_error(); static bool start(int *err_no); static bool stop(); @@ -91,8 +93,7 @@ public: static Event_db_repository * get_db_repository() { return db_repository; } - static bool - init(bool opt_noacl); + static bool init(THD *thd, bool opt_noacl); static void deinit(); @@ -130,6 +131,11 @@ public: static void dump_internal_status(); + static void set_original_state(ulong startup_state_org) + { + startup_state= startup_state_org; + } + private: static bool @@ -139,8 +145,6 @@ private: static Event_queue *event_queue; static Event_scheduler *scheduler; static Event_db_repository *db_repository; - /* Set to TRUE if an error at start up */ - static bool check_system_tables_error; private: /* Prevent use of these */ diff --git a/sql/filesort.cc b/sql/filesort.cc index ef91e227928..917b9de6038 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -25,7 +25,6 @@ #include <my_global.h> #include "sql_priv.h" #include "filesort.h" -#include "unireg.h" // REQUIRED by other includes #ifdef HAVE_STDDEF_H #include <stddef.h> /* for macro offsetof */ #endif diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 043f7fb280b..0e009e76066 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5271,6 +5271,7 @@ err: { (void) m_file[j]->ha_index_end(); } + destroy_record_priority_queue(); } DBUG_RETURN(error); } diff --git a/sql/handler.cc b/sql/handler.cc index 0f341a0ccc5..193d36a1122 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5113,7 +5113,7 @@ bool Discovered_table_list::add_table(const char *tname, size_t tlen) custom discover_table_names() method, that calls add_table() directly). Note: avoid comparing the same name twice (here and in add_file). */ - if (wild && my_wildcmp(files_charset_info, tname, tname + tlen, wild, wend, + if (wild && my_wildcmp(table_alias_charset, tname, tname + tlen, wild, wend, wild_prefix, wild_one, wild_many)) return 0; diff --git a/sql/hostname.cc b/sql/hostname.cc index 656663a9692..6aef84f1b26 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -26,6 +26,7 @@ */ #include <my_global.h> #include "sql_priv.h" +#include "unireg.h" // SPECIAL_NO_HOST_CACHE #include "hostname.h" #include "unireg.h" #ifndef __WIN__ diff --git a/sql/item.cc b/sql/item.cc index a1a91007a0a..0f10ccbd88c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -21,7 +21,6 @@ #endif #include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include <mysql.h> #include <m_ctype.h> #include "my_dir.h" @@ -4676,8 +4675,24 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) As this is an outer field it should be added to the list of non aggregated fields of the outer select. */ - marker= select->cur_pos_in_select_list; - select->join->non_agg_fields.push_back(this, thd->mem_root); + if (select->join) + { + marker= select->cur_pos_in_select_list; + select->join->non_agg_fields.push_back(this, thd->mem_root); + } + else + { + /* + join is absent if it is upper SELECT_LEX of non-select + command + */ + DBUG_ASSERT(select->master_unit()->outer_select() == NULL && + (thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_UPDATE_MULTI && + thd->lex->sql_command != SQLCOM_DELETE_MULTI && + thd->lex->sql_command != SQLCOM_INSERT_SELECT && + thd->lex->sql_command != SQLCOM_REPLACE_SELECT)); + } } if (*from_field != view_ref_found) { @@ -6582,6 +6597,7 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg) { List<Item> *all_fields= &select->join->all_fields; Item **ref_pointer_array= select->ref_pointer_array; + DBUG_ASSERT(all_fields->elements <= select->ref_pointer_array_size); int el= all_fields->elements; Item_ref *ref; diff --git a/sql/item.h b/sql/item.h index e662eed4a71..e262ce9d12d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -25,7 +25,6 @@ #include "sql_priv.h" /* STRING_BUFFER_USUAL_SIZE */ #include "unireg.h" #include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */ -#include "unireg.h" // REQUIRED: for other includes #include "thr_malloc.h" /* sql_calloc */ #include "field.h" /* Derivation */ #include "sql_type.h" @@ -4264,6 +4263,8 @@ public: bool eq(const Item *item, bool binary_cmp) const; Item *get_tmp_table_item(THD *thd) { + if (const_item()) + return copy_or_same(thd); Item *item= Item_ref::get_tmp_table_item(thd); item->name= name; return item; diff --git a/sql/key.cc b/sql/key.cc index aaecbda57ad..1b00e951de0 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -18,7 +18,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: by includes later #include "key.h" // key_rec_cmp #include "field.h" // Field diff --git a/sql/lock.cc b/sql/lock.cc index 7e7b378bfb4..2e44786d6fe 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -73,7 +73,6 @@ #include <my_global.h> #include "sql_priv.h" #include "debug_sync.h" -#include "unireg.h" // REQUIRED: for other includes #include "lock.h" #include "sql_base.h" // close_tables_for_reopen #include "sql_parse.h" // is_log_table_write_query diff --git a/sql/log.cc b/sql/log.cc index cea3d7e855e..ddf6bd07695 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8013,12 +8013,14 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd, int ret= 0; DBUG_ENTER("wait_for_update_bin_log"); + thd_wait_begin(thd, THD_WAIT_BINLOG); mysql_mutex_assert_owner(&LOCK_log); if (!timeout) mysql_cond_wait(&update_cond, &LOCK_log); else ret= mysql_cond_timedwait(&update_cond, &LOCK_log, const_cast<struct timespec *>(timeout)); + thd_wait_end(thd); DBUG_RETURN(ret); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f9a3c2a0b3a..9dcf87adecb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5876,7 +5876,15 @@ int mysqld_main(int argc, char **argv) execute_ddl_log_recovery(); - if (Events::init(opt_noacl || opt_bootstrap)) + /* + Change EVENTS_ORIGINAL to EVENTS_OFF (the default value) as there is no + point in using ORIGINAL during startup + */ + if (Events::opt_event_scheduler == Events::EVENTS_ORIGINAL) + Events::opt_event_scheduler= Events::EVENTS_OFF; + + Events::set_original_state(Events::opt_event_scheduler); + if (Events::init((THD*) 0, opt_noacl || opt_bootstrap)) unireg_abort(1); if (WSREP_ON) diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index e8cff9e69ab..f36887eb137 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -341,7 +341,8 @@ int opt_sum_query(THD *thd, there are no outer joins. */ if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null && - !outer_tables && maybe_exact_count) + !outer_tables && maybe_exact_count && + ((item->used_tables() & OUTER_REF_TABLE_BIT) == 0)) { if (!is_exact_count) { @@ -369,7 +370,8 @@ int opt_sum_query(THD *thd, indexes to find the key. */ Item *expr=item_sum->get_arg(0); - if (expr->real_item()->type() == Item::FIELD_ITEM) + if (((expr->used_tables() & OUTER_REF_TABLE_BIT) == 0) && + expr->real_item()->type() == Item::FIELD_ITEM) { uchar key_buff[MAX_KEY_LENGTH]; TABLE_REF ref; diff --git a/sql/protocol.cc b/sql/protocol.cc index 249dd73e2df..fa42915f5a9 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -27,7 +27,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "protocol.h" #include "sql_class.h" // THD #include <stdarg.h> diff --git a/sql/records.cc b/sql/records.cc index b6d68a5017f..ebda0ed35b0 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info); @param reverse Scan in the reverse direction */ -void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, +bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse) { int error; + DBUG_ENTER("init_read_record_idx"); + empty_record(table); bzero((char*) info,sizeof(*info)); info->thd= thd; @@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, /* read_record will be changed to rr_index in rr_index_first */ info->read_record= reverse ? rr_index_last : rr_index_first; + DBUG_RETURN(error != 0); } diff --git a/sql/records.h b/sql/records.h index 21477d4a30b..a3f0b5eb084 100644 --- a/sql/records.h +++ b/sql/records.h @@ -76,7 +76,7 @@ public: bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors, bool disable_rr_cache); -void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, +bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse); void end_read_record(READ_RECORD *info); diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index caa84d867ad..bff0da26862 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -15,7 +15,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED by later includes #include "rpl_injector.h" #include "transaction.h" #include "sql_parse.h" // begin_trans, end_trans, COMMIT diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 02104af8cd3..216fbde0177 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -17,7 +17,6 @@ #include <my_global.h> // For HAVE_REPLICATION #include "sql_priv.h" #include <my_dir.h> -#include "unireg.h" // REQUIRED by other includes #include "rpl_mi.h" #include "slave.h" // SLAVE_MAX_HEARTBEAT_PERIOD #include "strfunc.h" diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index 061fab78dbd..5b876373b9c 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -15,7 +15,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED by other includes #include "rpl_rli.h" #include "rpl_record_old.h" #include "log_event.h" // Log_event_type diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 679bd152a39..03fef5de866 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2693,7 +2693,8 @@ static int check_alter_user(THD *thd, const char *host, const char *user) } if (IF_WSREP((!WSREP(thd) || !thd->wsrep_applier), 1) && - !thd->slave_thread && !thd->security_ctx->priv_user[0]) + !thd->slave_thread && !thd->security_ctx->priv_user[0] && + !in_bootstrap) { my_message(ER_PASSWORD_ANONYMOUS_USER, ER_THD(thd, ER_PASSWORD_ANONYMOUS_USER), @@ -9110,8 +9111,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, So we need to examine the current element once again, but we don't need to restart the search from the beginning. */ - if (idx != elements) - idx++; + idx++; break; } @@ -9143,6 +9143,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, my_hash_update(roles_mappings_hash, (uchar*) role_grant_pair, (uchar*) old_key, old_key_length); + idx++; // see the comment above break; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1189a26f047..90ba0451e30 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6455,6 +6455,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, */ table_name && table_name[0] && (my_strcasecmp(table_alias_charset, table_list->alias, table_name) || + (db_name && db_name[0] && (!table_list->db || !table_list->db[0])) || (db_name && db_name[0] && table_list->db && table_list->db[0] && (table_list->schema_table ? my_strcasecmp(system_charset_info, db_name, table_list->db) : @@ -6928,7 +6929,10 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, for (uint i= 0; (item=li++); i++) { - if (field_name && item->real_item()->type() == Item::FIELD_ITEM) + if (field_name && + (item->real_item()->type() == Item::FIELD_ITEM || + ((item->type() == Item::REF_ITEM) && + (((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF)))) { Item_ident *item_field= (Item_ident*) item; @@ -7054,35 +7058,6 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, break; } } - else if (table_name && item->type() == Item::REF_ITEM && - ((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF) - { - /* - TODO:Here we process prefixed view references only. What we should - really do is process all types of Item_ref's. But this will currently - lead to a clash with the way references to outer SELECTs (from the - HAVING clause) are handled in e.g. : - SELECT 1 FROM t1 AS t1_o GROUP BY a - HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1). - Processing all Item_ref's here will cause t1_o.a to resolve to itself. - We still need to process the special case of Item_direct_view_ref - because in the context of views they have the same meaning as - Item_field for tables. - */ - Item_ident *item_ref= (Item_ident *) item; - if (field_name && item_ref->name && item_ref->table_name && - !my_strcasecmp(system_charset_info, item_ref->name, field_name) && - !my_strcasecmp(table_alias_charset, item_ref->table_name, - table_name) && - (!db_name || (item_ref->db_name && - !strcmp (item_ref->db_name, db_name)))) - { - found= li.ref(); - *counter= i; - *resolution= RESOLVED_IGNORING_ALIAS; - break; - } - } } if (!found) { diff --git a/sql/sql_base.h b/sql/sql_base.h index 1c0029d9692..3a23e2ea218 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -16,7 +16,6 @@ #ifndef SQL_BASE_INCLUDED #define SQL_BASE_INCLUDED -#include "unireg.h" // REQUIRED: for other includes #include "sql_trigger.h" /* trg_event_type */ #include "sql_class.h" /* enum_mark_columns */ #include "mysqld.h" /* key_map */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1bf48921998..e95e32a5e0b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -30,7 +30,6 @@ #include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_class.h" #include "sql_cache.h" // query_cache_abort #include "sql_base.h" // close_thread_tables diff --git a/sql/sql_class.h b/sql/sql_class.h index 2b62c462abc..aee6d560bfb 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -20,16 +20,14 @@ /* Classes in mysql */ -#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ -#ifdef MYSQL_SERVER -#include "unireg.h" // REQUIRED: for other includes -#endif +#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include <waiting_threads.h> #include "sql_const.h" #include <mysql/plugin_audit.h> #include "log.h" #include "rpl_tblmap.h" #include "mdl.h" +#include "field.h" // Create_field #include "probes_mysql.h" #include "sql_locale.h" /* my_locale_st */ #include "sql_profile.h" /* PROFILING */ diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index f6e37f07e60..7821b96b9bb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -28,7 +28,6 @@ #include "sql_audit.h" #include "sql_connect.h" #include "probes_mysql.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" // sql_command_flags, // execute_init_command, // do_command diff --git a/sql/sql_const.h b/sql/sql_const.h index f856362f4e5..76e47bd278b 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -17,12 +17,14 @@ @file File containing constants that can be used throughout the server. - @note This file shall not contain any includes of any kinds. + @note This file shall not contain or include any declarations of any kinds. */ #ifndef SQL_CONST_INCLUDED #define SQL_CONST_INCLUDED +#include <mysql_version.h> + #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ /* extra 4+4 bytes for slave tmp tables */ #define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 8995684b8f6..f49a053918b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -529,17 +529,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, free_underlaid_joins(thd, select_lex); DBUG_RETURN(TRUE); } + if (query_plan.index == MAX_KEY || (select && select->quick)) + error= init_read_record(&info, thd, table, select, 1, 1, FALSE); + else + error= init_read_record_idx(&info, thd, table, 1, query_plan.index, + reverse); + if (error) { - if (init_read_record(&info, thd, table, select, 1, 1, FALSE)) - { - delete select; - free_underlaid_joins(thd, select_lex); - DBUG_RETURN(TRUE); - } + delete select; + free_underlaid_joins(thd, select_lex); + DBUG_RETURN(TRUE); } - else - init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); init_ftfuncs(thd, select_lex, 1); THD_STAGE_INFO(thd, stage_updating); diff --git a/sql/sql_digest.h b/sql/sql_digest.h index ce159283d4d..eaf74b9542e 100644 --- a/sql/sql_digest.h +++ b/sql/sql_digest.h @@ -41,6 +41,9 @@ struct sql_digest_storage For Example: SELECT * FROM T1; <SELECT_TOKEN> <*> <FROM_TOKEN> <ID_TOKEN> <2> <T1> + + @note Only the first @c m_byte_count bytes are initialized, + out of @c m_token_array_length. */ unsigned char *m_token_array; /* Length of the token array to be considered for DIGEST_TEXT calculation. */ @@ -63,10 +66,6 @@ struct sql_digest_storage m_full= false; m_byte_count= 0; m_charset_number= 0; - if (m_token_array_length > 0) - { - memset(m_token_array, 0, m_token_array_length); - } memset(m_md5, 0, MD5_HASH_SIZE); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 47f24ad9cb8..b72d642efbc 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -510,8 +510,10 @@ Diagnostics_area::set_error_status(uint sql_errno, void Diagnostics_area::disable_status() { + DBUG_ENTER("disable_status"); DBUG_ASSERT(! is_set()); m_status= DA_DISABLED; + DBUG_VOID_RETURN; } Warning_info::Warning_info(ulonglong warn_id_arg, diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 05e333e37fc..662fa33dc9f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -55,7 +55,6 @@ #include <my_global.h> #include "sql_priv.h" #include "sql_handler.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_base.h" // close_thread_tables #include "lock.h" // mysql_unlock_tables #include "key.h" // key_copy diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 574e0892872..7a0a114971d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -58,7 +58,6 @@ #include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_insert.h" #include "sql_update.h" // compare_record #include "sql_base.h" // close_thread_tables diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3c4f99d1a7c..898e3ae33c6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -20,7 +20,6 @@ #define MYSQL_LEX 1 #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_class.h" // sql_lex.h: SQLCOM_END #include "sql_lex.h" #include "sql_parse.h" // add_to_list @@ -557,6 +556,16 @@ void lex_end(LEX *lex) DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); + lex_end_stage1(lex); + lex_end_stage2(lex); + + DBUG_VOID_RETURN; +} + +void lex_end_stage1(LEX *lex) +{ + DBUG_ENTER("lex_end_stage1"); + /* release used plugins */ if (lex->plugins.elements) /* No function call and no mutex if no plugins. */ { @@ -580,6 +589,19 @@ void lex_end(LEX *lex) lex->sphead= NULL; } + DBUG_VOID_RETURN; +} + +/* + MASTER INFO parameters (or state) is normally cleared towards the end + of a statement. But in case of PS, the state needs to be preserved during + its lifetime and should only be cleared on PS close or deallocation. +*/ +void lex_end_stage2(LEX *lex) +{ + DBUG_ENTER("lex_end_stage2"); + + /* Reset LEX_MASTER_INFO */ lex->mi.reset(lex->sql_command == SQLCOM_CHANGE_MASTER); DBUG_VOID_RETURN; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d39da819513..644d1a19cfd 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3119,6 +3119,8 @@ extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); +extern void lex_end_stage1(LEX *lex); +extern void lex_end_stage2(LEX *lex); void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex); int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex); extern int MYSQLlex(union YYSTYPE *yylval, THD *thd); diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index c6c465aa4e2..8cf849b97d0 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -24,7 +24,6 @@ #include <my_global.h> #include "sql_priv.h" #include "sql_manager.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_base.h" // flush_tables static bool volatile manager_thread_in_use; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6c965cf8359..1388ec01459 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -17,7 +17,6 @@ #define MYSQL_LEX 1 #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" // sql_kill, *_precheck, *_prepare #include "lock.h" // try_transactional_lock, // check_transactional_lock, @@ -693,7 +692,7 @@ static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error static void handle_bootstrap_impl(THD *thd) { MYSQL_FILE *file= bootstrap_file; - DBUG_ENTER("handle_bootstrap"); + DBUG_ENTER("handle_bootstrap_impl"); #ifndef EMBEDDED_LIBRARY pthread_detach_this_thread(); @@ -6691,6 +6690,7 @@ bool check_fk_parent_table_access(THD *thd, table_name.str= (char *) thd->memdup(fk_key->ref_table.str, fk_key->ref_table.length+1); table_name.length= my_casedn_str(files_charset_info, table_name.str); + db_name.length = my_casedn_str(files_charset_info, db_name.str); } parent_table.init_one_table(db_name.str, db_name.length, diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 8e77d77205c..16588871fd8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -49,7 +49,6 @@ #define MYSQL_LEX 1 #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_partition.h" #include "key.h" // key_restore #include "sql_parse.h" // parse_sql diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2b37cb172aa..dfe6d1c2117 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1419,7 +1419,8 @@ static int mysql_test_update(Prepared_statement *stmt, (SELECT_ACL & ~table_list->table->grant.privilege); table_list->register_want_access(SELECT_ACL); #endif - if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ DBUG_RETURN(0); @@ -3475,7 +3476,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) select_number_after_prepare= thd->select_number; - lex_end(lex); + /* Preserve CHANGE MASTER attributes */ + lex_end_stage1(lex); cleanup_stmt(); thd->restore_backup_statement(this, &stmt_backup); thd->stmt_arena= old_stmt_arena; @@ -4102,6 +4104,10 @@ void Prepared_statement::deallocate() { /* We account deallocate in the same manner as mysqld_stmt_close */ status_var_increment(thd->status_var.com_stmt_close); + + /* It should now be safe to reset CHANGE MASTER parameters */ + lex_end_stage2(lex); + /* Statement map calls delete stmt on erase */ thd->stmt_map.erase(this); } diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index bc11f5fdb21..48f7987daf5 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -31,7 +31,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_profile.h" #include <my_sys.h> #include "sql_show.h" // schema_table_store_record diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index e6c8e0777b8..7f2cf987f0e 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -94,6 +94,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, my_error(ER_UNKNOWN_ERROR, MYF(0)); } } + opt_noacl= 0; if (tmp_thd) { diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index d9cf0344cdf..17b297f63bd 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -274,8 +274,9 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, LEX_STRING table_name= { ren_table->table_name, ren_table->table_name_length }; LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) }; + LEX_STRING new_db_name= { (char*)new_db, strlen(new_db)}; (void) rename_table_in_stat_tables(thd, &db_name, &table_name, - &db_name, &new_table); + &new_db_name, &new_table); if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, old_alias, ren_table->table_name, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bc5cf2df0ca..3b339368d0a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -492,6 +492,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select, if (ref_pointer_array && !ref->found_in_select_list) { int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= select->ref_pointer_array_size); ref_pointer_array[el]= item; /* Add the field item to the select list of the current select. */ all_fields.push_front(item, thd->mem_root); @@ -907,6 +908,7 @@ JOIN::prepare(Item ***rref_pointer_array, { Item_field *field= new (thd->mem_root) Item_field(thd, *(Item_field**)ord->item); int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= select_lex->ref_pointer_array_size); ref_pointer_array[el]= field; all_fields.push_front(field, thd->mem_root); ord->item= ref_pointer_array + el; @@ -21980,6 +21982,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, return TRUE; /* Wrong field. */ uint el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= + thd->lex->current_select->ref_pointer_array_size); /* Add new field to field list. */ all_fields.push_front(order_item, thd->mem_root); ref_pointer_array[el]= order_item; @@ -22240,6 +22244,8 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, */ Item_field *new_item= new (thd->mem_root) Item_field(thd, (Item_field*)item); int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= + thd->lex->current_select->ref_pointer_array_size); orig_ref_pointer_array[el]= new_item; all_fields.push_front(new_item, thd->mem_root); ord->item= orig_ref_pointer_array + el; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 021e4c37e86..28e76ae43f1 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -592,6 +592,8 @@ public: stat_file->extra(HA_EXTRA_FLUSH); return FALSE; } + + friend class Stat_table_write_iter; }; @@ -888,7 +890,7 @@ public: @note A value from the field min_value/max_value is always converted - into a utf8 string. If the length of the column 'min_value'/'max_value' + into a varbinary string. If the length of the column 'min_value'/'max_value' is less than the length of the string the string is trimmed to fit the length of the column. */ @@ -896,7 +898,7 @@ public: void store_stat_fields() { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { @@ -913,7 +915,7 @@ public: else { table_field->collected_stats->min_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin); + stat_field->store(val.ptr(), val.length(), &my_charset_bin); } break; case COLUMN_STAT_MAX_VALUE: @@ -922,7 +924,7 @@ public: else { table_field->collected_stats->max_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin); + stat_field->store(val.ptr(), val.length(), &my_charset_bin); } break; case COLUMN_STAT_NULLS_RATIO: @@ -983,7 +985,7 @@ public: if (find_stat()) { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++) { @@ -1002,12 +1004,12 @@ public: case COLUMN_STAT_MIN_VALUE: stat_field->val_str(&val); table_field->read_stats->min_value->store(val.ptr(), val.length(), - &my_charset_utf8_bin); + &my_charset_bin); break; case COLUMN_STAT_MAX_VALUE: stat_field->val_str(&val); table_field->read_stats->max_value->store(val.ptr(), val.length(), - &my_charset_utf8_bin); + &my_charset_bin); break; case COLUMN_STAT_NULLS_RATIO: table_field->read_stats->set_nulls_ratio(stat_field->val_real()); @@ -1053,7 +1055,7 @@ public: if (find_stat()) { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); uint fldno= COLUMN_STAT_HISTOGRAM; Field *stat_field= stat_table->field[fldno]; table_field->read_stats->set_not_null(fldno); @@ -1264,6 +1266,117 @@ public: }; + +/* + An iterator to enumerate statistics table rows which allows to modify + the rows while reading them. + + Used by RENAME TABLE handling to assign new dbname.tablename to statistic + rows. +*/ +class Stat_table_write_iter +{ + Stat_table *owner; + IO_CACHE io_cache; + uchar *rowid_buf; + uint rowid_size; + +public: + Stat_table_write_iter(Stat_table *stat_table_arg) + : owner(stat_table_arg), rowid_buf(NULL), + rowid_size(owner->stat_file->ref_length) + { + my_b_clear(&io_cache); + } + + /* + Initialize the iterator. It will return rows with n_keyparts matching the + curernt values. + + @return false - OK + true - Error + */ + bool init(uint n_keyparts) + { + if (!(rowid_buf= (uchar*)my_malloc(rowid_size, MYF(0)))) + return true; + + if (open_cached_file(&io_cache, mysql_tmpdir, TEMP_PREFIX, + 1024, MYF(MY_WME))) + return true; + + handler *h= owner->stat_file; + uchar key[MAX_KEY_LENGTH]; + uint prefix_len= 0; + for (uint i= 0; i < n_keyparts; i++) + prefix_len += owner->stat_key_info->key_part[i].store_length; + + key_copy(key, owner->record[0], owner->stat_key_info, + prefix_len); + key_part_map prefix_map= (key_part_map) ((1 << n_keyparts) - 1); + h->ha_index_init(owner->stat_key_idx, false); + int res= h->ha_index_read_map(owner->record[0], key, prefix_map, + HA_READ_KEY_EXACT); + if (res) + { + reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0); + /* "Key not found" is not considered an error */ + return (res == HA_ERR_KEY_NOT_FOUND)? false: true; + } + + do { + h->position(owner->record[0]); + my_b_write(&io_cache, h->ref, rowid_size); + + } while (!h->ha_index_next_same(owner->record[0], key, prefix_len)); + + /* Prepare for reading */ + reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0); + h->ha_index_or_rnd_end(); + if (h->ha_rnd_init(false)) + return true; + + return false; + } + + /* + Read the next row. + + @return + false OK + true No more rows or error. + */ + bool get_next_row() + { + if (!my_b_inited(&io_cache) || my_b_read(&io_cache, rowid_buf, rowid_size)) + return true; /* No more data */ + + handler *h= owner->stat_file; + /* + We should normally be able to find the row that we have rowid for. If we + don't, let's consider this an error. + */ + int res= h->ha_rnd_pos(owner->record[0], rowid_buf); + + return (res==0)? false : true; + } + + void cleanup() + { + if (rowid_buf) + my_free(rowid_buf); + rowid_buf= NULL; + owner->stat_file->ha_index_or_rnd_end(); + close_cached_file(&io_cache); + my_b_clear(&io_cache); + } + + ~Stat_table_write_iter() + { + cleanup(); + } +}; + /* Histogram_builder is a helper class that is used to build histograms for columns @@ -3285,25 +3398,34 @@ int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab, stat_table= tables[INDEX_STAT].table; Index_stat index_stat(stat_table, db, tab); index_stat.set_full_table_name(); - while (index_stat.find_next_stat_for_prefix(2)) + + Stat_table_write_iter index_iter(&index_stat); + if (index_iter.init(2)) + rc= 1; + while (!index_iter.get_next_row()) { err= index_stat.update_table_name_key_parts(new_db, new_tab); if (err & !rc) rc= 1; index_stat.set_full_table_name(); } + index_iter.cleanup(); /* Rename table in the statistical table column_stats */ stat_table= tables[COLUMN_STAT].table; Column_stat column_stat(stat_table, db, tab); column_stat.set_full_table_name(); - while (column_stat.find_next_stat_for_prefix(2)) + Stat_table_write_iter column_iter(&column_stat); + if (column_iter.init(2)) + rc= 1; + while (!column_iter.get_next_row()) { err= column_stat.update_table_name_key_parts(new_db, new_tab); if (err & !rc) rc= 1; column_stat.set_full_table_name(); } + column_iter.cleanup(); /* Rename table in the statistical table table_stats */ stat_table= tables[TABLE_STAT].table; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 35d736ea8a3..5af13273130 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5848,6 +5848,13 @@ drop_create_field: { if (!key->if_not_exists() && !key->or_replace()) continue; + + /* Check if the table already has a PRIMARY KEY */ + bool dup_primary_key= key->type == Key::PRIMARY && + table->s->primary_key != MAX_KEY; + if (dup_primary_key) + goto remove_key; + /* If the name of the key is not specified, */ /* let us check the name of the first key part. */ if ((keyname= key->name.str) == NULL) @@ -5915,8 +5922,8 @@ remove_key: if (key->if_not_exists()) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_DUP_KEYNAME, ER_THD(thd, ER_DUP_KEYNAME), - keyname); + ER_DUP_KEYNAME, ER_THD(thd, dup_primary_key + ? ER_MULTIPLE_PRI_KEY : ER_DUP_KEYNAME), keyname); key_it.remove(); if (key->type == Key::FOREIGN_KEY) { diff --git a/sql/sql_time.cc b/sql/sql_time.cc index ccba3d16575..9785a1691af 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -19,7 +19,6 @@ #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED by other includes #include "sql_time.h" #include "tztime.h" // struct Time_zone #include "sql_class.h" // THD diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 52892550d35..7dfe8939945 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <mysqld_error.h> + /* Forward declarations */ class Item_trigger_field; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7a66cc3734c..0caae7ac821 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -22,7 +22,6 @@ #include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_update.h" #include "sql_cache.h" // query_cache_* #include "sql_base.h" // close_tables_for_reopen @@ -366,6 +365,9 @@ int mysql_update(THD *thd, DBUG_RETURN(1); /* purecov: inspected */ } + if (check_unique_table(thd, table_list)) + DBUG_RETURN(TRUE); + /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); @@ -460,7 +462,8 @@ int mysql_update(THD *thd, query_plan.scanned_rows= select? select->records: table->file->stats.records; if (select && select->quick && select->quick->unique_key_range()) - { // Single row select (always "ordered"): Ok to use with key field UPDATE + { + /* Single row select (always "ordered"): Ok to use with key field UPDATE */ need_sort= FALSE; query_plan.index= MAX_KEY; used_key_is_modified= FALSE; @@ -469,7 +472,8 @@ int mysql_update(THD *thd, { ha_rows scanned_limit= query_plan.scanned_rows; query_plan.index= get_index_for_order(order, table, select, limit, - &scanned_limit, &need_sort, &reverse); + &scanned_limit, &need_sort, + &reverse); if (!need_sort) query_plan.scanned_rows= scanned_limit; @@ -482,12 +486,15 @@ int mysql_update(THD *thd, else { if (need_sort) - { // Assign table scan index to check below for modified key fields: + { + /* Assign table scan index to check below for modified key fields: */ query_plan.index= table->file->key_used_on_scan; } if (query_plan.index != MAX_KEY) - { // Check if we are modifying a key that we are used to search with: - used_key_is_modified= is_key_used(table, query_plan.index, table->write_set); + { + /* Check if we are modifying a key that we are used to search with: */ + used_key_is_modified= is_key_used(table, query_plan.index, + table->write_set); } } } @@ -604,19 +611,20 @@ int mysql_update(THD *thd, B. query_plan.index != MAX_KEY B.1 quick select is used, start the scan with init_read_record B.2 quick select is not used, this is full index scan (with LIMIT) - Full index scan must be started with init_read_record_idx + Full index scan must be started with init_read_record_idx */ if (query_plan.index == MAX_KEY || (select && select->quick)) + error= init_read_record(&info, thd, table, select, 0, 1, FALSE); + else + error= init_read_record_idx(&info, thd, table, 1, query_plan.index, + reverse); + + if (error) { - if (init_read_record(&info, thd, table, select, 0, 1, FALSE)) - { - close_cached_file(&tempfile); - goto err; - } + close_cached_file(&tempfile); + goto err; } - else - init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); THD_STAGE_INFO(thd, stage_searching_rows_for_update); ha_rows tmp_limit= limit; @@ -1115,19 +1123,30 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); - /* Check that we are not using table that we are updating in a sub select */ - { - TABLE_LIST *duplicate; - if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) - { - update_non_unique_table_error(table_list, "UPDATE", duplicate); - DBUG_RETURN(TRUE); - } - } select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } +/** + Check that we are not using table that we are updating in a sub select + + @param thd Thread handle + @param table_list List of table with first to check + + @retval TRUE Error + @retval FALSE OK +*/ +bool check_unique_table(THD *thd, TABLE_LIST *table_list) +{ + TABLE_LIST *duplicate; + DBUG_ENTER("check_unique_table"); + if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) + { + update_non_unique_table_error(table_list, "UPDATE", duplicate); + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} /*************************************************************************** Update multiple tables from join diff --git a/sql/sql_update.h b/sql/sql_update.h index 64029c5d634..4c6f89d8468 100644 --- a/sql/sql_update.h +++ b/sql/sql_update.h @@ -27,6 +27,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT; bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order); +bool check_unique_table(THD *thd, TABLE_LIST *table_list); int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, List<Item> &values,COND *conds, uint order_num, ORDER *order, ha_rows limit, diff --git a/sql/sql_view.cc b/sql/sql_view.cc index b240958898c..85189fa481f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1532,6 +1532,11 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, */ lex->sql_command= old_lex->sql_command; lex->duplicates= old_lex->duplicates; + + /* Fields in this view can be used in upper select in case of merge. */ + if (table->select_lex) + table->select_lex->select_n_where_fields+= + lex->select_lex.select_n_where_fields; } /* This method has a dependency on the proper lock type being set, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6f05a2c6d9e..a5a62aeeafb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -35,7 +35,6 @@ #define Select Lex->current_select #include <my_global.h> #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" /* comp_*_creator */ #include "sql_table.h" /* primary_key_name */ #include "sql_partition.h" /* mem_alloc_error, partition_info, HASH_PARTITION */ @@ -10909,6 +10908,15 @@ table_factor: sel->add_joined_table($$); lex->pop_context(); lex->nest_level--; + /* + Fields in derived table can be used in upper select in + case of merge. We do not add HAVING fields because we do + not merge such derived. We do not add union because + also do not merge them + */ + if (!sel->next_select()) + $2->select_n_where_fields+= + sel->select_n_where_fields; } /*else if (($3->select_lex && $3->select_lex->master_unit()->is_union() && @@ -15418,6 +15426,9 @@ current_role: grant_role: ident_or_text { + CHARSET_INFO *cs= system_charset_info; + /* trim end spaces (as they'll be lost in mysql.user anyway) */ + $1.length= cs->cset->lengthsp(cs, $1.str, $1.length); if ($1.length == 0) { my_error(ER_INVALID_ROLE, MYF(0), ""); @@ -15433,7 +15444,7 @@ grant_role: if (check_string_char_length(&$$->user, ER_USERNAME, username_char_length, - system_charset_info, 0)) + cs, 0)) MYSQL_YYABORT; } | current_role diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 682d8039478..b3900dd5208 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -839,30 +839,26 @@ static Sys_var_ulong Sys_delayed_queue_size( VALID_RANGE(1, UINT_MAX), DEFAULT(DELAYED_QUEUE_SIZE), BLOCK_SIZE(1)); #ifdef HAVE_EVENT_SCHEDULER -static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", NullS }; +static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", + "ORIGINAL", NullS }; static bool event_scheduler_check(sys_var *self, THD *thd, set_var *var) { - /* DISABLED is only accepted on the command line */ - if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) - return true; - /* - If the scheduler was disabled because there are no/bad - system tables, produce a more meaningful error message - than ER_OPTION_PREVENTS_STATEMENT - */ - if (Events::check_if_system_tables_error()) - return true; if (Events::opt_event_scheduler == Events::EVENTS_DISABLED) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables"); return true; } + /* DISABLED is only accepted on the command line */ + if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) + return true; return false; } + static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) { int err_no= 0; + bool ret; uint opt_event_scheduler_value= Events::opt_event_scheduler; mysql_mutex_unlock(&LOCK_global_system_variables); /* @@ -881,9 +877,25 @@ static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) rare and it's difficult to avoid it without opening up possibilities for deadlocks. See bug#51160. */ - bool ret= opt_event_scheduler_value == Events::EVENTS_ON - ? Events::start(&err_no) - : Events::stop(); + + /* EVENTS_ORIGINAL means we should revert back to the startup state */ + if (opt_event_scheduler_value == Events::EVENTS_ORIGINAL) + { + opt_event_scheduler_value= Events::opt_event_scheduler= + Events::startup_state; + } + + /* + If the scheduler was not properly inited (because of wrong system tables), + try to init it again. This is needed for mysql_upgrade to work properly if + the event tables where upgraded. + */ + if (!Events::inited && (Events::init(thd, 0) || !Events::inited)) + ret= 1; + else + ret= opt_event_scheduler_value == Events::EVENTS_ON ? + Events::start(&err_no) : + Events::stop(); mysql_mutex_lock(&LOCK_global_system_variables); if (ret) { @@ -3388,7 +3400,7 @@ static char *server_version_compile_machine_ptr; static Sys_var_charptr Sys_version_compile_machine( "version_compile_machine", "version_compile_machine", READ_ONLY GLOBAL_VAR(server_version_compile_machine_ptr), - CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(MACHINE_TYPE)); + CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(DEFAULT_MACHINE)); static char *server_version_compile_os_ptr; static Sys_var_charptr Sys_version_compile_os( diff --git a/sql/table.cc b/sql/table.cc index 9c90e5026b8..6dedd2f8acc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -19,7 +19,6 @@ #include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "table.h" #include "key.h" // find_ref_key #include "sql_table.h" // build_table_filename, |