diff options
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r-- | sql/sql_show.cc | 469 |
1 files changed, 287 insertions, 182 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1e4723d1529..42da649e3d7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,8 +106,7 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), /* Match the values of enum ha_choice */ static const char *ha_choice_values[] = {"", "0", "1"}; -static void store_key_options(THD *thd, String *packet, TABLE *table, - KEY *key_info); +static void store_key_options(THD *, String *, TABLE *, KEY *); #ifdef WITH_PARTITION_STORAGE_ENGINE static void get_cs_converted_string_value(THD *thd, @@ -451,14 +450,19 @@ bool mysqld_show_authors(THD *thd) { List<Item> field_list; Protocol *protocol= thd->protocol; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_show_authors"); - field_list.push_back(new Item_empty_string("Name",40)); - field_list.push_back(new Item_empty_string("Location",40)); - field_list.push_back(new Item_empty_string("Comment",512)); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Name", 40), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Location", 40), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Comment", 512), + mem_root); if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) DBUG_RETURN(TRUE); show_table_authors_st *authors; @@ -485,14 +489,19 @@ bool mysqld_show_contributors(THD *thd) { List<Item> field_list; Protocol *protocol= thd->protocol; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_show_contributors"); - field_list.push_back(new Item_empty_string("Name",40)); - field_list.push_back(new Item_empty_string("Location",40)); - field_list.push_back(new Item_empty_string("Comment", 512)); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Name", 40), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Location", 40), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Comment", 512), + mem_root); if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) DBUG_RETURN(TRUE); show_table_contributors_st *contributors; @@ -562,14 +571,20 @@ bool mysqld_show_privileges(THD *thd) { List<Item> field_list; Protocol *protocol= thd->protocol; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_show_privileges"); - field_list.push_back(new Item_empty_string("Privilege",10)); - field_list.push_back(new Item_empty_string("Context",15)); - field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN)); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Privilege", 10), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Context", 15), + mem_root); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Comment", + NAME_CHAR_LEN), + mem_root); if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) DBUG_RETURN(TRUE); show_privileges_st *privilege= sys_privileges; @@ -1002,13 +1017,13 @@ public: failed is not available at this point. The only way for us to check is by reconstructing the actual error message and see if it's the same. */ - char* get_view_access_denied_message() + char* get_view_access_denied_message(THD *thd) { if (!m_view_access_denied_message_ptr) { m_view_access_denied_message_ptr= m_view_access_denied_message; my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE, - ER(ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW", + ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW", m_sctx->priv_user, m_sctx->host_or_ip, m_top_view->get_table_name()); } @@ -1033,7 +1048,7 @@ public: switch (sql_errno) { case ER_TABLEACCESS_DENIED_ERROR: - if (!strcmp(get_view_access_denied_message(), message)) + if (!strcmp(get_view_access_denied_message(thd), message)) { /* Access to top view is not granted, don't interfere. */ is_handled= FALSE; @@ -1053,7 +1068,7 @@ public: are missing. */ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_VIEW_INVALID, - ER(ER_VIEW_INVALID), + ER_THD(thd, ER_VIEW_INVALID), m_top_view->get_db_name(), m_top_view->get_table_name()); is_handled= TRUE; @@ -1092,6 +1107,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) String buffer(buff, sizeof(buff), system_charset_info); List<Item> field_list; bool error= TRUE; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_show_create"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->table_name)); @@ -1144,24 +1160,37 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) if (table_list->view) { - field_list.push_back(new Item_empty_string("View",NAME_CHAR_LEN)); - field_list.push_back(new Item_empty_string("Create View", - MY_MAX(buffer.length(),1024))); - field_list.push_back(new Item_empty_string("character_set_client", - MY_CS_NAME_SIZE)); - field_list.push_back(new Item_empty_string("collation_connection", - MY_CS_NAME_SIZE)); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "View", NAME_CHAR_LEN), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Create View", + MY_MAX(buffer.length(),1024)), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "character_set_client", + MY_CS_NAME_SIZE), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "collation_connection", + MY_CS_NAME_SIZE), + mem_root); } else { - field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN)); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Table", NAME_CHAR_LEN), + mem_root); // 1024 is for not to confuse old clients - field_list.push_back(new Item_empty_string("Create Table", - MY_MAX(buffer.length(),1024))); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Create Table", + MY_MAX(buffer.length(),1024)), + mem_root); } if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) goto exit; protocol->prepare_for_resend(); @@ -1215,6 +1244,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, #endif Schema_specification_st create; Protocol *protocol=thd->protocol; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysql_show_create_db"); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1228,7 +1258,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, status_var_increment(thd->status_var.access_denied_errors); my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->host_or_ip, dbname->str); - general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + general_log_print(thd,COM_INIT_DB,ER_THD(thd, ER_DBACCESS_DENIED_ERROR), sctx->priv_user, sctx->host_or_ip, orig_dbname->str); DBUG_RETURN(TRUE); } @@ -1249,11 +1279,16 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, load_db_opt_by_name(thd, dbname->str, &create); } List<Item> field_list; - field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN)); - field_list.push_back(new Item_empty_string("Create Database",1024)); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Database", NAME_CHAR_LEN), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Create Database", 1024), + mem_root); if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) DBUG_RETURN(TRUE); protocol->prepare_for_resend(); @@ -1295,6 +1330,7 @@ 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)); @@ -1313,16 +1349,19 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) !wild_case_compare(system_charset_info, field->field_name,wild)) { if (table_list->view) - field_list.push_back(new Item_ident_for_show(field, - table_list->view_db.str, - table_list->view_name.str)); + 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 Item_field(field)); + field_list.push_back(new (mem_root) Item_field(thd, field), mem_root); } } 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_result_set_metadata(&field_list, + Protocol::SEND_DEFAULTS)) DBUG_VOID_RETURN; my_eof(thd); DBUG_VOID_RETURN; @@ -1810,35 +1849,36 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, else packet->append(STRING_WITH_LEN(" VIRTUAL")); } - - if (flags & NOT_NULL_FLAG) - packet->append(STRING_WITH_LEN(" NOT NULL")); - else if (field->type() == MYSQL_TYPE_TIMESTAMP) - { - /* - TIMESTAMP field require explicit NULL flag, because unlike - all other fields they are treated as NOT NULL by default. - */ - packet->append(STRING_WITH_LEN(" NULL")); - } - - if (!field->vcol_info && - get_field_default_value(thd, field, &def_value, 1)) + else { - packet->append(STRING_WITH_LEN(" DEFAULT ")); - packet->append(def_value.ptr(), def_value.length(), system_charset_info); - } + if (flags & NOT_NULL_FLAG) + packet->append(STRING_WITH_LEN(" NOT NULL")); + else if (field->type() == MYSQL_TYPE_TIMESTAMP) + { + /* + TIMESTAMP field require explicit NULL flag, because unlike + all other fields they are treated as NOT NULL by default. + */ + packet->append(STRING_WITH_LEN(" NULL")); + } - if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false)) - { - packet->append(STRING_WITH_LEN(" ")); - packet->append(def_value); - } + if (get_field_default_value(thd, field, &def_value, 1)) + { + packet->append(STRING_WITH_LEN(" DEFAULT ")); + packet->append(def_value.ptr(), def_value.length(), system_charset_info); + } + if (!limited_mysql_mode && + print_on_update_clause(field, &def_value, false)) + { + packet->append(STRING_WITH_LEN(" ")); + packet->append(def_value); + } - if (field->unireg_check == Field::NEXT_NUMBER && - !(sql_mode & MODE_NO_FIELD_OPTIONS)) - packet->append(STRING_WITH_LEN(" AUTO_INCREMENT")); + if (field->unireg_check == Field::NEXT_NUMBER && + !(sql_mode & MODE_NO_FIELD_OPTIONS)) + packet->append(STRING_WITH_LEN(" AUTO_INCREMENT")); + } if (field->comment.length) { @@ -2152,11 +2192,13 @@ static void store_key_options(THD *thd, String *packet, TABLE *table, } -void -view_store_options(THD *thd, TABLE_LIST *table, String *buff) +void view_store_options(THD *thd, TABLE_LIST *table, String *buff) { - buff->append(STRING_WITH_LEN("ALGORITHM=")); - buff->append(view_algorithm(table)); + if (table->algorithm != VIEW_ALGORITHM_INHERIT) + { + buff->append(STRING_WITH_LEN("ALGORITHM=")); + buff->append(view_algorithm(table)); + } buff->append(' '); append_definer(thd, buff, &table->definer.user, &table->definer.host); if (table->view_suid) @@ -2166,15 +2208,8 @@ view_store_options(THD *thd, TABLE_LIST *table, String *buff) } -/* - Append DEFINER clause to the given buffer. - - SYNOPSIS - append_definer() - thd [in] thread handle - buffer [inout] buffer to hold DEFINER clause - definer_user [in] user name part of definer - definer_host [in] host name part of definer +/** + Returns ALGORITHM clause of a view */ static const LEX_STRING *view_algorithm(TABLE_LIST *table) @@ -2292,16 +2327,15 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) class thread_info :public ilink { public: - static void *operator new(size_t size) - { - return (void*) sql_alloc((uint) size); - } + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () + { return alloc_root(mem_root, size); } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) { TRASH(ptr, size); } ulong thread_id; - time_t start_time; + ulong os_thread_id; + ulonglong start_time; uint command; const char *user,*host,*db,*proc_info,*state_info; CSET_STRING query_string; @@ -2340,28 +2374,49 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) ulong max_query_length= (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"); - field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS)); - field_list.push_back(new Item_empty_string("User", USERNAME_CHAR_LENGTH)); - field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN)); - field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN)); + field_list.push_back(new (mem_root) + Item_int(thd, "Id", 0, MY_INT32_NUM_DECIMAL_DIGITS), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "User", + USERNAME_CHAR_LENGTH), + mem_root); + field_list.push_back(new (mem_root) + Item_empty_string(thd, "Host", + LIST_PROCESS_HOST_LEN), + mem_root); + field_list.push_back(field=new (mem_root) + Item_empty_string(thd, "db", NAME_CHAR_LEN), + mem_root); field->maybe_null=1; - field_list.push_back(new Item_empty_string("Command",16)); - field_list.push_back(field= new Item_return_int("Time",7, MYSQL_TYPE_LONG)); + field_list.push_back(new (mem_root) Item_empty_string(thd, "Command", 16), + mem_root); + field_list.push_back(field= new (mem_root) + Item_return_int(thd, "Time", 7, MYSQL_TYPE_LONG), + mem_root); field->unsigned_flag= 0; - field_list.push_back(field=new Item_empty_string("State",30)); + field_list.push_back(field=new (mem_root) + Item_empty_string(thd, "State", 30), + mem_root); field->maybe_null=1; - field_list.push_back(field=new Item_empty_string("Info",max_query_length)); + field_list.push_back(field=new (mem_root) + Item_empty_string(thd, "Info", max_query_length), + mem_root); field->maybe_null=1; if (!thd->variables.old_mode && !(thd->variables.old_behavior & OLD_MODE_NO_PROGRESS_INFO)) { - field_list.push_back(field= new Item_float("Progress", 0.0, 3, 7)); + field_list.push_back(field= new (mem_root) + Item_float(thd, "Progress", 0.0, 3, 7), + mem_root); field->maybe_null= 0; } if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) DBUG_VOID_RETURN; if (thd->killed) @@ -2375,11 +2430,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) Security_context *tmp_sctx= tmp->security_ctx; struct st_my_thread_var *mysys_var; if ((tmp->vio_ok() || tmp->system_thread) && - (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) + (!user || (!tmp->system_thread && + tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) { - thread_info *thd_info= new thread_info; + 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")); @@ -2432,7 +2489,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) } else thd_info->progress= 0.0; - thd_info->start_time= tmp->start_time; + 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 mysql_mutex_unlock(&tmp->LOCK_thd_data); thread_infos.append(thd_info); } @@ -2440,7 +2500,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) mysql_mutex_unlock(&LOCK_thread_count); thread_info *thd_info; - time_t now= my_time(0); + ulonglong now= microsecond_interval_timer(); char buff[20]; // For progress String store_buffer(buff, sizeof(buff), system_charset_info); @@ -2455,8 +2515,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) protocol->store(thd_info->proc_info, system_charset_info); else protocol->store(command_name[thd_info->command].str, system_charset_info); - if (thd_info->start_time) - protocol->store_long ((longlong) (now - thd_info->start_time)); + if (thd_info->start_time && now > thd_info->start_time) + protocol->store_long((now - thd_info->start_time) / HRTIME_RESOLUTION); else protocol->store_null(); protocol->store(thd_info->state_info, system_charset_info); @@ -2530,11 +2590,11 @@ int select_result_explain_buffer::send_data(List<Item> &items) DBUG_RETURN(MY_TEST(res)); } -bool select_result_text_buffer::send_result_set_metadata(List<Item> &fields, uint flag) +bool select_result_text_buffer::send_result_set_metadata(List<Item> &fields, + uint flag) { n_columns= fields.elements; return append_row(fields, true /*send item names */); - return send_data(fields); } @@ -2550,16 +2610,18 @@ int select_result_text_buffer::append_row(List<Item> &items, bool send_names) char **row; int column= 0; - if (!(row= (char**) thd->alloc(sizeof(char*) * n_columns))) + if (!(row= (char**) thd->alloc(sizeof(char*) * n_columns)) || + rows.push_back(row, thd->mem_root)) return true; - rows.push_back(row); while ((item= it++)) { DBUG_ASSERT(column < n_columns); StringBuffer<32> buf; const char *data_ptr; + char *ptr; size_t data_len; + if (send_names) { data_ptr= item->name; @@ -2581,8 +2643,8 @@ int select_result_text_buffer::append_row(List<Item> &items, bool send_names) } } - char *ptr= (char*)thd->alloc(data_len + 1); - memcpy(ptr, data_ptr, data_len + 1); + if (!(ptr= (char*) thd->memdup(data_ptr, data_len + 1))) + return true; row[column]= ptr; column++; @@ -2730,7 +2792,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; char *user; - my_hrtime_t unow= my_hrtime(); + ulonglong unow= microsecond_interval_timer(); DBUG_ENTER("fill_schema_processlist"); DEBUG_SYNC(thd,"fill_schema_processlist_after_unow"); @@ -2753,7 +2815,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) ulonglong max_counter; if ((!tmp->vio_ok() && !tmp->system_thread) || - (user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user)))) + (user && (tmp->system_thread || !tmp_sctx->user || + strcmp(tmp_sctx->user, user)))) continue; restore_record(table, s->default_values); @@ -2793,9 +2856,12 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[4]->store(command_name[tmp->get_command()].str, command_name[tmp->get_command()].length, cs); /* MYSQL_TIME */ - ulonglong start_utime= tmp->start_time * HRTIME_RESOLUTION + tmp->start_time_sec_part; - ulonglong utime= start_utime && start_utime < unow.val - ? unow.val - start_utime : 0; + 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; + table->field[5]->store(utime / HRTIME_RESOLUTION, TRUE); /* STATE */ if ((val= thread_state_info(tmp))) @@ -2859,6 +2925,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[15]->set_notnull(); } + table->field[16]->store(tmp->os_thread_id); + if (schema_table_store_record(thd, table)) { mysql_mutex_unlock(&LOCK_thread_count); @@ -3293,7 +3361,10 @@ void calc_sum_of_all_status(STATUS_VAR *to) /* Add to this status from existing threads */ while ((tmp= it++)) - add_to_status(to, &tmp->status_var); + { + if (!tmp->status_in_global) + add_to_status(to, &tmp->status_var); + } mysql_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; @@ -3519,7 +3590,7 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) } -COND *make_cond_for_info_schema(COND *cond, TABLE_LIST *table) +COND *make_cond_for_info_schema(THD *thd, COND *cond, TABLE_LIST *table) { if (!cond) return (COND*) 0; @@ -3528,16 +3599,16 @@ COND *make_cond_for_info_schema(COND *cond, TABLE_LIST *table) if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) { /* Create new top level AND item */ - Item_cond_and *new_cond=new Item_cond_and; + Item_cond_and *new_cond=new (thd->mem_root) Item_cond_and(thd); if (!new_cond) return (COND*) 0; List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); Item *item; while ((item=li++)) { - Item *fix= make_cond_for_info_schema(item, table); + Item *fix= make_cond_for_info_schema(thd, item, table); if (fix) - new_cond->argument_list()->push_back(fix); + new_cond->argument_list()->push_back(fix, thd->mem_root); } switch (new_cond->argument_list()->elements) { case 0: @@ -3551,17 +3622,17 @@ COND *make_cond_for_info_schema(COND *cond, TABLE_LIST *table) } else { // Or list - Item_cond_or *new_cond=new Item_cond_or; + Item_cond_or *new_cond= new (thd->mem_root) Item_cond_or(thd); if (!new_cond) return (COND*) 0; List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); Item *item; while ((item=li++)) { - Item *fix=make_cond_for_info_schema(item, table); + Item *fix=make_cond_for_info_schema(thd, item, table); if (!fix) return (COND*) 0; - new_cond->argument_list()->push_back(fix); + new_cond->argument_list()->push_back(fix, thd->mem_root); } new_cond->quick_fix_field(); new_cond->top_level_item(); @@ -4353,7 +4424,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_I_S_SKIPPED_TABLE, - ER(ER_WARN_I_S_SKIPPED_TABLE), + ER_THD(thd, ER_WARN_I_S_SKIPPED_TABLE), table_list.db, table_list.table_name); return 0; } @@ -5518,6 +5589,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, sp_head *sp; stored_procedure_type routine_type; bool free_sp_head; + bool error= 0; DBUG_ENTER("store_schema_params"); bzero((char*) &tbl, sizeof(TABLE)); @@ -5568,7 +5640,8 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, &tmp_string); table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs); field_def= &sp->m_return_field_def; - field= make_field(&share, (uchar*) 0, field_def->length, + field= make_field(&share, thd->mem_root, + (uchar*) 0, field_def->length, (uchar*) "", 0, field_def->pack_flag, field_def->sql_type, field_def->charset, field_def->geom_type, field_def->srid, Field::NONE, @@ -5621,7 +5694,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, &tmp_string); table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs); - field= make_field(&share, (uchar*) 0, field_def->length, + field= make_field(&share, thd->mem_root, (uchar*) 0, field_def->length, (uchar*) "", 0, field_def->pack_flag, field_def->sql_type, field_def->charset, field_def->geom_type, field_def->srid, Field::NONE, @@ -5632,17 +5705,15 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, store_column_type(table, field, cs, 6); if (schema_table_store_record(thd, table)) { - free_table_share(&share); - if (free_sp_head) - delete sp; - DBUG_RETURN(1); + error= 1; + break; } } if (free_sp_head) delete sp; } free_table_share(&share); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -5720,7 +5791,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, bzero((char*) &tbl, sizeof(TABLE)); (void) build_table_filename(path, sizeof(path), "", "", "", 0); init_tmp_table_share(thd, &share, "", 0, "", path); - field= make_field(&share, (uchar*) 0, field_def->length, + field= make_field(&share, thd->mem_root, (uchar*) 0, + field_def->length, (uchar*) "", 0, field_def->pack_flag, field_def->sql_type, field_def->charset, field_def->geom_type, field_def->srid, Field::NONE, @@ -7049,7 +7121,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) schema_table_idx == SCH_GLOBAL_VARIABLES) scope= OPT_GLOBAL; - COND *partial_cond= make_cond_for_info_schema(cond, tables); + COND *partial_cond= make_cond_for_info_schema(thd, cond, tables); mysql_rwlock_rdlock(&LOCK_system_variables_hash); res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, scope), @@ -7091,7 +7163,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) tmp1= &thd->status_var; } - COND *partial_cond= make_cond_for_info_schema(cond, tables); + COND *partial_cond= make_cond_for_info_schema(thd, cond, tables); // Evaluate and cache const subqueries now, before the mutex. if (partial_cond) partial_cond->val_int(); @@ -7304,6 +7376,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) ST_SCHEMA_TABLE *schema_table= table_list->schema_table; ST_FIELD_INFO *fields_info= schema_table->fields_info; CHARSET_INFO *cs= system_charset_info; + MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("create_schema_table"); for (; fields_info->field_name; fields_info++) @@ -7314,43 +7387,50 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONGLONG: case MYSQL_TYPE_INT24: - if (!(item= new Item_return_int(fields_info->field_name, - fields_info->field_length, - fields_info->field_type, - fields_info->value))) + if (!(item= new (mem_root) + Item_return_int(thd, fields_info->field_name, + fields_info->field_length, + fields_info->field_type, + fields_info->value))) { DBUG_RETURN(0); } item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED); break; case MYSQL_TYPE_DATE: - if (!(item=new Item_return_date_time(fields_info->field_name, - strlen(fields_info->field_name), - fields_info->field_type))) + if (!(item=new (mem_root) + Item_return_date_time(thd, fields_info->field_name, + strlen(fields_info->field_name), + fields_info->field_type))) DBUG_RETURN(0); break; case MYSQL_TYPE_TIME: - if (!(item=new Item_return_date_time(fields_info->field_name, - strlen(fields_info->field_name), - fields_info->field_type))) + if (!(item=new (mem_root) + Item_return_date_time(thd, fields_info->field_name, + strlen(fields_info->field_name), + fields_info->field_type))) DBUG_RETURN(0); break; case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATETIME: - if (!(item=new Item_return_date_time(fields_info->field_name, - strlen(fields_info->field_name), - fields_info->field_type))) + if (!(item=new (mem_root) + Item_return_date_time(thd, fields_info->field_name, + strlen(fields_info->field_name), + fields_info->field_type))) DBUG_RETURN(0); break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: - if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, - fields_info->field_length)) == NULL) + if ((item= new (mem_root) + Item_float(thd, fields_info->field_name, 0.0, + NOT_FIXED_DEC, + fields_info->field_length)) == NULL) DBUG_RETURN(NULL); break; case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - if (!(item= new Item_decimal((longlong) fields_info->value, false))) + if (!(item= new (mem_root) + Item_decimal(thd, (longlong) fields_info->value, false))) { DBUG_RETURN(0); } @@ -7358,7 +7438,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) Create a type holder, as we want the type of the item to defined the type of the object, not the value */ - if (!(item= new Item_type_holder(thd, item))) + if (!(item= new (mem_root) Item_type_holder(thd, item))) DBUG_RETURN(0); item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED); item->decimals= fields_info->field_length%10; @@ -7374,8 +7454,9 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: - if (!(item= new Item_blob(fields_info->field_name, - fields_info->field_length))) + if (!(item= new (mem_root) + Item_blob(thd, fields_info->field_name, + fields_info->field_length))) { DBUG_RETURN(0); } @@ -7384,7 +7465,8 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) /* Don't let unimplemented types pass through. Could be a grave error. */ DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING); - if (!(item= new Item_empty_string("", fields_info->field_length, cs))) + if (!(item= new (mem_root) + Item_empty_string(thd, "", fields_info->field_length, cs))) { DBUG_RETURN(0); } @@ -7392,7 +7474,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) strlen(fields_info->field_name), cs); break; } - field_list.push_back(item); + field_list.push_back(item, thd->mem_root); item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL); field_count++; } @@ -7443,8 +7525,8 @@ static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { if (field_info->old_name) { - Item_field *field= new Item_field(context, - NullS, NullS, field_info->field_name); + Item_field *field= new (thd->mem_root) + Item_field(thd, context, NullS, NullS, field_info->field_name); if (field) { field->set_name(field_info->old_name, @@ -7470,7 +7552,7 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= &schema_table->fields_info[1]; String buffer(tmp,sizeof(tmp), system_charset_info); - Item_field *field= new Item_field(context, + Item_field *field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (!field || add_item_to_list(thd, field)) return 1; @@ -7505,7 +7587,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(lex->wild->ptr()); buffer.append(')'); } - Item_field *field= new Item_field(context, + Item_field *field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; @@ -7514,7 +7596,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { field->set_name(buffer.ptr(), buffer.length(), system_charset_info); field_info= &schema_table->fields_info[3]; - field= new Item_field(context, NullS, NullS, field_info->field_name); + field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; field->set_name(field_info->old_name, strlen(field_info->old_name), @@ -7538,7 +7620,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) *field_num == 18 || *field_num == 19)) continue; - Item_field *field= new Item_field(context, + Item_field *field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (field) { @@ -7563,7 +7645,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; - Item_field *field= new Item_field(context, + Item_field *field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (field) { @@ -7588,7 +7670,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; - Item_field *field= new Item_field(context, + Item_field *field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); if (field) { @@ -7806,7 +7888,7 @@ static bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond if (plan->has_db_lookup_value() && plan->has_table_lookup_value()) plan->partial_cond= 0; else - plan->partial_cond= make_cond_for_info_schema(cond, tables); + plan->partial_cond= make_cond_for_info_schema(thd, cond, tables); end: DBUG_RETURN(0); @@ -7905,15 +7987,28 @@ bool get_schema_tables_result(JOIN *join, TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_information_schema_tables()) { - bool is_subselect= (&lex->unit != lex->current_select->master_unit() && - lex->current_select->master_unit()->item); + /* + Note, currently I_S tables are filled once per query. + This needs to be changed if if make_cond_for_info_schema() + will preserve outer fields (and thus I_S content will depend on + the outer subquery) - in this new case I_S tables will need to + be re-populated here. + + And in that case, get_all_tables() might be called O(N^2) times + (in self-join of TABLES, for example) and it will allocate + table names on THD::mem_root O(N^2) times. To fix it, get_all_tables + needs to be fixed to use a local memroot, that is reset or destroyed + between get_all_tables invocations. Or fixed not to allocate + table names on THD::memroot if these names don't satisfy lookup_field + */ + const bool is_subselect= false; /* A value of 0 indicates a dummy implementation */ if (table_list->schema_table->fill_table == 0) continue; /* skip I_S optimizations specific to get_all_tables */ - if (thd->lex->describe && + if (lex->describe && (table_list->schema_table->fill_table != get_all_tables)) continue; @@ -7946,7 +8041,6 @@ bool get_schema_tables_result(JOIN *join, } else table_list->table->file->stats.records= 0; - Item *cond= tab->select_cond; if (tab->cache_select && tab->cache_select->cond) @@ -8599,7 +8693,7 @@ ST_FIELD_INFO variables_fields_info[]= { {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name", SKIP_OPEN_TABLE}, - {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 0, "Value", SKIP_OPEN_TABLE}, + {"VARIABLE_VALUE", 2048, MYSQL_TYPE_STRING, 0, 0, "Value", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -8607,10 +8701,10 @@ ST_FIELD_INFO variables_fields_info[]= ST_FIELD_INFO sysvars_fields_info[]= { {"VARIABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0}, - {"SESSION_VALUE", 1024, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, - {"GLOBAL_VALUE", 1024, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, + {"SESSION_VALUE", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, + {"GLOBAL_VALUE", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, {"GLOBAL_VALUE_ORIGIN", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0}, - {"DEFAULT_VALUE", 1024, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, + {"DEFAULT_VALUE", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, 0}, {"VARIABLE_SCOPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0}, {"VARIABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0}, {"VARIABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, 0, 0}, @@ -8648,6 +8742,7 @@ ST_FIELD_INFO processlist_fields_info[]= {"QUERY_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE}, {"INFO_BINARY", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_BLOB, 0, 1, "Info_binary", SKIP_OPEN_TABLE}, + {"TID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Tid", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -9087,10 +9182,8 @@ static bool show_create_trigger_impl(THD *thd, int trigger_idx) { int ret_code; - Protocol *p= thd->protocol; List<Item> fields; - LEX_STRING trg_name; ulonglong trg_sql_mode; LEX_STRING trg_sql_mode_str; @@ -9098,8 +9191,8 @@ static bool show_create_trigger_impl(THD *thd, LEX_STRING trg_client_cs_name; LEX_STRING trg_connection_cl_name; LEX_STRING trg_db_cl_name; - CHARSET_INFO *trg_client_cs; + MEM_ROOT *mem_root= thd->mem_root; /* TODO: Check privileges here. This functionality will be added by @@ -9131,8 +9224,11 @@ static bool show_create_trigger_impl(THD *thd, /* Send header. */ - fields.push_back(new Item_empty_string("Trigger", NAME_LEN)); - fields.push_back(new Item_empty_string("sql_mode", trg_sql_mode_str.length)); + fields.push_back(new (mem_root) Item_empty_string(thd, "Trigger", NAME_LEN), + mem_root); + fields.push_back(new (mem_root) + Item_empty_string(thd, "sql_mode", trg_sql_mode_str.length), + mem_root); { /* @@ -9141,24 +9237,33 @@ static bool show_create_trigger_impl(THD *thd, */ Item_empty_string *stmt_fld= - new Item_empty_string("SQL Original Statement", - MY_MAX(trg_sql_original_stmt.length, 1024)); + new (mem_root) Item_empty_string(thd, "SQL Original Statement", + MY_MAX(trg_sql_original_stmt.length, + 1024)); stmt_fld->maybe_null= TRUE; - fields.push_back(stmt_fld); + fields.push_back(stmt_fld, mem_root); } - fields.push_back(new Item_empty_string("character_set_client", - MY_CS_NAME_SIZE)); + fields.push_back(new (mem_root) + Item_empty_string(thd, "character_set_client", + MY_CS_NAME_SIZE), + mem_root); - fields.push_back(new Item_empty_string("collation_connection", - MY_CS_NAME_SIZE)); + fields.push_back(new (mem_root) + Item_empty_string(thd, "collation_connection", + MY_CS_NAME_SIZE), + mem_root); - fields.push_back(new Item_empty_string("Database Collation", - MY_CS_NAME_SIZE)); + fields.push_back(new (mem_root) + Item_empty_string(thd, "Database Collation", + MY_CS_NAME_SIZE), + mem_root); - if (p->send_result_set_metadata(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + if (p->send_result_set_metadata(&fields, + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) return TRUE; /* Send data. */ |