diff --git a/mysql-test/main/information_schema_parameters.result b/mysql-test/main/information_schema_parameters.result index 7c73c312bd7..eff68bb816d 100644 --- a/mysql-test/main/information_schema_parameters.result +++ b/mysql-test/main/information_schema_parameters.result @@ -626,3 +626,168 @@ DTD_IDENTIFIER ROW ROUTINE_TYPE PROCEDURE -------- -------- DROP PROCEDURE p1; +# +# MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES +# +DROP DATABASE IF EXISTS i_s_parameters_test; +CREATE DATABASE i_s_parameters_test; +USE i_s_parameters_test; +CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30) +RETURN CONCAT('XYZ, ' ,s); +# +# We cannot use the index due to CONCAT() +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.PARAMETERS +WHERE CONCAT(SPECIFIC_SCHEMA) = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'test_func5'; +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 0 +PARAMETER_MODE NULL +PARAMETER_NAME NULL +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_TYPE FUNCTION +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 1 +PARAMETER_MODE IN +PARAMETER_NAME s +DATA_TYPE char +CHARACTER_MAXIMUM_LENGTH 20 +CHARACTER_OCTET_LENGTH 20 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER char(20) +ROUTINE_TYPE FUNCTION +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 54 +Handler_read_rnd_next 97 +# +# Now the index must be used +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.PARAMETERS +WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'test_func5'; +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 0 +PARAMETER_MODE NULL +PARAMETER_NAME NULL +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_TYPE FUNCTION +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 1 +PARAMETER_MODE IN +PARAMETER_NAME s +DATA_TYPE char +CHARACTER_MAXIMUM_LENGTH 20 +CHARACTER_OCTET_LENGTH 20 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER char(20) +ROUTINE_TYPE FUNCTION +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 3 +# +# Using the first key part of the index +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.PARAMETERS +WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'; +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 0 +PARAMETER_MODE NULL +PARAMETER_NAME NULL +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_TYPE FUNCTION +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME test_func5 +ORDINAL_POSITION 1 +PARAMETER_MODE IN +PARAMETER_NAME s +DATA_TYPE char +CHARACTER_MAXIMUM_LENGTH 20 +CHARACTER_OCTET_LENGTH 20 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER char(20) +ROUTINE_TYPE FUNCTION +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 3 +# +# Test non-latin letters in procedure name +SET NAMES koi8r; +CREATE PROCEDURE `процедурка`(a INT) SELECT a; +# +# The index must be used +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.PARAMETERS +WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'процедурка'; +SPECIFIC_CATALOG def +SPECIFIC_SCHEMA i_s_parameters_test +SPECIFIC_NAME процедурка +ORDINAL_POSITION 1 +PARAMETER_MODE IN +PARAMETER_NAME a +DATA_TYPE int +CHARACTER_MAXIMUM_LENGTH NULL +CHARACTER_OCTET_LENGTH NULL +NUMERIC_PRECISION 10 +NUMERIC_SCALE 0 +DATETIME_PRECISION NULL +CHARACTER_SET_NAME NULL +COLLATION_NAME NULL +DTD_IDENTIFIER int(11) +ROUTINE_TYPE PROCEDURE +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 2 +DROP DATABASE i_s_parameters_test; +USE test; diff --git a/mysql-test/main/information_schema_parameters.test b/mysql-test/main/information_schema_parameters.test index 81aef66bfcd..c53ecce8b2b 100644 --- a/mysql-test/main/information_schema_parameters.test +++ b/mysql-test/main/information_schema_parameters.test @@ -276,3 +276,56 @@ DELIMITER ;$$ SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1'; --horizontal_results DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES +--echo # +--disable_warnings +DROP DATABASE IF EXISTS i_s_parameters_test; +--enable_warnings + +CREATE DATABASE i_s_parameters_test; +USE i_s_parameters_test; + +CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30) + RETURN CONCAT('XYZ, ' ,s); + +--echo # +--echo # We cannot use the index due to CONCAT() +FLUSH STATUS; +query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS + WHERE CONCAT(SPECIFIC_SCHEMA) = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'test_func5'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Now the index must be used +FLUSH STATUS; +query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS + WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'test_func5'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Using the first key part of the index +FLUSH STATUS; +query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS + WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Test non-latin letters in procedure name +SET NAMES koi8r; +CREATE PROCEDURE `процедурка`(a INT) SELECT a; +--echo # +--echo # The index must be used +FLUSH STATUS; +query_vertical SELECT * FROM INFORMATION_SCHEMA.PARAMETERS + WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test' + AND SPECIFIC_NAME = 'процедурка'; +SHOW STATUS LIKE 'handler_read%next'; + +# Cleanup +DROP DATABASE i_s_parameters_test; +USE test; diff --git a/mysql-test/main/information_schema_routines.result b/mysql-test/main/information_schema_routines.result index 35f12510556..74c867ca2ca 100644 --- a/mysql-test/main/information_schema_routines.result +++ b/mysql-test/main/information_schema_routines.result @@ -851,3 +851,257 @@ WHERE ROUTINE_SCHEMA = 'i_s_routines_test' AND ROUTINE_NAME = 'test_func5'; SPECIFIC_NAME ROUTINE_CATALOG ROUTINE_SCHEMA ROUTINE_NAME ROUTINE_TYPE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION CHARACTER_SET_NAME COLLATION_NAME DTD_IDENTIFIER ROUTINE_BODY ROUTINE_DEFINITION EXTERNAL_NAME EXTERNAL_LANGUAGE PARAMETER_STYLE IS_DETERMINISTIC SQL_DATA_ACCESS SQL_PATH SECURITY_TYPE CREATED LAST_ALTERED SQL_MODE ROUTINE_COMMENT DEFINER CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION test_func5 def i_s_routines_test test_func5 FUNCTION varchar 30 90 NULL NULL NULL utf8mb3 utf8mb3_general_ci varchar(30) SQL RETURN CONCAT('XYZ, ' ,s) NULL NULL SQL NO CONTAINS SQL NULL DEFINER root@localhost latin1 latin1_swedish_ci utf8mb3_general_ci DROP DATABASE i_s_routines_test; +# +# MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES +# +DROP DATABASE IF EXISTS i_s_routines_test; +CREATE DATABASE i_s_routines_test; +USE i_s_routines_test; +CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30) +RETURN CONCAT('XYZ, ' ,s); +# +# We cannot use the index due to CONCAT() +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.ROUTINES +WHERE CONCAT(ROUTINE_SCHEMA) = 'i_s_routines_test' + AND ROUTINE_NAME = 'test_func5'; +SPECIFIC_NAME test_func5 +ROUTINE_CATALOG def +ROUTINE_SCHEMA i_s_routines_test +ROUTINE_NAME test_func5 +ROUTINE_TYPE FUNCTION +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_BODY SQL +ROUTINE_DEFINITION RETURN CONCAT('XYZ, ' ,s) +EXTERNAL_NAME NULL +EXTERNAL_LANGUAGE NULL +PARAMETER_STYLE SQL +IS_DETERMINISTIC NO +SQL_DATA_ACCESS CONTAINS SQL +SQL_PATH NULL +SECURITY_TYPE DEFINER +CREATED +LAST_ALTERED +SQL_MODE +ROUTINE_COMMENT +DEFINER root@localhost +CHARACTER_SET_CLIENT latin1 +COLLATION_CONNECTION latin1_swedish_ci +DATABASE_COLLATION latin1_swedish_ci +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 54 +Handler_read_rnd_next 55 +# +# Now the index must be used +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA = 'i_s_routines_test' + AND ROUTINE_NAME = 'test_func5'; +SPECIFIC_NAME test_func5 +ROUTINE_CATALOG def +ROUTINE_SCHEMA i_s_routines_test +ROUTINE_NAME test_func5 +ROUTINE_TYPE FUNCTION +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_BODY SQL +ROUTINE_DEFINITION RETURN CONCAT('XYZ, ' ,s) +EXTERNAL_NAME NULL +EXTERNAL_LANGUAGE NULL +PARAMETER_STYLE SQL +IS_DETERMINISTIC NO +SQL_DATA_ACCESS CONTAINS SQL +SQL_PATH NULL +SECURITY_TYPE DEFINER +CREATED +LAST_ALTERED +SQL_MODE +ROUTINE_COMMENT +DEFINER root@localhost +CHARACTER_SET_CLIENT latin1 +COLLATION_CONNECTION latin1_swedish_ci +DATABASE_COLLATION latin1_swedish_ci +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 2 +# +# Using the first key part of the index +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA = 'i_s_routines_test'; +SPECIFIC_NAME test_func5 +ROUTINE_CATALOG def +ROUTINE_SCHEMA i_s_routines_test +ROUTINE_NAME test_func5 +ROUTINE_TYPE FUNCTION +DATA_TYPE varchar +CHARACTER_MAXIMUM_LENGTH 30 +CHARACTER_OCTET_LENGTH 30 +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME latin1 +COLLATION_NAME latin1_swedish_ci +DTD_IDENTIFIER varchar(30) +ROUTINE_BODY SQL +ROUTINE_DEFINITION RETURN CONCAT('XYZ, ' ,s) +EXTERNAL_NAME NULL +EXTERNAL_LANGUAGE NULL +PARAMETER_STYLE SQL +IS_DETERMINISTIC NO +SQL_DATA_ACCESS CONTAINS SQL +SQL_PATH NULL +SECURITY_TYPE DEFINER +CREATED +LAST_ALTERED +SQL_MODE +ROUTINE_COMMENT +DEFINER root@localhost +CHARACTER_SET_CLIENT latin1 +COLLATION_CONNECTION latin1_swedish_ci +DATABASE_COLLATION latin1_swedish_ci +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 2 +# +# Test non-latin letters in procedure name +SET NAMES koi8r; +CREATE PROCEDURE `процедурка`(a INT) SELECT a; +# +# The index must be used +FLUSH STATUS; +SELECT * FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA = 'i_s_routines_test' + AND ROUTINE_NAME = 'процедурка'; +SPECIFIC_NAME процедурка +ROUTINE_CATALOG def +ROUTINE_SCHEMA i_s_routines_test +ROUTINE_NAME процедурка +ROUTINE_TYPE PROCEDURE +DATA_TYPE +CHARACTER_MAXIMUM_LENGTH NULL +CHARACTER_OCTET_LENGTH NULL +NUMERIC_PRECISION NULL +NUMERIC_SCALE NULL +DATETIME_PRECISION NULL +CHARACTER_SET_NAME NULL +COLLATION_NAME NULL +DTD_IDENTIFIER NULL +ROUTINE_BODY SQL +ROUTINE_DEFINITION SELECT a +EXTERNAL_NAME NULL +EXTERNAL_LANGUAGE NULL +PARAMETER_STYLE SQL +IS_DETERMINISTIC NO +SQL_DATA_ACCESS CONTAINS SQL +SQL_PATH NULL +SECURITY_TYPE DEFINER +CREATED +LAST_ALTERED +SQL_MODE +ROUTINE_COMMENT +DEFINER root@localhost +CHARACTER_SET_CLIENT koi8r +COLLATION_CONNECTION koi8r_general_ci +DATABASE_COLLATION latin1_swedish_ci +SHOW STATUS LIKE 'handler_read%next'; +Variable_name Value +Handler_read_next 1 +Handler_read_rnd_next 2 +# +# Test SHOW PROCEDURE STATUS. It's impossible to use the index here +# so don't check Handler_read counters, only the results correctness +SHOW FUNCTION STATUS LIKE 'test_func5'; +Db i_s_routines_test +Name test_func5 +Type FUNCTION +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +SHOW FUNCTION STATUS LIKE 'test_%'; +Db i_s_routines_test +Name test_func5 +Type FUNCTION +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +SHOW FUNCTION STATUS LIKE '%func%'; +Db i_s_routines_test +Name test_func5 +Type FUNCTION +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +SHOW FUNCTION STATUS LIKE 'test'; +SHOW PROCEDURE STATUS LIKE 'процедурка'; +Db i_s_routines_test +Name процедурка +Type PROCEDURE +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client koi8r +collation_connection koi8r_general_ci +Database Collation latin1_swedish_ci +SHOW PROCEDURE STATUS LIKE '%оцедурка'; +Db i_s_routines_test +Name процедурка +Type PROCEDURE +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client koi8r +collation_connection koi8r_general_ci +Database Collation latin1_swedish_ci +SHOW PROCEDURE STATUS LIKE '%оцедур%'; +Db i_s_routines_test +Name процедурка +Type PROCEDURE +Definer root@localhost +Modified +Created +Security_type DEFINER +Comment +character_set_client koi8r +collation_connection koi8r_general_ci +Database Collation latin1_swedish_ci +SHOW PROCEDURE STATUS LIKE 'такой_нет'; +DROP DATABASE i_s_routines_test; +USE test; diff --git a/mysql-test/main/information_schema_routines.test b/mysql-test/main/information_schema_routines.test index a07e54cd70b..bf8e4dd7894 100644 --- a/mysql-test/main/information_schema_routines.test +++ b/mysql-test/main/information_schema_routines.test @@ -249,3 +249,79 @@ WHERE ROUTINE_SCHEMA = 'i_s_routines_test' AND ROUTINE_NAME = 'test_func5'; # final clean up DROP DATABASE i_s_routines_test; + +--echo # +--echo # MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES +--echo # +--disable_warnings +DROP DATABASE IF EXISTS i_s_routines_test; +--enable_warnings + +CREATE DATABASE i_s_routines_test; +USE i_s_routines_test; + +CREATE FUNCTION test_func5 (s CHAR(20)) RETURNS VARCHAR(30) + RETURN CONCAT('XYZ, ' ,s); + +--echo # +--echo # We cannot use the index due to CONCAT() +FLUSH STATUS; +--replace_column 24 25 +query_vertical SELECT * FROM INFORMATION_SCHEMA.ROUTINES + WHERE CONCAT(ROUTINE_SCHEMA) = 'i_s_routines_test' + AND ROUTINE_NAME = 'test_func5'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Now the index must be used +FLUSH STATUS; +--replace_column 24 25 +query_vertical SELECT * FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA = 'i_s_routines_test' + AND ROUTINE_NAME = 'test_func5'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Using the first key part of the index +FLUSH STATUS; +--replace_column 24 25 +query_vertical SELECT * FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA = 'i_s_routines_test'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Test non-latin letters in procedure name +SET NAMES koi8r; +CREATE PROCEDURE `процедурка`(a INT) SELECT a; +--echo # +--echo # The index must be used +FLUSH STATUS; +--replace_column 24 25 +query_vertical SELECT * FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA = 'i_s_routines_test' + AND ROUTINE_NAME = 'процедурка'; +SHOW STATUS LIKE 'handler_read%next'; + +--echo # +--echo # Test SHOW PROCEDURE STATUS. It's impossible to use the index here +--echo # so don't check Handler_read counters, only the results correctness +--replace_column 5 6 +query_vertical SHOW FUNCTION STATUS LIKE 'test_func5'; +--replace_column 5 6 +query_vertical SHOW FUNCTION STATUS LIKE 'test_%'; +--replace_column 5 6 +query_vertical SHOW FUNCTION STATUS LIKE '%func%'; +--replace_column 5 6 +query_vertical SHOW FUNCTION STATUS LIKE 'test'; +--replace_column 5 6 +query_vertical SHOW PROCEDURE STATUS LIKE 'процедурка'; +--replace_column 5 6 +query_vertical SHOW PROCEDURE STATUS LIKE '%оцедурка'; +--replace_column 5 6 +query_vertical SHOW PROCEDURE STATUS LIKE '%оцедур%'; +--replace_column 5 6 +query_vertical SHOW PROCEDURE STATUS LIKE 'такой_нет'; + +# Cleanup +DROP DATABASE i_s_routines_test; +USE test; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2e7001f1e66..bafd3b000e6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -65,7 +65,7 @@ #include "transaction.h" #include "opt_trace.h" #include "my_cpu.h" - +#include "key.h" #include "lex_symbol.h" #define KEYWORD_SIZE 64 @@ -150,7 +150,8 @@ static int show_create_sequence(THD *thd, TABLE_LIST *table_list, static const LEX_CSTRING *view_algorithm(TABLE_LIST *table); -bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *); +bool get_lookup_field_values(THD *, COND *, bool, TABLE_LIST *, + LOOKUP_FIELD_VALUES *); /** Try to lock a mutex, but give up after a short while to not cause deadlocks @@ -340,7 +341,7 @@ int fill_all_plugins(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; LOOKUP_FIELD_VALUES lookup; - if (get_lookup_field_values(thd, cond, tables, &lookup)) + if (get_lookup_field_values(thd, cond, true, tables, &lookup)) DBUG_RETURN(0); if (lookup.db_value.str && !lookup.db_value.str[0]) @@ -4257,7 +4258,8 @@ COND *make_cond_for_info_schema(THD *thd, COND *cond, TABLE_LIST *table) 1 error, there can be no matching records for the condition */ -bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, +bool get_lookup_field_values(THD *thd, COND *cond, bool fix_table_name_case, + TABLE_LIST *tables, LOOKUP_FIELD_VALUES *lookup_field_values) { LEX *lex= thd->lex; @@ -4292,7 +4294,7 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, lex->first_select_lex()->db.length); if (wild) { - thd->make_lex_string(&lookup_field_values->table_value, + thd->make_lex_string(&lookup_field_values->table_value, wild->ptr(), wild->length()); lookup_field_values->wild_table_value= 1; } @@ -4315,7 +4317,8 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0]) my_casedn_str(system_charset_info, (char*) lookup_field_values->db_value.str); - if (lookup_field_values->table_value.str && + if (fix_table_name_case && + lookup_field_values->table_value.str && lookup_field_values->table_value.str[0]) my_casedn_str(system_charset_info, (char*) lookup_field_values->table_value.str); @@ -5470,7 +5473,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) #endif DBUG_ENTER("fill_schema_shemata"); - if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals)) + if (get_lookup_field_values(thd, cond, true, tables, &lookup_field_vals)) DBUG_RETURN(0); DBUG_PRINT("INDEX VALUES",("db_name: %s table_name: %s", lookup_field_vals.db_value.str, @@ -6448,19 +6451,18 @@ static inline void copy_field_as_string(Field *to_field, Field *from_field) @param[in] thd thread handler @param[in] table I_S table @param[in] proc_table 'mysql.proc' table - @param[in] wild wild string, not used for now, - will be useful - if we add 'SHOW PARAMETERs' @param[in] full_access if 1 user has privileges on the routine @param[in] sp_user user in 'user@host' format @return Operation status @retval 0 ok - @retval 1 error + @retval != 0 error / HA_ERR_END_OF_FILE + (if there are no more + matching records) */ -bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, - const char *wild, bool full_access, +int store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, + LOOKUP_FIELD_VALUES *lookup, bool full_access, const char *sp_user) { TABLE_SHARE share; @@ -6482,6 +6484,15 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db); proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name); + + if (lookup->db_value.str) + { + if (cmp(lookup->db_value, db)) + DBUG_RETURN(HA_ERR_END_OF_FILE); + if (lookup->table_value.str && cmp(lookup->table_value, name)) + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer); sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); sph= Sp_handler::handler_mysql_proc((enum_sp_type) @@ -6585,16 +6596,33 @@ 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) +int store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, + LOOKUP_FIELD_VALUES *lookup, bool full_access, + const char *sp_user) { LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; const Sp_handler *sph; LEX_CSTRING db, name, definer, returns= empty_clex_str; + const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db); proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name); + + if (lookup->db_value.str) + { + if (cmp(lookup->db_value, db)) + return HA_ERR_END_OF_FILE; + if (lookup->table_value.str) + { + CHARSET_INFO *cs= proc_table->field[MYSQL_PROC_FIELD_NAME]->charset(); + if (my_ci_strnncoll(cs, (const uchar*)lookup->table_value.str, + lookup->table_value.length, + (const uchar*) name.str, name.length, 0)) + return HA_ERR_END_OF_FILE; + } + } + proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer); sph= Sp_handler::handler_mysql_proc((enum_sp_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> @@ -6706,7 +6734,6 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) { TABLE *proc_table; TABLE_LIST proc_tables; - const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; int res= 0; TABLE *table= tables->table; bool full_access; @@ -6726,6 +6753,13 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE, 1, TRUE); + LOOKUP_FIELD_VALUES lookup; + if (get_lookup_field_values(thd, cond, false, tables, &lookup)) + { + // There can be no matching records for the condition + return 0; + } + start_new_trans new_trans(thd); if (!(proc_table= open_proc_table_for_read(thd))) @@ -6744,34 +6778,51 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) goto err; } - if ((res= proc_table->file->ha_index_first(proc_table->record[0]))) + if (lookup.db_value.str) { - res= (res == HA_ERR_END_OF_FILE) ? 0 : 1; - goto err; - } - - if (schema_table_idx == SCH_PROCEDURES ? - store_schema_proc(thd, table, proc_table, wild, full_access, definer) : - store_schema_params(thd, table, proc_table, wild, full_access, definer)) - { - res= 1; - goto err; - } - while (!proc_table->file->ha_index_next(proc_table->record[0])) - { - if (schema_table_idx == SCH_PROCEDURES ? - store_schema_proc(thd, table, proc_table, wild, full_access, definer): - store_schema_params(thd, table, proc_table, wild, full_access, definer)) + KEY *keyinfo= proc_table->key_info; + uint keylen= keyinfo->key_part[0].length; + key_part_map keypart_map= 1; + enum ha_rkey_function find_flag= HA_READ_PREFIX; + uchar keybuf[NAME_CHAR_LEN * 2 * 4 * 64]; + proc_table->field[0]->store(lookup.db_value.str, lookup.db_value.length, + system_charset_info); + if (lookup.table_value.str) { - res= 1; - goto err; + proc_table->field[1]->store(lookup.table_value.str, + lookup.table_value.length, + system_charset_info); + keylen+= keyinfo->key_part[1].length; + keypart_map= 3; + find_flag= HA_READ_KEY_EXACT; } + key_copy(keybuf, proc_table->record[0], keyinfo, keylen, 0); + res= proc_table->file->ha_index_read_map(proc_table->record[0], keybuf, + keypart_map, find_flag); + } + else + res= proc_table->file->ha_index_first(proc_table->record[0]); + + if (res) + goto err; + + res= schema_table_idx == SCH_PROCEDURES ? + store_schema_proc(thd, table, proc_table, &lookup, full_access,definer) : + store_schema_params(thd, table, proc_table, &lookup, full_access, definer); + while (!res && !proc_table->file->ha_index_next(proc_table->record[0])) + { + res= schema_table_idx == SCH_PROCEDURES ? + store_schema_proc(thd, table, proc_table, &lookup, full_access, definer) : + store_schema_params(thd, table, proc_table, &lookup, full_access, definer); } err: if (proc_table->file->inited) (void) proc_table->file->ha_index_end(); + if (res == HA_ERR_END_OF_FILE || res == HA_ERR_KEY_NOT_FOUND) + res= 0; + thd->commit_whole_transaction_and_close_tables(); new_trans.restore_old_transaction(); @@ -8669,7 +8720,8 @@ static bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond goto end; } - if (get_lookup_field_values(thd, cond, tables, &plan->lookup_field_vals)) + if (get_lookup_field_values(thd, cond, true, tables, + &plan->lookup_field_vals)) { plan->no_rows= true; goto end; @@ -9861,7 +9913,7 @@ ST_SCHEMA_TABLE schema_tables[]= {"OPTIMIZER_TRACE", Show::optimizer_trace_info, 0, fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0}, {"PARAMETERS", Show::parameters_fields_info, 0, - fill_schema_proc, 0, 0, -1, -1, 0, 0}, + fill_schema_proc, 0, 0, 1, 2, 0, 0}, {"PARTITIONS", Show::partitions_fields_info, 0, get_all_tables, 0, get_schema_partitions_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, @@ -9876,7 +9928,7 @@ ST_SCHEMA_TABLE schema_tables[]= 0, get_all_tables, 0, get_referential_constraints_record, 1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"ROUTINES", Show::proc_fields_info, 0, - fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0}, + fill_schema_proc, make_proc_old_format, 0, 2, 3, 0, 0}, {"SCHEMATA", Show::schema_fields_info, 0, fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0}, {"SCHEMA_PRIVILEGES", Show::schema_privileges_fields_info, 0,