* rename to follow the standard vprintf name convention
* remove `(LEX_CSTRING*) &lex_string` casts
* remove some redundant casts too
* LEX_CSTRING -> Lex_ident_db in path
* Hash_set<Sroutine_hash_entry>
* move assert out of the loop
* some comments and whitespace changes
This commit is contained in:
Sergei Golubchik 2026-02-03 21:38:14 +01:00
commit 5b0818ee63
28 changed files with 178 additions and 244 deletions

View file

@ -794,7 +794,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
result = 0;
if (db && db[0])
{
result = mysql_change_db(thd, &db_str, FALSE);
result = mysql_change_db(thd, db_str, FALSE);
if (!result)
{
my_free(mysql->db);

View file

@ -84,7 +84,7 @@ RETURN func2();
END;
$$
SELECT func();
ERROR 42000: FUNCTION test.func2 does not exist
Got one of the listed errors
DROP FUNCTION func;
DROP DATABASE test2;
DROP DATABASE test3;

View file

@ -99,7 +99,7 @@ END;
$$
DELIMITER ;$$
--error ER_SP_DOES_NOT_EXIST
--error ER_SP_DOES_NOT_EXIST,ER_VIEW_INVALID
SELECT func();
DROP FUNCTION func;

View file

@ -1,7 +1,13 @@
# this test cannot run in view protocol, because every view creation flushes
# SP cache and next package function invocation instantiates the package
# anew. Package instantiation includes SELECT's, which cannot be done
# from inside a function call (package function, that caused instantiation)
source include/no_view_protocol.inc;
--echo #
--echo # Package's routine resolution shadowed by schema
--echo #
SET PATH 'pkg, test';
CREATE DATABASE pkg;
DELIMITER /;
@ -71,11 +77,11 @@ CREATE OR REPLACE PACKAGE BODY pkg
BEGIN
RETURN priv_f1(CONCAT(a, 'implicit_priv->'));
END;
CALL test.pkg.p1('explicit_init->');
CALL pkg.p1('schema_implicit_init->');
CALL p1('implicit_init->');
SELECT test.pkg.f1('explicit_init->');
SELECT pkg.f1('schema_implicit_init->');
SELECT f1('implicit_init->');
@ -123,4 +129,4 @@ SELECT f1('implicit_stmt->');
USE test;
DROP PACKAGE pkg;
DROP DATABASE pkg;
DROP DATABASE pkg;

View file

@ -258,63 +258,63 @@ SET @@session.path = @start_session_value;
SELECT @@session.path;
SET @@global.path = @start_global_value;
SELECT @@global.path;
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`a';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"a';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'a`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'a"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"d"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`aaa';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'aaa`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"aaa';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'aaa"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`aaa"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"aaa`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"ggg,hhh';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'ggg",hhh';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"ggg",hhh';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'hhh,`iii`,jjj,"kkk",lll';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'hello,world,deadpool,wolverine,aaa,deadpool,ccc';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`,Ɣ';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '",Ɣ';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'Ɣ,`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'Ɣ,"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`Œ';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"c';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'Œ`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH 'Œ"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '`Œ"';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"Œ`';
--Error ER_WRONG_VALUE_FOR_VAR
--Error ER_WRONG_VALUE_FOR_VAR
SET PATH '"Ɣ"';
SELECT @@path;

View file

@ -1377,10 +1377,9 @@ Event_job_data::execute(THD *thd, bool drop)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (event_sctx.change_security_context(thd, &definer_user, &definer_host,
&dbname, &save_sctx) ||
mysql_change_db(thd, &dbname, false))
mysql_change_db(thd, dbname, FALSE))
{
sql_print_error("Event Scheduler: "
"[%s].[%s.%s] execution failed, "
sql_print_error("Event Scheduler: [%s].[%s.%s] execution failed, "
"failed to authenticate the user.",
definer.str, dbname.str, name.str);
goto end;
@ -1395,8 +1394,7 @@ Event_job_data::execute(THD *thd, bool drop)
privilege is revoked from trigger definer,
triggers are not executed.
*/
sql_print_error("Event Scheduler: "
"[%s].[%s.%s] execution failed, "
sql_print_error("Event Scheduler: [%s].[%s.%s] execution failed, "
"user no longer has EVENT privilege.",
definer.str, dbname.str, name.str);
goto end;

View file

@ -3050,12 +3050,12 @@ Create_sp_func::create_with_db(THD *thd,
Only add to used routine if m_db was resolved, we want to defer
error handling for ER_SP_DOES_NOT_EXIST until execution for error
message consistency
*/
*/
sph->add_used_routine(lex, thd, qname);
if (pkgname.m_name.length)
sp_handler_package_body.add_used_routine(lex, thd, &pkgname);
}
Name_resolution_context *ctx= lex->current_context();
if (arg_count > 0)
func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph, *item_list);

View file

@ -6365,15 +6365,14 @@ String *Item_func_current_path::val_str(String *str)
{
DBUG_ASSERT(fixed());
THD *thd= current_thd;
auto length= thd->variables.path.text_format_nbytes_needed();
if (str->realloc(length))
return NULL;
length= thd->variables.path.print(&(*str)[0], str->alloced_length());
str->length(length);
null_value= 0;
return str;
}

View file

@ -99,7 +99,7 @@ void push_warning_safe(THD *thd, Sql_condition::enum_warning_level level,
va_start(args,format);
bool save_abort_on_warning= thd->abort_on_warning;
thd->abort_on_warning= false; // Don't escalate to the level of error
push_warning_printf_va_list(thd, level,code, format, args);
push_warning_vprintf(thd, level,code, format, args);
va_end(args);
thd->abort_on_warning= save_abort_on_warning;
DBUG_VOID_RETURN;

View file

@ -655,7 +655,7 @@ bool st_sp_chistics::read_from_mysql_proc_row(THD *thd, TABLE *table)
if (table->field[MYSQL_PROC_FIELD_COMMENT]->val_str_nopad(thd->mem_root,
&comment))
return true;
return false;
}
@ -981,9 +981,8 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
{
LEX *old_lex= thd->lex, newlex;
String defstr;
char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
char saved_cur_db_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db= { saved_cur_db_buf, sizeof(saved_cur_db_buf) };
bool cur_db_changed;
Bad_db_error_handler db_not_exists_handler;
@ -1017,7 +1016,7 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
TODO: why do we force switch here?
*/
if (mysql_opt_change_db(thd, &name->m_db, &saved_cur_db_name, TRUE,
if (mysql_opt_change_db(thd, name->m_db, &saved_cur_db, TRUE,
&cur_db_changed))
{
ret= SP_INTERNAL_ERROR;
@ -1041,9 +1040,7 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
generate an error.
*/
if (cur_db_changed && mysql_change_db(thd,
(LEX_CSTRING*) &saved_cur_db_name,
TRUE))
if (cur_db_changed && mysql_change_db(thd, saved_cur_db, TRUE))
{
ret= SP_INTERNAL_ERROR;
goto end;
@ -2099,7 +2096,7 @@ Sp_handler::sp_clone_and_link_routine(THD *thd,
const Database_qualified_name *name,
sp_head *sp) const
{
DBUG_ENTER("sp_link_routine");
DBUG_ENTER("sp_clone_and_link_routine");
int rc;
ulong level;
sp_head *new_sp;
@ -2475,8 +2472,7 @@ extern "C" const uchar *sp_sroutine_key(const void *ptr, size_t *plen, my_bool)
*/
bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
const MDL_key *key,
const Sp_handler *handler,
const MDL_key *key, const Sp_handler *handler,
TABLE_LIST *belong_to_view)
{
my_hash_init_opt(PSI_INSTRUMENT_ME, &prelocking_ctx->sroutines,
@ -2852,17 +2848,14 @@ void sp_remove_not_own_routines(Query_tables_list *prelocking_ctx)
@return FALSE Success
*/
bool sp_update_sp_used_routines(HASH *dst, HASH *src)
bool sp_update_sp_used_routines(Sroutine_hash *dst, HASH *src)
{
for (uint i=0 ; i < src->records ; i++)
{
Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
if (!my_hash_search(dst, (uchar *)rt->mdl_request.key.ptr(),
rt->mdl_request.key.length()))
{
if (my_hash_insert(dst, (uchar *)rt))
return TRUE;
}
if (!dst->find(rt->mdl_request.key.ptr(), rt->mdl_request.key.length()) &&
dst->insert(rt))
return TRUE;
}
return FALSE;
}
@ -2884,19 +2877,17 @@ bool sp_update_sp_used_routines(HASH *dst, HASH *src)
void
sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
HASH *src, TABLE_LIST *belong_to_view)
Sroutine_hash *src, TABLE_LIST *belong_to_view)
{
for (uint i=0 ; i < src->records ; i++)
Query_arena *arena __attribute__((unused))= thd->active_stmt_arena_to_use();
DBUG_ASSERT(src->is_empty() ||
arena->is_stmt_prepare_or_first_stmt_execute() ||
arena->is_conventional() ||
arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS);
for (Sroutine_hash_entry &rt: *src)
{
Sroutine_hash_entry *rt= (Sroutine_hash_entry *)my_hash_element(src, i);
DBUG_ASSERT(thd->active_stmt_arena_to_use()->
is_stmt_prepare_or_first_stmt_execute() ||
thd->active_stmt_arena_to_use()->
is_conventional() ||
thd->active_stmt_arena_to_use()->state ==
Query_arena::STMT_SP_QUERY_ARGUMENTS);
(void)sp_add_used_routine(prelocking_ctx, thd->active_stmt_arena_to_use(),
&rt->mdl_request.key, rt->m_handler,
&rt.mdl_request.key, rt.m_handler,
belong_to_view);
}
}
@ -2932,8 +2923,7 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
prelocking until 'sp_name' is eradicated as a class.
*/
int Sroutine_hash_entry::sp_cache_routine(THD *thd,
sp_head **sp) const
int Sroutine_hash_entry::sp_cache_routine(THD *thd, sp_head **sp) const
{
char qname_buff[NAME_LEN*2+1+1];
sp_name name(&mdl_request.key, qname_buff);
@ -2941,7 +2931,7 @@ int Sroutine_hash_entry::sp_cache_routine(THD *thd,
Check that we have an MDL lock on this routine, unless it's a top-level
CALL. The assert below should be unambiguous: the first element
in sroutines_list has an MDL lock unless it's a top-level call, or a
trigger, but triggers can't occur here (see the preceding assert).
trigger, but triggers can't occur here.
*/
DBUG_ASSERT(mdl_request.ticket || this == thd->lex->sroutines_list.first);
@ -2965,8 +2955,7 @@ int Sroutine_hash_entry::sp_cache_routine(THD *thd,
@retval non-0 Error while loading routine from mysql,proc table.
*/
int Sp_handler::sp_cache_routine(THD *thd,
const Database_qualified_name *name,
int Sp_handler::sp_cache_routine(THD *thd, const Database_qualified_name *name,
sp_head **sp) const
{
int ret= 0;
@ -2983,7 +2972,7 @@ int Sp_handler::sp_cache_routine(THD *thd,
{
if ((*sp)->sp_cache_version() < thd->sp_cache_version())
sp_cache_remove(spc, sp);
if (*sp)
else
DBUG_RETURN(SP_OK);
}

View file

@ -22,6 +22,7 @@
#include "sql_string.h" // LEX_STRING
#include "sql_cmd.h"
#include "mdl.h"
#include "sql_hset.h"
class Field;
class Open_tables_backup;
@ -677,16 +678,20 @@ public:
int sp_cache_routine(THD *thd, sp_head **sp) const;
};
typedef Hash_set<Sroutine_hash_entry> Sroutine_hash;
bool is_package_public_routine(THD *thd, const Lex_ident_db &db,
const LEX_CSTRING &package,
const LEX_CSTRING &routine, enum_sp_type type);
bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
const MDL_key *key,
const Sp_handler *handler,
TABLE_LIST *belong_to_view);
void sp_remove_not_own_routines(Query_tables_list *prelocking_ctx);
bool sp_update_sp_used_routines(HASH *dst, HASH *src);
bool sp_update_sp_used_routines(Sroutine_hash *dst, HASH *src);
void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
HASH *src, TABLE_LIST *belong_to_view);
Sroutine_hash *src, TABLE_LIST *belong_to_view);
void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx,
SQL_I_List<Sroutine_hash_entry> *src,
TABLE_LIST *belong_to_view);

View file

@ -578,6 +578,8 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent,
m_modified(0),
m_recursion_level(0),
m_next_cached_sp(0),
m_sroutines(key_memory_sp_head_main_root, Lex_ident_routine::charset_info(),
0, 0, 0, sp_sroutine_key, 0, 0),
m_param_begin(NULL),
m_param_end(NULL),
m_cpp_body_begin(NULL),
@ -606,9 +608,6 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent,
sizeof(sp_instr *), 16, 8, MYF(0));
my_hash_init(key_memory_sp_head_main_root, &m_sptabs,
table_alias_charset, 0, 0, 0, sp_table_key, 0, 0);
my_hash_init(key_memory_sp_head_main_root, &m_sroutines,
Lex_ident_routine::charset_info(),
0, 0, 0, sp_sroutine_key, 0, 0);
m_sql_path= sql_path;
@ -833,7 +832,9 @@ sp_head::init_sp_name(const sp_name *spname)
/* Must be initialized in the parser. */
DBUG_ASSERT(spname && spname->m_db.str && spname->m_db.length);
DBUG_ASSERT(spname);
DBUG_ASSERT(spname->m_db.str);
DBUG_ASSERT(spname->m_db.length);
m_explicit_name= spname->m_explicit_name;
/* We have to copy strings to get them into the right memroot. */
@ -920,7 +921,6 @@ sp_head::~sp_head()
unwind_aux_lexes_and_restore_original_lex();
my_hash_free(&m_sptabs);
my_hash_free(&m_sroutines);
sp_head::destroy(m_next_cached_sp);
@ -1120,14 +1120,9 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
m_first_instance->m_last_cached_sp == this) ||
(m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
/*
NOTE: The SQL Standard does not specify the context that should be
preserved for stored routines. However, at SAP/Walldorf meeting it was
decided that current database should be preserved.
*/
/* m_db is empty for sp-less compound statements. */
if (m_db.length &&
(err_status= mysql_opt_change_db(thd, &m_db, &saved_cur_db_name, FALSE,
(err_status= mysql_opt_change_db(thd, m_db, &saved_cur_db_name, FALSE,
&cur_db_changed)))
{
goto done;
@ -1527,7 +1522,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
NULL. In this case, mysql_change_db() would generate an error.
*/
err_status|= mysql_change_db(thd, (LEX_CSTRING*)&saved_cur_db_name, TRUE) != 0;
err_status|= mysql_change_db(thd, saved_cur_db_name, TRUE) != 0;
}
#ifdef PROTECT_STATEMENT_MEMROOT

View file

@ -319,7 +319,7 @@ public:
by using for this set same objects that are used in 'sroutines' sets
for statements of which this stored routine consists.
*/
HASH m_sroutines;
Sroutine_hash m_sroutines;
// Pointers set during parsing
const char *m_param_begin;
const char *m_param_end;
@ -658,7 +658,7 @@ public:
initialized and linked. It gets automatically deleted
by the Bison %destructor in sql_yacc.yy.
*/
LEX *oldlex= (LEX *) m_lex.pop();
LEX *oldlex= m_lex.pop();
if (!oldlex)
DBUG_RETURN(false); // Nothing to restore
// This restores thd->lex and thd->stmt_lex

View file

@ -15320,7 +15320,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
/* Change a database if necessary */
if (mpvio.db.length)
{
uint err = mysql_change_db(thd, &mpvio.db, FALSE);
uint err= mysql_change_db(thd, mpvio.db, FALSE);
if(err)
{
if (err == ER_DBACCESS_DENIED_ERROR)

View file

@ -3218,9 +3218,8 @@ check_and_update_table_version(THD *thd,
@retval FALSE success, version in Sroutine_hash_entry has been updated
*/
static bool
check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
sp_head *sp)
static bool check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
sp_head *sp)
{
ulong spc_version= thd->sp_cache_version();
/* sp is NULL if there is no such routine. */
@ -3866,7 +3865,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
switch (mdl_type)
{
case MDL_key::PACKAGE_BODY:
DBUG_ASSERT(rt != (Sroutine_hash_entry*)prelocking_ctx->sroutines_list.first);
DBUG_ASSERT(rt != prelocking_ctx->sroutines_list.first);
/*
No need to cache the package body itself.
It gets cached during open_and_process_routine()
@ -3887,7 +3886,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
the binlog as only the statements in the called procedure show
up there, not the CALL itself.
*/
if (rt != (Sroutine_hash_entry*)prelocking_ctx->sroutines_list.first ||
if (rt != prelocking_ctx->sroutines_list.first ||
mdl_type != MDL_key::PROCEDURE)
{
/*

View file

@ -60,10 +60,8 @@ static bool find_db_tables_and_rm_known_files(THD *, MY_DIR *,
long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);
my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error);
static void mysql_change_db_impl(THD *thd,
LEX_CSTRING *new_db_name,
privilege_t new_db_access,
CHARSET_INFO *new_db_charset);
static void mysql_change_db_impl(THD *, LEX_CSTRING *, privilege_t,
CHARSET_INFO *);
static bool mysql_rm_db_internal(THD *thd, const Lex_ident_db &db,
bool if_exists, bool silent);
@ -1565,8 +1563,7 @@ err:
@param new_db_charset Character set of the new database.
*/
static void mysql_change_db_impl(THD *thd,
LEX_CSTRING *new_db_name,
static void mysql_change_db_impl(THD *thd, LEX_CSTRING *new_db_name,
privilege_t new_db_access,
CHARSET_INFO *new_db_charset)
{
@ -1630,8 +1627,7 @@ static void mysql_change_db_impl(THD *thd,
"length" is set to 0.
*/
static void backup_current_db_name(THD *thd,
LEX_STRING *saved_db_name)
static void backup_current_db_name(THD *thd, LEX_STRING *saved_db_name)
{
DBUG_ASSERT(saved_db_name->length >= SAFE_NAME_LEN +1);
if (!thd->db.str)
@ -1653,7 +1649,7 @@ static void backup_current_db_name(THD *thd,
@param thd thread handle
@param new_db_name database name
@param force_switch if force_switch is FALSE, then the operation will fail if
@param force if force is FALSE, then the operation will fail if
- new_db_name is NULL or empty;
@ -1664,7 +1660,7 @@ static void backup_current_db_name(THD *thd,
- OR new database does not exist;
if force_switch is TRUE, then
if force is TRUE, then
- if new_db_name is NULL or empty, the current
database will be NULL, @@collation_database will
@ -1711,8 +1707,7 @@ static void backup_current_db_name(THD *thd,
@retval >0 Error
*/
uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
bool force_switch)
uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force)
{
DBNameBuffer new_db_buff;
LEX_CSTRING new_db_file_name;
@ -1722,9 +1717,9 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
CHARSET_INFO *db_default_cl;
DBUG_ENTER("mysql_change_db");
if (new_db_name->length == 0)
if (new_db_name.length == 0)
{
if (force_switch)
if (force)
{
/*
This can happen only if we're switching the current database back
@ -1746,9 +1741,9 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
DBUG_RETURN(ER_NO_DB_ERROR);
}
}
DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
DBUG_PRINT("enter",("name: '%s'", new_db_name.str));
if (is_infoschema_db(new_db_name))
if (is_infoschema_db(&new_db_name))
{
/* Switch the current database to INFORMATION_SCHEMA. */
@ -1759,8 +1754,8 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
new_db_file_name= lower_case_table_names == 1 ?
new_db_buff.copy_casedn(&my_charset_utf8mb3_general_ci,
*new_db_name).to_lex_cstring() :
*new_db_name;
new_db_name).to_lex_cstring() :
new_db_name;
/*
NOTE: if Lex_ident_db::check_name() fails,
@ -1775,7 +1770,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
if (Lex_ident_db::check_name_with_error(new_db_file_name))
{
if (force_switch)
if (force)
mysql_change_db_impl(thd, NULL, NO_ACL, thd->variables.collation_server);
DBUG_RETURN(ER_WRONG_DB_NAME);
@ -1794,8 +1789,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
db_access|= sctx->master_access;
}
if (!force_switch &&
!(db_access & DB_ACLS) &&
if (!force&& !(db_access & DB_ACLS) &&
check_grant_db(thd, new_db_file_name.str))
{
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
@ -1812,7 +1806,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
if (check_db_dir_existence(new_db_file_name.str))
{
if (force_switch)
if (force)
{
/* Throw a warning and free new_db_file_name. */
@ -1847,8 +1841,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
NOTE: in mysql_change_db_impl() new_db_file_name is assigned to THD
attributes and will be freed in THD::~THD().
*/
if (const char *tmp= my_strndup(key_memory_THD_db,
new_db_file_name.str,
if (const char *tmp= my_strndup(key_memory_THD_db, new_db_file_name.str,
new_db_file_name.length, MYF(MY_WME)))
{
LEX_CSTRING new_db_malloced({tmp, new_db_file_name.length});
@ -1868,8 +1861,8 @@ done:
Change the current database and its attributes if needed.
@param thd thread handle
@param new_db_name database name
@param[in, out] saved_db_name IN: "str" points to a buffer where to store
@param new_db database name
@param[in, out] saved_db IN: "str" points to a buffer where to store
the old database name, "length" contains the
buffer size
OUT: if the current (default) database is
@ -1884,21 +1877,18 @@ done:
the function suceeded)
*/
bool mysql_opt_change_db(THD *thd,
const LEX_CSTRING *new_db_name,
LEX_STRING *saved_db_name,
bool force_switch,
bool mysql_opt_change_db(THD *thd, const LEX_CSTRING &new_db,
LEX_STRING *saved_db, bool force_switch,
bool *cur_db_changed)
{
*cur_db_changed= !cmp_db_names(Lex_ident_db(thd->db),
Lex_ident_db(*new_db_name));
*cur_db_changed= !cmp_db_names(Lex_ident_db(thd->db), Lex_ident_db(new_db));
if (!*cur_db_changed)
return FALSE;
backup_current_db_name(thd, saved_db_name);
backup_current_db_name(thd, saved_db);
return mysql_change_db(thd, new_db_name, force_switch);
return mysql_change_db(thd, new_db, force_switch);
}
@ -1973,9 +1963,8 @@ bool mysql_upgrade_db(THD *thd, const Lex_ident_db &old_db)
}
/* Step1: Create the new database */
if (unlikely((error= mysql_create_db_internal(thd, new_db,
DDL_options(), &create_info,
1))))
if (unlikely((error= mysql_create_db_internal(thd, new_db, DDL_options(),
&create_info, 1))))
goto exit;
/* Step2: Move tables to the new database */
@ -2031,8 +2020,7 @@ bool mysql_upgrade_db(THD *thd, const Lex_ident_db &old_db)
If some tables were left in the new directory, rmdir() will fail.
It guarantees we never lose any tables.
*/
build_table_filename(path, sizeof(path)-1,
new_db.str,"",MY_DB_OPT_FILE, 0);
build_table_filename(path, sizeof(path)-1, new_db.str,"",MY_DB_OPT_FILE, 0);
mysql_file_delete(key_file_dbopt, path, MYF(MY_WME));
length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0);
if (length && path[length-1] == FN_LIBCHAR)
@ -2113,7 +2101,7 @@ bool mysql_upgrade_db(THD *thd, const Lex_ident_db &old_db)
/* Step9: Let's do "use newdb" if we renamed the current database */
if (change_to_newdb)
error|= mysql_change_db(thd, & new_db, FALSE) != 0;
error|= mysql_change_db(thd, new_db, FALSE) != 0;
exit:
DBUG_RETURN(error);

View file

@ -26,13 +26,10 @@ bool mysql_alter_db(THD *thd, const Lex_ident_db &db,
const Schema_specification_st *create);
bool mysql_rm_db(THD *thd, const Lex_ident_db &db, bool if_exists);
bool mysql_upgrade_db(THD *thd, const Lex_ident_db &old_db);
uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
bool force_switch);
uint mysql_change_db(THD *thd, const LEX_CSTRING &new_db_name, bool force);
bool mysql_opt_change_db(THD *thd,
const LEX_CSTRING *new_db_name,
LEX_STRING *saved_db_name,
bool force_switch,
bool mysql_opt_change_db(THD *thd, const LEX_CSTRING &new_db_name,
LEX_STRING *saved_db_name, bool force_switch,
bool *cur_db_changed);
bool my_dboptions_cache_init(void);
void my_dboptions_cache_free(void);

View file

@ -791,7 +791,7 @@ void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
DBUG_PRINT("enter",("warning: %u", code));
va_start(args,format);
push_warning_printf_va_list(thd, level,code, format, args);
push_warning_vprintf(thd, level,code, format, args);
va_end(args);
DBUG_VOID_RETURN;
}
@ -802,9 +802,8 @@ void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
of format arguments.
*/
void push_warning_printf_va_list(THD *thd,
Sql_condition::enum_warning_level level,
uint code, const char *format, va_list args)
void push_warning_vprintf(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *format, va_list args)
{
char warning[MYSQL_ERRMSG_SIZE];

View file

@ -1335,9 +1335,8 @@ void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *format, ...)
ATTRIBUTE_FORMAT(printf, 4, 5);
void push_warning_printf_va_list(THD *thd,
Sql_condition::enum_warning_level level,
uint code, const char *format, va_list args);
void push_warning_vprintf(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *format, va_list args);
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);

View file

@ -8021,20 +8021,16 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name,
sp_head *sp;
/* Order is important here: new - reset - init */
if (likely((sp= sp_head::create(package, sph, agg_type,
thd->variables.sql_mode,
thd->variables.path,
sp_mem_root_ptr))))
if ((sp= sp_head::create(package, sph, agg_type, thd->variables.sql_mode,
thd->variables.path, sp_mem_root_ptr)))
{
sp->reset_thd_mem_root(thd);
sp->init(this);
if (name)
{
if (package)
sp->make_package_routine_name(sp->get_main_mem_root(),
package->m_db,
package->m_name,
name->m_name);
sp->make_package_routine_name(sp->get_main_mem_root(), package->m_db,
package->m_name, name->m_name);
else
sp->init_sp_name(name);
if (!(sp->m_qname=
@ -8065,10 +8061,9 @@ sp_head *LEX::make_sp_head_no_recursive(THD *thd, const sp_name *name,
*/
if (package && package->m_is_cloning_routine)
sph= sph->package_routine_handler();
if (!sphead ||
(package &&
(sph == &sp_handler_package_procedure ||
sph == &sp_handler_package_function)))
if (!sphead || (package &&
(sph == &sp_handler_package_procedure ||
sph == &sp_handler_package_function)))
return make_sp_head(thd, name, sph, agg_type);
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), sph->type_str());
return NULL;
@ -10189,10 +10184,8 @@ bool LEX::add_create_view(THD *thd, DDL_options_st ddl,
if (unlikely(set_create_options_with_check(ddl)))
return true;
if (unlikely(!(create_view= new (thd->mem_root)
Create_view_info(ddl.or_replace() ?
VIEW_CREATE_OR_REPLACE :
VIEW_CREATE_NEW,
algorithm, suid))))
Create_view_info(ddl.or_replace() ? VIEW_CREATE_OR_REPLACE
: VIEW_CREATE_NEW, algorithm, suid))))
return true;
return create_or_alter_view_finalize(thd, table_ident);
}
@ -10202,15 +10195,11 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
{
Database_qualified_name pkgname;
const Sp_handler *sph= &sp_handler_procedure;
Sql_cmd_call *cmd_call= nullptr;
sql_command= SQLCOM_CALL;
value_list.empty();
thd->variables.path.resolve(thd, sphead, name, &sph, &pkgname);
if (unlikely(!(cmd_call= new (thd->mem_root) Sql_cmd_call(name, sph))))
return true;
// Only add to used routines if we have a valid database name
if (name->m_db.str)
{
@ -10219,8 +10208,7 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
sp_handler_package_body.add_used_routine(this, thd, &pkgname);
}
m_sql_cmd= cmd_call;
return false;
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(name, sph));
}

View file

@ -1711,7 +1711,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD *
if (unlikely(thd->copy_with_error(system_charset_info, (LEX_STRING*) &tmp,
thd->charset(), packet, packet_length)))
break;
if (!mysql_change_db(thd, &tmp, FALSE))
if (!mysql_change_db(thd, tmp, FALSE))
{
general_log_write(thd, command, thd->db.str, thd->db.length);
my_ok(thd);
@ -3250,8 +3250,7 @@ bool Sql_cmd_call::execute(THD *thd)
This will cache all SP and SF and open and lock all tables
required for execution.
*/
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
UINT_MAX, FALSE) ||
if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE) ||
open_and_lock_tables(thd, all_tables, TRUE, 0))
return true;
@ -3265,10 +3264,8 @@ bool Sql_cmd_call::execute(THD *thd)
If the routine is not found, let's still check EXECUTE_ACL to decide
whether to return "Access denied" or "Routine does not exist".
*/
if (check_routine_access(thd, EXECUTE_ACL, &m_name->m_db,
&m_name->m_name,
&sp_handler_procedure,
false))
if (check_routine_access(thd, EXECUTE_ACL, &m_name->m_db, &m_name->m_name,
&sp_handler_procedure, false))
return true;
/*
sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
@ -4860,7 +4857,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
#endif
case SQLCOM_CHANGE_DB:
{
if (!mysql_change_db(thd, &select_lex->db, FALSE))
if (!mysql_change_db(thd, select_lex->db, FALSE))
my_ok(thd);
break;

View file

@ -5,7 +5,7 @@
#include "sql_db.h"
#include "sql_path.h"
static constexpr LEX_CSTRING cur_schema= {STRING_WITH_LEN("CURRENT_SCHEMA")};
static constexpr Lex_ident_ci cur_schema= {STRING_WITH_LEN("CURRENT_SCHEMA")};
Sql_path::Sql_path() : m_count(0)
{
@ -19,16 +19,8 @@ Sql_path& Sql_path::operator=(const Sql_path &rhs)
}
bool
is_package_public_routine(THD *thd,
const Lex_ident_db &db,
const LEX_CSTRING &package,
const LEX_CSTRING &routine,
enum_sp_type type);
LEX_CSTRING Sql_path::resolve_current_schema(THD *thd, sp_head *caller,
const LEX_CSTRING &schema) const
Lex_ident_db Sql_path::resolve_current_schema(THD *thd, sp_head *caller,
const Lex_ident_db &schema) const
{
/*
Check if this is the CURRENT_SCHEMA token
@ -36,20 +28,12 @@ LEX_CSTRING Sql_path::resolve_current_schema(THD *thd, sp_head *caller,
if (!is_cur_schema(schema))
return schema;
/*
Resolve CURRENT_SCHEMA to actual database name.
*/
Lex_ident_db_normalized dbn;
/* Resolve CURRENT_SCHEMA to actual database name. */
if (caller && caller->m_name.str)
dbn= thd->to_ident_db_normalized_with_error(caller->m_db);
else if (thd->db.str || thd->lex->sphead)
dbn= thd->copy_db_normalized();
// If neither condition is met or oom, dbn.str remains null
if (unlikely(!dbn.str))
return {nullptr, 0};
return {dbn.str, dbn.length};
return thd->to_ident_db_normalized_with_error(caller->m_db);
if (thd->db.str || thd->lex->sphead)
return thd->copy_db_normalized();
return {nullptr, 0};
}
@ -116,7 +100,8 @@ bool Sql_path::resolve(THD *thd, sp_head *caller, sp_name *name,
if (name->m_explicit_name && strchr(name->m_name.str, '.'))
return false;
if (!name->m_db.str || !name->m_explicit_name)
DBUG_ASSERT(!name->m_explicit_name || name->m_db.str);
if (!name->m_explicit_name)
{
// Implicit name
if (caller && caller->m_name.str)
@ -161,7 +146,7 @@ bool Sql_path::resolve(THD *thd, sp_head *caller, sp_name *name,
bool resolved= false;
for (size_t i= 0; i < m_count; i++)
{
LEX_CSTRING schema= m_schemas[i];
Lex_ident_db schema= m_schemas[i];
// Resolve CURRENT_SCHEMA if needed
schema= resolve_current_schema(thd, caller, schema);
@ -207,8 +192,7 @@ bool Sql_path::init()
bool Sql_path::is_cur_schema(const LEX_CSTRING &schema) const
{
return schema.length == cur_schema.length &&
!strncasecmp(schema.str, cur_schema.str, schema.length);
return cur_schema.streq(schema);
}

View file

@ -16,7 +16,7 @@ class Lex_ident_db_normalized;
struct Sql_path
{
private:
LEX_CSTRING m_schemas[16];
Lex_ident_db m_schemas[16];
uint m_count;
public:
@ -91,8 +91,8 @@ protected:
Helper function to resolve CURRENT_SCHEMA to actual database name.
Returns the resolved schema, or {nullptr, 0} if resolution fails.
*/
LEX_CSTRING resolve_current_schema(THD *thd, sp_head *caller,
const LEX_CSTRING &schema) const;
Lex_ident_db resolve_current_schema(THD *thd, sp_head *caller,
const Lex_ident_db &schema) const;
/*
Helper function to try resolving a routine in a specific schema.
Returns true if error occured.

View file

@ -4809,7 +4809,7 @@ Prepared_statement::reprepare()
status_var_increment(thd->status_var.com_stmt_reprepare);
if (unlikely(mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name,
if (unlikely(mysql_opt_change_db(thd, stmt_db_name, &saved_cur_db_name,
TRUE, &cur_db_changed)))
return TRUE;
@ -4821,7 +4821,7 @@ Prepared_statement::reprepare()
validate_metadata(&copy));
if (cur_db_changed)
mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
mysql_change_db(thd, saved_cur_db_name, TRUE);
if (likely(!error))
{
@ -4940,7 +4940,7 @@ Prepared_statement::swap_prepared_statement(Prepared_statement *copy)
swap_variables(THD::used_t,
m_prepare_time_thd_used_flags,
copy->m_prepare_time_thd_used_flags);
swap_variables(LEX_CSTRING, m_sql_path, copy->m_sql_path);
DBUG_ASSERT(param_count == copy->param_count);
@ -4978,12 +4978,9 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Query_arena *old_stmt_arena;
bool error= TRUE;
bool qc_executed= FALSE;
char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
char saved_db_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_db= { saved_db_buf, sizeof(saved_db_buf) };
bool cur_db_changed;
LEX_CSTRING stmt_db_name= db;
if (check_charset_collation_map_version(thd, thd->m_reprepare_observer))
@ -5040,8 +5037,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
selected).
*/
if (mysql_opt_change_db(thd, &stmt_db_name, &saved_cur_db_name, TRUE,
&cur_db_changed))
if (mysql_opt_change_db(thd, stmt_db_name, &saved_db, TRUE, &cur_db_changed))
goto error;
/* Allocate query. */
@ -5137,7 +5133,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
*/
if (cur_db_changed)
mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
mysql_change_db(thd, saved_db, TRUE);
/* Assert that if an error, no cursor is open */
DBUG_ASSERT(! (error && cursor));

View file

@ -5014,8 +5014,7 @@ warn:
-1 Table was used with IF NOT EXISTS and table existed (warning, not error)
*/
int mysql_create_table_no_lock(THD *thd,
DDL_LOG_STATE *ddl_log_state_create,
int mysql_create_table_no_lock(THD *thd, DDL_LOG_STATE *ddl_log_state_create,
DDL_LOG_STATE *ddl_log_state_rm,
Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans,

View file

@ -1810,9 +1810,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
*/
sql_mode= ((trg_sql_mode= itm++) ? *trg_sql_mode :
(ulonglong) global_system_variables.sql_mode);
sql_path= ((trg_sql_path= it_paths++) ?
*trg_sql_path :
sql_path= ((trg_sql_path= it_paths++) ? *trg_sql_path :
global_system_variables.path.lex_cstring(&table->mem_root));
trg_create_time= it_create_times++; // May be NULL if old file
@ -1874,8 +1873,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
if (lex.sphead)
lex.sphead->m_sql_mode= sql_mode;
if (unlikely(!(trigger= (new (&table->mem_root)
Trigger(trigger_list, lex.sphead)))))
trigger= new (&table->mem_root) Trigger(trigger_list, lex.sphead);
if (unlikely(!trigger))
goto err_with_lex_cleanup;
lex.sphead= NULL; /* Prevent double cleanup. */
@ -1918,9 +1917,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
trigger_list->add_trigger(lex.trg_chistics.events,
lex.trg_chistics.action_time,
TRG_ORDER_NONE,
anchor_trg_name,
trigger);
TRG_ORDER_NONE, anchor_trg_name, trigger);
}
if (unlikely(parse_error))

View file

@ -1514,7 +1514,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *view_table_alias,
{
char old_db_buf[SAFE_NAME_LEN+1];
LEX_CSTRING old_db= { old_db_buf, sizeof(old_db_buf) };
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
Parser_state parser_state;
if (parser_state.init(thd, view_table_alias->select_stmt.str,
@ -1525,9 +1525,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *view_table_alias,
Use view db name as thread default database, in order to ensure
that the view is parsed and prepared correctly.
*/
if ((result= mysql_opt_change_db(thd, &view_table_alias->view_db,
(LEX_STRING*) &old_db, 1,
&dbchanged)))
if ((result= mysql_opt_change_db(thd, view_table_alias->view_db,
&old_db, true, &dbchanged)))
goto end;
lex_start(thd);
@ -1550,7 +1549,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *view_table_alias,
(parent_query_lex->sql_command == SQLCOM_SHOW_CREATE))
view_query_lex->sql_command= parent_query_lex->sql_command;
if (dbchanged && mysql_change_db(thd, &old_db, TRUE))
if (dbchanged && mysql_change_db(thd, old_db, TRUE))
goto err;
}
if (!parse_status)

View file

@ -17341,7 +17341,7 @@ set_param:
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
FOR_SYM directly_executable_statement
FOR_SYM directly_executable_statement
| PATH_SYM
{
if (Lex->is_in_sf_or_trg())