From 310fd6ff695541247db766baf3ade1e3b4db16e9 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 21 May 2024 08:53:40 +0400 Subject: [PATCH] Backporting bugs fixes fixed by MDEV-31340 from 11.5 The patch for MDEV-31340 fixed the following bugs: MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0 MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0 MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0 MDEV-33088 Cannot create triggers in the database `MYSQL` MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0 MDEV-33108 TABLE_STATISTICS and INDEX_STATISTICS are case insensitive with lower-case-table-names=0 MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0 MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0 MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0 Backporting the fixes from 11.5 to 10.5 --- mysql-test/main/lowercase_table5.result | 142 +++++++++++++++++++ mysql-test/main/lowercase_table5.test | 138 ++++++++++++++++++ mysql-test/main/view_grant.result | 31 ++++ mysql-test/main/view_grant.test | 27 ++++ mysql-test/suite/csv/lowercase_table0.result | 15 ++ mysql-test/suite/csv/lowercase_table0.test | 16 +++ sql/lex_ident.h | 85 +++++++++++ sql/sql_acl.cc | 18 +-- sql/sql_base.cc | 52 +++---- sql/sql_base.h | 3 +- sql/sql_class.cc | 5 +- sql/sql_class.h | 1 + sql/sql_connect.cc | 6 +- sql/sql_db.cc | 3 +- sql/sql_handler.cc | 7 +- sql/sql_parse.cc | 15 +- sql/sql_show.cc | 12 +- sql/sql_string.h | 5 + sql/sql_trigger.cc | 2 +- sql/table.cc | 35 +++-- sql/table.h | 17 ++- sql/temporary_tables.cc | 13 +- storage/csv/ha_tina.cc | 3 +- 23 files changed, 561 insertions(+), 90 deletions(-) create mode 100644 mysql-test/suite/csv/lowercase_table0.result create mode 100644 mysql-test/suite/csv/lowercase_table0.test create mode 100644 sql/lex_ident.h diff --git a/mysql-test/main/lowercase_table5.result b/mysql-test/main/lowercase_table5.result index 7e78f71b75f..cededde9525 100644 --- a/mysql-test/main/lowercase_table5.result +++ b/mysql-test/main/lowercase_table5.result @@ -47,3 +47,145 @@ DROP PROCEDURE SP; # # End of 10.4 tests # +# +# Start of 10.5 tests +# +# +# MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0 +# +CREATE SEQUENCE t1; +CREATE SEQUENCE T1; +SELECT nextval(t1), lastval(t1); +nextval(t1) lastval(t1) +1 1 +SELECT nextval(T1), lastval(T1); +nextval(T1) lastval(T1) +1 1 +SELECT lastval(t1), lastval(T1) l2; +lastval(t1) l2 +1 1 +DROP SEQUENCE t1, T1; +# +# MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0 +# +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +SELECT * FROM db1.t1; +a +SHOW OPEN TABLES IN DB1; +Database Table In_use Name_locked +SHOW OPEN TABLES IN db1; +Database Table In_use Name_locked +db1 t1 0 0 +DROP DATABASE db1; +# +# MDEV-33088 Cannot create triggers in the database `MYSQL` +# +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.t1 (a INT); +CREATE TABLE MYSQL.t2 (a INT); +CREATE TRIGGER MYSQL.tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (new.a); +INSERT INTO MYSQL.t1 VALUES (10); +SELECT * FROM MYSQL.t1; +a +10 +SELECT * FROM MYSQL.t2; +a +10 +DROP DATABASE MYSQL; +# +# MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0 +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS t2; +a +1 +UNLOCK TABLES; +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS T2; +ERROR HY000: Table 'T2' was not locked with LOCK TABLES +UNLOCK TABLES; +DROP TABLE t1; +# +# MDEV-33108 TABLE_STATISTICS and INDEX_STATISTICS are case insensitive with lower-case-table-names=0 +# +SET GLOBAL userstat=1; +CREATE TABLE t1 (a INT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +CREATE TABLE T1 (a INT, KEY(a)); +INSERT INTO T1 VALUES (1),(2),(3),(4); +SELECT * FROM T1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM INFORMATION_SCHEMA.TABLE_STATISTICS ORDER BY BINARY TABLE_NAME; +TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES +test T1 4 4 4 +test t1 4 4 4 +SELECT * FROM INFORMATION_SCHEMA.INDEX_STATISTICS ORDER BY BINARY TABLE_NAME; +TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ +test T1 a 4 +test t1 a 4 +DROP TABLE t1; +DROP TABLE T1; +SET GLOBAL userstat=DEFAULT; +# +# MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0 +# +CREATE DATABASE MYSQL; +CREATE FUNCTION MYSQL.f1() RETURNS INT RETURN 1; +DROP DATABASE MYSQL; +SELECT db, name, body FROM mysql.proc WHERE db=BINARY 'MYSQL' AND name='f1'; +db name body +# +# MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0 +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a +1 +CREATE OR REPLACE TABLE T1 (a INT); +DROP TABLE T1; +HANDLER t1 READ NEXT; +a +2 +HANDLER t1 CLOSE; +DROP TABLE t1; +# +# MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0 +# +CREATE TABLE mysql.GENERAL_log (a INT); +INSERT INTO mysql.GENERAL_log VALUES (1),(2); +DROP TABLE mysql.GENERAL_log; +CREATE TABLE mysql.SLOW_log (a INT); +INSERT INTO mysql.SLOW_log VALUES (1),(2); +DROP TABLE mysql.SLOW_log; +CREATE TABLE mysql.TRANSACTION_registry (a INT); +INSERT INTO mysql.TRANSACTION_registry VALUES (1),(2); +DROP TABLE mysql.TRANSACTION_registry; +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.general_log (a INT); +INSERT INTO MYSQL.general_log VALUES (1),(2); +DROP TABLE MYSQL.general_log; +CREATE TABLE MYSQL.slow_log (a INT); +INSERT INTO MYSQL.slow_log VALUES (1),(2); +DROP TABLE MYSQL.slow_log; +CREATE TABLE MYSQL.transaction_registry (a INT); +INSERT INTO MYSQL.transaction_registry VALUES (1),(2); +DROP TABLE MYSQL.transaction_registry; +DROP DATABASE MYSQL; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/lowercase_table5.test b/mysql-test/main/lowercase_table5.test index 0103dbf5fd2..fcbb3fefb33 100644 --- a/mysql-test/main/lowercase_table5.test +++ b/mysql-test/main/lowercase_table5.test @@ -49,3 +49,141 @@ DROP PROCEDURE SP; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0 +--echo # + +CREATE SEQUENCE t1; +CREATE SEQUENCE T1; +--disable_ps2_protocol +SELECT nextval(t1), lastval(t1); +SELECT nextval(T1), lastval(T1); +SELECT lastval(t1), lastval(T1) l2; +--enable_ps2_protocol +DROP SEQUENCE t1, T1; + +--echo # +--echo # MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0 +--echo # + +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +SELECT * FROM db1.t1; +SHOW OPEN TABLES IN DB1; +SHOW OPEN TABLES IN db1; +DROP DATABASE db1; + +--echo # +--echo # MDEV-33088 Cannot create triggers in the database `MYSQL` +--echo # + +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.t1 (a INT); +CREATE TABLE MYSQL.t2 (a INT); +CREATE TRIGGER MYSQL.tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (new.a); +INSERT INTO MYSQL.t1 VALUES (10); +SELECT * FROM MYSQL.t1; +SELECT * FROM MYSQL.t2; +DROP DATABASE MYSQL; + + +--echo # +--echo # MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0 +--echo # + +--disable_view_protocol +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS t2; +UNLOCK TABLES; +LOCK TABLE t1 AS t2 READ; +--error ER_TABLE_NOT_LOCKED +SELECT * FROM t1 AS T2; +UNLOCK TABLES; +DROP TABLE t1; +--enable_view_protocol + + +--echo # +--echo # MDEV-33108 TABLE_STATISTICS and INDEX_STATISTICS are case insensitive with lower-case-table-names=0 +--echo # + +SET GLOBAL userstat=1; +CREATE TABLE t1 (a INT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4); +--disable_ps2_protocol +SELECT * FROM t1 ORDER BY a; +CREATE TABLE T1 (a INT, KEY(a)); +INSERT INTO T1 VALUES (1),(2),(3),(4); +SELECT * FROM T1 ORDER BY a; +--enable_ps2_protocol +SELECT * FROM INFORMATION_SCHEMA.TABLE_STATISTICS ORDER BY BINARY TABLE_NAME; +SELECT * FROM INFORMATION_SCHEMA.INDEX_STATISTICS ORDER BY BINARY TABLE_NAME; +DROP TABLE t1; +DROP TABLE T1; +SET GLOBAL userstat=DEFAULT; + + +--echo # +--echo # MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0 +--echo # + +CREATE DATABASE MYSQL; +CREATE FUNCTION MYSQL.f1() RETURNS INT RETURN 1; +DROP DATABASE MYSQL; +SELECT db, name, body FROM mysql.proc WHERE db=BINARY 'MYSQL' AND name='f1'; + + +--echo # +--echo # MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0 +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +CREATE OR REPLACE TABLE T1 (a INT); +DROP TABLE T1; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; +DROP TABLE t1; + +--echo # +--echo # MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0 +--echo # + +CREATE TABLE mysql.GENERAL_log (a INT); +INSERT INTO mysql.GENERAL_log VALUES (1),(2); +DROP TABLE mysql.GENERAL_log; + +CREATE TABLE mysql.SLOW_log (a INT); +INSERT INTO mysql.SLOW_log VALUES (1),(2); +DROP TABLE mysql.SLOW_log; + +CREATE TABLE mysql.TRANSACTION_registry (a INT); +INSERT INTO mysql.TRANSACTION_registry VALUES (1),(2); +DROP TABLE mysql.TRANSACTION_registry; + +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.general_log (a INT); +INSERT INTO MYSQL.general_log VALUES (1),(2); +DROP TABLE MYSQL.general_log; + +CREATE TABLE MYSQL.slow_log (a INT); +INSERT INTO MYSQL.slow_log VALUES (1),(2); +DROP TABLE MYSQL.slow_log; + +CREATE TABLE MYSQL.transaction_registry (a INT); +INSERT INTO MYSQL.transaction_registry VALUES (1),(2); +DROP TABLE MYSQL.transaction_registry; +DROP DATABASE MYSQL; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result index 04e3d013b48..818a15f86ce 100644 --- a/mysql-test/main/view_grant.result +++ b/mysql-test/main/view_grant.result @@ -1954,3 +1954,34 @@ connection default; drop user user_11766767; drop database mysqltest1; drop database mysqltest2; +# +# MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS +# +USE test; +CREATE USER foo; +CREATE USER FOO; +GRANT SELECT ON test.* TO foo; +GRANT SELECT ON test.* TO FOO; +CREATE DEFINER=foo SQL SECURITY INVOKER VIEW v1 AS SELECT 1 AS c1; +connect FOO, localhost, FOO, , test; +connection FOO; +SELECT CURRENT_USER; +CURRENT_USER +FOO@% +SELECT * FROM INFORMATION_SCHEMA.VIEWS; +TABLE_CATALOG def +TABLE_SCHEMA test +TABLE_NAME v1 +VIEW_DEFINITION +CHECK_OPTION NONE +IS_UPDATABLE NO +DEFINER foo@% +SECURITY_TYPE INVOKER +CHARACTER_SET_CLIENT latin1 +COLLATION_CONNECTION latin1_swedish_ci +ALGORITHM UNDEFINED +disconnect FOO; +connection default; +DROP VIEW v1; +DROP USER foo; +DROP USER FOO; diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test index c9bb9569145..a5019e88d65 100644 --- a/mysql-test/main/view_grant.test +++ b/mysql-test/main/view_grant.test @@ -2207,3 +2207,30 @@ drop database mysqltest2; # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc + +--echo # +--echo # MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS +--echo # + +USE test; +CREATE USER foo; +CREATE USER FOO; +GRANT SELECT ON test.* TO foo; +GRANT SELECT ON test.* TO FOO; + +CREATE DEFINER=foo SQL SECURITY INVOKER VIEW v1 AS SELECT 1 AS c1; + +--connect (FOO, localhost, FOO, , test) +--connection FOO + +SELECT CURRENT_USER; +--vertical_results +--query_vertical SELECT * FROM INFORMATION_SCHEMA.VIEWS +--horizontal_results + +--disconnect FOO +--connection default + +DROP VIEW v1; +DROP USER foo; +DROP USER FOO; diff --git a/mysql-test/suite/csv/lowercase_table0.result b/mysql-test/suite/csv/lowercase_table0.result new file mode 100644 index 00000000000..fba6a509aea --- /dev/null +++ b/mysql-test/suite/csv/lowercase_table0.result @@ -0,0 +1,15 @@ +# +# MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0 +# +CREATE OR REPLACE TABLE t1 (a INT NOT NULL) ENGINE=CSV; +CREATE OR REPLACE TABLE T1 (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t1 VALUES (10); +INSERT INTO T1 VALUES (20); +SELECT * FROM t1; +a +10 +SELECT * FROM T1; +a +20 +DROP TABLE t1; +DROP TABLE T1; diff --git a/mysql-test/suite/csv/lowercase_table0.test b/mysql-test/suite/csv/lowercase_table0.test new file mode 100644 index 00000000000..2bb0e486cb6 --- /dev/null +++ b/mysql-test/suite/csv/lowercase_table0.test @@ -0,0 +1,16 @@ +--source include/have_csv.inc +--source include/have_lowercase0.inc +--source include/have_case_sensitive_file_system.inc + +--echo # +--echo # MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0 +--echo # + +CREATE OR REPLACE TABLE t1 (a INT NOT NULL) ENGINE=CSV; +CREATE OR REPLACE TABLE T1 (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t1 VALUES (10); +INSERT INTO T1 VALUES (20); +SELECT * FROM t1; +SELECT * FROM T1; +DROP TABLE t1; +DROP TABLE T1; diff --git a/sql/lex_ident.h b/sql/lex_ident.h new file mode 100644 index 00000000000..3af52ab99d0 --- /dev/null +++ b/sql/lex_ident.h @@ -0,0 +1,85 @@ +#ifndef LEX_IDENT_INCLUDED +#define LEX_IDENT_INCLUDED +/* + Copyright (c) 2023, MariaDB + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + + +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset; + + +/* + Identifiers for the database objects stored on disk, + e.g. databases, tables, triggers. +*/ +class Lex_ident_fs: public LEX_CSTRING +{ +public: + static CHARSET_INFO *charset_info() + { + return table_alias_charset; + } +public: + Lex_ident_fs() + :LEX_CSTRING({0,0}) + { } + Lex_ident_fs(const char *str, size_t length) + :LEX_CSTRING({str, length}) + { } + explicit Lex_ident_fs(const LEX_CSTRING &str) + :LEX_CSTRING(str) + { } +#if MYSQL_VERSION_ID<=110501 +private: + static bool is_valid_ident(const LEX_CSTRING &str) + { + // NULL identifier, or 0-terminated identifier + return (str.str == NULL && str.length == 0) || str.str[str.length] == 0; + } +public: + bool streq(const LEX_CSTRING &rhs) const + { + DBUG_ASSERT(is_valid_ident(*this)); + DBUG_ASSERT(is_valid_ident(rhs)); + return length == rhs.length && + my_strcasecmp(charset_info(), str, rhs.str) == 0; + } +#else +/* + Starting from 11.5.1 streq() is inherited from the base. + The above implementations of streq() and is_valid_ident() should be removed. +*/ +#error Remove streq() above. +#endif +}; + + +class Lex_ident_db: public Lex_ident_fs +{ +public: + using Lex_ident_fs::Lex_ident_fs; +}; + + +class Lex_ident_table: public Lex_ident_fs +{ +public: + using Lex_ident_fs::Lex_ident_fs; +}; + + +#endif // LEX_IDENT_INCLUDED diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8aee0624ed1..dd222998b3a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7226,8 +7226,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, continue; // Add next user } - db_name= table_list->get_db_name(); - table_name= table_list->get_table_name(); + db_name= table_list->get_db_name().str; + table_name= table_list->get_table_name().str; /* Find/create cached table grant */ grant_table= table_hash_search(Str->host.str, NullS, db_name, @@ -8294,8 +8294,8 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, - t_ref->get_db_name(), - t_ref->get_table_name()); + t_ref->get_db_name().str, + t_ref->get_table_name().str); if (access) { @@ -8359,14 +8359,14 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, } grant_table= table_hash_search(sctx->host, sctx->ip, - t_ref->get_db_name(), + t_ref->get_db_name().str, sctx->priv_user, - t_ref->get_table_name(), + t_ref->get_table_name().str, FALSE); if (sctx->priv_role[0]) - grant_table_role= table_hash_search("", NULL, t_ref->get_db_name(), + grant_table_role= table_hash_search("", NULL, t_ref->get_db_name().str, sctx->priv_role, - t_ref->get_table_name(), + t_ref->get_table_name().str, TRUE); if (!grant_table && !grant_table_role) @@ -8414,7 +8414,7 @@ err: command, sctx->priv_user, sctx->host_or_ip, tl ? tl->db.str : "unknown", - tl ? tl->get_table_name() : "unknown"); + tl ? tl->get_table_name().str : "unknown"); } DBUG_RETURN(TRUE); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f1fd0053a82..eb66d33b5b0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -200,9 +200,9 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key) is properly initialized, so table definition cache can be produced from key used by MDL subsystem. */ - DBUG_ASSERT(!strcmp(table_list->get_db_name(), + DBUG_ASSERT(!strcmp(table_list->get_db_name().str, table_list->mdl_request.key.db_name())); - DBUG_ASSERT(!strcmp(table_list->get_table_name(), + DBUG_ASSERT(!strcmp(table_list->get_table_name().str, table_list->mdl_request.key.name())); *key= (const char*)table_list->mdl_request.key.ptr() + 1; @@ -233,33 +233,40 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key) # Pointer to list of names of open tables. */ -struct list_open_tables_arg +class list_open_tables_arg { +public: THD *thd; - const char *db; + const Lex_ident_db db; const char *wild; TABLE_LIST table_list; OPEN_TABLE_LIST **start_list, *open_list; + + list_open_tables_arg(THD *thd_arg, const LEX_CSTRING &db_arg, + const char *wild_arg) + :thd(thd_arg), db(db_arg), wild(wild_arg), + start_list(&open_list), open_list(0) + { + bzero((char*) &table_list, sizeof(table_list)); + } }; static my_bool list_open_tables_callback(TDC_element *element, list_open_tables_arg *arg) { - const char *db= (char*) element->m_key; - size_t db_length= strlen(db); - const char *table_name= db + db_length + 1; + const Lex_ident_db + db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key)); + const char *table_name= db.str + db.length + 1; - if (arg->db && my_strcasecmp(system_charset_info, arg->db, db)) + if (arg->db.str && !arg->db.streq(db)) return FALSE; if (arg->wild && wild_compare(table_name, arg->wild, 0)) return FALSE; /* Check if user has SELECT privilege for any column in the table */ - arg->table_list.db.str= db; - arg->table_list.db.length= db_length; - arg->table_list.table_name.str= table_name; - arg->table_list.table_name.length= strlen(table_name); + arg->table_list.db= db; + arg->table_list.table_name= Lex_cstring_strlen(table_name); arg->table_list.grant.privilege= NO_ACL; if (check_table_access(arg->thd, SELECT_ACL, &arg->table_list, TRUE, 1, TRUE)) @@ -271,7 +278,7 @@ static my_bool list_open_tables_callback(TDC_element *element, strmov((*arg->start_list)->table= strmov(((*arg->start_list)->db= (char*) ((*arg->start_list) + 1)), - db) + 1, table_name); + db.str) + 1, table_name); (*arg->start_list)->in_use= 0; mysql_mutex_lock(&element->LOCK_table_share); @@ -288,17 +295,12 @@ static my_bool list_open_tables_callback(TDC_element *element, } -OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) +OPEN_TABLE_LIST *list_open_tables(THD *thd, + const LEX_CSTRING &db, + const char *wild) { - list_open_tables_arg argument; DBUG_ENTER("list_open_tables"); - - argument.thd= thd; - argument.db= db; - argument.wild= wild; - bzero((char*) &argument.table_list, sizeof(argument.table_list)); - argument.start_list= &argument.open_list; - argument.open_list= 0; + list_open_tables_arg argument(thd, db, wild); if (tdc_iterate(thd, (my_hash_walk_action) list_open_tables_callback, &argument, true)) @@ -1682,7 +1684,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) TABLE *table; const char *key; uint key_length; - const char *alias= table_list->alias.str; + const LEX_CSTRING &alias= table_list->alias; uint flags= ot_ctx->get_flags(); MDL_ticket *mdl_ticket; TABLE_SHARE *share; @@ -1750,7 +1752,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (table->s->table_cache_key.length == key_length && !memcmp(table->s->table_cache_key.str, key, key_length)) { - if (!my_strcasecmp(system_charset_info, table->alias.c_ptr(), alias) && + if (Lex_ident_table(table->alias.to_lex_cstring()).streq(alias) && table->query_id != thd->query_id && /* skip tables already used */ (thd->locked_tables_mode == LTM_LOCK_TABLES || table->query_id == 0)) @@ -1821,7 +1823,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (thd->locked_tables_mode == LTM_PRELOCKED) my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db.str, table_list->alias.str); else - my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); + my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias.str); DBUG_RETURN(TRUE); } diff --git a/sql/sql_base.h b/sql/sql_base.h index 267acede7dd..7cfe10ea2d1 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -309,7 +309,8 @@ bool flush_tables(THD *thd, flush_tables_type flag); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, ha_extra_function extra, TABLE *skip_table); -OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild); +OPEN_TABLE_LIST *list_open_tables(THD *thd, const LEX_CSTRING &db, + const char *wild); bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags); TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7913f1a40d2..34cd63d7839 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -855,7 +855,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); - my_hash_init(PSI_INSTRUMENT_ME, &sequences, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &sequences, Lex_ident_fs::charset_info(), SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key) get_sequence_last_key, (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC); @@ -1450,7 +1450,8 @@ void THD::change_user(void) my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); - my_hash_init(key_memory_user_var_entry, &sequences, system_charset_info, + my_hash_init(key_memory_user_var_entry, &sequences, + Lex_ident_fs::charset_info(), SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key) get_sequence_last_key, (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC); diff --git a/sql/sql_class.h b/sql/sql_class.h index 7e5d9ac96e3..7324ba73bf1 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -23,6 +23,7 @@ #include "dur_prop.h" #include #include "sql_const.h" +#include "lex_ident.h" #include #include "log.h" #include "rpl_tblmap.h" diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 61d6a529045..b371e27eb3a 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -509,7 +509,8 @@ extern "C" void free_table_stats(TABLE_STATS* table_stats) void init_global_table_stats(void) { - my_hash_init(PSI_INSTRUMENT_ME, &global_table_stats, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &global_table_stats, + Lex_ident_fs::charset_info(), max_connections, 0, 0, (my_hash_get_key) get_key_table_stats, (my_hash_free_key) free_table_stats, 0); } @@ -528,7 +529,8 @@ extern "C" void free_index_stats(INDEX_STATS* index_stats) void init_global_index_stats(void) { - my_hash_init(PSI_INSTRUMENT_ME, &global_index_stats, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &global_index_stats, + Lex_ident_fs::charset_info(), max_connections, 0, 0, (my_hash_get_key) get_key_index_stats, (my_hash_free_key) free_index_stats, 0); } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 1dcc51f1332..63cd5c83d98 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -919,8 +919,7 @@ mysql_rm_db_internal(THD *thd, const LEX_CSTRING *db, bool if_exists, bool silen Disable drop of enabled log tables, must be done before name locking. This check is only needed if we are dropping the "mysql" database. */ - if ((rm_mysql_schema= - (my_strcasecmp(system_charset_info, MYSQL_SCHEMA_NAME.str, db->str) == 0))) + if ((rm_mysql_schema= MYSQL_SCHEMA_NAME.streq(*db))) { for (table= tables; table; table= table->next_local) if (check_if_log_table(table, TRUE, "DROP")) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 276cef6236b..4108f42eb14 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -1067,10 +1067,9 @@ static SQL_HANDLER *mysql_ha_find_match(THD *thd, TABLE_LIST *tables) if (tables->is_anonymous_derived_table()) continue; if ((! tables->db.str[0] || - ! my_strcasecmp(&my_charset_latin1, hash_tables->db.str, - tables->get_db_name())) && - ! my_strcasecmp(&my_charset_latin1, hash_tables->table_name.str, - tables->get_table_name())) + Lex_ident_db(tables->get_db_name()).streq(hash_tables->db)) && + Lex_ident_table(tables->get_table_name()). + streq(hash_tables->table_name)) { /* Link into hash_tables list */ hash_tables->next= head; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5db53b6f2b8..e458cd51dde 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1154,8 +1154,9 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) { for (const TABLE_LIST *table= tables; table; table= table->next_global) { - LEX_CSTRING db= table->db, tn= table->table_name; - if (get_table_category(&db, &tn) < TABLE_CATEGORY_INFORMATION) + if (get_table_category(Lex_ident_db(table->db), + Lex_ident_table(table->table_name)) + < TABLE_CATEGORY_INFORMATION) return false; } return tables != NULL; @@ -6522,15 +6523,15 @@ static TABLE *find_temporary_table_for_rename(THD *thd, { TABLE_LIST *next= table->next_local; - if (!strcmp(table->get_db_name(), cur_table->get_db_name()) && - !strcmp(table->get_table_name(), cur_table->get_table_name())) + if (!strcmp(table->get_db_name().str, cur_table->get_db_name().str) && + !strcmp(table->get_table_name().str, cur_table->get_table_name().str)) { /* Table was moved away, can't be same as 'table' */ found= 1; res= 0; // Table can't be a temporary table } - if (!strcmp(next->get_db_name(), cur_table->get_db_name()) && - !strcmp(next->get_table_name(), cur_table->get_table_name())) + if (!strcmp(next->get_db_name().str, cur_table->get_db_name().str) && + !strcmp(next->get_table_name().str, cur_table->get_table_name().str)) { /* Table has matching name with new name of this table. cur_table should @@ -7299,7 +7300,7 @@ check_table_access(THD *thd, privilege_t requirements, TABLE_LIST *tables, INSERT_ACL : SELECT_ACL); } - if (check_access(thd, want_access, table_ref->get_db_name(), + if (check_access(thd, want_access, table_ref->get_db_name().str, &table_ref->grant.privilege, &table_ref->grant.m_internal, 0, no_errors)) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3ed8e108f8d..eb84ef56419 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1053,7 +1053,8 @@ public: ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW", m_sctx->priv_user, m_sctx->host_or_ip, - m_top_view->get_db_name(), m_top_view->get_table_name()); + m_top_view->get_db_name().str, + m_top_view->get_table_name().str); } return m_view_access_denied_message_ptr; } @@ -1098,8 +1099,8 @@ public: push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_VIEW_INVALID, ER_THD(thd, ER_VIEW_INVALID), - m_top_view->get_db_name(), - m_top_view->get_table_name()); + m_top_view->get_db_name().str, + m_top_view->get_table_name().str); is_handled= TRUE; break; @@ -6887,8 +6888,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, Security_context *sctx= thd->security_ctx; if (!tables->allowed_show) { - if (!my_strcasecmp(system_charset_info, tables->definer.user.str, - sctx->priv_user) && + if (!strcmp(tables->definer.user.str, sctx->priv_user) && !my_strcasecmp(system_charset_info, tables->definer.host.str, sctx->priv_host)) tables->allowed_show= TRUE; @@ -7981,7 +7981,7 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; OPEN_TABLE_LIST *open_list; - if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db.str, + if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db, wild)) && thd->is_fatal_error) DBUG_RETURN(1); diff --git a/sql/sql_string.h b/sql/sql_string.h index 3dbeb7b83cf..0475b2d1f6e 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -572,6 +572,11 @@ public: if (str.Alloced_length) Alloced_length= (uint32) (str.Alloced_length - offset); } + LEX_CSTRING to_lex_cstring() const + { + LEX_CSTRING tmp= {Ptr, str_length}; + return tmp; + } inline LEX_CSTRING *get_value(LEX_CSTRING *res) { res->str= Ptr; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index d2e5ecbb4d8..8a0d761f51d 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -446,7 +446,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* We don't allow creating triggers on tables in the 'mysql' schema */ - if (create && lex_string_eq(&tables->db, STRING_WITH_LEN("mysql"))) + if (create && Lex_ident_db(tables->db).streq(MYSQL_SCHEMA_NAME)) { my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0)); DBUG_RETURN(TRUE); diff --git a/sql/table.cc b/sql/table.cc index cc8fb094e36..8f5b0ce3bcc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -89,7 +89,7 @@ LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")}; LEX_CSTRING PERFORMANCE_SCHEMA_DB_NAME= {STRING_WITH_LEN("performance_schema")}; /* MYSQL_SCHEMA name */ -LEX_CSTRING MYSQL_SCHEMA_NAME= {STRING_WITH_LEN("mysql")}; +Lex_ident_db MYSQL_SCHEMA_NAME= {STRING_WITH_LEN("mysql")}; /* GENERAL_LOG name */ LEX_CSTRING GENERAL_LOG_NAME= {STRING_WITH_LEN("general_log")}; @@ -273,42 +273,38 @@ const char *fn_frm_ext(const char *name) } -TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, - const LEX_CSTRING *name) +TABLE_CATEGORY get_table_category(const Lex_ident_db &db, + const Lex_ident_table &name) { - DBUG_ASSERT(db != NULL); - DBUG_ASSERT(name != NULL); - #ifdef WITH_WSREP - if (db->str && - my_strcasecmp(system_charset_info, db->str, WSREP_SCHEMA) == 0) + if (db.str && db.streq(MYSQL_SCHEMA_NAME)) { - if ((my_strcasecmp(system_charset_info, name->str, WSREP_STREAMING_TABLE) == 0 || - my_strcasecmp(system_charset_info, name->str, WSREP_CLUSTER_TABLE) == 0 || - my_strcasecmp(system_charset_info, name->str, WSREP_MEMBERS_TABLE) == 0)) + if (name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_STREAMING_TABLE)}) || + name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_CLUSTER_TABLE)}) || + name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_MEMBERS_TABLE)})) { return TABLE_CATEGORY_INFORMATION; } } #endif /* WITH_WSREP */ - if (is_infoschema_db(db)) + if (is_infoschema_db(&db)) return TABLE_CATEGORY_INFORMATION; - if (is_perfschema_db(db)) + if (is_perfschema_db(&db)) return TABLE_CATEGORY_PERFORMANCE; - if (lex_string_eq(&MYSQL_SCHEMA_NAME, db)) + if (db.streq(MYSQL_SCHEMA_NAME)) { - if (is_system_table_name(name->str, name->length)) + if (is_system_table_name(name.str, name.length)) return TABLE_CATEGORY_SYSTEM; - if (lex_string_eq(&GENERAL_LOG_NAME, name)) + if (name.streq(GENERAL_LOG_NAME)) return TABLE_CATEGORY_LOG; - if (lex_string_eq(&SLOW_LOG_NAME, name)) + if (name.streq(SLOW_LOG_NAME)) return TABLE_CATEGORY_LOG; - if (lex_string_eq(&TRANSACTION_REG_NAME, name)) + if (name.streq(TRANSACTION_REG_NAME)) return TABLE_CATEGORY_LOG; } @@ -361,7 +357,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, strmov(path_buff, path); share->normalized_path.str= share->path.str; share->normalized_path.length= path_length; - share->table_category= get_table_category(& share->db, & share->table_name); + share->table_category= get_table_category(Lex_ident_db(share->db), + Lex_ident_table(share->table_name)); share->open_errno= ENOENT; /* The following will be updated in open_table_from_share */ share->can_do_row_logging= 1; diff --git a/sql/table.h b/sql/table.h index 97e595979b9..16a42b6e81e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -22,6 +22,7 @@ #include "datadict.h" #include "sql_string.h" /* String */ #include "lex_string.h" +#include "lex_ident.h" #ifndef MYSQL_CLIENT @@ -522,8 +523,8 @@ enum enum_table_category typedef enum enum_table_category TABLE_CATEGORY; -TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, - const LEX_CSTRING *name); +TABLE_CATEGORY get_table_category(const Lex_ident_db &db, + const Lex_ident_table &name); typedef struct st_table_field_type @@ -2880,7 +2881,10 @@ struct TABLE_LIST @brief Returns the name of the database that the referenced table belongs to. */ - const char *get_db_name() const { return view != NULL ? view_db.str : db.str; } + const LEX_CSTRING get_db_name() const + { + return view != NULL ? view_db : db; + } /** @brief Returns the name of the table that this TABLE_LIST represents. @@ -2888,7 +2892,10 @@ struct TABLE_LIST @details The unqualified table name or view name for a table or view, respectively. */ - const char *get_table_name() const { return view != NULL ? view_name.str : table_name.str; } + const LEX_CSTRING get_table_name() const + { + return view != NULL ? view_name : table_name; + } bool is_active_sjm(); bool is_jtbm() { return MY_TEST(jtbm_subselect != NULL); } st_select_lex_unit *get_unit(); @@ -3292,7 +3299,7 @@ extern LEX_CSTRING TRANSACTION_REG_NAME; /* information schema */ extern LEX_CSTRING INFORMATION_SCHEMA_NAME; -extern LEX_CSTRING MYSQL_SCHEMA_NAME; +extern Lex_ident_db MYSQL_SCHEMA_NAME; /* table names */ extern LEX_CSTRING MYSQL_PROC_NAME; diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index a28b5f96935..9687506762c 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -154,7 +154,8 @@ TABLE *THD::find_temporary_table(const TABLE_LIST *tl, Temporary_table_state state) { DBUG_ENTER("THD::find_temporary_table"); - TABLE *table= find_temporary_table(tl->get_db_name(), tl->get_table_name(), + TABLE *table= find_temporary_table(tl->get_db_name().str, + tl->get_table_name().str, state); DBUG_RETURN(table); } @@ -243,8 +244,8 @@ TMP_TABLE_SHARE *THD::find_tmp_table_share(const char *db, TMP_TABLE_SHARE *THD::find_tmp_table_share(const TABLE_LIST *tl) { DBUG_ENTER("THD::find_tmp_table_share"); - TMP_TABLE_SHARE *share= find_tmp_table_share(tl->get_db_name(), - tl->get_table_name()); + TMP_TABLE_SHARE *share= find_tmp_table_share(tl->get_db_name().str, + tl->get_table_name().str); DBUG_RETURN(share); } @@ -385,7 +386,7 @@ bool THD::open_temporary_table(TABLE_LIST *tl) */ if (!table && (share= find_tmp_table_share(tl))) { - table= open_temporary_table(share, tl->get_table_name()); + table= open_temporary_table(share, tl->get_table_name().str); /* Temporary tables are not safe for parallel replication. They were designed to be visible to one thread only, so have no table locking. @@ -1172,8 +1173,8 @@ bool THD::find_and_use_tmp_table(const TABLE_LIST *tl, TABLE **out_table) bool result; DBUG_ENTER("THD::find_and_use_tmp_table"); - key_length= create_tmp_table_def_key(key, tl->get_db_name(), - tl->get_table_name()); + key_length= create_tmp_table_def_key(key, tl->get_db_name().str, + tl->get_table_name().str); result= use_temporary_table(find_temporary_table(key, key_length, TMP_TABLE_NOT_IN_USE), out_table); diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index ec569feec9d..04e63530c0e 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -184,7 +184,8 @@ static int tina_init_func(void *p) tina_hton= (handlerton *)p; mysql_mutex_init(csv_key_mutex_tina, &tina_mutex, MY_MUTEX_INIT_FAST); (void) my_hash_init(csv_key_memory_tina_share, &tina_open_tables, - system_charset_info, 32, 0, 0, (my_hash_get_key) + Lex_ident_table::charset_info(), + 32, 0, 0, (my_hash_get_key) tina_get_key, 0, 0); tina_hton->db_type= DB_TYPE_CSV_DB; tina_hton->create= tina_create_handler;