perfschema sp instrumentation related changes

This commit is contained in:
Sergei Golubchik 2020-02-14 16:29:16 +01:00
parent d5a0069702
commit 70e7b5095d
16 changed files with 410 additions and 83 deletions

View File

@ -32,6 +32,7 @@
#include "event_db_repository.h"
#include "sp_head.h"
#include "sql_show.h" // append_definer, append_identifier
#include "mysql/psi/mysql_sp.h"
#ifdef WITH_WSREP
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
@ -1456,6 +1457,9 @@ Event_job_data::execute(THD *thd, bool drop)
sphead->set_creation_ctx(creation_ctx);
sphead->optimize();
sphead->m_sp_share= MYSQL_GET_SP_SHARE(SP_TYPE_EVENT,
dbname.str, dbname.length,
name.str, name.length);
ret= sphead->execute_procedure(thd, &empty_item_list);
/*
There is no pre-locking and therefore there should be no

View File

@ -24,6 +24,7 @@
#include "tztime.h" // my_tz_find, my_tz_OFFSET0, struct Time_zone
#include "log.h" // sql_print_error
#include "sql_class.h" // struct THD
#include "mysql/psi/mysql_sp.h"
/**
@addtogroup Event_Scheduler
@ -351,6 +352,9 @@ Event_queue::drop_matching_events(THD *thd, const LEX_CSTRING *pattern,
is ok.
*/
queue_remove(&queue, i);
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(SP_TYPE_EVENT, et->dbname.str, et->dbname.length,
et->name.str, et->name.length);
delete et;
}
else

View File

@ -34,6 +34,7 @@
#include "sp_head.h" // for Stored_program_creation_ctx
#include "set_var.h"
#include "lock.h" // lock_object_name
#include "mysql/psi/mysql_sp.h"
/**
@addtogroup Event_Scheduler
@ -620,6 +621,9 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
/* Binlog the drop event. */
DBUG_ASSERT(thd->query() && thd->query_length());
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(SP_TYPE_EVENT,
dbname->str, dbname->length, name->str, name->length);
}
thd->restore_stmt_binlog_format(save_binlog_format);

View File

@ -113,6 +113,7 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_reload.h" // reload_acl_and_cache
#include "sp_head.h" // init_sp_psi_keys
#ifdef HAVE_POLL_H
#include <poll.h>
@ -9698,6 +9699,8 @@ void init_server_psi_keys(void)
count= array_elements(sql_statement_info);
mysql_statement_register(category, sql_statement_info, count);
init_sp_psi_keys();
category= "com";
init_com_statement_info();

View File

@ -34,6 +34,7 @@
#include "lock.h" // lock_object_name
#include <my_user.h>
#include "mysql/psi/mysql_sp.h"
sp_cache **Sp_handler_procedure::get_cache(THD *thd) const
{
@ -718,7 +719,7 @@ Sp_handler::db_find_routine(THD *thd,
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root,
&params);
if (type() != TYPE_ENUM_FUNCTION)
if (type() != SP_TYPE_FUNCTION)
returns= empty_clex_str;
else if (table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
&returns))
@ -866,6 +867,8 @@ static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode,
thd->spcont= old_spcont;
thd->variables.sql_mode= old_sql_mode;
thd->variables.select_limit= old_select_limit;
if (sp != NULL)
sp->init_psi_share();
return sp;
}
@ -1001,7 +1004,7 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
(*sphp)->set_creation_ctx(creation_ctx);
(*sphp)->optimize();
if (type() == TYPE_ENUM_PACKAGE_BODY)
if (type() == SP_TYPE_PACKAGE_BODY)
{
sp_package *package= (*sphp)->get_package();
List_iterator<LEX> it(package->m_routine_implementations);
@ -1104,6 +1107,9 @@ Sp_handler::sp_drop_routine_internal(THD *thd,
DBUG_ASSERT(spc);
if ((sp= sp_cache_lookup(spc, name)))
sp_cache_flush_obsolete(spc, &sp);
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(type(), name->m_db.str, name->m_db.length,
name->m_name.str, name->m_name.length);
DBUG_RETURN(SP_OK);
}
@ -1231,16 +1237,17 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
if (lex->create_info.or_replace())
{
switch (type()) {
case TYPE_ENUM_PACKAGE:
case SP_TYPE_PACKAGE:
// Drop together with its PACKAGE BODY mysql.proc record
ret= sp_handler_package_spec.sp_find_and_drop_routine(thd, table, sp);
break;
case TYPE_ENUM_PACKAGE_BODY:
case TYPE_ENUM_FUNCTION:
case TYPE_ENUM_PROCEDURE:
case SP_TYPE_PACKAGE_BODY:
case SP_TYPE_FUNCTION:
case SP_TYPE_PROCEDURE:
ret= sp_drop_routine_internal(thd, sp, table);
break;
case TYPE_ENUM_TRIGGER:
case SP_TYPE_TRIGGER:
case SP_TYPE_EVENT:
DBUG_ASSERT(0);
ret= SP_OK;
}
@ -1257,7 +1264,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
ret= FALSE;
// Setting retstr as it is used for logging.
if (type() == TYPE_ENUM_FUNCTION)
if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@ -1340,7 +1347,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params, system_charset_info);
if (type() == TYPE_ENUM_FUNCTION)
if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@ -1372,7 +1379,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
store(sp->comment(), system_charset_info);
}
if (type() == TYPE_ENUM_FUNCTION &&
if (type() == SP_TYPE_FUNCTION &&
!trust_function_creators && mysql_bin_log.is_open())
{
if (!sp->detistic())
@ -1624,7 +1631,7 @@ Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name,
if ((ret= db_find_routine_aux(thd, name, table)) == SP_OK)
{
if (type() == TYPE_ENUM_FUNCTION && ! trust_function_creators &&
if (type() == SP_TYPE_FUNCTION && ! trust_function_creators &&
mysql_bin_log.is_open() &&
(chistics->daccess == SP_CONTAINS_SQL ||
chistics->daccess == SP_MODIFIES_SQL_DATA))
@ -1770,7 +1777,7 @@ bool lock_db_routines(THD *thd, const char *db)
longlong sp_type= table->field[MYSQL_PROC_MYSQL_TYPE]->val_int();
MDL_request *mdl_request= new (thd->mem_root) MDL_request;
const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
const Sp_handler *sph= Sp_handler::handler((enum_sp_type)
sp_type);
if (!sph)
sph= &sp_handler_procedure;
@ -1813,6 +1820,8 @@ sp_drop_db_routines(THD *thd, const char *db)
uint key_len;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
uchar keybuf[MAX_KEY_LENGTH];
size_t db_length= strlen(db);
Sql_mode_instant_remove smir(thd, MODE_PAD_CHAR_TO_FULL_LENGTH); // see below
DBUG_ENTER("sp_drop_db_routines");
DBUG_PRINT("enter", ("db: %s", db));
@ -1820,7 +1829,7 @@ sp_drop_db_routines(THD *thd, const char *db)
if (!(table= open_proc_table_for_update(thd)))
goto err;
table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
table->field[MYSQL_PROC_FIELD_DB]->store(db, db_length, system_charset_info);
key_len= table->key_info->key_part[0].store_length;
table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW);
@ -1839,7 +1848,18 @@ sp_drop_db_routines(THD *thd, const char *db)
do
{
if (! table->file->ha_delete_row(table->record[0]))
{
deleted= TRUE; /* We deleted something */
#ifdef HAVE_PSI_SP_INTERFACE
String buf;
// the following assumes MODE_PAD_CHAR_TO_FULL_LENGTH being *unset*
String *name= table->field[MYSQL_PROC_FIELD_NAME]->val_str(&buf);
enum_sp_type sp_type= (enum_sp_type) table->field[MYSQL_PROC_MYSQL_TYPE]->ptr[0];
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(sp_type, db, db_length, name->ptr(), name->length());
#endif
}
else
{
ret= SP_DELETE_ROW_FAILED;
@ -2013,7 +2033,7 @@ Sp_handler::sp_clone_and_link_routine(THD *thd,
DBUG_RETURN(0);
}
if (type() == TYPE_ENUM_FUNCTION)
if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@ -2361,7 +2381,7 @@ is_package_public_routine(THD *thd,
const LEX_CSTRING &db,
const LEX_CSTRING &package,
const LEX_CSTRING &routine,
stored_procedure_type type)
enum_sp_type type)
{
sp_head *sp= NULL;
Database_qualified_name tmp(db, package);
@ -2395,7 +2415,7 @@ is_package_public_routine_quick(THD *thd,
const LEX_CSTRING &db,
const LEX_CSTRING &pkgname,
const LEX_CSTRING &name,
stored_procedure_type type)
enum_sp_type type)
{
Database_qualified_name tmp(db, pkgname);
sp_head *sp= sp_cache_lookup(&thd->sp_package_spec_cache, &tmp);
@ -2414,7 +2434,7 @@ static bool
is_package_body_routine(THD *thd, sp_package *pkg,
const LEX_CSTRING &name1,
const LEX_CSTRING &name2,
stored_procedure_type type)
enum_sp_type type)
{
return Sp_handler::eq_routine_name(pkg->m_name, name1) &&
(pkg->m_routine_declarations.find(name2, type) ||
@ -2842,7 +2862,7 @@ Sp_handler::sp_cache_package_routine(THD *thd,
bool lookup_only, sp_head **sp) const
{
DBUG_ENTER("sp_cache_package_routine");
DBUG_ASSERT(type() == TYPE_ENUM_FUNCTION || type() == TYPE_ENUM_PROCEDURE);
DBUG_ASSERT(type() == SP_TYPE_FUNCTION || type() == SP_TYPE_PROCEDURE);
sp_name pkgname(&name->m_db, &pkgname_cstr, false);
sp_head *ph= NULL;
int ret= sp_handler_package_body.sp_cache_routine(thd, &pkgname,
@ -2941,7 +2961,7 @@ Sp_handler::show_create_sp(THD *thd, String *buf,
buf->append('(');
buf->append(&params);
buf->append(')');
if (type() == TYPE_ENUM_FUNCTION)
if (type() == SP_TYPE_FUNCTION)
{
if (sql_mode & MODE_ORACLE)
buf->append(STRING_WITH_LEN(" RETURN "));

View File

@ -47,17 +47,18 @@ template <typename T> class SQL_I_List;
/*
Values for the type enum. This reflects the order of the enum declaration
in the CREATE TABLE command.
See also storage/perfschema/my_thread.h
*/
enum stored_procedure_type
enum enum_sp_type
{
TYPE_ENUM_FUNCTION=1,
TYPE_ENUM_PROCEDURE=2,
TYPE_ENUM_PACKAGE=3,
TYPE_ENUM_PACKAGE_BODY=4,
TYPE_ENUM_TRIGGER=5
SP_TYPE_FUNCTION=1,
SP_TYPE_PROCEDURE=2,
SP_TYPE_PACKAGE=3,
SP_TYPE_PACKAGE_BODY=4,
SP_TYPE_TRIGGER=5,
SP_TYPE_EVENT=6,
};
class Sp_handler
{
bool sp_resolve_package_routine_explicit(THD *thd,
@ -120,13 +121,13 @@ public: // TODO: make it private or protected
public:
virtual ~Sp_handler() {}
static const Sp_handler *handler(enum enum_sql_command cmd);
static const Sp_handler *handler(stored_procedure_type type);
static const Sp_handler *handler(enum_sp_type type);
static const Sp_handler *handler(MDL_key::enum_mdl_namespace ns);
/*
Return a handler only those SP objects that store
definitions in the mysql.proc system table
*/
static const Sp_handler *handler_mysql_proc(stored_procedure_type type)
static const Sp_handler *handler_mysql_proc(enum_sp_type type)
{
const Sp_handler *sph= handler(type);
return sph ? sph->sp_handler_mysql_proc() : NULL;
@ -153,7 +154,7 @@ public:
{
return this;
}
virtual stored_procedure_type type() const= 0;
virtual enum_sp_type type() const= 0;
virtual LEX_CSTRING type_lex_cstring() const= 0;
virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
@ -248,7 +249,7 @@ public:
class Sp_handler_procedure: public Sp_handler
{
public:
stored_procedure_type type() const { return TYPE_ENUM_PROCEDURE; }
enum_sp_type type() const { return SP_TYPE_PROCEDURE; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")};
@ -298,7 +299,7 @@ public:
class Sp_handler_function: public Sp_handler
{
public:
stored_procedure_type type() const { return TYPE_ENUM_FUNCTION; }
enum_sp_type type() const { return SP_TYPE_FUNCTION; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")};
@ -367,7 +368,7 @@ public: // TODO: make it private or protected
const Database_qualified_name *name)
const;
public:
stored_procedure_type type() const { return TYPE_ENUM_PACKAGE; }
enum_sp_type type() const { return SP_TYPE_PACKAGE; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")};
@ -400,7 +401,7 @@ public:
class Sp_handler_package_body: public Sp_handler_package
{
public:
stored_procedure_type type() const { return TYPE_ENUM_PACKAGE_BODY; }
enum_sp_type type() const { return SP_TYPE_PACKAGE_BODY; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")};
@ -433,7 +434,7 @@ public:
class Sp_handler_trigger: public Sp_handler
{
public:
stored_procedure_type type() const { return TYPE_ENUM_TRIGGER; }
enum_sp_type type() const { return SP_TYPE_TRIGGER; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("TRIGGER")};
@ -492,19 +493,21 @@ inline const Sp_handler *Sp_handler::handler(enum_sql_command cmd)
}
inline const Sp_handler *Sp_handler::handler(stored_procedure_type type)
inline const Sp_handler *Sp_handler::handler(enum_sp_type type)
{
switch (type) {
case TYPE_ENUM_PROCEDURE:
case SP_TYPE_PROCEDURE:
return &sp_handler_procedure;
case TYPE_ENUM_FUNCTION:
case SP_TYPE_FUNCTION:
return &sp_handler_function;
case TYPE_ENUM_PACKAGE:
case SP_TYPE_PACKAGE:
return &sp_handler_package_spec;
case TYPE_ENUM_PACKAGE_BODY:
case SP_TYPE_PACKAGE_BODY:
return &sp_handler_package_body;
case TYPE_ENUM_TRIGGER:
case SP_TYPE_TRIGGER:
return &sp_handler_trigger;
case SP_TYPE_EVENT:
break;
}
return NULL;
}

View File

@ -56,8 +56,39 @@
#define SP_INSTR_UINT_MAXLEN 8
#define SP_STMT_PRINT_MAXLEN 40
#include <my_user.h>
#include "mysql/psi/mysql_statement.h"
#include "mysql/psi/mysql_sp.h"
#ifdef HAVE_PSI_INTERFACE
void init_sp_psi_keys()
{
const char *category= "sp";
const int num __attribute__((unused)) = __LINE__ + 3;
PSI_server->register_statement(category, & sp_instr_stmt::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_set::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_set_trigger_field::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_jump::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_jump_if_not::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_freturn::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_preturn::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_hpush_jump::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_hpop::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_hreturn::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_cpush::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_cpop::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_copen::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_cclose::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_cfetch::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_agg_cfetch::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_cursor_copy_struct::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_error::psi_info, 1);
PSI_server->register_statement(category, & sp_instr_set_case_expr::psi_info, 1);
DBUG_ASSERT(SP_PSI_STATEMENT_INFO_COUNT == __LINE__ - num);
}
#endif
extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first);
@ -605,7 +636,7 @@ bool sp_head::eq_routine_spec(const sp_head *sp) const
bool sp_package::validate_after_parser(THD *thd)
{
if (m_handler->type() != TYPE_ENUM_PACKAGE_BODY)
if (m_handler->type() != SP_TYPE_PACKAGE_BODY)
return false;
sp_head *sp= sp_cache_lookup(&thd->sp_package_spec_cache, this);
sp_package *spec= sp ? sp->get_package() : NULL;
@ -684,7 +715,7 @@ bool sp_package::validate_private_routines(THD *thd)
LEX *sp_package::LexList::find(const LEX_CSTRING &name,
stored_procedure_type type)
enum_sp_type type)
{
List_iterator<LEX> it(*this);
for (LEX *lex; (lex= it++); )
@ -707,7 +738,7 @@ LEX *sp_package::LexList::find(const LEX_CSTRING &name,
LEX *sp_package::LexList::find_qualified(const LEX_CSTRING &name,
stored_procedure_type type)
enum_sp_type type)
{
List_iterator<LEX> it(*this);
for (LEX *lex; (lex= it++); )
@ -721,6 +752,17 @@ LEX *sp_package::LexList::find_qualified(const LEX_CSTRING &name,
}
void sp_package::init_psi_share()
{
List_iterator<LEX> it(m_routine_implementations);
for (LEX *lex; (lex= it++); )
{
DBUG_ASSERT(lex->sphead);
lex->sphead->init_psi_share();
}
sp_head::init_psi_share();
}
void
sp_head::init(LEX *lex)
{
@ -756,6 +798,13 @@ sp_head::init_sp_name(const sp_name *spname)
DBUG_VOID_RETURN;
}
void
sp_head::init_psi_share()
{
m_sp_share= MYSQL_GET_SP_SHARE(m_handler->type(), m_db.str, m_db.length,
m_name.str, m_name.length);
}
void
sp_head::set_body_start(THD *thd, const char *begin_ptr)
@ -1358,8 +1407,24 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
WSREP_DEBUG("assigned new next trx ID for SP, trx id: %" PRIu64, thd->wsrep_next_trx_id());
}
#endif /* WITH_WSREP */
#ifdef HAVE_PSI_STATEMENT_INTERFACE
PSI_statement_locker_state state;
PSI_statement_locker *parent_locker;
PSI_statement_info *psi_info = i->get_psi_info();
parent_locker= thd->m_statement_psi;
thd->m_statement_psi= MYSQL_START_STATEMENT(& state, psi_info->m_key,
thd->db.str, thd->db.length, thd->charset(), m_sp_share);
#endif
err_status= i->execute(thd, &ip);
#ifdef HAVE_PSI_STATEMENT_INTERFACE
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
thd->m_statement_psi= parent_locker;
#endif
#ifdef WITH_WSREP
if (WSREP(thd))
{
@ -1830,7 +1895,12 @@ sp_head::execute_trigger(THD *thd,
thd->spcont= nctx;
err_status= execute(thd, FALSE);
{
PSI_sp_locker_state psi_state;
PSI_sp_locker *locker= MYSQL_START_SP(&psi_state, m_sp_share);
err_status= execute(thd, FALSE);
MYSQL_END_SP(locker);
}
err_with_cleanup:
thd->restore_active_arena(&call_arena, &backup_arena);
@ -2080,7 +2150,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
*/
thd->set_n_backup_active_arena(call_arena, &backup_arena);
err_status= execute(thd, TRUE);
{
PSI_sp_locker_state psi_state;
PSI_sp_locker *locker= MYSQL_START_SP(&psi_state, m_sp_share);
err_status= execute(thd, TRUE);
MYSQL_END_SP(locker);
}
thd->restore_active_arena(call_arena, &backup_arena);
@ -2361,11 +2436,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
#endif
opt_trace_disable_if_no_stored_proc_func_access(thd, this);
PSI_sp_locker_state psi_state;
PSI_sp_locker *locker= MYSQL_START_SP(&psi_state, m_sp_share);
if (!err_status)
{
err_status= execute(thd, TRUE);
DBUG_PRINT("info", ("execute returned %d", (int) err_status));
}
MYSQL_END_SP(locker);
if (save_log_general)
thd->variables.option_bits &= ~OPTION_LOG_OFF;
@ -3554,6 +3630,9 @@ int sp_instr::exec_core(THD *thd, uint *nextp)
sp_instr_stmt class functions
*/
PSI_statement_info sp_instr_stmt::psi_info=
{ 0, "stmt", 0};
int
sp_instr_stmt::execute(THD *thd, uint *nextp)
{
@ -3564,6 +3643,8 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
DBUG_ENTER("sp_instr_stmt::execute");
DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command()));
MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, m_query.str, m_query.length);
#if defined(ENABLED_PROFILING)
/* This s-p instr is profilable and will be captured. */
thd->profiling.set_query_source(m_query.str, m_query.length);
@ -3690,6 +3771,9 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp)
sp_instr_set class functions
*/
PSI_statement_info sp_instr_set::psi_info=
{ 0, "set", 0};
int
sp_instr_set::execute(THD *thd, uint *nextp)
{
@ -3840,6 +3924,9 @@ sp_instr_set_row_field_by_name::print(String *str)
sp_instr_set_trigger_field class functions
*/
PSI_statement_info sp_instr_set_trigger_field::psi_info=
{ 0, "set_trigger_field", 0};
int
sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
{
@ -3883,6 +3970,9 @@ uint sp_instr_opt_meta::get_cont_dest() const
sp_instr_jump class functions
*/
PSI_statement_info sp_instr_jump::psi_info=
{ 0, "jump", 0};
int
sp_instr_jump::execute(THD *thd, uint *nextp)
{
@ -3948,6 +4038,9 @@ sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp)
sp_instr_jump_if_not class functions
*/
PSI_statement_info sp_instr_jump_if_not::psi_info=
{ 0, "jump_if_not", 0};
int
sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
{
@ -4043,6 +4136,9 @@ sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr> *bp)
sp_instr_freturn class functions
*/
PSI_statement_info sp_instr_freturn::psi_info=
{ 0, "freturn", 0};
int
sp_instr_freturn::execute(THD *thd, uint *nextp)
{
@ -4106,10 +4202,34 @@ sp_instr_freturn::print(String *str)
QT_ITEM_ORIGINAL_FUNC_NULLIF));
}
/*
sp_instr_preturn class functions
*/
PSI_statement_info sp_instr_preturn::psi_info=
{ 0, "preturn", 0};
int
sp_instr_preturn::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_preturn::execute");
*nextp= UINT_MAX;
DBUG_RETURN(0);
}
void
sp_instr_preturn::print(String *str)
{
str->append(STRING_WITH_LEN("preturn"));
}
/*
sp_instr_hpush_jump class functions
*/
PSI_statement_info sp_instr_hpush_jump::psi_info=
{ 0, "hpush_jump", 0};
int
sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
{
@ -4186,6 +4306,9 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp, List<sp_instr> *leads)
sp_instr_hpop class functions
*/
PSI_statement_info sp_instr_hpop::psi_info=
{ 0, "hpop", 0};
int
sp_instr_hpop::execute(THD *thd, uint *nextp)
{
@ -4210,6 +4333,9 @@ sp_instr_hpop::print(String *str)
sp_instr_hreturn class functions
*/
PSI_statement_info sp_instr_hreturn::psi_info=
{ 0, "hreturn", 0};
int
sp_instr_hreturn::execute(THD *thd, uint *nextp)
{
@ -4269,6 +4395,9 @@ sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads)
sp_instr_cpush class functions
*/
PSI_statement_info sp_instr_cpush::psi_info=
{ 0, "cpush", 0};
int
sp_instr_cpush::execute(THD *thd, uint *nextp)
{
@ -4310,6 +4439,9 @@ sp_instr_cpush::print(String *str)
sp_instr_cpop class functions
*/
PSI_statement_info sp_instr_cpop::psi_info=
{ 0, "cpop", 0};
int
sp_instr_cpop::execute(THD *thd, uint *nextp)
{
@ -4340,6 +4472,9 @@ sp_instr_cpop::print(String *str)
Assert that we either have an error or a cursor
*/
PSI_statement_info sp_instr_copen::psi_info=
{ 0, "copen", 0};
int
sp_instr_copen::execute(THD *thd, uint *nextp)
{
@ -4398,6 +4533,9 @@ sp_instr_copen::print(String *str)
sp_instr_cclose class functions
*/
PSI_statement_info sp_instr_cclose::psi_info=
{ 0, "cclose", 0};
int
sp_instr_cclose::execute(THD *thd, uint *nextp)
{
@ -4440,6 +4578,9 @@ sp_instr_cclose::print(String *str)
sp_instr_cfetch class functions
*/
PSI_statement_info sp_instr_cfetch::psi_info=
{ 0, "cfetch", 0};
int
sp_instr_cfetch::execute(THD *thd, uint *nextp)
{
@ -4487,6 +4628,13 @@ sp_instr_cfetch::print(String *str)
}
}
/*
sp_instr_agg_cfetch class functions
*/
PSI_statement_info sp_instr_agg_cfetch::psi_info=
{ 0, "agg_cfetch", 0};
int
sp_instr_agg_cfetch::execute(THD *thd, uint *nextp)
{
@ -4539,6 +4687,9 @@ sp_instr_agg_cfetch::print(String *str)
- copies the cursor structure to the associated %ROWTYPE variable.
*/
PSI_statement_info sp_instr_cursor_copy_struct::psi_info=
{ 0, "cursor_copy_struct", 0};
int
sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp)
{
@ -4611,6 +4762,9 @@ sp_instr_cursor_copy_struct::print(String *str)
sp_instr_error class functions
*/
PSI_statement_info sp_instr_error::psi_info=
{ 0, "error", 0};
int
sp_instr_error::execute(THD *thd, uint *nextp)
{
@ -4637,6 +4791,9 @@ sp_instr_error::print(String *str)
sp_instr_set_case_expr class implementation
**************************************************************************/
PSI_statement_info sp_instr_set_case_expr::psi_info=
{ 0, "set_case_expr", 0};
int
sp_instr_set_case_expr::execute(THD *thd, uint *nextp)
{

View File

@ -47,6 +47,14 @@ class sp_instr;
class sp_instr_opt_meta;
class sp_instr_jump_if_not;
/**
Number of PSI_statement_info instruments
for internal stored programs statements.
*/
#ifdef HAVE_PSI_INTERFACE
void init_sp_psi_keys(void);
#endif
/*************************************************************************/
/**
@ -174,6 +182,11 @@ public:
const Sp_handler *m_handler;
uint m_flags; // Boolean attributes of a stored routine
/**
Instrumentation interface for SP.
*/
PSI_sp_share *m_sp_share;
Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */
const char *m_tmp_query; ///< Temporary pointer to sub query string
@ -856,6 +869,8 @@ public:
return NULL;
}
virtual void init_psi_share();
protected:
MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root
@ -931,9 +946,9 @@ public:
public:
LexList() { elements= 0; }
// Find a package routine by a non qualified name
LEX *find(const LEX_CSTRING &name, stored_procedure_type type);
LEX *find(const LEX_CSTRING &name, enum_sp_type type);
// Find a package routine by a package-qualified name, e.g. 'pkg.proc'
LEX *find_qualified(const LEX_CSTRING &name, stored_procedure_type type);
LEX *find_qualified(const LEX_CSTRING &name, enum_sp_type type);
// Check if a routine with the given qualified name already exists
bool check_dup_qualified(const LEX_CSTRING &name, const Sp_handler *sph)
{
@ -990,6 +1005,7 @@ public:
m_routine_implementations.push_back(lex, &main_mem_root);
}
sp_package *get_package() { return this; }
void init_psi_share();
bool is_invoked() const
{
/*
@ -1156,6 +1172,7 @@ public:
{
m_ip= dst;
}
virtual PSI_statement_info* get_psi_info() = 0;
}; // class sp_instr : public Sql_alloc
@ -1282,6 +1299,12 @@ private:
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_stmt : public sp_instr
@ -1316,6 +1339,12 @@ protected:
uint m_offset; ///< Frame offset
Item *m_value;
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_set : public sp_instr
@ -1424,6 +1453,12 @@ private:
Item_trigger_field *trigger_field;
Item *value;
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_trigger_field : public sp_instr
@ -1510,6 +1545,11 @@ public:
m_dest= new_dest;
}
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_jump : public sp_instr_opt_meta
@ -1561,6 +1601,11 @@ private:
Item *m_expr; ///< The condition
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_jump_if_not : public sp_instr_jump
@ -1578,17 +1623,9 @@ public:
virtual ~sp_instr_preturn()
{}
virtual int execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_preturn::execute");
*nextp= UINT_MAX;
DBUG_RETURN(0);
}
virtual int execute(THD *thd, uint *nextp);
virtual void print(String *str)
{
str->append(STRING_WITH_LEN("preturn"));
}
virtual void print(String *str);
virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
{
@ -1596,6 +1633,11 @@ public:
return UINT_MAX;
}
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_preturn : public sp_instr
@ -1633,6 +1675,11 @@ protected:
const Type_handler *m_type_handler;
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_freturn : public sp_instr
@ -1698,6 +1745,11 @@ private:
// debug version only). It's used in print().
uint m_frame;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_hpush_jump : public sp_instr_jump
@ -1728,6 +1780,11 @@ private:
uint m_count;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_hpop : public sp_instr
@ -1762,12 +1819,16 @@ private:
uint m_frame;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_hreturn : public sp_instr_jump
/** This is DECLARE CURSOR */
class sp_instr_cpush : public sp_instr,
public sp_cursor
class sp_instr_cpush : public sp_instr, public sp_cursor
{
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
void operator=(sp_instr_cpush &);
@ -1796,6 +1857,11 @@ private:
sp_lex_keeper m_lex_keeper;
uint m_cursor; /**< Frame offset (for debugging) */
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_cpush : public sp_instr
@ -1826,6 +1892,11 @@ private:
uint m_count;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_cpop : public sp_instr
@ -1853,6 +1924,11 @@ private:
uint m_cursor; ///< Stack index
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_copen : public sp_instr_stmt
@ -1880,6 +1956,12 @@ public:
virtual int execute(THD *thd, uint *nextp);
virtual int exec_core(THD *thd, uint *nextp);
virtual void print(String *str);
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
};
@ -1905,6 +1987,11 @@ private:
uint m_cursor;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_cclose : public sp_instr
@ -1939,6 +2026,11 @@ private:
List<sp_variable> m_varlist;
bool m_error_on_no_data;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_cfetch : public sp_instr
/*
@ -1963,6 +2055,12 @@ public:
virtual int execute(THD *thd, uint *nextp);
virtual void print(String *str);
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_agg_cfetch : public sp_instr
@ -1996,6 +2094,11 @@ private:
int m_errcode;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_error : public sp_instr
@ -2035,6 +2138,11 @@ private:
Item *m_case_expr;
sp_lex_keeper m_lex_keeper;
#ifdef HAVE_PSI_INTERFACE
public:
virtual PSI_statement_info* get_psi_info() { return & psi_info; }
static PSI_statement_info psi_info;
#endif
}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access);

View File

@ -5886,18 +5886,19 @@ struct PRIVS_TO_MERGE
};
static enum PRIVS_TO_MERGE::what sp_privs_to_merge(stored_procedure_type type)
static enum PRIVS_TO_MERGE::what sp_privs_to_merge(enum_sp_type type)
{
switch (type) {
case TYPE_ENUM_FUNCTION:
case SP_TYPE_FUNCTION:
return PRIVS_TO_MERGE::FUNC;
case TYPE_ENUM_PROCEDURE:
case SP_TYPE_PROCEDURE:
return PRIVS_TO_MERGE::PROC;
case TYPE_ENUM_PACKAGE:
case SP_TYPE_PACKAGE:
return PRIVS_TO_MERGE::PACKAGE_SPEC;
case TYPE_ENUM_PACKAGE_BODY:
case SP_TYPE_PACKAGE_BODY:
return PRIVS_TO_MERGE::PACKAGE_BODY;
case TYPE_ENUM_TRIGGER:
case SP_TYPE_EVENT:
case SP_TYPE_TRIGGER:
break;
}
DBUG_ASSERT(0);
@ -7748,7 +7749,7 @@ static bool grant_load(THD *thd,
continue;
}
}
stored_procedure_type type= (stored_procedure_type)procs_priv.routine_type()->val_int();
enum_sp_type type= (enum_sp_type)procs_priv.routine_type()->val_int();
const Sp_handler *sph= Sp_handler::handler(type);
if (!sph || !(hash= sph->get_priv_hash()))
{

View File

@ -309,4 +309,6 @@
#define QUERY_PRIOR 6
#endif /* __WIN92__ */
#define SP_PSI_STATEMENT_INFO_COUNT 19
#endif /* SQL_CONST_INCLUDED */

View File

@ -6257,7 +6257,7 @@ static bool is_old(const char *str)
bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) const
{
// "name" is not necessarily NULL-terminated!
return sphead && sphead->m_handler->type() == TYPE_ENUM_TRIGGER &&
return sphead && sphead->m_handler->type() == SP_TYPE_TRIGGER &&
name->length == 3 && (is_new(name->str) || is_old(name->str));
}
@ -9010,7 +9010,7 @@ sp_package *LEX::create_package_start(THD *thd,
}
if (unlikely(set_command_with_check(command, options)))
return NULL;
if (sph->type() == TYPE_ENUM_PACKAGE_BODY)
if (sph->type() == SP_TYPE_PACKAGE_BODY)
{
/*
If we start parsing a "CREATE PACKAGE BODY", we need to load

View File

@ -30,7 +30,7 @@
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
#include "sql_trigger.h"
#include "sp.h" // enum stored_procedure_type
#include "sp.h" // enum enum_sp_type
#include "sql_tvc.h"
#include "item.h"
#include "sql_limit.h" // Select_limit_counters

View File

@ -101,6 +101,7 @@
#include "sql_bootstrap.h"
#include "sql_sequence.h"
#include "opt_trace.h"
#include "mysql/psi/mysql_sp.h"
#include "my_json_writer.h"
@ -3063,7 +3064,7 @@ mysql_create_routine(THD *thd, LEX *lex)
const LEX_CSTRING *name= lex->sphead->name();
#ifdef HAVE_DLOPEN
if (lex->sphead->m_handler->type() == TYPE_ENUM_FUNCTION)
if (lex->sphead->m_handler->type() == SP_TYPE_FUNCTION)
{
udf_func *udf = find_udf(name->str, name->length);
@ -5617,12 +5618,18 @@ mysql_execute_command(THD *thd)
break; /* break super switch */
} /* end case group bracket */
case SQLCOM_COMPOUND:
{
sp_head *sp= lex->sphead;
DBUG_ASSERT(all_tables == 0);
DBUG_ASSERT(thd->in_sub_stmt == 0);
lex->sphead->m_sql_mode= thd->variables.sql_mode;
sp->m_sql_mode= thd->variables.sql_mode;
sp->m_sp_share= MYSQL_GET_SP_SHARE(sp->m_handler->type(),
sp->m_db.str, sp->m_db.length,
sp->m_name.str, sp->m_name.length);
if (do_execute_sp(thd, lex->sphead))
goto error;
break;
}
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_FUNCTION:

View File

@ -6232,11 +6232,11 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
sph= Sp_handler::handler_mysql_proc((enum_sp_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
if (!sph || sph->type() == TYPE_ENUM_PACKAGE ||
sph->type() == TYPE_ENUM_PACKAGE_BODY)
if (!sph || sph->type() == SP_TYPE_PACKAGE ||
sph->type() == SP_TYPE_PACKAGE_BODY)
DBUG_RETURN(0);
if (!full_access)
@ -6247,7 +6247,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root,
&params);
if (sph->type() == TYPE_ENUM_FUNCTION)
if (sph->type() == SP_TYPE_FUNCTION)
proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
&returns);
sp= sph->sp_load_for_information_schema(thd, proc_table, db, name,
@ -6260,7 +6260,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
Sql_mode_save sql_mode_backup(thd);
thd->variables.sql_mode= sql_mode;
if (sph->type() == TYPE_ENUM_FUNCTION)
if (sph->type() == SP_TYPE_FUNCTION)
{
restore_record(table, s->default_values);
table->field[0]->store(STRING_WITH_LEN("def"), cs);
@ -6344,7 +6344,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db);
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
sph= Sp_handler::handler_mysql_proc((enum_sp_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
if (!sph)
@ -6373,7 +6373,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
copy_field_as_string(table->field[4],
proc_table->field[MYSQL_PROC_MYSQL_TYPE]);
if (sph->type() == TYPE_ENUM_FUNCTION)
if (sph->type() == SP_TYPE_FUNCTION)
{
sp_head *sp;
bool free_sp_head;

View File

@ -35,6 +35,7 @@
#include "sp_cache.h" // sp_invalidate_cache
#include <mysys_err.h>
#include "debug_sync.h"
#include "mysql/psi/mysql_sp.h"
/*************************************************************************/
@ -624,7 +625,13 @@ end:
thd->lex->restore_backup_query_tables_list(&backup);
if (!result)
{
my_ok(thd);
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(SP_TYPE_TRIGGER,
thd->lex->spname->m_db.str, thd->lex->spname->m_db.length,
thd->lex->spname->m_name.str, thd->lex->spname->m_name.length);
}
DBUG_RETURN(result);
#ifdef WITH_WSREP
@ -1554,6 +1561,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
trigger->definer= *trg_definer;
}
sp->m_sp_share= MYSQL_GET_SP_SHARE(SP_TYPE_TRIGGER,
sp->m_db.str, sp->m_db.length,
sp->m_name.str, sp->m_name.length);
#ifndef DBUG_OFF
/*
Let us check that we correctly update trigger definitions when we
@ -1846,6 +1857,9 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db,
*/
result= 1;
}
/* Drop statistics for this stored program from performance schema. */
MYSQL_DROP_SP(SP_TYPE_TRIGGER, db->str, db->length,
trigger->name.str, trigger->name.length);
}
}
}

View File

@ -1916,7 +1916,7 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
log_query.set_charset(system_charset_info);
if (sp->m_handler->type() == TYPE_ENUM_FUNCTION)
if (sp->m_handler->type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();