MDEV-31606 Refactor check_db_name() to get a const argument

Problem:
Under terms of MDEV-27490, we'll update Unicode version used
to compare identifiers to 14.0.0. Unlike in the old Unicode version,
in the new version a string can grow during lower-case. We cannot
perform check_db_name() inplace any more.

Change summary:

- Allocate memory to store lower-cased identifiers in memory root

- Removing check_db_name() performing both in-place lower-casing and validation
  at the same time. Splitting it into two separate stages:
  * creating a memory-root lower-cased copy of an identifier
    (using new MEM_ROOT functions and Query_arena wrapper methods)
  * performing validation on a constant string
    (using Lex_ident_fs methods)

Implementation details:

- Adding a mysys helper function to allocate lower-cased strings on MEM_ROOT:

    lex_string_casedn_root()

  and a Query_arena wrappers for it:

    make_ident_casedn()
    make_ident_opt_casedn()

- Adding a Query_arena method to perform both MEM_ROOT lower-casing and
  database name validation at the same time:

    to_ident_db_internal_with_error()

  This method is very close to the old (pre-11.3) check_db_name(),
  but performs lower-casing to a newly allocated MEM_ROOT
  memory (instead of performing lower-casing the original string in-place).

- Adding a Table_ident method which additionally handles derived table names:

    to_ident_db_internal_with_error()

- Removing the old check_db_name()
This commit is contained in:
Alexander Barkov 2023-07-04 14:09:43 +04:00
parent e987b9350c
commit f5aae71661
15 changed files with 245 additions and 173 deletions

View File

@ -908,6 +908,20 @@ static inline char *safe_strdup_root(MEM_ROOT *root, const char *str)
extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len);
extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len);
extern LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str);
static inline LEX_STRING lex_string_strmake_root(MEM_ROOT *mem_root,
const char *str, size_t length)
{
LEX_STRING tmp;
tmp.str= strmake_root(mem_root, str, length);
tmp.length= tmp.str ? length : 0;
return tmp;
}
extern LEX_STRING lex_string_casedn_root(MEM_ROOT *root,
CHARSET_INFO *cs,
const char *str, size_t length);
extern my_bool my_compress(uchar *, size_t *, size_t *);
extern my_bool my_uncompress(uchar *, size_t , size_t *);
extern uchar *my_compress_alloc(const uchar *packet, size_t *len,

View File

@ -623,3 +623,16 @@ LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str)
res.length= str.length;
return res;
}
LEX_STRING lex_string_casedn_root(MEM_ROOT *root, CHARSET_INFO *cs,
const char *str, size_t length)
{
size_t nbytes= length * cs->cset->casedn_multiply(cs);
LEX_STRING res= {NULL, 0};
if (!(res.str= alloc_root(root, nbytes + 1)))
return res;
res.length= cs->cset->casedn(cs, str, length, res.str, nbytes);
res.str[res.length]= '\0';
return res;
}

View File

@ -42,6 +42,7 @@ public:
bool check_db_name() const;
bool check_db_name_with_error() const;
#ifndef DBUG_OFF
bool is_in_lower_case() const;
bool ok_for_lower_case_names() const;
#endif
};
@ -55,6 +56,11 @@ public:
*/
class Lex_ident_db: public Lex_ident_fs
{
// {empty_c_string,0} is used by derived tables
bool is_empty() const
{
return length == 0 && str != NULL;
}
public:
Lex_ident_db()
:Lex_ident_fs(NULL, 0)
@ -62,7 +68,7 @@ public:
Lex_ident_db(const char *str, size_t length)
:Lex_ident_fs(str, length)
{
DBUG_SLOW_ASSERT(!check_db_name());
DBUG_SLOW_ASSERT(is_empty() || !check_db_name());
}
};

View File

@ -2620,9 +2620,9 @@ bool Sp_handler::
pkgstr, name->m_name, type()))
{
DBUG_ASSERT(ret == SP_OK);
pkgname->copy(thd->mem_root, caller->m_db, pkgstr);
*pkg_routine_handler= package_routine_handler();
if (name->make_package_routine_name(thd->mem_root, pkgstr, name->m_name))
if (pkgname->copy_sp_name_internal(thd->mem_root, caller->m_db, pkgstr) ||
name->make_package_routine_name(thd->mem_root, pkgstr, name->m_name))
return true;
}
return ret != SP_OK;

View File

@ -810,7 +810,7 @@ sp_head::init(LEX *lex)
}
void
bool
sp_head::init_sp_name(const sp_name *spname)
{
DBUG_ENTER("sp_head::init_sp_name");
@ -819,10 +819,10 @@ sp_head::init_sp_name(const sp_name *spname)
DBUG_ASSERT(spname && spname->m_db.str && spname->m_db.length);
/* We have to copy strings to get them into the right memroot. */
Database_qualified_name::copy(&main_mem_root, spname->m_db, spname->m_name);
m_explicit_name= spname->m_explicit_name;
DBUG_VOID_RETURN;
/* We have to copy strings to get them into the right memroot. */
DBUG_RETURN(copy_sp_name_internal(&main_mem_root,
spname->m_db, spname->m_name));
}
void

View File

@ -339,7 +339,7 @@ public:
init(LEX *lex);
/** Copy sp name from parser. */
void
bool
init_sp_name(const sp_name *spname);
/** Set the body-definition start position. */

View File

@ -3975,6 +3975,49 @@ Query_arena::Type Statement::type() const
}
/*
Return an internal database name:
- validated with Lex_ident_db::check_db_name()
- optionally converted to lower-case when lower_case_table_names==1
The lower-cased copy is made on mem_root when needed.
An error is raised in case of EOM or a bad database name.
@param src - the database name
@returns - {NULL,0} on EOM or a bad database name,
or a good database name otherwise
*/
Lex_ident_db
Query_arena::to_ident_db_internal_with_error(const LEX_CSTRING &src)
{
DBUG_ASSERT(src.str);
if (src.str == any_db.str) // e.g. JSON table
return any_db; // preserve any_db - it has a special meaning
bool casedn= lower_case_table_names == 1;
const LEX_CSTRING tmp= casedn ? make_ident_casedn(src) : src;
if (!tmp.str /*EOM*/ ||
Lex_ident_fs(tmp).check_db_name_with_error())
return Lex_ident_db();
return Lex_ident_db(tmp.str, tmp.length);
}
Lex_ident_db
Table_ident::to_ident_db_internal_with_error(Query_arena *arena) const
{
if (is_derived_table())
{
DBUG_ASSERT(db.str == empty_c_string && db.length == 0);
return Lex_ident_db(empty_c_string, 0);
}
// Normal table or JSON table
return arena->to_ident_db_internal_with_error(db);
}
void Statement::set_statement(Statement *stmt)
{
id= stmt->id;
@ -8168,14 +8211,18 @@ void AUTHID::parse(const char *str, size_t length)
}
void Database_qualified_name::copy(MEM_ROOT *mem_root,
const LEX_CSTRING &db,
const LEX_CSTRING &name)
bool Database_qualified_name::copy_sp_name_internal(MEM_ROOT *mem_root,
const LEX_CSTRING &db,
const LEX_CSTRING &name)
{
m_db.length= db.length;
m_db.str= strmake_root(mem_root, db.str, db.length);
m_name.length= name.length;
m_name.str= strmake_root(mem_root, name.str, name.length);
DBUG_ASSERT(db.str);
DBUG_ASSERT(name.str);
m_db= lower_case_table_names == 1 ?
lex_string_casedn_root(mem_root, &my_charset_utf8mb3_general_ci,
db.str, db.length) :
lex_string_strmake_root(mem_root, db.str, db.length);
m_name= lex_string_strmake_root(mem_root, name.str, name.length);
return m_db.str == NULL || m_name.str == NULL; // check if EOM
}

View File

@ -1355,6 +1355,45 @@ public:
return false;
}
/*
Make a lower-cased copy of an identifier on mem_root.
@param src - The original identifier (usually coming from the parser)
@return - {NULL,0} in case of EOM, or a non-NULL LEX_STRING
with the lower-cased identifier copy.
*/
LEX_STRING make_ident_casedn(const LEX_CSTRING &src)
{
return lex_string_casedn_root(mem_root, &my_charset_utf8mb3_general_ci,
src.str, src.length);
}
/*
Make an exact copy or a lower-cased copy of an identifier on mem_root.
@param src - The original identifier (usually coming from the parser)
@param casedn - If the name should be converted to lower case
@return - {NULL,0} in case of EOM,
or a non-NULL LEX_STRING with the identifier copy.
*/
LEX_STRING make_ident_opt_casedn(const LEX_CSTRING &src, bool casedn)
{
return casedn ? make_ident_casedn(src) :
lex_string_strmake_root(mem_root, src.str, src.length);
}
/*
Convert a LEX_CSTRING to a valid internal database name:
- validated with Lex_ident_fs::check_db_name()
- optionally lower-cased when lower_case_table_names==1
The lower-cased copy is created on Query_arena::mem_root, when needed.
@param name - The name to normalize. Must not be {NULL,0}.
@return - {NULL,0} on EOM or a bad database name
(with an errror is raised,
or a good database name otherwise.
*/
Lex_ident_db to_ident_db_internal_with_error(const LEX_CSTRING &name);
void set_query_arena(Query_arena *set);
@ -7051,6 +7090,16 @@ public:
}
bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs);
bool append_to(THD *thd, String *to) const;
/*
Convert Table_ident::m_db to a valid internal database name:
- validated with Lex_ident_fs::check_db_name()
- optionally lower-cased when lower_case_table_names==1
@param arena - the arena to allocate the lower-cased copy on, when needed.
@return {NULL,0} in case of EOM or invalid database name,
or a good identifier otherwise.
*/
Lex_ident_db to_ident_db_internal_with_error(Query_arena *arena) const;
};
@ -7865,8 +7914,13 @@ public:
!cs->strnncoll(m_name.str, m_name.length,
other->m_name.str, other->m_name.length);
}
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
const LEX_CSTRING &name);
/*
Make copies of "db" and "name" on the memory root in internal format:
- Lower-case "db" if lower-case-table-names==1.
- Preserve "name" as is.
*/
bool copy_sp_name_internal(MEM_ROOT *mem_root, const LEX_CSTRING &db,
const LEX_CSTRING &name);
// Export db and name as a qualified name string: 'db.name'
size_t make_qname(char *dst, size_t dstlen) const

View File

@ -7389,14 +7389,9 @@ sp_name *LEX::make_sp_name(THD *thd, const Lex_ident_sys_st &name1,
{
DBUG_ASSERT(name1.str);
sp_name *res;
LEX_CSTRING norm_name1;
if (unlikely(!thd->make_lex_string(&norm_name1, name1.str, name1.length)) ||
unlikely(check_db_name((LEX_STRING *) &norm_name1)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), name1.str);
return NULL;
}
if (unlikely(check_routine_name(&name2)) ||
const Lex_ident_db norm_name1= thd->to_ident_db_internal_with_error(name1);
if (unlikely(!norm_name1.str) ||
unlikely(check_routine_name(&name2)) ||
unlikely(!(res= new (thd->mem_root) sp_name(&norm_name1, &name2, true))))
return NULL;
return res;
@ -9309,20 +9304,16 @@ bool LEX::call_statement_start(THD *thd,
const Lex_ident_sys_st *pkg,
const Lex_ident_sys_st *proc)
{
DBUG_ASSERT(db->str);
Database_qualified_name q_db_pkg(db, pkg);
Identifier_chain2 q_pkg_proc(*pkg, *proc);
sp_name *spname;
sql_command= SQLCOM_CALL;
if (check_db_name(reinterpret_cast<LEX_STRING*>
(const_cast<LEX_CSTRING*>
(static_cast<const LEX_CSTRING*>(db)))))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
return true;
}
if (check_routine_name(pkg) ||
const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(*db);
if (!db_int.str ||
check_routine_name(pkg) ||
check_routine_name(proc))
return true;
@ -9330,7 +9321,7 @@ bool LEX::call_statement_start(THD *thd,
LEX_CSTRING pkg_dot_proc;
if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) ||
check_ident_length(&pkg_dot_proc) ||
!(spname= new (thd->mem_root) sp_name(db, &pkg_dot_proc, true)))
!(spname= new (thd->mem_root) sp_name(&db_int, &pkg_dot_proc, true)))
return true;
sp_handler_package_function.add_used_routine(thd->lex, thd, spname);
@ -9575,17 +9566,13 @@ Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
version() (a vendor can specify any schema).
*/
if (!name.str || check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
return NULL;
}
if (check_routine_name(&name))
const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(db);
if (!db_int.str || check_routine_name(&name))
return NULL;
Create_qfunc *builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
return builder->create_with_db(thd, &db, &name, true, args);
return builder->create_with_db(thd, &db_int, &name, true, args);
}
@ -9609,12 +9596,9 @@ Item *LEX::make_item_func_call_generic(THD *thd,
if (db.is_null() || pkg.is_null() || func.is_null())
return NULL; // EOM
if (check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
return NULL;
}
if (check_routine_name(&pkg) ||
const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(db);
if (!db_int.str ||
check_routine_name(&pkg) ||
check_routine_name(&func))
return NULL;
@ -9622,7 +9606,7 @@ Item *LEX::make_item_func_call_generic(THD *thd,
LEX_CSTRING pkg_dot_func;
if (q_pkg_func.make_qname(thd->mem_root, &pkg_dot_func) ||
check_ident_length(&pkg_dot_func) ||
!(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true)))
!(qname= new (thd->mem_root) sp_name(&db_int, &pkg_dot_func, true)))
return NULL;
sp_handler_package_function.add_used_routine(thd->lex, thd, qname);
@ -11427,13 +11411,18 @@ bool LEX::stmt_alter_table_exchange_partition(Table_ident *table)
bool LEX::stmt_alter_table(Table_ident *table)
{
DBUG_ASSERT(sql_command == SQLCOM_ALTER_TABLE);
first_select_lex()->db= table->db;
if (first_select_lex()->db.str == NULL &&
copy_db_to(&first_select_lex()->db))
if (table->db.str)
{
const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(table->db);
if (!db_int.str)
return true;
first_select_lex()->db= db_int;
}
else if (copy_db_to(&first_select_lex()->db))
return true;
if (unlikely(check_table_name(table->table.str, table->table.length,
false)) ||
(table->db.str && unlikely(check_db_name((LEX_STRING*) &table->db))))
false)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
return true;
@ -11502,18 +11491,19 @@ bool LEX::stmt_drop_function(const DDL_options_st &options,
const Lex_ident_sys_st &db,
const Lex_ident_sys_st &name)
{
if (unlikely(db.str && check_db_name((LEX_STRING*) &db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
DBUG_ASSERT(db.str);
DBUG_ASSERT(name.str);
const Lex_ident_db db_int= thd->to_ident_db_internal_with_error(db);
if (unlikely(!db_int.str))
return true;
}
if (unlikely(sphead))
{
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
return true;
}
set_command(SQLCOM_DROP_FUNCTION, options);
spname= new (thd->mem_root) sp_name(&db, &name, true);
spname= new (thd->mem_root) sp_name(&db_int, &name, true);
return spname == NULL;
}

View File

@ -1424,8 +1424,8 @@ public:
bool add_ftfunc_to_list(THD *thd, Item_func_match *func);
bool add_order_to_list(THD *thd, Item *item, bool asc);
bool add_gorder_to_list(THD *thd, Item *item, bool asc);
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
LEX_CSTRING *alias,
TABLE_LIST* add_table_to_list(THD *thd, const Table_ident *table,
const LEX_CSTRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
enum_mdl_type mdl_type= MDL_SHARED_READ,

View File

@ -2623,18 +2623,11 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
schema_select_lex= new (thd->mem_root) SELECT_LEX();
schema_select_lex->table_list.first= NULL;
if (lower_case_table_names == 1)
lex->first_select_lex()->db.str=
thd->strdup(lex->first_select_lex()->db.str);
lex->first_select_lex()->db=
thd->make_ident_casedn(lex->first_select_lex()->db);
schema_select_lex->db= lex->first_select_lex()->db;
/*
check_db_name() may change db.str if lower_case_table_names == 1,
but that's ok as the db is allocted above in this case.
*/
if (check_db_name((LEX_STRING*) &lex->first_select_lex()->db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), lex->first_select_lex()->db.str);
if (Lex_ident_fs(lex->first_select_lex()->db).check_db_name_with_error())
DBUG_RETURN(1);
}
break;
}
#endif
@ -3045,15 +3038,11 @@ mysql_create_routine(THD *thd, LEX *lex)
{
DBUG_ASSERT(lex->sphead != 0);
DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
/*
Verify that the database name is allowed, optionally
lowercase it.
*/
if (check_db_name((LEX_STRING*) &lex->sphead->m_db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
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())
return true;
}
if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
NULL, NULL, 0, 0))
@ -7056,7 +7045,7 @@ bool check_global_access(THD *thd, privilege_t want_access, bool no_errors)
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
const char* create_db)
const LEX_CSTRING &create_db)
{
Key *key;
List_iterator<Key> key_iterator(alter_info->key_list);
@ -7079,54 +7068,37 @@ bool check_fk_parent_table_access(THD *thd,
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
return true;
}
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names &&
!(table_name= thd->make_ident_casedn(fk_key->ref_table)).str)
return true;
if (fk_key->ref_db.str)
{
if (!(db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
fk_key->ref_db.length+1)))
if (Lex_ident_fs(fk_key->ref_db).check_db_name_with_error() ||
!(db_name= thd->make_ident_opt_casedn(fk_key->ref_db,
lower_case_table_names)).str)
return true;
db_name.length= fk_key->ref_db.length;
// Check if database name is valid or not.
if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
}
}
else
{
if (!thd->db.str)
{
DBUG_ASSERT(create_db);
db_name.length= strlen(create_db);
if (!(db_name.str= (char *) thd->memdup(create_db,
db_name.length+1)))
DBUG_ASSERT(create_db.str);
if (Lex_ident_fs(create_db).check_db_name_with_error() ||
!(db_name= thd->make_ident_opt_casedn(create_db,
lower_case_table_names)).str)
return true;
if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
}
}
else
{
if (thd->lex->copy_db_to(&db_name))
if (thd->lex->copy_db_to(&db_name) ||
(lower_case_table_names &&
!(db_name= thd->make_ident_casedn(db_name)).str))
return true;
}
}
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names)
{
char *name;
table_name.str= name= (char *) thd->memdup(fk_key->ref_table.str,
fk_key->ref_table.length+1);
table_name.length= my_casedn_str(files_charset_info, name);
db_name.length= my_casedn_str(files_charset_info, (char*) db_name.str);
}
parent_table.init_one_table(&db_name, &table_name, 0, TL_IGNORE);
/*
@ -7892,11 +7864,30 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
0 Error
@retval
\# Pointer to TABLE_LIST element added to the total table list
This method can be called in contexts when the "table" argument has a longer
life cycle than TABLE_LIST and belongs to a different MEM_ROOT than
the current THD::mem_root.
For example, it's called from Table_ident::resolve_table_rowtype_ref()
during sp_head::rcontext_create() during a CALL statement.
"table" in this case belongs to sp_pcontext, which must stay valid
(inside its SP cache sp_head entry) after the end of the current statement.
Let's allocate normalized copies of table.db and table.table on the current
THD::mem_root and store them in the TABLE_LIST.
We should not touch "table" and replace table.db and table.table to their
normalized copies allocated on the current THD::mem_root, because it'll be
freed at the end of the current statement, while table.db and table.table
should stay valid. Let's keep them in the original state.
*/
TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Table_ident *table,
LEX_CSTRING *alias,
const Table_ident *table,
const LEX_CSTRING *alias,
ulong table_options,
thr_lock_type lock_type,
enum_mdl_type mdl_type,
@ -7928,11 +7919,8 @@ 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) &&
check_db_name((LEX_STRING*) &table->db)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
Lex_ident_fs(table->db).check_db_name_with_error()))
DBUG_RETURN(0);
}
if (!alias) /* Alias is case sensitive */
{
@ -7960,16 +7948,17 @@ 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;
if (lower_case_table_names)
{
if (table->table.length)
table->table.length= my_casedn_str(files_charset_info,
(char*) table->table.str);
if (ptr->db.length && ptr->db.str != any_db.str)
ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str);
if (!(ptr->table_name= thd->make_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)
DBUG_RETURN(0);
}
ptr->table_name= table->table;
ptr->lock_type= lock_type;
ptr->mdl_type= mdl_type;
ptr->table_options= table_options;
@ -9693,7 +9682,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
}
if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info,
create_table->db.str))
create_table->db))
goto err;
error= FALSE;

View File

@ -50,7 +50,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
const char* create_db);
const LEX_CSTRING &create_db);
bool parse_sql(THD *thd, Parser_state *parser_state,
Object_creation_ctx *creation_ctx, bool do_pfs_digest=false);

View File

@ -10409,7 +10409,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
till this point for the alter operation.
*/
if ((alter_info->flags & ALTER_ADD_FOREIGN_KEY) &&
check_fk_parent_table_access(thd, create_info, alter_info, new_db->str))
check_fk_parent_table_access(thd, create_info, alter_info, *new_db))
DBUG_RETURN(true);
/*

View File

@ -5146,57 +5146,16 @@ uint calculate_key_len(TABLE *table, uint key, const uchar *buf,
*/
bool Lex_ident_fs::ok_for_lower_case_names() const
{
if (!lower_case_table_names || !str)
return true;
DBNameBuffer buf(*this, lower_case_table_names);
return !lower_case_table_names || !str || is_in_lower_case();
}
bool Lex_ident_fs::is_in_lower_case() const
{
DBNameBuffer buf(*this, true);
return cmp(*this, buf.to_lex_cstring()) == 0;
}
#endif
/*
Check if database name is valid
SYNPOSIS
check_db_name()
org_name Name of database
NOTES
If lower_case_table_names is set to 1 then database name is converted
to lower case
RETURN
0 ok
1 error
*/
bool check_db_name(LEX_STRING *org_name)
{
char *name= org_name->str;
size_t name_length= org_name->length;
bool disallow_path_chars;
if ((disallow_path_chars= check_mysql50_prefix(name)))
{
name+= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
name_length-= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
}
if (!name_length || name_length > NAME_LEN)
return 1;
if (lower_case_table_names == 1 && name != any_db.str)
{
org_name->length= name_length= my_casedn_str(files_charset_info, name);
if (disallow_path_chars)
org_name->length+= MYSQL50_TABLE_NAME_PREFIX_LENGTH;
}
if (db_name_is_in_ignore_db_dirs_list(name))
return 1;
return check_table_name(name, name_length, disallow_path_chars);
}
/*
Allow anything as a table name, as long as it doesn't contain an
' ' at the end

View File

@ -3398,7 +3398,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share,
void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
int db_errno);
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
bool check_db_name(LEX_STRING *db);
bool check_column_name(const char *name);
bool check_period_name(const char *name);
bool check_table_name(const char *name, size_t length, bool check_for_path_chars);