mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-20609 Full table scan in INFORMATION_SCHEMA.PARAMETERS/ROUTINES
Queries to INFORMATION_SCHEMA.PARAMETERS and ROUTINES tables are always performed using full index scan of the mysql.proc primary key on fields (`db`,`name`,`type`). This can be done in a much more effective way if `db` and `name` field values can be derived from the WHERE statement, like here: SELECT * FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_SCHEMA = 'test' AND SPECIFIC_NAME = 'my_func' or here: SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA='test' AND ROUTINE_NAME='my_func'. In such cases index range scan may be employed instead of full index scan. This commit makes the server retrieve lookup field values from the SQL statement and perform index range scan instead of full index scan if possible.
This commit is contained in:
@ -626,3 +626,168 @@ DTD_IDENTIFIER ROW
|
|||||||
ROUTINE_TYPE PROCEDURE
|
ROUTINE_TYPE PROCEDURE
|
||||||
-------- --------
|
-------- --------
|
||||||
DROP PROCEDURE p1;
|
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;
|
||||||
|
@ -276,3 +276,56 @@ DELIMITER ;$$
|
|||||||
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1';
|
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1';
|
||||||
--horizontal_results
|
--horizontal_results
|
||||||
DROP PROCEDURE p1;
|
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;
|
||||||
|
@ -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
|
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 <created> <modified> root@localhost latin1 latin1_swedish_ci utf8mb3_general_ci
|
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 <created> <modified> root@localhost latin1 latin1_swedish_ci utf8mb3_general_ci
|
||||||
DROP DATABASE i_s_routines_test;
|
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 <created>
|
||||||
|
LAST_ALTERED <modified>
|
||||||
|
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 <created>
|
||||||
|
LAST_ALTERED <modified>
|
||||||
|
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 <created>
|
||||||
|
LAST_ALTERED <modified>
|
||||||
|
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 <created>
|
||||||
|
LAST_ALTERED <modified>
|
||||||
|
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 <modified>
|
||||||
|
Created <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 <modified>
|
||||||
|
Created <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 <modified>
|
||||||
|
Created <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 <modified>
|
||||||
|
Created <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 <modified>
|
||||||
|
Created <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 <modified>
|
||||||
|
Created <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;
|
||||||
|
@ -249,3 +249,79 @@ WHERE ROUTINE_SCHEMA = 'i_s_routines_test' AND ROUTINE_NAME = 'test_func5';
|
|||||||
|
|
||||||
# final clean up
|
# final clean up
|
||||||
DROP DATABASE i_s_routines_test;
|
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 <created> 25 <modified>
|
||||||
|
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 <created> 25 <modified>
|
||||||
|
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 <created> 25 <modified>
|
||||||
|
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 <created> 25 <modified>
|
||||||
|
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 <modified> 6 <created>
|
||||||
|
query_vertical SHOW FUNCTION STATUS LIKE 'test_func5';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW FUNCTION STATUS LIKE 'test_%';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW FUNCTION STATUS LIKE '%func%';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW FUNCTION STATUS LIKE 'test';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW PROCEDURE STATUS LIKE 'процедурка';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW PROCEDURE STATUS LIKE '%оцедурка';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW PROCEDURE STATUS LIKE '%оцедур%';
|
||||||
|
--replace_column 5 <modified> 6 <created>
|
||||||
|
query_vertical SHOW PROCEDURE STATUS LIKE 'такой_нет';
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
DROP DATABASE i_s_routines_test;
|
||||||
|
USE test;
|
||||||
|
122
sql/sql_show.cc
122
sql/sql_show.cc
@ -65,7 +65,7 @@
|
|||||||
#include "transaction.h"
|
#include "transaction.h"
|
||||||
#include "opt_trace.h"
|
#include "opt_trace.h"
|
||||||
#include "my_cpu.h"
|
#include "my_cpu.h"
|
||||||
|
#include "key.h"
|
||||||
|
|
||||||
#include "lex_symbol.h"
|
#include "lex_symbol.h"
|
||||||
#define KEYWORD_SIZE 64
|
#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);
|
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
|
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;
|
TABLE *table= tables->table;
|
||||||
LOOKUP_FIELD_VALUES lookup;
|
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);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
if (lookup.db_value.str && !lookup.db_value.str[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
|
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)
|
LOOKUP_FIELD_VALUES *lookup_field_values)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
@ -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])
|
if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0])
|
||||||
my_casedn_str(system_charset_info,
|
my_casedn_str(system_charset_info,
|
||||||
(char*) lookup_field_values->db_value.str);
|
(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])
|
lookup_field_values->table_value.str[0])
|
||||||
my_casedn_str(system_charset_info,
|
my_casedn_str(system_charset_info,
|
||||||
(char*) lookup_field_values->table_value.str);
|
(char*) lookup_field_values->table_value.str);
|
||||||
@ -5470,7 +5473,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("fill_schema_shemata");
|
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_RETURN(0);
|
||||||
DBUG_PRINT("INDEX VALUES",("db_name: %s table_name: %s",
|
DBUG_PRINT("INDEX VALUES",("db_name: %s table_name: %s",
|
||||||
lookup_field_vals.db_value.str,
|
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] thd thread handler
|
||||||
@param[in] table I_S table
|
@param[in] table I_S table
|
||||||
@param[in] proc_table 'mysql.proc' 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] full_access if 1 user has privileges on the routine
|
||||||
@param[in] sp_user user in 'user@host' format
|
@param[in] sp_user user in 'user@host' format
|
||||||
|
|
||||||
@return Operation status
|
@return Operation status
|
||||||
@retval 0 ok
|
@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,
|
int store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
|
||||||
const char *wild, bool full_access,
|
LOOKUP_FIELD_VALUES *lookup, bool full_access,
|
||||||
const char *sp_user)
|
const char *sp_user)
|
||||||
{
|
{
|
||||||
TABLE_SHARE share;
|
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_DB]->val_str_nopad(thd->mem_root, &db);
|
||||||
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
|
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);
|
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();
|
sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
|
||||||
sph= Sp_handler::handler_mysql_proc((enum_sp_type)
|
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,
|
int store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
|
||||||
const char *wild, bool full_access, const char *sp_user)
|
LOOKUP_FIELD_VALUES *lookup, bool full_access,
|
||||||
|
const char *sp_user)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
CHARSET_INFO *cs= system_charset_info;
|
CHARSET_INFO *cs= system_charset_info;
|
||||||
const Sp_handler *sph;
|
const Sp_handler *sph;
|
||||||
LEX_CSTRING db, name, definer, returns= empty_clex_str;
|
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_DB]->val_str_nopad(thd->mem_root, &db);
|
||||||
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
|
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);
|
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
|
||||||
sph= Sp_handler::handler_mysql_proc((enum_sp_type)
|
sph= Sp_handler::handler_mysql_proc((enum_sp_type)
|
||||||
proc_table->field[MYSQL_PROC_MYSQL_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 *proc_table;
|
||||||
TABLE_LIST proc_tables;
|
TABLE_LIST proc_tables;
|
||||||
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
|
|
||||||
int res= 0;
|
int res= 0;
|
||||||
TABLE *table= tables->table;
|
TABLE *table= tables->table;
|
||||||
bool full_access;
|
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,
|
full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE,
|
||||||
1, TRUE);
|
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);
|
start_new_trans new_trans(thd);
|
||||||
|
|
||||||
if (!(proc_table= open_proc_table_for_read(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;
|
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;
|
KEY *keyinfo= proc_table->key_info;
|
||||||
goto err;
|
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)
|
||||||
|
{
|
||||||
|
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 (schema_table_idx == SCH_PROCEDURES ?
|
if (res)
|
||||||
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;
|
goto err;
|
||||||
}
|
|
||||||
while (!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);
|
||||||
|
while (!res && !proc_table->file->ha_index_next(proc_table->record[0]))
|
||||||
{
|
{
|
||||||
if (schema_table_idx == SCH_PROCEDURES ?
|
res= schema_table_idx == SCH_PROCEDURES ?
|
||||||
store_schema_proc(thd, table, proc_table, wild, full_access, definer):
|
store_schema_proc(thd, table, proc_table, &lookup, full_access, definer) :
|
||||||
store_schema_params(thd, table, proc_table, wild, full_access, definer))
|
store_schema_params(thd, table, proc_table, &lookup, full_access, definer);
|
||||||
{
|
|
||||||
res= 1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (proc_table->file->inited)
|
if (proc_table->file->inited)
|
||||||
(void) proc_table->file->ha_index_end();
|
(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();
|
thd->commit_whole_transaction_and_close_tables();
|
||||||
new_trans.restore_old_transaction();
|
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;
|
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;
|
plan->no_rows= true;
|
||||||
goto end;
|
goto end;
|
||||||
@ -9861,7 +9913,7 @@ ST_SCHEMA_TABLE schema_tables[]=
|
|||||||
{"OPTIMIZER_TRACE", Show::optimizer_trace_info, 0,
|
{"OPTIMIZER_TRACE", Show::optimizer_trace_info, 0,
|
||||||
fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0},
|
fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0},
|
||||||
{"PARAMETERS", Show::parameters_fields_info, 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,
|
{"PARTITIONS", Show::partitions_fields_info, 0,
|
||||||
get_all_tables, 0, get_schema_partitions_record, 1, 2, 0,
|
get_all_tables, 0, get_schema_partitions_record, 1, 2, 0,
|
||||||
OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
|
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,
|
0, get_all_tables, 0, get_referential_constraints_record,
|
||||||
1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
|
1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
|
||||||
{"ROUTINES", Show::proc_fields_info, 0,
|
{"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,
|
{"SCHEMATA", Show::schema_fields_info, 0,
|
||||||
fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
|
fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
|
||||||
{"SCHEMA_PRIVILEGES", Show::schema_privileges_fields_info, 0,
|
{"SCHEMA_PRIVILEGES", Show::schema_privileges_fields_info, 0,
|
||||||
|
Reference in New Issue
Block a user