diff --git a/mysql-test/collections/default.push b/mysql-test/collections/default.push index 0f4115c8565..638918d1026 100644 --- a/mysql-test/collections/default.push +++ b/mysql-test/collections/default.push @@ -1,2 +1,2 @@ -perl mysql-test-run.pl --timer --force --comment=n_stm -perl mysql-test-run.pl --timer --force --comment=ps_stm --ps-protocol +perl mysql-test-run.pl --timer --force --vardir=var-n_stm --comment=n_stm +perl mysql-test-run.pl --timer --force --vardir=var-ps_stm --comment=ps_stm --ps-protocol diff --git a/mysql-test/r/federated_bug_35333.result b/mysql-test/r/federated_bug_35333.result new file mode 100644 index 00000000000..964fedc3205 --- /dev/null +++ b/mysql-test/r/federated_bug_35333.result @@ -0,0 +1,76 @@ +# +# Bug 35333 "If a Federated table can't connect to the remote hose, can't retrieve metadata" +# +# Queries such as SHOW TABLE STATUS and SELECT * FROM INFORMATION_SCHEMA.TABLES fail +# when encountering a federated table that cannot connect to its remote table. +# +# The fix is to store the error text in the TABLE COMMENTS column of I_S.TABLES, clear +# the remote connection error and push a warning instead. This allows the SELECT operation +# to complete while still indicating a problem. This fix applies to any non-fatal system +# error that occurs during a query against I_S.TABLES.de +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +stop slave; +DROP DATABASE IF EXISTS federated; +CREATE DATABASE federated; +DROP DATABASE IF EXISTS federated; +CREATE DATABASE federated; +CREATE DATABASE IF NOT EXISTS realdb; +DROP TABLE IF EXISTS realdb.t0; +DROP TABLE IF EXISTS federated.t0; +# +# Create the base table to be referenced +# +CREATE TABLE realdb.t0 (a text, b text) ENGINE=MYISAM; +# +# Create a federated table with a bogus port number +# +CREATE TABLE federated.t0 (a text, b text) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:63333/realdb/t0'; +# +# Trigger a federated system error during a INFORMATION_SCHEMA.TABLES query +# +SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT +FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'realdb' or TABLE_SCHEMA = 'federated'; +TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE ROW_FORMAT TABLE_ROWS DATA_LENGTH TABLE_COMMENT +federated t0 NULL NULL NULL NULL Unable to connect to foreign data source: Can't connect to MySQL server on '127. +realdb t0 BASE TABLE MyISAM Dynamic 0 0 +Warnings: +Warning 1429 Unable to connect to foreign data source: Can't connect to MySQL server on '127.0.0.1' (socket errno) +SHOW WARNINGS; +Level Code Message +Warning 1429 Unable to connect to foreign data source: Can't connect to MySQL server on '127.0.0.1' (socket errno) +# +# Create a MyISAM table then corrupt the file +# +USE realdb; +CREATE TABLE t1 (c1 int) ENGINE=MYISAM; +# +# Corrupt the MyISAM table by deleting the base file +# +# +# Trigger a MyISAM system error during an INFORMATION_SCHEMA.TABLES query +# +SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT +FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE ROW_FORMAT TABLE_ROWS DATA_LENGTH TABLE_COMMENT +realdb t1 BASE TABLE NULL NULL NULL NULL Can't find file: 't1' (errno: 2) +Warnings: +Warning 1017 Can't find file: 't1' (errno: 2) +SHOW WARNINGS; +Level Code Message +Warning 1017 Can't find file: 't1' (errno: 2) +# +# Cleanup +# +DROP TABLE IF EXISTS realdb.t0; +DROP TABLE IF EXISTS federated.t0; +DROP DATABASE realdb; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d69a340cddb..ca09a3285ec 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -989,4 +989,22 @@ SELECT 1 FROM 1 1 DROP TABLE t1; +# +# Bug #54476: crash when group_concat and 'with rollup' in prepared statements +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +EXECUTE stmt; +GROUP_CONCAT(t1.a ORDER BY t1.a) +1,1 +2,2 +1,1,2,2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 54fa4be027e..9c3d9e09bad 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1053,6 +1053,8 @@ select table_type from information_schema.tables where table_name="v1"; table_type VIEW +Warnings: +Warning 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1; create temporary table t1(f1 int, index(f1)); show columns from t1; diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 92c5b6de2ec..552114849c4 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -65,10 +65,14 @@ select table_name, table_type, table_comment from information_schema.tables where table_schema='inf%' and func2(); table_name table_type table_comment v1 VIEW View 'inf%.v1' references invalid table(s) or column(s) or function(s) or define +Warnings: +Warning 1356 View 'inf%.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them select table_name, table_type, table_comment from information_schema.tables where table_schema='inf%' and func2(); table_name table_type table_comment v1 VIEW View 'inf%.v1' references invalid table(s) or column(s) or function(s) or define +Warnings: +Warning 1356 View 'inf%.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1; drop function func1; drop function func2; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index ad73fc650a5..2d9565ac54d 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -622,6 +622,8 @@ flush tables; SHOW TABLE STATUS like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 NULL NULL NULL NULL # # # # NULL NULL NULL NULL NULL NULL NULL NULL Incorrect information in file: './test/t1.frm' +Warnings: +Warning 1033 Incorrect information in file: './test/t1.frm' show create table t1; ERROR HY000: Incorrect information in file: './test/t1.frm' drop table t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 715fb225550..d98ef86b7c3 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -840,6 +840,8 @@ show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL # NULL NULL NULL # # NULL NULL NULL NULL View 'test.v1' references invalid table(s) or column(s) or function(s) or define +Warnings: +Warning 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them drop view v1; drop table t1; create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1; diff --git a/mysql-test/t/federated_bug_35333.test b/mysql-test/t/federated_bug_35333.test new file mode 100644 index 00000000000..e04e719827e --- /dev/null +++ b/mysql-test/t/federated_bug_35333.test @@ -0,0 +1,74 @@ +--echo # +--echo # Bug 35333 "If a Federated table can't connect to the remote hose, can't retrieve metadata" +--echo # +--echo # Queries such as SHOW TABLE STATUS and SELECT * FROM INFORMATION_SCHEMA.TABLES fail +--echo # when encountering a federated table that cannot connect to its remote table. +--echo # +--echo # The fix is to store the error text in the TABLE COMMENTS column of I_S.TABLES, clear +--echo # the remote connection error and push a warning instead. This allows the SELECT operation +--echo # to complete while still indicating a problem. This fix applies to any non-fatal system +--echo # error that occurs during a query against I_S.TABLES.de + +--source include/federated.inc + +--disable_warnings +CREATE DATABASE IF NOT EXISTS realdb; +# Federated database exists +DROP TABLE IF EXISTS realdb.t0; +DROP TABLE IF EXISTS federated.t0; +--enable_warnings + +--echo # +--echo # Create the base table to be referenced +--echo # +CREATE TABLE realdb.t0 (a text, b text) ENGINE=MYISAM; + +--echo # +--echo # Create a federated table with a bogus port number +--echo # +CREATE TABLE federated.t0 (a text, b text) ENGINE=FEDERATED + CONNECTION='mysql://root@127.0.0.1:63333/realdb/t0'; + +#--warning ER_CONNECT_TO_FOREIGN_DATA_SOURCE + +--echo # +--echo # Trigger a federated system error during a INFORMATION_SCHEMA.TABLES query +--echo # +# Remove O/S-specific socket error +--replace_regex /\(.*\)/(socket errno)/ +SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT + FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'realdb' or TABLE_SCHEMA = 'federated'; + +# Remove O/S-specific socket error +--replace_regex /\(.*\)/(socket errno)/ +SHOW WARNINGS; + +--echo # +--echo # Create a MyISAM table then corrupt the file +--echo # +USE realdb; +CREATE TABLE t1 (c1 int) ENGINE=MYISAM; +--echo # +--echo # Corrupt the MyISAM table by deleting the base file +--echo # +let $MYSQLD_DATADIR= `SELECT @@datadir`; +--remove_file $MYSQLD_DATADIR/realdb/t1.MYD +--remove_file $MYSQLD_DATADIR/realdb/t1.MYI + +--echo # +--echo # Trigger a MyISAM system error during an INFORMATION_SCHEMA.TABLES query +--echo # +SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT + FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; + +SHOW WARNINGS; +--echo # +--echo # Cleanup +--echo # +--disable_warnings +DROP TABLE IF EXISTS realdb.t0; +DROP TABLE IF EXISTS federated.t0; +DROP DATABASE realdb; +--enable_warnings + +--source include/federated_cleanup.inc diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 1cbf045e95d..ee9ddf1f1a9 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -708,4 +708,18 @@ SELECT 1 FROM DROP TABLE t1; +--echo # +--echo # Bug #54476: crash when group_concat and 'with rollup' in prepared statements +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP"; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4c2bde90100..244ea4c34b6 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3170,7 +3170,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, tree(item->tree), unique_filter(item->unique_filter), table(item->table), - order(item->order), context(item->context), arg_count_order(item->arg_count_order), arg_count_field(item->arg_count_field), @@ -3183,6 +3182,24 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, { quick_group= item->quick_group; result.set_charset(collation.collation); + + /* + Since the ORDER structures pointed to by the elements of the 'order' array + may be modified in find_order_in_list() called from + Item_func_group_concat::setup(), create a copy of those structures so that + such modifications done in this object would not have any effect on the + object being copied. + */ + ORDER *tmp; + if (!(order= (ORDER **) thd->alloc(sizeof(ORDER *) * arg_count_order + + sizeof(ORDER) * arg_count_order))) + return; + tmp= (ORDER *)(order + arg_count_order); + for (uint i= 0; i < arg_count_order; i++, tmp++) + { + memcpy(tmp, item->order[i], sizeof(ORDER)); + order[i]= tmp; + } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 13045280c5f..1075e7f76d1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -48,7 +48,7 @@ bool schema_table_store_record(THD *thd, TABLE *table); /*************************************************************************** -** List all table types supported +** List all table types supported ***************************************************************************/ bool mysqld_show_storage_engines(THD *thd) @@ -65,7 +65,7 @@ bool mysqld_show_storage_engines(THD *thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - const char *default_type_name= + const char *default_type_name= ha_get_storage_engine((enum db_type)thd->variables.table_type); handlerton **types; @@ -406,7 +406,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) /* Clear all messages with 'error' level status and - issue a warning with 'warning' level status in + issue a warning with 'warning' level status in case of invalid view and last error is ER_VIEW_INVALID */ mysql_reset_errors(thd, true); @@ -603,7 +603,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) Field **ptr,*field; for (ptr=table->field ; (field= *ptr); ptr++) { - if (!wild || !wild[0] || + if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) { if (table_list->view) @@ -809,13 +809,13 @@ static bool get_field_default_value(THD *thd, TABLE *table, bool has_default; bool has_now_default; enum enum_field_types field_type= field->type(); - /* + /* We are using CURRENT_TIMESTAMP instead of NOW because it is more standard */ - has_now_default= table->timestamp_field == field && + has_now_default= table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_UN_FIELD; - + has_default= (field_type != FIELD_TYPE_BLOB && !(field->flags & NO_DEFAULT_VALUE_FLAG) && field->unireg_check != Field::NEXT_NUMBER && @@ -837,7 +837,7 @@ static bool get_field_default_value(THD *thd, TABLE *table, char *ptr= longlong2str(dec, tmp + 2, 2); uint32 length= (uint32) (ptr - tmp); tmp[0]= 'b'; - tmp[1]= '\''; + tmp[1]= '\''; tmp[length]= '\''; type.length(length + 1); quoted= 0; @@ -929,7 +929,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) field->sql_type(type); packet->append(type.ptr(), type.length(), system_charset_info); - if (field->has_charset() && + if (field->has_charset() && !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) { if (field->charset() != share->table_charset) @@ -937,8 +937,8 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(STRING_WITH_LEN(" character set ")); packet->append(field->charset()->csname); } - /* - For string types dump collation name only if + /* + For string types dump collation name only if collation is not primary for the given charset */ if (!(field->charset()->state & MY_CS_PRIMARY)) @@ -965,11 +965,11 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(def_value.ptr(), def_value.length(), system_charset_info); } - if (!limited_mysql_mode && table->timestamp_field == field && + if (!limited_mysql_mode && table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD) packet->append(STRING_WITH_LEN(" on update CURRENT_TIMESTAMP")); - if (field->unireg_check == Field::NEXT_NUMBER && + if (field->unireg_check == Field::NEXT_NUMBER && !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS)) packet->append(STRING_WITH_LEN(" auto_increment")); @@ -1088,7 +1088,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(buff, (uint) (end - buff)); } - + if (share->table_charset && !(thd->variables.sql_mode & MODE_MYSQL323) && !(thd->variables.sql_mode & MODE_MYSQL40)) @@ -1179,7 +1179,7 @@ view_store_options(THD *thd, TABLE_LIST *table, String *buff) /* Append DEFINER clause to the given buffer. - + SYNOPSIS append_definer() thd [in] thread handle @@ -1209,7 +1209,7 @@ static void append_algorithm(TABLE_LIST *table, String *buff) /* Append DEFINER clause to the given buffer. - + SYNOPSIS append_definer() thd [in] thread handle @@ -1374,8 +1374,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) "%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 : + thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? + tmp_sctx->host_or_ip : tmp_sctx->host ? tmp_sctx->host : ""); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); @@ -1852,14 +1852,14 @@ void calc_sum_of_all_status(STATUS_VAR *to) I_List_iterator it(threads); THD *tmp; - + /* Get global values as base */ *to= global_status_var; - + /* Add to this status from existing threads */ while ((tmp= it++)) add_to_status(to, &tmp->status_var); - + VOID(pthread_mutex_unlock(&LOCK_thread_count)); DBUG_VOID_RETURN; } @@ -1911,7 +1911,7 @@ bool schema_table_store_record(THD *thd, TABLE *table) int error; if ((error= table->file->write_row(table->record[0]))) { - if (create_myisam_from_heap(thd, table, + if (create_myisam_from_heap(thd, table, table->pos_in_table_list->schema_table_param, error, 0)) return 1; @@ -1946,7 +1946,7 @@ int make_table_list(THD *thd, SELECT_LEX *sel, { Table_ident *table_ident; LEX_STRING ident_db, ident_table; - ident_db.str= db; + ident_db.str= db; ident_db.length= (uint) strlen(db); ident_table.str= table; ident_table.length= (uint) strlen(table); @@ -1980,10 +1980,10 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : ""; if (table->table != item_field->field->table || (cs->coll->strnncollsp(cs, (uchar *) field_name1, (uint) strlen(field_name1), - (uchar *) item_field->field_name, + (uchar *) item_field->field_name, (uint) strlen(item_field->field_name), 0) && cs->coll->strnncollsp(cs, (uchar *) field_name2, (uint) strlen(field_name2), - (uchar *) item_field->field_name, + (uchar *) item_field->field_name, (uint) strlen(item_field->field_name), 0))) return 0; } @@ -2072,7 +2072,7 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table) with_i_schema returns 1 if we added 'IS' name to list otherwise returns 0 is_wild_value if value is 1 then idx_field_vals->db_name is - wild string otherwise it's db name; + wild string otherwise it's db name; RETURN zero success @@ -2094,7 +2094,7 @@ int make_db_list(THD *thd, List *files, LIKE clause (see also get_index_field_values() function) */ if (!idx_field_vals->db_value || - !wild_case_compare(system_charset_info, + !wild_case_compare(system_charset_info, INFORMATION_SCHEMA_NAME.str, idx_field_vals->db_value)) { @@ -2179,7 +2179,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) List bases; List_iterator_fast it(bases); COND *partial_cond; - uint derived_tables= lex->derived_tables; + uint derived_tables= lex->derived_tables; int error= 1; db_type not_used; Open_tables_state open_tables_state_backup; @@ -2217,7 +2217,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) Let us set fake sql_command so views won't try to merge themselves into main statement. If we don't do this, SELECT * from information_schema.xxxx will cause problems. - SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' + SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' */ lex->sql_command= SQLCOM_SHOW_FIELDS; res= open_normal_and_derived_tables(thd, show_table_list, @@ -2227,15 +2227,15 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) get_all_tables() returns 1 on failure and 0 on success thus return only these and not the result code of ::process_table() - We should use show_table_list->alias instead of + We should use show_table_list->alias instead of show_table_list->table_name because table_name could be changed during opening of I_S tables. It's safe - to use alias because alias contains original table name - in this case(this part of code is used only for + to use alias because alias contains original table name + in this case(this part of code is used only for 'show columns' & 'show statistics' commands). */ error= test(schema_table->process_table(thd, show_table_list, - table, res, + table, res, (show_table_list->view ? show_table_list->view_db.str : show_table_list->db), @@ -2263,7 +2263,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) (base_name= select_lex->db) && !bases.elements)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!check_access(thd,SELECT_ACL, base_name, + if (!check_access(thd,SELECT_ACL, base_name, &thd->col_access, 0, 1, with_i_schema) || sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(sctx->host, sctx->ip, sctx->priv_user, base_name,0) || @@ -2281,7 +2281,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) strxmov(path, mysql_data_home, "/", base_name, NullS); end= path + (len= unpack_dirname(path,path)); len= FN_LEN - len; - find_files_result res= find_files(thd, &files, base_name, + find_files_result res= find_files(thd, &files, base_name, path, idx_field_vals.table_value, 0); if (res != FIND_FILES_OK) { @@ -2367,9 +2367,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); lex->sql_command= save_sql_command; - /* + /* They can drop table after table names list creation and - before table opening. We open non existing table and + before table opening. We open non existing table and get ER_NO_SUCH_TABLE error. In this case we do not store the record into I_S table and clear error. */ @@ -2381,10 +2381,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) else { /* - We should use show_table_list->alias instead of + We should use show_table_list->alias instead of show_table_list->table_name because table_name could be changed during opening of I_S tables. It's safe - to use alias because alias contains original table name + to use alias because alias contains original table name in this case. */ res= schema_table->process_table(thd, show_table_list, table, @@ -2486,28 +2486,28 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, { const char *tmp_buff; MYSQL_TIME time; + int info_error= 0; CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_tables_record"); restore_record(table, s->default_values); table->field[1]->store(base_name, (uint) strlen(base_name), cs); table->field[2]->store(file_name, (uint) strlen(file_name), cs); + if (res) { - /* - there was errors during opening tables - */ - const char *error= thd->net.last_error; + /* There was a table open error, so set the table type and return */ if (tables->view) table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); else if (tables->schema_table) table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); else table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); - table->field[20]->store(error, (uint) strlen(error), cs); - thd->clear_error(); + + goto err; } - else if (tables->view) + + if (tables->view) { table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); table->field[20]->store(STRING_WITH_LEN("VIEW"), cs); @@ -2518,8 +2518,15 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, TABLE_SHARE *share= show_table->s; handler *file= show_table->file; - file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO | - HA_STATUS_NO_LOCK); + if (!file) + goto err; + + if ((info_error= file->info(HA_STATUS_VARIABLE | + HA_STATUS_TIME | + HA_STATUS_AUTO | + HA_STATUS_NO_LOCK)) != 0) + goto err; + if (share->tmp_table == SYSTEM_TMP_TABLE) table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); else if (share->tmp_table) @@ -2636,7 +2643,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) ptr=strmov(ptr," delay_key_write=1"); if (share->row_type != ROW_TYPE_DEFAULT) - ptr=strxmov(ptr, " row_format=", + ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) share->row_type], NullS); if (file->raid_type) @@ -2649,7 +2656,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, ptr=strmov(ptr,buff); } table->field[19]->store(option_buff+1, - (ptr == option_buff ? 0 : + (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1), cs); { char *comment; @@ -2658,13 +2665,32 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, { table->field[20]->store(comment, (comment == share->comment.str ? - share->comment.length : + share->comment.length : (uint) strlen(comment)), cs); if (comment != share->comment.str) my_free(comment, MYF(0)); } } } + +err: + if (res || info_error) + { + /* + If an error was encountered, push a warning, set the TABLE COMMENT + column with the error text, and clear the error so that the operation + can continue. + */ + const char *error= thd->net.last_error; + if (error) + { + table->field[20]->store(error, strlen(error), cs); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + thd->net.last_errno, thd->net.last_error); + thd->clear_error(); + } + } + DBUG_RETURN(schema_table_store_record(thd, table)); } @@ -2691,7 +2717,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, /* I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS - */ + */ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); thd->clear_error(); @@ -2732,7 +2758,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, uint col_access; check_access(thd,SELECT_ACL | EXTRA_ACL, base_name, &tables->grant.privilege, 0, 0, test(tables->schema_table)); - col_access= get_column_grant(thd, &tables->grant, + col_access= get_column_grant(thd, &tables->grant, base_name, file_name, field->field_name) & COL_ACLS; if (!tables->schema_table && !col_access) @@ -2755,9 +2781,9 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, cs); table->field[4]->store((longlong) count, TRUE); field->sql_type(type); - table->field[14]->store(type.ptr(), type.length(), cs); + table->field[14]->store(type.ptr(), type.length(), cs); tmp_buff= strchr(type.ptr(), '('); - table->field[7]->store(type.ptr(), (uint) + table->field[7]->store(type.ptr(), (uint) (tmp_buff ? tmp_buff - type.ptr() : type.length()), cs); @@ -2778,7 +2804,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, uint32 octet_max_length= field->max_display_length(); if (is_blob && octet_max_length != (uint32) 4294967295U) octet_max_length /= field->charset()->mbmaxlen; - longlong char_max_len= is_blob ? + longlong char_max_len= is_blob ? (longlong) octet_max_length / field->charset()->mbminlen : (longlong) octet_max_length / field->charset()->mbmaxlen; table->field[8]->store(char_max_len, TRUE); @@ -2811,7 +2837,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, field_length= field->max_display_length(); decimals= -1; // return NULL break; - case FIELD_TYPE_FLOAT: + case FIELD_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: field_length= field->field_length; if (decimals == NOT_FIXED_DEC) @@ -2874,7 +2900,7 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) for (cs= all_charsets ; cs < all_charsets+255 ; cs++) { CHARSET_INFO *tmp_cs= cs[0]; - if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && + if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && (tmp_cs->state & MY_CS_AVAILABLE) && !(wild && wild[0] && wild_case_compare(scs, tmp_cs->csname,wild))) @@ -2904,13 +2930,13 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; - if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || + if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; - if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || + if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || !my_charset_same(tmp_cs, tmp_cl)) continue; if (!(wild && wild[0] && @@ -2944,13 +2970,13 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; - if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || + if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; for (cl= all_charsets; cl < all_charsets+255 ;cl ++) { CHARSET_INFO *tmp_cl= cl[0]; - if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || + if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || !my_charset_same(tmp_cs,tmp_cl)) continue; restore_record(table, s->default_values); @@ -3014,7 +3040,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, table->field[10]->store(STRING_WITH_LEN("SQL"), cs); get_field(thd->mem_root, proc_table->field[6], &tmp_string); table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[12]->store(sp_data_access_name[enum_idx].str, + table->field[12]->store(sp_data_access_name[enum_idx].str, sp_data_access_name[enum_idx].length , cs); get_field(thd->mem_root, proc_table->field[7], &tmp_string); table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); @@ -3290,10 +3316,10 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, if (schema_table_store_record(thd, table)) DBUG_RETURN(1); if (res) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->net.last_errno, thd->net.last_error); } - if (res) + if (res) thd->clear_error(); DBUG_RETURN(0); } @@ -3334,7 +3360,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) @@ -3363,7 +3389,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, List_iterator_fast it(f_key_list); while ((f_key_info=it++)) { - if (store_constraints(thd, table, base_name, file_name, + if (store_constraints(thd, table, base_name, file_name, f_key_info->forein_id->str, (uint) strlen(f_key_info->forein_id->str), "FOREIGN KEY", 11)) @@ -3472,7 +3498,7 @@ ret: void store_key_column_usage(TABLE *table, const char*db, const char *tname, - const char *key_name, uint key_len, + const char *key_name, uint key_len, const char *con_type, uint con_len, longlong idx) { CHARSET_INFO *cs= system_charset_info; @@ -3506,7 +3532,7 @@ static int get_schema_key_column_usage_record(THD *thd, TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; uint primary_key= show_table->s->primary_key; - show_table->file->info(HA_STATUS_VARIABLE | + show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) @@ -3523,8 +3549,8 @@ static int get_schema_key_column_usage_record(THD *thd, restore_record(table, s->default_values); store_key_column_usage(table, base_name, file_name, key_info->name, - (uint) strlen(key_info->name), - key_part->field->field_name, + (uint) strlen(key_info->name), + key_part->field->field_name, (uint) strlen(key_part->field->field_name), (longlong) f_idx); if (schema_table_store_record(thd, table)) @@ -3560,7 +3586,7 @@ static int get_schema_key_column_usage_record(THD *thd, system_charset_info); table->field[9]->set_notnull(); table->field[10]->store(f_key_info->referenced_table->str, - f_key_info->referenced_table->length, + f_key_info->referenced_table->length, system_charset_info); table->field[10]->set_notnull(); table->field[11]->store(r_info->str, r_info->length, @@ -3607,7 +3633,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) LEX *lex= thd->lex; const char *wild= lex->wild ? lex->wild->ptr() : NullS; pthread_mutex_lock(&LOCK_global_system_variables); - res= show_status_array(thd, wild, init_vars, + res= show_status_array(thd, wild, init_vars, lex->option_type, 0, "", tables->table); pthread_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(res); @@ -3626,7 +3652,7 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) if (lex->option_type == OPT_GLOBAL) calc_sum_of_all_status(&tmp); res= show_status_array(thd, wild, status_vars, OPT_GLOBAL, - (lex->option_type == OPT_GLOBAL ? + (lex->option_type == OPT_GLOBAL ? &tmp: &thd->status_var), "",tables->table); pthread_mutex_unlock(&LOCK_status); DBUG_RETURN(res); @@ -3717,7 +3743,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: - if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, + if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, fields_info->field_length)) == NULL) DBUG_RETURN(NULL); break; @@ -3761,7 +3787,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->schema_table= 1; SELECT_LEX *select_lex= thd->lex->current_select; if (!(table= create_tmp_table(thd, tmp_table_param, - field_list, (ORDER*) 0, 0, 0, + field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, table_list->alias))) @@ -4102,7 +4128,7 @@ bool get_schema_tables_result(JOIN *join, thd->no_warnings_for_error= 1; for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++) - { + { if (!tab->table || !tab->table->pos_in_table_list) break; @@ -4454,13 +4480,13 @@ ST_FIELD_INFO variables_fields_info[]= ST_SCHEMA_TABLE schema_tables[]= { - {"CHARACTER_SETS", charsets_fields_info, create_schema_table, + {"CHARACTER_SETS", charsets_fields_info, create_schema_table, fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0}, - {"COLLATIONS", collation_fields_info, create_schema_table, + {"COLLATIONS", collation_fields_info, create_schema_table, fill_schema_collation, make_old_format, 0, -1, -1, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0}, - {"COLUMNS", columns_fields_info, create_schema_table, + {"COLUMNS", columns_fields_info, create_schema_table, get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0}, {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table, fill_schema_column_privileges, 0, 0, -1, -1, 0}, @@ -4469,19 +4495,19 @@ ST_SCHEMA_TABLE schema_tables[]= {"OPEN_TABLES", open_tables_fields_info, create_schema_table, fill_open_tables, make_old_format, 0, -1, -1, 1}, {"PROFILING", query_profile_statistics_info, create_schema_table, - fill_query_profile_statistics_info, make_profile_table_for_show, + fill_query_profile_statistics_info, make_profile_table_for_show, NULL, -1, -1, false}, - {"ROUTINES", proc_fields_info, create_schema_table, + {"ROUTINES", proc_fields_info, create_schema_table, fill_schema_proc, make_proc_old_format, 0, -1, -1, 0}, {"SCHEMATA", schema_fields_info, create_schema_table, fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0}, {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table, fill_schema_schema_privileges, 0, 0, -1, -1, 0}, - {"STATISTICS", stat_fields_info, create_schema_table, + {"STATISTICS", stat_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0}, - {"STATUS", variables_fields_info, create_schema_table, fill_status, + {"STATUS", variables_fields_info, create_schema_table, fill_status, make_old_format, 0, -1, -1, 1}, - {"TABLES", tables_fields_info, create_schema_table, + {"TABLES", tables_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0}, {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table, get_all_tables, 0, get_schema_constraints_record, 3, 4, 0}, @@ -4491,11 +4517,11 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_table_privileges, 0, 0, -1, -1, 0}, {"TRIGGERS", triggers_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0}, - {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, + {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, fill_schema_user_privileges, 0, 0, -1, -1, 0}, {"VARIABLES", variables_fields_info, create_schema_table, fill_variables, make_old_format, 0, -1, -1, 1}, - {"VIEWS", view_fields_info, create_schema_table, + {"VIEWS", view_fields_info, create_schema_table, get_all_tables, 0, get_schema_views_record, 1, 2, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/table.h b/sql/table.h index f162c2ed8ca..0a89db8bbff 100644 --- a/sql/table.h +++ b/sql/table.h @@ -31,7 +31,6 @@ typedef struct st_order { struct st_order *next; Item **item; /* Point at item in select fields */ Item *item_ptr; /* Storage for initial item */ - Item **item_copy; /* For SPs; the original item ptr */ int counter; /* position in SELECT list, correct only if counter_used is true*/ bool asc; /* true if ascending */