diff --git a/mysql-test/suite/compat/oracle/r/perfschema.result b/mysql-test/suite/compat/oracle/r/perfschema.result new file mode 100644 index 0000000000000..4b1afa0efab03 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/perfschema.result @@ -0,0 +1,47 @@ +# +# MDEV-34817 Performance schema does not clear package routines +# +SET sql_mode=ORACLE; +CREATE DATABASE mdev34817_db; +CREATE PACKAGE mdev34817_db.pkg1 AS +PROCEDURE p1(); +END; +$$ +CREATE PACKAGE BODY mdev34817_db.pkg1 AS +PROCEDURE p1() AS +BEGIN +NULL; +END; +END; +$$ +CALL mdev34817_db.pkg1.p1(); +# Testing DROP DATABASE +DROP DATABASE mdev34817_db; +SELECT object_type, object_schema, object_name +FROM performance_schema.events_statements_summary_by_program +WHERE LOWER(object_schema)='mdev34817_db'; +object_type object_schema object_name +# Testing DROP PACKAGE BODY +CREATE DATABASE mdev34817_db; +CREATE PACKAGE mdev34817_db.pkg1 AS +PROCEDURE p1(); +END; +$$ +CREATE PACKAGE BODY mdev34817_db.pkg1 AS +PROCEDURE p1() AS +BEGIN +NULL; +END; +END; +$$ +CALL mdev34817_db.pkg1.p1(); +DROP PACKAGE BODY mdev34817_db.pkg1; +SELECT object_type, object_schema, object_name +FROM performance_schema.events_statements_summary_by_program +WHERE LOWER(object_schema)='mdev34817_db'; +object_type object_schema object_name + mdev34817_db pkg1 +DROP DATABASE mdev34817_db; +# +# End of 10.11 tests +# diff --git a/mysql-test/suite/compat/oracle/t/perfschema.test b/mysql-test/suite/compat/oracle/t/perfschema.test new file mode 100644 index 0000000000000..71eab84256329 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/perfschema.test @@ -0,0 +1,66 @@ +--echo # +--echo # MDEV-34817 Performance schema does not clear package routines +--echo # + +SET sql_mode=ORACLE; +CREATE DATABASE mdev34817_db; + +DELIMITER $$; + +CREATE PACKAGE mdev34817_db.pkg1 AS + PROCEDURE p1(); +END; +$$ + +CREATE PACKAGE BODY mdev34817_db.pkg1 AS + PROCEDURE p1() AS + BEGIN + NULL; + END; +END; +$$ + +DELIMITER ;$$ + +CALL mdev34817_db.pkg1.p1(); + +--echo # Testing DROP DATABASE +DROP DATABASE mdev34817_db; + +SELECT object_type, object_schema, object_name +FROM performance_schema.events_statements_summary_by_program +WHERE LOWER(object_schema)='mdev34817_db'; + +--echo # Testing DROP PACKAGE BODY +CREATE DATABASE mdev34817_db; + +DELIMITER $$; + +CREATE PACKAGE mdev34817_db.pkg1 AS + PROCEDURE p1(); +END; +$$ + +CREATE PACKAGE BODY mdev34817_db.pkg1 AS + PROCEDURE p1() AS + BEGIN + NULL; + END; +END; +$$ + +DELIMITER ;$$ + +CALL mdev34817_db.pkg1.p1(); + +DROP PACKAGE BODY mdev34817_db.pkg1; + +SELECT object_type, object_schema, object_name +FROM performance_schema.events_statements_summary_by_program +WHERE LOWER(object_schema)='mdev34817_db'; + +DROP DATABASE mdev34817_db; + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/sql/sp.cc b/sql/sp.cc index d393f06d67589..aeedd0bf87afd 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1104,6 +1104,35 @@ sp_returns_type(THD *thd, String &result, const sp_head *sp) used to indicate about errors. */ +#ifdef HAVE_PSI_SP_INTERFACE +/** + Drop statistics for all package sub-routines from performance schema. + @param spc The cache to look up the package body. + @param name The package body name. +*/ +static void sp_psi_drop_package_routines(sp_cache **spc, + const Database_qualified_name *name) +{ + sp_head *ph; + if ((ph= sp_cache_lookup(spc, name))) + { + sp_package *pkg= ph->get_package(); + if (pkg) + { + List_iterator it(pkg->m_routine_implementations); + for (LEX *lex; (lex= it++); ) + { + sp_head *sub= lex->sphead; + MYSQL_DROP_SP(sub->m_handler->type(), name->m_db.str, + static_cast(name->m_db.length), + sub->m_name.str, static_cast(sub->m_name.length)); + } + } + } +} +#endif + + int Sp_handler::sp_drop_routine_internal(THD *thd, const Database_qualified_name *name, @@ -1126,6 +1155,11 @@ Sp_handler::sp_drop_routine_internal(THD *thd, sp_head *sp; sp_cache **spc= get_cache(thd); DBUG_ASSERT(spc); +#ifdef HAVE_PSI_SP_INTERFACE + if (type() == SP_TYPE_PACKAGE_BODY) + sp_psi_drop_package_routines(spc, name); +#endif + if ((sp= sp_cache_lookup(spc, name))) sp_cache_remove(spc, &sp); /* Drop statistics for this stored program from performance schema. */ @@ -1871,10 +1905,18 @@ sp_drop_db_routines(THD *thd, const char *db) String buf; // the following assumes MODE_PAD_CHAR_TO_FULL_LENGTH being *unset* String *name= table->field[MYSQL_PROC_FIELD_NAME]->val_str(&buf); + name->strip_sp(); - enum_sp_type sp_type= (enum_sp_type) table->field[MYSQL_PROC_MYSQL_TYPE]->ptr[0]; + enum_sp_type sp_type= (enum_sp_type) table->field[MYSQL_PROC_MYSQL_TYPE]->val_int(); /* Drop statistics for this stored program from performance schema. */ MYSQL_DROP_SP(sp_type, db, static_cast(db_length), name->ptr(), name->length()); + if (sp_type == SP_TYPE_PACKAGE_BODY) + { + LEX_CSTRING db_cstr= {db, db_length}; + LEX_CSTRING name_cstr= {name->ptr(), name->length()}; + sp_name spn(&db_cstr, &name_cstr, true); + sp_psi_drop_package_routines(&thd->sp_package_body_cache, &spn); + } #endif } else