mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-31340 Remove MY_COLLATION_HANDLER::strcasecmp()
This patch also fixes: MDEV-33050 Build-in schemas like oracle_schema are accent insensitive 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-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 - Removing the virtual function strnncoll() from MY_COLLATION_HANDLER - Adding a wrapper function CHARSET_INFO::streq(), to compare two strings for equality. For now it calls strnncoll() internally. In the future it will turn into a virtual function. - Adding new accent sensitive case insensitive collations: - utf8mb4_general1400_as_ci - utf8mb3_general1400_as_ci They implement accent sensitive case insensitive comparison. The weight of a character is equal to the code point of its upper case variant. These collations use Unicode-14.0.0 casefolding data. The result of my_charset_utf8mb3_general1400_as_ci.strcoll() is very close to the former my_charset_utf8mb3_general_ci.strcasecmp() There is only a difference in a couple dozen rare characters, because: - the switch from "tolower" to "toupper" comparison, to make utf8mb3_general1400_as_ci closer to utf8mb3_general_ci - the switch from Unicode-3.0.0 to Unicode-14.0.0 This difference should be tolarable. See the list of affected characters in the MDEV description. Note, utf8mb4_general1400_as_ci correctly handles non-BMP characters! Unlike utf8mb4_general_ci, it does not treat all BMP characters as equal. - Adding classes representing names of the file based database objects: Lex_ident_db Lex_ident_table Lex_ident_trigger Their comparison collation depends on the underlying file system case sensitivity and on --lower-case-table-names and can be either my_charset_bin or my_charset_utf8mb3_general1400_as_ci. - Adding classes representing names of other database objects, whose names have case insensitive comparison style, using my_charset_utf8mb3_general1400_as_ci: Lex_ident_column Lex_ident_sys_var Lex_ident_user_var Lex_ident_sp_var Lex_ident_ps Lex_ident_i_s_table Lex_ident_window Lex_ident_func Lex_ident_partition Lex_ident_with_element Lex_ident_rpl_filter Lex_ident_master_info Lex_ident_host Lex_ident_locale Lex_ident_plugin Lex_ident_engine Lex_ident_server Lex_ident_savepoint Lex_ident_charset engine_option_value::Name - All the mentioned Lex_ident_xxx classes implement a method streq(): if (ident1.streq(ident2)) do_equal(); This method works as a wrapper for CHARSET_INFO::streq(). - Changing a lot of "LEX_CSTRING name" to "Lex_ident_xxx name" in class members and in function/method parameters. - Replacing all calls like system_charset_info->coll->strcasecmp(ident1, ident2) to ident1.streq(ident2) - Taking advantage of the c++11 user defined literal operator for LEX_CSTRING (see m_strings.h) and Lex_ident_xxx (see lex_ident.h) data types. Use example: const Lex_ident_column primary_key_name= "PRIMARY"_Lex_ident_column; is now a shorter version of: const Lex_ident_column primary_key_name= Lex_ident_column({STRING_WITH_LEN("PRIMARY")});
This commit is contained in:
@ -1129,10 +1129,9 @@ void cleanup_items(Item *item)
|
||||
#ifdef WITH_WSREP
|
||||
static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
|
||||
{
|
||||
for (const TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
for (const TABLE_LIST *t= tables; t; t= t->next_global)
|
||||
{
|
||||
LEX_CSTRING db= table->db, tn= table->table_name;
|
||||
if (get_table_category(&db, &tn) < TABLE_CATEGORY_INFORMATION)
|
||||
if (get_table_category(t->db, t->table_name) < TABLE_CATEGORY_INFORMATION)
|
||||
return false;
|
||||
}
|
||||
return tables != NULL;
|
||||
@ -2033,7 +2032,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
|
||||
}
|
||||
thd->convert_string(&table_name, system_charset_info,
|
||||
packet, arg_length, thd->charset());
|
||||
if (check_table_name(table_name.str, table_name.length, FALSE))
|
||||
if (Lex_ident_table::check_name(table_name, false))
|
||||
{
|
||||
/* this is OK due to convert_string() null-terminating the string */
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
|
||||
@ -2648,7 +2647,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
lex->first_select_lex()->db=
|
||||
thd->make_ident_casedn(lex->first_select_lex()->db);
|
||||
schema_select_lex->db= lex->first_select_lex()->db;
|
||||
if (Lex_ident_fs(lex->first_select_lex()->db).check_db_name_with_error())
|
||||
if (Lex_ident_db::check_name_with_error(lex->first_select_lex()->db))
|
||||
DBUG_RETURN(1);
|
||||
break;
|
||||
}
|
||||
@ -2831,8 +2830,8 @@ bool sp_process_definer(THD *thd)
|
||||
bool curuser= !strcmp(d->user.str, thd->security_ctx->priv_user);
|
||||
bool currole= !curuser && !strcmp(d->user.str, thd->security_ctx->priv_role);
|
||||
bool curuserhost= curuser && d->host.str &&
|
||||
!my_strcasecmp(system_charset_info, d->host.str,
|
||||
thd->security_ctx->priv_host);
|
||||
Lex_ident_host(d->host).
|
||||
streq(Lex_cstring_strlen(thd->security_ctx->priv_host));
|
||||
if (!curuserhost && !currole &&
|
||||
check_global_access(thd, PRIV_DEFINER_CLAUSE, false))
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -2841,7 +2840,7 @@ bool sp_process_definer(THD *thd)
|
||||
/* Check that the specified definer exists. Emit a warning if not. */
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (!is_acl_user(lex->definer->host.str, lex->definer->user.str))
|
||||
if (!is_acl_user(lex->definer->host, lex->definer->user))
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_NO_SUCH_USER, ER_THD(thd, ER_NO_SUCH_USER),
|
||||
@ -3073,7 +3072,7 @@ mysql_create_routine(THD *thd, LEX *lex)
|
||||
DBUG_ASSERT(lower_case_table_names != 1 ||
|
||||
Lex_ident_fs(lex->sphead->m_db).is_in_lower_case());
|
||||
|
||||
if (Lex_ident_fs(lex->sphead->m_db).check_db_name_with_error())
|
||||
if (Lex_ident_db::check_name_with_error(lex->sphead->m_db))
|
||||
return true;
|
||||
|
||||
if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
|
||||
@ -3089,15 +3088,15 @@ mysql_create_routine(THD *thd, LEX *lex)
|
||||
return true;
|
||||
}
|
||||
|
||||
const LEX_CSTRING *name= lex->sphead->name();
|
||||
const Lex_ident_routine name= Lex_ident_routine(*lex->sphead->name());
|
||||
#ifdef HAVE_DLOPEN
|
||||
if (lex->sphead->m_handler->type() == SP_TYPE_FUNCTION)
|
||||
{
|
||||
udf_func *udf = find_udf(name->str, name->length);
|
||||
udf_func *udf= find_udf(name.str, name.length);
|
||||
|
||||
if (udf)
|
||||
{
|
||||
my_error(ER_UDF_EXISTS, MYF(0), name->str);
|
||||
my_error(ER_UDF_EXISTS, MYF(0), name.str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3141,7 +3140,7 @@ mysql_create_routine(THD *thd, LEX *lex)
|
||||
which doesn't any check routine privileges,
|
||||
so no routine privilege record will insert into mysql.procs_priv.
|
||||
*/
|
||||
if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
|
||||
if (thd->slave_thread && is_acl_user(definer->host, definer->user))
|
||||
{
|
||||
security_context.change_security_context(thd, &thd->lex->definer->user,
|
||||
&thd->lex->definer->host,
|
||||
@ -3152,10 +3151,10 @@ mysql_create_routine(THD *thd, LEX *lex)
|
||||
|
||||
if (sp_automatic_privileges && !opt_noacl &&
|
||||
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
|
||||
&lex->sphead->m_db, name,
|
||||
&lex->sphead->m_db, &name,
|
||||
Sp_handler::handler(lex->sql_command), 1))
|
||||
{
|
||||
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name->str,
|
||||
if (sp_grant_privileges(thd, lex->sphead->m_db, name,
|
||||
Sp_handler::handler(lex->sql_command)))
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_PROC_AUTO_GRANT_FAIL, ER_THD(thd, ER_PROC_AUTO_GRANT_FAIL));
|
||||
@ -5568,7 +5567,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
|
||||
case SQLCOM_SHOW_PACKAGE_BODY_CODE:
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
Database_qualified_name pkgname(&null_clex_str, &null_clex_str);
|
||||
Database_qualified_name pkgname;
|
||||
sp_head *sp;
|
||||
const Sp_handler *sph= Sp_handler::handler(lex->sql_command);
|
||||
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
|
||||
@ -6192,15 +6191,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
|
||||
@ -6305,7 +6304,7 @@ show_create_db(THD *thd, LEX *lex)
|
||||
my_error(ER_UNKNOWN_ERROR, MYF(0)); return 1;);
|
||||
|
||||
const DBNameBuffer dbbuf(lex->name, lower_case_table_names == 1);
|
||||
if (Lex_ident_fs(dbbuf.to_lex_cstring()).check_db_name_with_error())
|
||||
if (Lex_ident_db::check_name_with_error(dbbuf.to_lex_cstring()))
|
||||
return 1;
|
||||
LEX_CSTRING db= dbbuf.to_lex_cstring();
|
||||
return mysqld_show_create_db(thd, &db, &lex->name, lex->create_info);
|
||||
@ -6423,7 +6422,8 @@ absent:
|
||||
|
||||
if (sp_result != SP_KEY_NOT_FOUND &&
|
||||
sp_automatic_privileges && !opt_noacl &&
|
||||
sp_revoke_privileges(thd, lex->spname->m_db.str, lex->spname->m_name.str,
|
||||
sp_revoke_privileges(thd, lex->spname->m_db,
|
||||
Lex_ident_routine(lex->spname->m_name),
|
||||
Sp_handler::handler(lex->sql_command)))
|
||||
{
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
@ -6953,7 +6953,7 @@ check_table_access(THD *thd, privilege_t requirements, TABLE_LIST *tables,
|
||||
}
|
||||
|
||||
if (check_access(thd, want_access,
|
||||
table_ref->get_db_name(),
|
||||
table_ref->get_db_name().str,
|
||||
&table_ref->grant.privilege,
|
||||
&table_ref->grant.m_internal,
|
||||
0, no_errors))
|
||||
@ -6973,8 +6973,8 @@ check_routine_access(THD *thd, privilege_t want_access, const LEX_CSTRING *db,
|
||||
TABLE_LIST tables[1];
|
||||
|
||||
bzero((char *)tables, sizeof(TABLE_LIST));
|
||||
tables->db= *db;
|
||||
tables->table_name= tables->alias= *name;
|
||||
tables->db= Lex_ident_db(*db);
|
||||
tables->table_name= tables->alias= Lex_ident_table(*name);
|
||||
|
||||
/*
|
||||
The following test is just a shortcut for check_access() (to avoid
|
||||
@ -7145,7 +7145,7 @@ bool check_fk_parent_table_access(THD *thd,
|
||||
|
||||
// Check if tablename is valid or not.
|
||||
DBUG_ASSERT(table_name.str != NULL);
|
||||
if (check_table_name(table_name.str, table_name.length, false))
|
||||
if (Lex_ident_table::check_name(table_name, false))
|
||||
{
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
|
||||
return true;
|
||||
@ -7157,7 +7157,7 @@ bool check_fk_parent_table_access(THD *thd,
|
||||
|
||||
if (fk_key->ref_db.str)
|
||||
{
|
||||
if (Lex_ident_fs(fk_key->ref_db).check_db_name_with_error() ||
|
||||
if (Lex_ident_db::check_name_with_error(fk_key->ref_db) ||
|
||||
!(db_name= thd->make_ident_opt_casedn(fk_key->ref_db,
|
||||
lower_case_table_names)).str)
|
||||
return true;
|
||||
@ -7167,7 +7167,7 @@ bool check_fk_parent_table_access(THD *thd,
|
||||
if (!thd->db.str)
|
||||
{
|
||||
DBUG_ASSERT(create_db.str);
|
||||
if (Lex_ident_fs(create_db).check_db_name_with_error() ||
|
||||
if (Lex_ident_db::check_name_with_error(create_db) ||
|
||||
!(db_name= thd->make_ident_opt_casedn(create_db,
|
||||
lower_case_table_names)).str)
|
||||
return true;
|
||||
@ -7980,7 +7980,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
{
|
||||
TABLE_LIST *ptr;
|
||||
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
|
||||
LEX_CSTRING alias_str;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_ENTER("add_table_to_list");
|
||||
DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)",
|
||||
@ -7991,10 +7990,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
|
||||
if (unlikely(!table))
|
||||
DBUG_RETURN(0); // End of memory
|
||||
alias_str= alias ? *alias : table->table;
|
||||
Lex_ident_table alias_str= alias ? Lex_ident_table(*alias) :
|
||||
Lex_ident_table(table->table);
|
||||
DBUG_ASSERT(alias_str.str);
|
||||
if (!MY_TEST(table_options & TL_OPTION_ALIAS) &&
|
||||
unlikely(check_table_name(table->table.str, table->table.length, FALSE)))
|
||||
unlikely(Lex_ident_table::check_name(table->table, false)))
|
||||
{
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
|
||||
DBUG_RETURN(0);
|
||||
@ -8002,7 +8002,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
|
||||
if (unlikely(table->is_derived_table() == FALSE && table->db.str &&
|
||||
!(table_options & TL_OPTION_TABLE_FUNCTION) &&
|
||||
Lex_ident_fs(table->db).check_db_name_with_error()))
|
||||
Lex_ident_db::check_name_with_error(table->db)))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (!alias) /* Alias is case sensitive */
|
||||
@ -8022,7 +8022,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
if (table->db.str)
|
||||
{
|
||||
ptr->is_fqtn= TRUE;
|
||||
ptr->db= table->db;
|
||||
ptr->db= Lex_ident_db(table->db);
|
||||
}
|
||||
else if (!lex->with_cte_resolution && lex->copy_db_to(&ptr->db))
|
||||
DBUG_RETURN(0);
|
||||
@ -8031,14 +8031,14 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
|
||||
ptr->alias= alias_str;
|
||||
ptr->is_alias= alias ? TRUE : FALSE;
|
||||
ptr->table_name= table->table;
|
||||
ptr->table_name= Lex_ident_table(table->table);
|
||||
|
||||
if (lower_case_table_names)
|
||||
{
|
||||
if (!(ptr->table_name= thd->make_ident_casedn(ptr->table_name)).str)
|
||||
if (!(ptr->table_name= thd->lex_ident_casedn(ptr->table_name)).str)
|
||||
DBUG_RETURN(0);
|
||||
if (ptr->db.length && ptr->db.str != any_db.str &&
|
||||
!(ptr->db= thd->make_ident_casedn(ptr->db)).str)
|
||||
!(ptr->db= thd->lex_ident_casedn(ptr->db)).str)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -8064,7 +8064,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
}
|
||||
ST_SCHEMA_TABLE *schema_table;
|
||||
schema_table= find_schema_table(thd, &ptr->table_name);
|
||||
ptr->schema_table_name= ptr->table_name;
|
||||
ptr->schema_table_name= Lex_ident_i_s_table(ptr->table_name);
|
||||
ptr->schema_table= schema_table;
|
||||
}
|
||||
ptr->select_lex= this;
|
||||
@ -8085,8 +8085,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
tables ;
|
||||
tables=tables->next_local)
|
||||
{
|
||||
if (unlikely(!my_strcasecmp(table_alias_charset, alias_str.str,
|
||||
tables->alias.str) &&
|
||||
if (unlikely(alias_str.streq(tables->alias) &&
|
||||
(tables->db.str == any_db.str || ptr->db.str == any_db.str ||
|
||||
!cmp(&ptr->db, &tables->db)) &&
|
||||
!tables->sequence))
|
||||
@ -9451,12 +9450,12 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
|
||||
if (tbl->is_fqtn && elem->is_alias)
|
||||
continue; /* no match */
|
||||
if (tbl->is_fqtn && elem->is_fqtn)
|
||||
res= (my_strcasecmp(table_alias_charset, tbl->table_name.str, elem->table_name.str) ||
|
||||
res= (!tbl->table_name.streq(elem->table_name) ||
|
||||
cmp(&tbl->db, &elem->db));
|
||||
else if (elem->is_alias)
|
||||
res= my_strcasecmp(table_alias_charset, tbl->alias.str, elem->alias.str);
|
||||
res= !tbl->alias.streq(elem->alias);
|
||||
else
|
||||
res= (my_strcasecmp(table_alias_charset, tbl->table_name.str, elem->table_name.str) ||
|
||||
res= (!tbl->table_name.streq(elem->table_name) ||
|
||||
cmp(&tbl->db, &elem->db));
|
||||
|
||||
if (res)
|
||||
@ -9974,7 +9973,8 @@ bool check_string_char_length(const LEX_CSTRING *str, uint err_msg,
|
||||
|
||||
bool check_ident_length(const LEX_CSTRING *ident)
|
||||
{
|
||||
if (check_string_char_length(ident, 0, NAME_CHAR_LEN, system_charset_info, 1))
|
||||
if (check_string_char_length(ident, 0, NAME_CHAR_LEN,
|
||||
Lex_ident_ci::charset_info(), 1))
|
||||
{
|
||||
my_error(ER_TOO_LONG_IDENT, MYF(0), ident->str);
|
||||
return 1;
|
||||
|
Reference in New Issue
Block a user