diff --git a/include/my_global.h b/include/my_global.h index 3c0266d2e71..e8f93ee5d7a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -661,6 +661,7 @@ typedef SOCKET_SIZE_TYPE size_socket; #define UINT_MAX16 0xFFFF #define INT_MIN8 (~0x7F) #define INT_MAX8 0x7F +#define UINT_MAX8 0xFF /* From limits.h instead */ #ifndef DBL_MIN diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 68568f97dea..2e9721abbe3 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3442,7 +3442,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, longlong data= my_strntoll(&my_charset_latin1, value, length, 10, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT8_MIN, INT8_MAX, UINT8_MAX) | + INT_MIN8, INT_MAX8, UINT_MAX8) | test(err)); *buffer= (uchar) data; break; @@ -3452,7 +3452,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, longlong data= my_strntoll(&my_charset_latin1, value, length, 10, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT16_MIN, INT16_MAX, UINT16_MAX) | + INT_MIN16, INT_MAX16, UINT_MAX16) | test(err)); shortstore(buffer, (short) data); break; @@ -3462,7 +3462,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, longlong data= my_strntoll(&my_charset_latin1, value, length, 10, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT32_MIN, INT32_MAX, UINT32_MAX) | + INT_MIN32, INT_MAX32, UINT_MAX32) | test(err)); longstore(buffer, (int32) data); break; @@ -3564,17 +3564,17 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, break; case MYSQL_TYPE_TINY: *param->error= IS_TRUNCATED(value, param->is_unsigned, - INT8_MIN, INT8_MAX, UINT8_MAX); + INT_MIN8, INT_MAX8, UINT_MAX8); *(uchar *)param->buffer= (uchar) value; break; case MYSQL_TYPE_SHORT: *param->error= IS_TRUNCATED(value, param->is_unsigned, - INT16_MIN, INT16_MAX, UINT16_MAX); + INT_MIN16, INT_MAX16, UINT_MAX16); shortstore(buffer, (short) value); break; case MYSQL_TYPE_LONG: *param->error= IS_TRUNCATED(value, param->is_unsigned, - INT32_MIN, INT32_MAX, UINT32_MAX); + INT_MIN32, INT_MAX32, UINT_MAX32); longstore(buffer, (int32) value); break; case MYSQL_TYPE_LONGLONG: @@ -3978,7 +3978,7 @@ static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field, my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG); uchar data= **row; *(uchar *)param->buffer= data; - *param->error= param->is_unsigned != field_is_unsigned && data > INT8_MAX; + *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8; (*row)++; } @@ -3988,7 +3988,7 @@ static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field, my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG); ushort data= (ushort) sint2korr(*row); shortstore(param->buffer, data); - *param->error= param->is_unsigned != field_is_unsigned && data > INT16_MAX; + *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16; *row+= 2; } @@ -3999,7 +3999,7 @@ static void fetch_result_int32(MYSQL_BIND *param, my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG); uint32 data= (uint32) sint4korr(*row); longstore(param->buffer, data); - *param->error= param->is_unsigned != field_is_unsigned && data > INT32_MAX; + *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32; *row+= 4; } @@ -4009,7 +4009,7 @@ static void fetch_result_int64(MYSQL_BIND *param, { my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG); ulonglong data= (ulonglong) sint8korr(*row); - *param->error= param->is_unsigned != field_is_unsigned && data > INT64_MAX; + *param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX; longlongstore(param->buffer, data); *row+= 8; } @@ -4149,7 +4149,7 @@ static my_bool is_binary_compatible(enum enum_field_types type1, MYSQL_TYPE_DECIMAL, 0 }, *range_list[]= { range1, range2, range3, range4 }, **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list); - enum enum_field_types **range, *type; + const enum enum_field_types **range, *type; if (type1 == type2) return TRUE; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 6c427f7fe1d..d421ac1d184 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -590,3 +590,40 @@ TABLES TABLE_PRIVILEGES TABLE_CONSTRAINTS TABLE_NAMES +use test; +create function sub1(i int) returns int +return i+1; +create table t1(f1 int); +create view t2 (c) as select f1 from t1; +create view t3 (c) as select sub1(1); +create table t4(f1 int, KEY f1_key (f1)); +drop table t1; +drop function sub1; +select table_name from information_schema.views +where table_schema='test'; +table_name +Warnings: +Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s) +select table_name from information_schema.views +where table_schema='test'; +table_name +Warnings: +Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s) +select column_name from information_schema.columns +where table_schema='test'; +column_name +f1 +Warnings: +Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s) +Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s) +select index_name from information_schema.statistics where table_schema='test'; +index_name +f1_key +select constraint_name from information_schema.table_constraints +where table_schema='test'; +constraint_name +drop view t2; +drop view t3; +drop table t4; diff --git a/mysql-test/r/init_connect.result b/mysql-test/r/init_connect.result index db1e72dfca9..eeae422edc4 100644 --- a/mysql-test/r/init_connect.result +++ b/mysql-test/r/init_connect.result @@ -12,7 +12,7 @@ set GLOBAL init_connect=DEFAULT; select @a; @a NULL -set global init_connect="create table t1(a char(10));\ +set global init_connect="drop table if exists t1; create table t1(a char(10));\ insert into t1 values ('\0');insert into t1 values('abc')"; select hex(a) from t1; hex(a) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 41de883a4d6..366d799fde3 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -983,10 +983,10 @@ create view v1 as select * from t1; drop table t1; create table t1 (col1 char(5),newcol2 char(5)); insert into v1 values('a','aa'); -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) drop table t1; select * from v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) drop view v1; create view v1 (a,a) as select 'a','a'; ERROR 42S21: Duplicate column name 'a' @@ -1217,11 +1217,11 @@ create table t1 (s1 int); create view v1 as select x1() from t1; drop function x1; select * from v1; -ERROR 42000: FUNCTION test.x1 does not exist +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) 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 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL -v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL FUNCTION test.x1 does not exist +v1 NULL 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) drop view v1; drop table t1; create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1; @@ -1655,7 +1655,7 @@ test.t1 check status OK drop table t1; check table v1; Table Op Msg_type Msg_text -test.v1 check error View 'test.v1' references invalid table(s) or column(s) +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) drop view v1; create table t1 (a int); create table t2 (a int); diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index b909e8b8e53..0fe7636e500 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -292,3 +292,29 @@ use test; show tables; use information_schema; show tables like "T%"; + +# +# Bug#7212: information_schema: "Can't find file" errors if storage engine gone +# Bug#7211: information_schema: crash if bad view +# +use test; +create function sub1(i int) returns int + return i+1; +create table t1(f1 int); +create view t2 (c) as select f1 from t1; +create view t3 (c) as select sub1(1); +create table t4(f1 int, KEY f1_key (f1)); +drop table t1; +drop function sub1; +select table_name from information_schema.views +where table_schema='test'; +select table_name from information_schema.views +where table_schema='test'; +select column_name from information_schema.columns +where table_schema='test'; +select index_name from information_schema.statistics where table_schema='test'; +select constraint_name from information_schema.table_constraints +where table_schema='test'; +drop view t2; +drop view t3; +drop table t4; diff --git a/mysql-test/t/init_connect.test b/mysql-test/t/init_connect.test index 29962abc04d..d9682eb8122 100644 --- a/mysql-test/t/init_connect.test +++ b/mysql-test/t/init_connect.test @@ -19,7 +19,7 @@ connect (con3,localhost,user_1,,); connection con3; select @a; connection con0; -set global init_connect="create table t1(a char(10));\ +set global init_connect="drop table if exists t1; create table t1(a char(10));\ insert into t1 values ('\0');insert into t1 values('abc')"; connect (con4,localhost,user_1,,); connection con4; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 65f464fc77b..cb398fed856 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1169,7 +1169,7 @@ create function x1 () returns int return 5; create table t1 (s1 int); create view v1 as select x1() from t1; drop function x1; --- error 1305 +-- error 1356 select * from v1; --replace_column 12 # 13 # --replace_result "2147483647 " "21474836479 " diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 714b18b39f2..06f4b0fc0b2 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5464,10 +5464,9 @@ ER_WARN_VIEW_WITHOUT_KEY serbian "View '%-.64s.%-.64s' references invalid table(s) or column(s)" ukr "View, що оновлюеться, не м╕стить повного ключа таблиц╕(ь), що викор╕стана в ньюому" ER_VIEW_INVALID - eng "View '%-.64s.%-.64s' references invalid table(s) or column(s)" - rus "View '%-.64s.%-.64s' ссылается на несуществующие таблицы или столбцы" + eng "View '%-.64s.%-.64s' references invalid table(s) or column(s) or function(s)" + rus "View '%-.64s.%-.64s' ссылается на несуществующие таблицы или столбцы или функции" serbian "Can't drop a %s from within another stored routine" - ukr "View '%-.64s.%-.64s' посила╓тся на не╕снуюч╕ таблиц╕ або стовбц╕" ER_SP_NO_DROP_SP eng "Can't drop a %s from within another stored routine" serbian "GOTO is not allowed in a stored procedure handler" diff --git a/sql/sp.cc b/sql/sp.cc index 9eff1655711..4605d49f3ab 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -981,6 +981,7 @@ sp_cache_functions(THD *thd, LEX *lex) thd->lex= newlex; newlex->proc_table= oldlex->proc_table; // hint if mysql.oper is opened + newlex->current_select= NULL; name.m_name.str= strchr(name.m_qname.str, '.'); name.m_db.length= name.m_name.str - name.m_qname.str; name.m_db.str= strmake_root(thd->mem_root, diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 69511018880..7cea1c6fcee 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -140,6 +140,18 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) derived_result->set_table(table); exit: + /* Hide "Unknown column" or "Unknown function" error */ + if (orig_table_list->view) + { + if (thd->net.last_errno == ER_BAD_FIELD_ERROR || + thd->net.last_errno == ER_SP_DOES_NOT_EXIST) + { + thd->clear_error(); + my_error(ER_VIEW_INVALID, MYF(0), orig_table_list->db, + orig_table_list->real_name); + } + } + /* if it is preparation PS only or commands that need only VIEW structure then we do not need real data and we can skip execution (and parameters diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ed3606856a0..13f556efa16 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11654,8 +11654,21 @@ calc_group_buffer(JOIN *join,ORDER *group) key_length+=sizeof(double); else if ((*group->item)->result_type() == INT_RESULT) key_length+=sizeof(longlong); + else if ((*group->item)->result_type() == STRING_RESULT) + { + /* + Group strings are taken as varstrings and require an length field. + A field is not yet created by create_tmp_field() + and the sizes should match up. + */ + key_length+= (*group->item)->max_length + HA_KEY_BLOB_LENGTH; + } else - key_length+=(*group->item)->max_length; + { + /* This case should never be choosen */ + DBUG_ASSERT(0); + current_thd->fatal_error(); + } parts++; if ((*group->item)->maybe_null) null_parts++; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e50c68dd289..5a135faf52f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2374,12 +2374,24 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, const char *file_name) { TIME time; - const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; + LEX *lex= thd->lex; + const char *wild= lex->wild ? lex->wild->ptr() : NullS; CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_column_record"); if (res) { - DBUG_RETURN(1); + if (lex->orig_sql_command != SQLCOM_SHOW_FIELDS) + { + /* + 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(); + res= 0; + } + DBUG_RETURN(res); } TABLE *show_table= tables->table; @@ -2745,7 +2757,23 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables, { CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_stat_record"); - if (!res && !tables->view) + if (res) + { + if (thd->lex->orig_sql_command != SQLCOM_SHOW_KEYS) + { + /* + I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS + rather than in SHOW KEYS + */ + if (!tables->view) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + thd->net.last_errno, thd->net.last_error); + thd->clear_error(); + res= 0; + } + DBUG_RETURN(res); + } + else if (!tables->view) { TABLE *show_table= tables->table; KEY *key_info=show_table->key_info; @@ -2843,7 +2871,14 @@ static int get_schema_views_record(THD *thd, struct st_table_list *tables, table->file->write_row(table->record[0]); } } - DBUG_RETURN(res); + else + { + if (tables->view) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + thd->net.last_errno, thd->net.last_error); + thd->clear_error(); + } + DBUG_RETURN(0); } @@ -2868,7 +2903,15 @@ static int get_schema_constraints_record(THD *thd, struct st_table_list *tables, const char *file_name) { DBUG_ENTER("get_schema_constraints_record"); - if (!res && !tables->view) + if (res) + { + if (!tables->view) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + thd->net.last_errno, thd->net.last_error); + thd->clear_error(); + DBUG_RETURN(0); + } + else if (!tables->view) { List f_key_list; TABLE *show_table= tables->table; @@ -2925,7 +2968,15 @@ static int get_schema_key_column_usage_record(THD *thd, { DBUG_ENTER("get_schema_key_column_usage_record"); CHARSET_INFO *cs= system_charset_info; - if (!res && !tables->view) + if (res) + { + if (!tables->view) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + thd->net.last_errno, thd->net.last_error); + thd->clear_error(); + DBUG_RETURN(0); + } + else if (!tables->view) { List f_key_list; TABLE *show_table= tables->table; diff --git a/sql/table.cc b/sql/table.cc index b4a07448b14..b54cc351dff 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1845,8 +1845,9 @@ ok: DBUG_RETURN(0); err: - /* Hide "Unknown column" error */ - if (thd->net.last_errno == ER_BAD_FIELD_ERROR) + /* Hide "Unknown column" or "Unknown function" error */ + if (thd->net.last_errno == ER_BAD_FIELD_ERROR || + thd->net.last_errno == ER_SP_DOES_NOT_EXIST) { thd->clear_error(); my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str); diff --git a/tests/client_test.c b/tests/client_test.c index e63580ce031..b00be2d35b8 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -12065,6 +12065,7 @@ static void test_truncation() MYSQL_STMT *stmt; const char *stmt_text; int rc; + uint bind_count; MYSQL_BIND *bind_array, *bind; myheader("test_truncation"); @@ -12112,7 +12113,7 @@ static void test_truncation() check_execute(stmt, rc); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - uint bind_count= (uint) mysql_stmt_field_count(stmt); + bind_count= (uint) mysql_stmt_field_count(stmt); /*************** Fill in the bind structure and bind it **************/ bind_array= malloc(sizeof(MYSQL_BIND) * bind_count);