diff options
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r-- | sql/sql_show.cc | 659 |
1 files changed, 349 insertions, 310 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a0ac96a1c0d..a0cde02be65 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -63,6 +63,7 @@ #include "ha_partition.h" #endif #include "transaction.h" +#include "opt_trace.h" enum enum_i_s_events_fields { @@ -1034,9 +1035,9 @@ find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db, if (!(dirp = my_dir(path, MY_THREAD_SPECIFIC | (db ? 0 : MY_WANT_STAT)))) { if (my_errno == ENOENT) - my_error(ER_BAD_DB_ERROR, MYF(ME_BELL | ME_WAITTANG), db->str); + my_error(ER_BAD_DB_ERROR, MYF(0), db->str); else - my_error(ER_CANT_READ_DIR, MYF(ME_BELL | ME_WAITTANG), path, my_errno); + my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno); DBUG_RETURN(FIND_FILES_DIR); } @@ -1563,7 +1564,6 @@ void mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) { TABLE *table; - MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_list_fields"); DBUG_PRINT("enter",("table: %s", table_list->table_name.str)); @@ -1573,28 +1573,18 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) DBUG_VOID_RETURN; table= table_list->table; - List<Item> field_list; + List<Field> field_list; Field **ptr,*field; for (ptr=table->field ; (field= *ptr); ptr++) { if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name.str,wild)) - { - if (table_list->view) - field_list.push_back(new (mem_root) - Item_ident_for_show(thd, field, - table_list->view_db.str, - table_list->view_name.str), - mem_root); - else - field_list.push_back(new (mem_root) Item_field(thd, field), mem_root); - } + field_list.push_back(field); } restore_record(table, s->default_values); // Get empty record table->use_all_columns(); - if (thd->protocol->send_result_set_metadata(&field_list, - Protocol::SEND_DEFAULTS)) + if (thd->protocol->send_list_fields(&field_list, table_list)) DBUG_VOID_RETURN; my_eof(thd); DBUG_VOID_RETURN; @@ -2089,6 +2079,22 @@ end_options: append_directory(thd, packet, "INDEX", create_info.index_file_name); } +static void append_period(THD *thd, String *packet, const LEX_CSTRING &start, + const LEX_CSTRING &end, const LEX_CSTRING &period, + bool ident) +{ + packet->append(STRING_WITH_LEN(",\n PERIOD FOR ")); + if (ident) + append_identifier(thd, packet, period.str, period.length); + else + packet->append(period); + packet->append(STRING_WITH_LEN(" (")); + append_identifier(thd, packet, start.str, start.length); + packet->append(STRING_WITH_LEN(", ")); + append_identifier(thd, packet, end.str, end.length); + packet->append(STRING_WITH_LEN(")")); +} + /* Build a CREATE TABLE statement for a table. @@ -2127,6 +2133,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, KEY *key_info; TABLE *table= table_list->table; TABLE_SHARE *share= table->s; + TABLE_SHARE::period_info_t &period= share->period; sql_mode_t sql_mode= thd->variables.sql_mode; bool explicit_fields= false; bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | @@ -2227,6 +2234,12 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, field->sql_type(type); packet->append(type.ptr(), type.length(), system_charset_info); + DBUG_EXECUTE_IF("sql_type", + packet->append(" /* "); + packet->append(field->type_handler()->version().ptr()); + packet->append(" */ "); + ); + if (field->has_charset() && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) { if (field->charset() != share->table_charset) @@ -2326,7 +2339,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } - key_info= table->key_info; + key_info= table->s->key_info; primary_key= share->primary_key; for (uint i=0 ; i < share->keys ; i++,key_info++) @@ -2381,7 +2394,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } } packet->append(')'); - store_key_options(thd, packet, table, key_info); + store_key_options(thd, packet, table, &table->key_info[i]); if (key_info->parser) { LEX_CSTRING *parser_name= plugin_name(key_info->parser); @@ -2403,11 +2416,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, DBUG_ASSERT(!explicit_fields || fe->invisible < INVISIBLE_SYSTEM); if (explicit_fields) { - packet->append(STRING_WITH_LEN(",\n PERIOD FOR SYSTEM_TIME (")); - append_identifier(thd,packet,fs->field_name.str, fs->field_name.length); - packet->append(STRING_WITH_LEN(", ")); - append_identifier(thd,packet,fe->field_name.str, fe->field_name.length); - packet->append(STRING_WITH_LEN(")")); + append_period(thd, packet, fs->field_name, fe->field_name, + table->s->vers.name, false); } else { @@ -2416,6 +2426,15 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } } + if (period.name) + { + append_period(thd, packet, + period.start_field(share)->field_name, + period.end_field(share)->field_name, + period.name, true); + } + + /* Get possible foreign key definitions stored in InnoDB and append them to the CREATE TABLE statement @@ -2433,8 +2452,12 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, for (uint i= share->field_check_constraints; i < share->table_check_constraints ; i++) { - StringBuffer<MAX_FIELD_WIDTH> str(&my_charset_utf8mb4_general_ci); Virtual_column_info *check= table->check_constraints[i]; + // period constraint is implicit + if (share->period.constr_name.streq(check->name)) + continue; + + StringBuffer<MAX_FIELD_WIDTH> str(&my_charset_utf8mb4_general_ci); check->print(&str); packet->append(STRING_WITH_LEN(",\n ")); @@ -2506,7 +2529,8 @@ static void store_key_options(THD *thd, String *packet, TABLE *table, if (key_info->algorithm == HA_KEY_ALG_BTREE) packet->append(STRING_WITH_LEN(" USING BTREE")); - if (key_info->algorithm == HA_KEY_ALG_HASH) + if (key_info->algorithm == HA_KEY_ALG_HASH || + key_info->algorithm == HA_KEY_ALG_LONG_HASH) packet->append(STRING_WITH_LEN(" USING HASH")); /* send USING only in non-default case: non-spatial rtree */ @@ -2774,13 +2798,111 @@ static const char *thread_state_info(THD *tmp) } +struct list_callback_arg +{ + list_callback_arg(const char *u, THD *t, ulong m): + user(u), thd(t), max_query_length(m) {} + I_List<thread_info> thread_infos; + const char *user; + THD *thd; + ulong max_query_length; +}; + + +static my_bool list_callback(THD *tmp, list_callback_arg *arg) +{ + + Security_context *tmp_sctx= tmp->security_ctx; + bool got_thd_data; + if ((tmp->vio_ok() || tmp->system_thread) && + (!arg->user || (!tmp->system_thread && + tmp_sctx->user && !strcmp(tmp_sctx->user, arg->user)))) + { + thread_info *thd_info= new (arg->thd->mem_root) thread_info; + + thd_info->thread_id=tmp->thread_id; + thd_info->os_thread_id=tmp->os_thread_id; + thd_info->user= arg->thd->strdup(tmp_sctx->user ? tmp_sctx->user : + (tmp->system_thread ? + "system user" : "unauthenticated user")); + if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && + arg->thd->security_ctx->host_or_ip[0]) + { + if ((thd_info->host= (char*) arg->thd->alloc(LIST_PROCESS_HOST_LEN+1))) + my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, + "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); + } + else + thd_info->host= arg->thd->strdup(tmp_sctx->host_or_ip[0] ? + tmp_sctx->host_or_ip : + tmp_sctx->host ? tmp_sctx->host : ""); + thd_info->command=(int) tmp->get_command(); + + if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) + { + /* This is an approximation */ + thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ? + "Killed" : 0); + + /* The following variables are only safe to access under a lock */ + thd_info->db= 0; + if (tmp->db.str) + thd_info->db= arg->thd->strmake(tmp->db.str, tmp->db.length); + + if (tmp->query()) + { + uint length= MY_MIN(arg->max_query_length, tmp->query_length()); + char *q= arg->thd->strmake(tmp->query(),length); + /* Safety: in case strmake failed, we set length to 0. */ + thd_info->query_string= + CSET_STRING(q, q ? length : 0, tmp->query_charset()); + } + + /* + Progress report. We need to do this under a lock to ensure that all + is from the same stage. + */ + if (tmp->progress.max_counter) + { + uint max_stage= MY_MAX(tmp->progress.max_stage, 1); + thd_info->progress= (((tmp->progress.stage / (double) max_stage) + + ((tmp->progress.counter / + (double) tmp->progress.max_counter) / + (double) max_stage)) * + 100.0); + set_if_smaller(thd_info->progress, 100); + } + else + thd_info->progress= 0.0; + } + else + { + thd_info->proc_info= "Busy"; + thd_info->progress= 0.0; + thd_info->db= ""; + } + + thd_info->state_info= thread_state_info(tmp); + thd_info->start_time= tmp->start_utime; + ulonglong utime_after_query_snapshot= tmp->utime_after_query; + if (thd_info->start_time < utime_after_query_snapshot) + thd_info->start_time= utime_after_query_snapshot; // COM_SLEEP + + if (got_thd_data) + mysql_mutex_unlock(&tmp->LOCK_thd_data); + arg->thread_infos.append(thd_info); + } + return 0; +} + + void mysqld_list_processes(THD *thd,const char *user, bool verbose) { Item *field; List<Item> field_list; - I_List<thread_info> thread_infos; - ulong max_query_length= (verbose ? thd->variables.max_allowed_packet : - PROCESS_LIST_WIDTH); + list_callback_arg arg(user, thd, + verbose ? thd->variables.max_allowed_packet : + PROCESS_LIST_WIDTH); Protocol *protocol= thd->protocol; MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_list_processes"); @@ -2811,7 +2933,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) mem_root); field->maybe_null=1; field_list.push_back(field=new (mem_root) - Item_empty_string(thd, "Info", max_query_length), + Item_empty_string(thd, "Info", arg.max_query_length), mem_root); field->maybe_null=1; if (!thd->variables.old_mode && @@ -2830,102 +2952,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) if (thd->killed) DBUG_VOID_RETURN; - mysql_mutex_lock(&LOCK_thread_count); // For unlink from list - I_List_iterator<THD> it(threads); - THD *tmp; - while ((tmp=it++)) - { - Security_context *tmp_sctx= tmp->security_ctx; - bool got_thd_data; - if ((tmp->vio_ok() || tmp->system_thread) && - (!user || (!tmp->system_thread && - tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) - { - thread_info *thd_info= new (thd->mem_root) thread_info; - - thd_info->thread_id=tmp->thread_id; - thd_info->os_thread_id=tmp->os_thread_id; - thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user : - (tmp->system_thread ? - "system user" : "unauthenticated user")); - if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && - thd->security_ctx->host_or_ip[0]) - { - if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1))) - my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, - "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); - } - else - thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? - tmp_sctx->host_or_ip : - tmp_sctx->host ? tmp_sctx->host : ""); - thd_info->command=(int) tmp->get_command(); - - if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) - { - /* This is an approximation */ - thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ? - "Killed" : 0); - /* - The following variables are only safe to access under a lock - */ - - thd_info->db= 0; - if (tmp->db.str) - thd_info->db= thd->strmake(tmp->db.str, tmp->db.length); - - if (tmp->query()) - { - uint length= MY_MIN(max_query_length, tmp->query_length()); - char *q= thd->strmake(tmp->query(),length); - /* Safety: in case strmake failed, we set length to 0. */ - thd_info->query_string= - CSET_STRING(q, q ? length : 0, tmp->query_charset()); - } - - /* - Progress report. We need to do this under a lock to ensure that all - is from the same stage. - */ - if (tmp->progress.max_counter) - { - uint max_stage= MY_MAX(tmp->progress.max_stage, 1); - thd_info->progress= (((tmp->progress.stage / (double) max_stage) + - ((tmp->progress.counter / - (double) tmp->progress.max_counter) / - (double) max_stage)) * - 100.0); - set_if_smaller(thd_info->progress, 100); - } - else - thd_info->progress= 0.0; - } - else - { - thd_info->proc_info= "Busy"; - thd_info->progress= 0.0; - thd_info->db= ""; - } + server_threads.iterate(list_callback, &arg); - thd_info->state_info= thread_state_info(tmp); - thd_info->start_time= tmp->start_utime; - ulonglong utime_after_query_snapshot= tmp->utime_after_query; - if (thd_info->start_time < utime_after_query_snapshot) - thd_info->start_time= utime_after_query_snapshot; // COM_SLEEP - - if (got_thd_data) - mysql_mutex_unlock(&tmp->LOCK_thd_data); - thread_infos.append(thd_info); - } - } - mysql_mutex_unlock(&LOCK_thread_count); - - thread_info *thd_info; ulonglong now= microsecond_interval_timer(); char buff[20]; // For progress String store_buffer(buff, sizeof(buff), system_charset_info); - while ((thd_info=thread_infos.get())) + while (auto thd_info= arg.thread_infos.get()) { protocol->prepare_for_resend(); protocol->store(thd_info->thread_id); @@ -3209,152 +3242,150 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) } -int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) +struct processlist_callback_arg { - TABLE *table= tables->table; - CHARSET_INFO *cs= system_charset_info; - char *user; - ulonglong unow= microsecond_interval_timer(); - DBUG_ENTER("fill_schema_processlist"); + processlist_callback_arg(THD *thd_arg, TABLE *table_arg): + thd(thd_arg), table(table_arg), unow(microsecond_interval_timer()) {} + THD *thd; + TABLE *table; + ulonglong unow; +}; - DEBUG_SYNC(thd,"fill_schema_processlist_after_unow"); - user= thd->security_ctx->master_access & PROCESS_ACL ? - NullS : thd->security_ctx->priv_user; +static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg) +{ + Security_context *tmp_sctx= tmp->security_ctx; + CHARSET_INFO *cs= system_charset_info; + const char *val; + ulonglong max_counter; + bool got_thd_data; + char *user= arg->thd->security_ctx->master_access & PROCESS_ACL ? + NullS : arg->thd->security_ctx->priv_user; + + if ((!tmp->vio_ok() && !tmp->system_thread) || + (user && (tmp->system_thread || !tmp_sctx->user || + strcmp(tmp_sctx->user, user)))) + return 0; - mysql_mutex_lock(&LOCK_thread_count); + restore_record(arg->table, s->default_values); + /* ID */ + arg->table->field[0]->store((longlong) tmp->thread_id, TRUE); + /* USER */ + val= tmp_sctx->user ? tmp_sctx->user : + (tmp->system_thread ? "system user" : "unauthenticated user"); + arg->table->field[1]->store(val, strlen(val), cs); + /* HOST */ + if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && + arg->thd->security_ctx->host_or_ip[0]) + { + char host[LIST_PROCESS_HOST_LEN + 1]; + my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u", + tmp_sctx->host_or_ip, tmp->peer_port); + arg->table->field[2]->store(host, strlen(host), cs); + } + else + arg->table->field[2]->store(tmp_sctx->host_or_ip, + strlen(tmp_sctx->host_or_ip), cs); - if (!thd->killed) + if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) { - I_List_iterator<THD> it(threads); - THD* tmp; - - while ((tmp= it++)) + /* DB */ + if (tmp->db.str) { - Security_context *tmp_sctx= tmp->security_ctx; - const char *val; - ulonglong max_counter; - bool got_thd_data; - - if ((!tmp->vio_ok() && !tmp->system_thread) || - (user && (tmp->system_thread || !tmp_sctx->user || - strcmp(tmp_sctx->user, user)))) - continue; + arg->table->field[3]->store(tmp->db.str, tmp->db.length, cs); + arg->table->field[3]->set_notnull(); + } + } - restore_record(table, s->default_values); - /* ID */ - table->field[0]->store((longlong) tmp->thread_id, TRUE); - /* USER */ - val= tmp_sctx->user ? tmp_sctx->user : - (tmp->system_thread ? "system user" : "unauthenticated user"); - table->field[1]->store(val, strlen(val), cs); - /* HOST */ - if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && - thd->security_ctx->host_or_ip[0]) - { - char host[LIST_PROCESS_HOST_LEN + 1]; - my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u", - tmp_sctx->host_or_ip, tmp->peer_port); - table->field[2]->store(host, strlen(host), cs); - } - else - table->field[2]->store(tmp_sctx->host_or_ip, - strlen(tmp_sctx->host_or_ip), cs); + /* COMMAND */ + if ((val= (char *) (!got_thd_data ? "Busy" : + (tmp->killed >= KILL_QUERY ? + "Killed" : 0)))) + arg->table->field[4]->store(val, strlen(val), cs); + else + arg->table->field[4]->store(command_name[tmp->get_command()].str, + command_name[tmp->get_command()].length, cs); - if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) - { - /* DB */ - if (tmp->db.str) - { - table->field[3]->store(tmp->db.str, tmp->db.length, cs); - table->field[3]->set_notnull(); - } - } + /* MYSQL_TIME */ + ulonglong utime= tmp->start_utime; + ulonglong utime_after_query_snapshot= tmp->utime_after_query; + if (utime < utime_after_query_snapshot) + utime= utime_after_query_snapshot; // COM_SLEEP + utime= utime && utime < arg->unow ? arg->unow - utime : 0; - /* COMMAND */ - if ((val= (char *) (!got_thd_data ? "Busy" : - (tmp->killed >= KILL_QUERY ? - "Killed" : 0)))) - table->field[4]->store(val, strlen(val), cs); - else - table->field[4]->store(command_name[tmp->get_command()].str, - command_name[tmp->get_command()].length, cs); + arg->table->field[5]->store(utime / HRTIME_RESOLUTION, TRUE); - /* MYSQL_TIME */ - ulonglong utime= tmp->start_utime; - ulonglong utime_after_query_snapshot= tmp->utime_after_query; - if (utime < utime_after_query_snapshot) - utime= utime_after_query_snapshot; // COM_SLEEP - utime= utime && utime < unow ? unow - utime : 0; + if (got_thd_data) + { + if (tmp->query()) + { + arg->table->field[7]->store(tmp->query(), + MY_MIN(PROCESS_LIST_INFO_WIDTH, + tmp->query_length()), cs); + arg->table->field[7]->set_notnull(); - table->field[5]->store(utime / HRTIME_RESOLUTION, TRUE); + /* INFO_BINARY */ + arg->table->field[16]->store(tmp->query(), + MY_MIN(PROCESS_LIST_INFO_WIDTH, + tmp->query_length()), + &my_charset_bin); + arg->table->field[16]->set_notnull(); + } - if (got_thd_data) - { - if (tmp->query()) - { - table->field[7]->store(tmp->query(), - MY_MIN(PROCESS_LIST_INFO_WIDTH, - tmp->query_length()), cs); - table->field[7]->set_notnull(); + /* + Progress report. We need to do this under a lock to ensure that all + is from the same stage. + */ + if ((max_counter= tmp->progress.max_counter)) + { + arg->table->field[9]->store((longlong) tmp->progress.stage + 1, 1); + arg->table->field[10]->store((longlong) tmp->progress.max_stage, 1); + arg->table->field[11]->store((double) tmp->progress.counter / + (double) max_counter*100.0); + } + mysql_mutex_unlock(&tmp->LOCK_thd_data); + } - /* INFO_BINARY */ - table->field[16]->store(tmp->query(), - MY_MIN(PROCESS_LIST_INFO_WIDTH, - tmp->query_length()), - &my_charset_bin); - table->field[16]->set_notnull(); - } + /* STATE */ + if ((val= thread_state_info(tmp))) + { + arg->table->field[6]->store(val, strlen(val), cs); + arg->table->field[6]->set_notnull(); + } - /* - Progress report. We need to do this under a lock to ensure that all - is from the same stage. - */ - if ((max_counter= tmp->progress.max_counter)) - { - table->field[9]->store((longlong) tmp->progress.stage + 1, 1); - table->field[10]->store((longlong) tmp->progress.max_stage, 1); - table->field[11]->store((double) tmp->progress.counter / - (double) max_counter*100.0); - } - mysql_mutex_unlock(&tmp->LOCK_thd_data); - } + /* TIME_MS */ + arg->table->field[8]->store((double)(utime / (HRTIME_RESOLUTION / 1000.0))); - /* STATE */ - if ((val= thread_state_info(tmp))) - { - table->field[6]->store(val, strlen(val), cs); - table->field[6]->set_notnull(); - } + /* + This may become negative if we free a memory allocated by another + thread in this thread. However it's better that we notice it eventually + than hide it. + */ + arg->table->field[12]->store((longlong) tmp->status_var.local_memory_used, + FALSE); + arg->table->field[13]->store((longlong) tmp->status_var.max_local_memory_used, + FALSE); + arg->table->field[14]->store((longlong) tmp->get_examined_row_count(), TRUE); - /* TIME_MS */ - table->field[8]->store((double)(utime / (HRTIME_RESOLUTION / 1000.0))); + /* QUERY_ID */ + arg->table->field[15]->store(tmp->query_id, TRUE); - /* - This may become negative if we free a memory allocated by another - thread in this thread. However it's better that we notice it eventually - than hide it. - */ - table->field[12]->store((longlong) tmp->status_var.local_memory_used, - FALSE); - table->field[13]->store((longlong) tmp->status_var.max_local_memory_used, - FALSE); - table->field[14]->store((longlong) tmp->get_examined_row_count(), TRUE); + arg->table->field[17]->store(tmp->os_thread_id); - /* QUERY_ID */ - table->field[15]->store(tmp->query_id, TRUE); - - table->field[17]->store(tmp->os_thread_id); + if (schema_table_store_record(arg->thd, arg->table)) + return 1; + return 0; +} - if (schema_table_store_record(thd, table)) - { - mysql_mutex_unlock(&LOCK_thread_count); - DBUG_RETURN(1); - } - } - } - mysql_mutex_unlock(&LOCK_thread_count); +int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) +{ + processlist_callback_arg arg(thd, tables->table); + DBUG_ENTER("fill_schema_processlist"); + DEBUG_SYNC(thd,"fill_schema_processlist_after_unow"); + if (!thd->killed && + server_threads.iterate(processlist_callback, &arg)) + DBUG_RETURN(1); DBUG_RETURN(0); } @@ -3416,7 +3447,7 @@ int add_status_vars(SHOW_VAR *list) { int res= 0; if (status_vars_inited) - mysql_mutex_lock(&LOCK_show_status); + mysql_rwlock_wrlock(&LOCK_all_status_vars); if (!all_status_vars.buffer && // array is not allocated yet - do it now my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 250, 50, MYF(0))) { @@ -3431,7 +3462,7 @@ int add_status_vars(SHOW_VAR *list) sort_dynamic(&all_status_vars, show_var_cmp); err: if (status_vars_inited) - mysql_mutex_unlock(&LOCK_show_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return res; } @@ -3493,7 +3524,7 @@ void remove_status_vars(SHOW_VAR *list) { if (status_vars_inited) { - mysql_mutex_lock(&LOCK_show_status); + mysql_rwlock_wrlock(&LOCK_all_status_vars); SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); for (; list->name; list++) @@ -3514,7 +3545,7 @@ void remove_status_vars(SHOW_VAR *list) } } shrink_var_array(&all_status_vars); - mysql_mutex_unlock(&LOCK_show_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); } else { @@ -3810,36 +3841,38 @@ end: Return number of threads used */ -uint calc_sum_of_all_status(STATUS_VAR *to) +struct calc_sum_callback_arg { - uint count= 0; - DBUG_ENTER("calc_sum_of_all_status"); + calc_sum_callback_arg(STATUS_VAR *to_arg): to(to_arg), count(0) {} + STATUS_VAR *to; + uint count; +}; - /* Ensure that thread id not killed during loop */ - mysql_mutex_lock(&LOCK_thread_count); // For unlink from list - I_List_iterator<THD> it(threads); - THD *tmp; +static my_bool calc_sum_callback(THD *thd, calc_sum_callback_arg *arg) +{ + arg->count++; + if (!thd->status_in_global) + { + add_to_status(arg->to, &thd->status_var); + arg->to->local_memory_used+= thd->status_var.local_memory_used; + } + if (thd->get_command() != COM_SLEEP) + arg->to->threads_running++; + return 0; +} + + +uint calc_sum_of_all_status(STATUS_VAR *to) +{ + calc_sum_callback_arg arg(to); + DBUG_ENTER("calc_sum_of_all_status"); - /* Get global values as base */ *to= global_status_var; to->local_memory_used= 0; - /* Add to this status from existing threads */ - while ((tmp= it++)) - { - count++; - if (!tmp->status_in_global) - { - add_to_status(to, &tmp->status_var); - to->local_memory_used+= tmp->status_var.local_memory_used; - } - if (tmp->get_command() != COM_SLEEP) - to->threads_running++; - } - - mysql_mutex_unlock(&LOCK_thread_count); - DBUG_RETURN(count); + server_threads.iterate(calc_sum_callback, &arg); + DBUG_RETURN(arg.count); } @@ -4189,8 +4222,9 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, case SQLCOM_SHOW_TABLE_STATUS: case SQLCOM_SHOW_TRIGGERS: case SQLCOM_SHOW_EVENTS: - thd->make_lex_string(&lookup_field_values->db_value, - lex->select_lex.db.str, lex->select_lex.db.length); + thd->make_lex_string(&lookup_field_values->db_value, + lex->first_select_lex()->db.str, + lex->first_select_lex()->db.length); if (wild) { thd->make_lex_string(&lookup_field_values->table_value, @@ -4583,10 +4617,10 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root, temporary LEX. The latter is required to correctly open views and produce table describing their structure. */ - if (make_table_list(thd, &lex->select_lex, &db_name, &table_name)) + if (make_table_list(thd, lex->first_select_lex(), &db_name, &table_name)) goto end; - table_list= lex->select_lex.table_list.first; + table_list= lex->first_select_lex()->table_list.first; if (is_show_fields_or_keys) { @@ -6375,7 +6409,6 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, const char *wild, bool full_access, const char *sp_user) { - MYSQL_TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; const Sp_handler *sph; @@ -6463,14 +6496,11 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, copy_field_as_string(table->field[22], proc_table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]); - bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_CREATED])-> - get_time(&time); - table->field[23]->store_time(&time); - bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_MODIFIED])-> - get_time(&time); - table->field[24]->store_time(&time); + proc_table->field[MYSQL_PROC_FIELD_CREATED]-> + save_in_field(table->field[23]); + proc_table->field[MYSQL_PROC_FIELD_MODIFIED]-> + save_in_field(table->field[24]); + copy_field_as_string(table->field[25], proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]); copy_field_as_string(table->field[26], @@ -6633,15 +6663,20 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, table->field[8]->set_notnull(); } KEY *key=show_table->key_info+i; - if (key->rec_per_key[j]) + if (key->rec_per_key[j] && key->algorithm != HA_KEY_ALG_LONG_HASH) { ha_rows records= (ha_rows) ((double) show_table->stat_records() / key->actual_rec_per_key(j)); table->field[9]->store((longlong) records, TRUE); table->field[9]->set_notnull(); } - const char *tmp= show_table->file->index_type(i); - table->field[13]->store(tmp, strlen(tmp), cs); + if (key->algorithm == HA_KEY_ALG_LONG_HASH) + table->field[13]->store(STRING_WITH_LEN("HASH"), cs); + else + { + const char *tmp= show_table->file->index_type(i); + table->field[13]->store(tmp, strlen(tmp), cs); + } } if (!(key_info->flags & HA_FULLTEXT) && (key_part->field && @@ -6763,7 +6798,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, & 'field_translation_end' are uninitialized is this case. */ - List<Item> *fields= &tables->view->select_lex.item_list; + List<Item> *fields= &tables->view->first_select_lex()->item_list; List_iterator<Item> it(*fields); Item *item; Item_field *field; @@ -6892,7 +6927,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, { List<FOREIGN_KEY_INFO> f_key_list; TABLE *show_table= tables->table; - KEY *key_info=show_table->key_info; + KEY *key_info=show_table->s->key_info; uint primary_key= show_table->s->primary_key; show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | @@ -7090,7 +7125,7 @@ static int get_schema_key_column_usage_record(THD *thd, { List<FOREIGN_KEY_INFO> f_key_list; TABLE *show_table= tables->table; - KEY *key_info=show_table->key_info; + KEY *key_info=show_table->s->key_info; uint primary_key= show_table->s->primary_key; show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | @@ -7412,7 +7447,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, break; default: DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); DBUG_RETURN(1); } table->field[7]->set_notnull(); @@ -7538,7 +7573,8 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, } else if (part_info->vers_info->interval.is_set()) { - table->field[11]->store_timestamp((my_time_t)part_elem->range_value, 0); + Timeval tv((my_time_t) part_elem->range_value, 0); + table->field[11]->store_timestamp_dec(tv, AUTO_SEC_PART_DIGITS); table->field[11]->set_notnull(); } } @@ -7724,11 +7760,11 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) sch_table->field[ISE_ON_COMPLETION]-> store(STRING_WITH_LEN("PRESERVE"), scs); - number_to_datetime(et.created, 0, &time, 0, ¬_used); + number_to_datetime_or_date(et.created, 0, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); sch_table->field[ISE_CREATED]->store_time(&time); - number_to_datetime(et.modified, 0, &time, 0, ¬_used); + number_to_datetime_or_date(et.modified, 0, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); sch_table->field[ISE_LAST_ALTERED]->store_time(&time); @@ -7774,9 +7810,9 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; OPEN_TABLE_LIST *open_list; - if (unlikely(!(open_list= list_open_tables(thd, thd->lex->select_lex.db.str, - wild))) && - unlikely(thd->is_fatal_error)) + if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db.str, + wild)) + && thd->is_fatal_error) DBUG_RETURN(1); for (; open_list ; open_list=open_list->next) @@ -7869,18 +7905,15 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) if (scope == OPT_GLOBAL) { - /* We only hold LOCK_status for summary status vars */ - mysql_mutex_lock(&LOCK_status); calc_sum_of_all_status(&tmp); - mysql_mutex_unlock(&LOCK_status); } - mysql_mutex_lock(&LOCK_show_status); + mysql_rwlock_rdlock(&LOCK_all_status_vars); res= show_status_array(thd, wild, (SHOW_VAR *)all_status_vars.buffer, scope, tmp1, "", tables->table, upper_case_names, partial_cond); - mysql_mutex_unlock(&LOCK_show_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); DBUG_RETURN(res); } @@ -8270,7 +8303,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->table_charset= cs; tmp_table_param->field_count= field_count; tmp_table_param->schema_table= 1; - SELECT_LEX *select_lex= thd->lex->current_select; + SELECT_LEX *select_lex= table_list->select_lex; bool keep_row_order= is_show_command(thd); if (!(table= create_tmp_table(thd, tmp_table_param, field_list, (ORDER*) 0, 0, 0, @@ -8307,7 +8340,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= schema_table->fields_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; field_info->field_name; field_info++) { if (field_info->old_name) @@ -8367,14 +8400,14 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) char tmp[128]; String buffer(tmp,sizeof(tmp), thd->charset()); LEX *lex= thd->lex; - Name_resolution_context *context= &lex->select_lex.context; + Name_resolution_context *context= &lex->first_select_lex()->context; ST_FIELD_INFO *field_info= &schema_table->fields_info[2]; LEX_CSTRING field_name= {field_info->field_name, strlen(field_info->field_name) }; buffer.length(0); buffer.append(field_info->old_name); - buffer.append(&lex->select_lex.db); + buffer.append(&lex->first_select_lex()->db); if (lex->wild && lex->wild->ptr()) { buffer.append(STRING_WITH_LEN(" (")); @@ -8407,7 +8440,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {3, 15, 14, 6, 16, 5, 17, 18, 19, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { @@ -8438,7 +8471,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {0, 2, 1, 3, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { @@ -8465,7 +8498,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {2, 3, 4, 27, 24, 23, 22, 26, 28, 29, 30, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { @@ -9800,6 +9833,10 @@ ST_FIELD_INFO check_constraints_fields_info[]= OPEN_FULL_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; + +/** For creating fields of information_schema.OPTIMIZER_TRACE */ +extern ST_FIELD_INFO optimizer_trace_info[]; + /* Description of ST_FIELD_INFO in table.h @@ -9852,6 +9889,8 @@ ST_SCHEMA_TABLE schema_tables[]= OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"OPEN_TABLES", open_tables_fields_info, 0, fill_open_tables, make_old_format, 0, -1, -1, 1, 0}, + {"OPTIMIZER_TRACE", optimizer_trace_info, 0, + fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0}, {"PARAMETERS", parameters_fields_info, 0, fill_schema_proc, 0, 0, -1, -1, 0, 0}, {"PARTITIONS", partitions_fields_info, 0, |