MySQL 9.1.0
Source Code Documentation
|
#include "sql/sp.h"
#include <string.h>
#include <algorithm>
#include <atomic>
#include <memory>
#include <new>
#include <utility>
#include <vector>
#include "lex_string.h"
#include "m_string.h"
#include "my_alloc.h"
#include "my_base.h"
#include "my_dbug.h"
#include "my_psi_config.h"
#include "my_sqlcommand.h"
#include "my_sys.h"
#include "mysql/components/services/bits/psi_bits.h"
#include "mysql/components/services/bits/psi_statement_bits.h"
#include "mysql/components/services/log_builtins.h"
#include "mysql/components/services/log_shared.h"
#include "mysql/my_loglevel.h"
#include "mysql/psi/mysql_sp.h"
#include "mysql/strings/m_ctype.h"
#include "mysql_com.h"
#include "mysqld_error.h"
#include "sql/auth/auth_acls.h"
#include "sql/auth/auth_common.h"
#include "sql/auth/sql_security_ctx.h"
#include "sql/binlog.h"
#include "sql/dd/cache/dictionary_client.h"
#include "sql/dd/dd_routine.h"
#include "sql/dd/dd_utility.h"
#include "sql/dd/string_type.h"
#include "sql/dd/types/function.h"
#include "sql/dd/types/procedure.h"
#include "sql/dd/types/routine.h"
#include "sql/dd/types/schema.h"
#include "sql/dd/types/trigger.h"
#include "sql/dd_sp.h"
#include "sql/dd_sql_view.h"
#include "sql/dd_table_share.h"
#include "sql/debug_sync.h"
#include "sql/error_handler.h"
#include "sql/field.h"
#include "sql/handler.h"
#include "sql/lock.h"
#include "sql/log_event.h"
#include "sql/mdl.h"
#include "sql/mysqld.h"
#include "sql/protocol.h"
#include "sql/psi_memory_key.h"
#include "sql/set_var.h"
#include "sql/sp_cache.h"
#include "sql/sp_head.h"
#include "sql/sp_pcontext.h"
#include "sql/sql_class.h"
#include "sql/sql_const.h"
#include "sql/sql_db.h"
#include "sql/sql_digest_stream.h"
#include "sql/sql_error.h"
#include "sql/sql_list.h"
#include "sql/sql_parse.h"
#include "sql/sql_show.h"
#include "sql/sql_table.h"
#include "sql/strfunc.h"
#include "sql/system_variables.h"
#include "sql/table.h"
#include "sql/thd_raii.h"
#include "sql/thr_malloc.h"
#include "sql/transaction.h"
#include "sql/transaction_info.h"
#include "sql_string.h"
#include "string_with_len.h"
#include "template_utils.h"
Classes | |
class | anonymous_namespace{sp.cc}::Silence_deprecated_warning |
Silence DEPRECATED SYNTAX warnings when loading a stored procedure into the cache. More... | |
class | Bad_db_error_handler |
Namespaces | |
namespace | anonymous_namespace{sp.cc} |
Macros | |
#define | SP_TYPE_STRING(type) (type == enum_sp_type::FUNCTION ? "FUNCTION" : "PROCEDURE") |
Functions | |
static bool | create_string (THD *thd, String *buf, enum_sp_type type, const char *db, size_t dblen, const char *name, size_t namelen, const char *params, size_t paramslen, const char *returns, size_t returnslen, const char *body, size_t bodylen, st_sp_chistics *chistics, const LEX_CSTRING &definer_user, const LEX_CSTRING &definer_host, sql_mode_t sql_mode, bool if_not_exists) |
Generates the CREATE... string from the table information. More... | |
bool | load_charset (MEM_ROOT *mem_root, Field *field, const CHARSET_INFO *dflt_cs, const CHARSET_INFO **cs) |
bool | load_collation (MEM_ROOT *mem_root, Field *field, const CHARSET_INFO *dflt_cl, const CHARSET_INFO **cl) |
static bool | lock_routine_name (THD *thd, enum_sp_type type, const sp_name *name, enum_mdl_type mdl_lock_type) |
Acquire Shared MDL lock on the routine object. More... | |
static void | recursion_level_error (THD *thd, sp_head *sp) |
Return appropriate error about recursion limit reaching. More... | |
static enum_sp_return_code | db_find_routine (THD *thd, enum_sp_type type, const sp_name *name, sp_head **sphp) |
Find routine definition in data dictionary table and create corresponding sp_head object for it. More... | |
static sp_head * | sp_compile (THD *thd, String *defstr, sql_mode_t sql_mode, Stored_program_creation_ctx *creation_ctx) |
The function parses input strings and returns SP structure. More... | |
enum_sp_return_code | db_load_routine (THD *thd, enum_sp_type type, const char *sp_db, size_t sp_db_len, const char *sp_name, size_t sp_name_len, sp_head **sphp, sql_mode_t sql_mode, const char *params, const char *returns, const char *body, st_sp_chistics *sp_chistics, const char *definer_user, const char *definer_host, longlong created, longlong modified, Stored_program_creation_ctx *creation_ctx) |
static bool | check_routine_already_exists (THD *thd, sp_head *sp, bool if_not_exists, bool &already_exists) |
Method to check if routine with same name already exists. More... | |
static bool | create_routine_precheck (THD *thd, sp_head *sp) |
Precheck for create routine statement. More... | |
static bool | sp_binlog_create_routine_stmt (THD *thd, sp_head *sp, const LEX_USER *definer, bool if_not_exists, bool already_exists) |
Method to log create routine event to binlog. More... | |
bool | sp_create_routine (THD *thd, sp_head *sp, const LEX_USER *definer, bool if_not_exists, bool &sp_already_exists) |
Creates a stored routine. More... | |
enum_sp_return_code | sp_drop_routine (THD *thd, enum_sp_type type, sp_name *name) |
Drops a stored routine. More... | |
bool | sp_update_routine (THD *thd, enum_sp_type type, sp_name *name, st_sp_chistics *chistics) |
Updates(Alter) a stored routine. More... | |
bool | lock_db_routines (THD *thd, const dd::Schema &schema) |
Acquires exclusive metadata lock on all stored routines in the given database. More... | |
bool | sp_drop_db_routines (THD *thd, const dd::Schema &schema) |
Drop all routines in database 'db'. More... | |
static bool | show_create_routine_from_dd_routine (THD *thd, enum_sp_type type, sp_name *sp, const dd::Routine *routine) |
Prepare show create routine output from the DD routine object. More... | |
bool | sp_show_create_routine (THD *thd, enum_sp_type type, sp_name *name) |
Implement SHOW CREATE statement for stored routines. More... | |
sp_head * | sp_find_routine (THD *thd, enum_sp_type type, sp_name *name, sp_cache **cp, bool cache_only) |
Obtain object representing stored procedure/function by its name from stored procedures cache and looking into data dictionary if needed. More... | |
sp_head * | sp_setup_routine (THD *thd, enum_sp_type type, sp_name *name, sp_cache **cp) |
Setup a cached routine for execution. More... | |
bool | sp_exist_routines (THD *thd, Table_ref *routines, bool is_proc) |
This is used by sql_acl.cc:mysql_routine_grant() and is used to find the routines in 'routines'. More... | |
static bool | sp_add_used_routine (Query_tables_list *prelocking_ctx, Query_arena *arena, const uchar *key, size_t key_length, size_t db_length, const char *name, size_t name_length, Table_ref *belong_to_view) |
Auxiliary function that adds new element to the set of stored routines used by statement. More... | |
bool | sp_add_used_routine (Query_tables_list *prelocking_ctx, Query_arena *arena, Sroutine_hash_entry::entry_type type, const char *db, size_t db_length, const char *name, size_t name_length, bool lowercase_db, Sp_name_normalize_type name_normalize_type, bool own_routine, Table_ref *belong_to_view) |
Add routine or trigger which is used by statement to the set of stored routines used by this statement. More... | |
void | sp_remove_not_own_routines (Query_tables_list *prelocking_ctx) |
Remove routines which are only indirectly used by statement from the set of routines used by this statement. More... | |
void | sp_update_stmt_used_routines (THD *thd, Query_tables_list *prelocking_ctx, malloc_unordered_map< std::string, Sroutine_hash_entry * > *src, Table_ref *belong_to_view) |
Add contents of hash representing set of routines to the set of routines used by statement. More... | |
void | sp_update_stmt_used_routines (THD *thd, Query_tables_list *prelocking_ctx, SQL_I_List< Sroutine_hash_entry > *src, Table_ref *belong_to_view) |
Add contents of list representing set of routines to the set of routines used by statement. More... | |
enum_sp_return_code | sp_cache_routine (THD *thd, Sroutine_hash_entry *rt, bool lookup_only, sp_head **sp) |
A helper wrapper around sp_cache_routine() to use from prelocking until 'sp_name' is eradicated as a class. More... | |
enum_sp_return_code | sp_cache_routine (THD *thd, enum_sp_type type, const sp_name *name, bool lookup_only, sp_head **sp) |
Ensure that routine is present in cache by loading it from the data dictionary if needed. More... | |
static bool | strnstr (const char *str, size_t length, const char *substr) |
static size_t | find_dollar_quote (const st_sp_chistics *chistics, const char *sp_body, size_t sp_body_len, char *quote, size_t max_quote_len) |
Make sure to choose a dollar quote that does not conflict with the content of the routine. More... | |
sp_head * | sp_start_parsing (THD *thd, enum_sp_type sp_type, sp_name *sp_name) |
Start parsing of a stored program. More... | |
void | sp_finish_parsing (THD *thd) |
Finish parsing of a stored program. More... | |
uint | sp_get_flags_for_command (LEX *lex) |
bool | sp_check_name (LEX_STRING *ident) |
Check that the name 'ident' is ok. More... | |
Item * | sp_prepare_func_item (THD *thd, bool standalone, Item **it_addr) |
Prepare an Item for evaluation (call of fix_fields). More... | |
bool | sp_eval_expr (THD *thd, bool standalone, Field *result_field, Item **expr_item_ptr) |
Evaluate an expression and store the result in the field. More... | |
String * | sp_get_item_value (THD *thd, Item *item, String *str) |
Return a string representation of the Item value. More... | |
#define SP_TYPE_STRING | ( | type | ) | (type == enum_sp_type::FUNCTION ? "FUNCTION" : "PROCEDURE") |
|
static |
Method to check if routine with same name already exists.
thd | Thread context. | |
sp | Stored routine object to store. | |
if_not_exists | True if 'IF NOT EXISTS' clause was specified. | |
[out] | already_exists | Set to true if routine already exists. |
false | Success. |
true | Error. |
Precheck for create routine statement.
thd | Thread context. |
sp | Stored routine object to store. |
false | Success. |
true | Error. |
|
static |
Generates the CREATE... string from the table information.
|
static |
Find routine definition in data dictionary table and create corresponding sp_head object for it.
thd | Thread context |
type | Type of routine (PROCEDURE/...) |
name | Name of routine |
sphp | Out parameter in which pointer to created sp_head object is returned (0 in case of error). |
SP_OK | Success |
non-SP_OK | Error (one of special codes like SP_DOES_NOT_EXISTS) |
enum_sp_return_code db_load_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
const char * | sp_db, | ||
size_t | sp_db_len, | ||
const char * | sp_name, | ||
size_t | sp_name_len, | ||
sp_head ** | sphp, | ||
sql_mode_t | sql_mode, | ||
const char * | params, | ||
const char * | returns, | ||
const char * | body, | ||
st_sp_chistics * | sp_chistics, | ||
const char * | definer_user, | ||
const char * | definer_host, | ||
longlong | created, | ||
longlong | modified, | ||
Stored_program_creation_ctx * | creation_ctx | ||
) |
|
static |
Make sure to choose a dollar quote that does not conflict with the content of the routine.
This is only used for external language routines.
[in] | chistics | Routine characteristics |
[in] | sp_body | Start of external language routine body |
[in] | sp_body_len | Length of routine body |
[out] | quote | Buffer to put the dollar quote in |
[in] | max_quote_len | Max length of dollar quote (incl. null term.) |
bool load_charset | ( | MEM_ROOT * | mem_root, |
Field * | field, | ||
const CHARSET_INFO * | dflt_cs, | ||
const CHARSET_INFO ** | cs | ||
) |
bool load_collation | ( | MEM_ROOT * | mem_root, |
Field * | field, | ||
const CHARSET_INFO * | dflt_cl, | ||
const CHARSET_INFO ** | cl | ||
) |
bool lock_db_routines | ( | THD * | thd, |
const dd::Schema & | schema | ||
) |
Acquires exclusive metadata lock on all stored routines in the given database.
thd | Thread handler |
schema | Schema object |
false | Success |
true | Failure |
|
static |
Acquire Shared MDL lock on the routine object.
thd | Thread context |
type | Type of the routine (enum_sp_type::PROCEDURE/...) |
name | Name of the routine |
mdl_lock_type | Type of MDL lock be acquired on the routine. |
false | Success |
true | Error |
Return appropriate error about recursion limit reaching.
thd | Thread handle |
sp | The stored procedure executed |
|
static |
Prepare show create routine output from the DD routine object.
[in] | thd | Thread handle. |
[in] | type | Stored routine type. |
[in] | sp | Stored routine name. |
[in] | routine | Routine object read for the routine. |
false | on success |
true | on error |
|
static |
Auxiliary function that adds new element to the set of stored routines used by statement.
The elements of Query_tables_list::sroutines set are accessed on prepared statement re-execution. Because of this we have to allocate memory for both hash element and copy of its key in persistent arena.
prelocking_ctx | Prelocking context of the statement |
arena | Arena in which memory for new element will be allocated |
key | Key for the hash representing set |
key_length | Key length. |
db_length | Length of db name component in the key. |
name | Name of the routine. |
name_length | Length of the routine name. |
belong_to_view | Uppermost view which uses this routine (0 if routine is not used by view) |
true | new element was added. |
false | element was not added (because it is already present in the set). |
bool sp_add_used_routine | ( | Query_tables_list * | prelocking_ctx, |
Query_arena * | arena, | ||
Sroutine_hash_entry::entry_type | type, | ||
const char * | db, | ||
size_t | db_length, | ||
const char * | name, | ||
size_t | name_length, | ||
bool | lowercase_db, | ||
Sp_name_normalize_type | name_normalize_type, | ||
bool | own_routine, | ||
Table_ref * | belong_to_view | ||
) |
Add routine or trigger which is used by statement to the set of stored routines used by this statement.
To be friendly towards prepared statements one should pass persistent arena as second argument.
prelocking_ctx | Prelocking context of the statement |
arena | Arena in which memory for new element of the set will be allocated |
type | Routine type (one of FUNCTION/PROCEDURE/ TRIGGER ...) |
db | Database name |
db_length | Database name length |
name | Routine name |
name_length | Routine name length |
lowercase_db | Indicates whether db needs to be lowercased when constructing key. |
name_normalize_type | Indicates if names needs to be normalized (lowercased / accent needs to be removed). |
own_routine | Indicates whether routine is explicitly or implicitly used. |
belong_to_view | Uppermost view which uses this routine (nullptr if routine is not used by view) |
True | - new element was added. |
False | - element was not added (because it is already present in the set). |
|
static |
Method to log create routine event to binlog.
thd | Thread context. |
sp | Stored routine object to store. |
definer | Definer of the routine. |
if_not_exists | True if 'IF NOT EXISTS' clause was specified. |
already_exists | True if routine already exists. |
false | success |
true | error |
enum_sp_return_code sp_cache_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
const sp_name * | name, | ||
bool | lookup_only, | ||
sp_head ** | sp | ||
) |
Ensure that routine is present in cache by loading it from the data dictionary if needed.
If the routine is present but old, reload it. Emit an appropriate error if there was a problem during loading.
[in] | thd | Thread context. |
[in] | type | Type of object (FUNCTION or PROCEDURE). |
[in] | name | Name of routine. |
[in] | lookup_only | Only check that the routine is in the cache. If it's not, don't try to load. If it is present, but old, don't try to reload. |
[out] | sp | Pointer to sp_head object for routine, NULL if routine was not found. |
SP_OK | Either routine is found and was successfully loaded into cache or it does not exist. |
non-SP_OK | Error while loading routine from DD table. |
enum_sp_return_code sp_cache_routine | ( | THD * | thd, |
Sroutine_hash_entry * | rt, | ||
bool | lookup_only, | ||
sp_head ** | sp | ||
) |
A helper wrapper around sp_cache_routine() to use from prelocking until 'sp_name' is eradicated as a class.
bool sp_check_name | ( | LEX_STRING * | ident | ) |
Check that the name 'ident' is ok.
It's assumed to be an 'ident' from the parser, so we only have to check length and trailing spaces. The former is a standard requirement (and 'show status' assumes a non-empty name), the latter is a mysql:ism as trailing spaces are removed by get_field().
true | bad name |
false | name is ok |
|
static |
The function parses input strings and returns SP structure.
[in] | thd | Thread handler |
[in] | defstr | CREATE... string |
[in] | sql_mode | SQL mode |
[in] | creation_ctx | Creation context of stored routines |
Pointer | on sp_head struct Success |
NULL | error |
bool sp_create_routine | ( | THD * | thd, |
sp_head * | sp, | ||
const LEX_USER * | definer, | ||
bool | if_not_exists, | ||
bool & | sp_already_exists | ||
) |
Creates a stored routine.
Atomicity: The operation to create a stored routine is atomic/crash-safe. Changes to the Data-dictionary and writing event to binlog are part of the same transaction. All the changes are done as part of the same transaction or do not have any side effects on the operation failure. Data-dictionary, stored routines and table definition caches are in sync with operation state. Cache do not contain any stale/incorrect data in case of failure. In case of crash, there won't be any discrepancy between the data-dictionary table and the binary log.
thd | Thread context. | |
sp | Stored routine object to store. | |
definer | Definer of the SP. | |
if_not_exists | True if 'IF NOT EXISTS' clause was specified. | |
[out] | sp_already_exists | Set to true if routine already exists. |
false | Success. |
true | Error. |
bool sp_drop_db_routines | ( | THD * | thd, |
const dd::Schema & | schema | ||
) |
Drop all routines in database 'db'.
thd | Thread context. |
schema | Schema object. |
false | Success |
true | Error |
enum_sp_return_code sp_drop_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
sp_name * | name | ||
) |
Drops a stored routine.
Atomicity: The operation to drop a stored routine is atomic/crash-safe. Changes to the Data-dictionary and writing event to binlog are part of the same transaction. All the changes are done as part of the same transaction or do not have any side effects on the operation failure. Data-dictionary, stored routines and table definition caches are in sync with operation state. Cache do not contain any stale/incorrect data in case of failure. In case of crash, there won't be any discrepancy between the data-dictionary table and the binary log.
thd | Thread context. |
type | Stored routine type (PROCEDURE or FUNCTION) |
name | Stored routine name. |
Evaluate an expression and store the result in the field.
thd | current thread object |
standalone | if true, thd->lex contains preparation and execution state of item, otherwise item is part of a query expression that is already in executing state. |
result_field | the field to store the result |
expr_item_ptr | the root item of the expression |
This is used by sql_acl.cc:mysql_routine_grant() and is used to find the routines in 'routines'.
thd | Thread handler |
routines | List of needles in the hay stack |
is_proc | Indicates whether routines in the list are procedures or functions. |
false | Found. |
true | Not found |
sp_head * sp_find_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
sp_name * | name, | ||
sp_cache ** | cp, | ||
bool | cache_only | ||
) |
Obtain object representing stored procedure/function by its name from stored procedures cache and looking into data dictionary if needed.
thd | thread context |
type | type of object (FUNCTION or PROCEDURE) |
name | name of procedure |
cp | hash to look routine in |
cache_only | if true perform cache-only lookup (Don't look in data dictionary) |
NonNULL | pointer to sp_head object for the procedure |
NULL | in case of error. |
void sp_finish_parsing | ( | THD * | thd | ) |
Finish parsing of a stored program.
This is a counterpart of sp_start_parsing().
thd | Thread context. |
uint sp_get_flags_for_command | ( | LEX * | lex | ) |
lex | LEX-object, representing an SQL-statement inside SP. |
Return a string representation of the Item value.
thd | Thread context. |
item | The item to evaluate |
str | String buffer for representation of the value. |
NULL | on error |
non-NULL | a pointer to valid a valid string on success |
Prepare an Item for evaluation (call of fix_fields).
thd | thread handler |
standalone | if true, thd->lex is directly associated with item. Preparation and execution state will be changed and preparation data will be saved for later executions. If false, item is part of a larger query expression and no such state transitions should take place. It also means that such items cannot save preparation data. |
it_addr | pointer to item reference |
void sp_remove_not_own_routines | ( | Query_tables_list * | prelocking_ctx | ) |
Remove routines which are only indirectly used by statement from the set of routines used by this statement.
prelocking_ctx | Prelocking context of the statement |
sp_head * sp_setup_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
sp_name * | name, | ||
sp_cache ** | cp | ||
) |
Setup a cached routine for execution.
thd | thread context |
type | type of object (FUNCTION or PROCEDURE) |
name | name of procedure |
cp | hash to look routine in |
NonNULL | pointer to sp_head object for the procedure |
NULL | in case of error. |
bool sp_show_create_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
sp_name * | name | ||
) |
Implement SHOW CREATE statement for stored routines.
The operation finds the stored routine object specified by name and then calls show_create_routine_from_dd_routine().
thd | Thread context. |
type | Stored routine type (PROCEDURE or FUNCTION) |
name | Stored routine name. |
false | on success |
true | on error |
sp_head * sp_start_parsing | ( | THD * | thd, |
enum_sp_type | sp_type, | ||
sp_name * | sp_name | ||
) |
Start parsing of a stored program.
This function encapsulates all the steps necessary to initialize sp_head to start parsing SP.
Every successful call of sp_start_parsing() must finish with sp_finish_parsing().
thd | Thread context. |
sp_type | The stored program type |
sp_name | The stored program name |
bool sp_update_routine | ( | THD * | thd, |
enum_sp_type | type, | ||
sp_name * | name, | ||
st_sp_chistics * | chistics | ||
) |
Updates(Alter) a stored routine.
Atomicity: The operation to Update(Alter) a stored routine is atomic/crash-safe. Changes to the Data-dictionary and writing event to binlog are part of the same transaction. All the changes are done as part of the same transaction or do not have any side effects on the operation failure. Data-dictionary and stored routines caches caches are in sync with operation state. Cache do not contain any stale/incorrect data in case of failure. In case of crash, there won't be any discrepancy between the data-dictionary table and the binary log.
thd | Thread context. |
type | Stored routine type (PROCEDURE or FUNCTION) |
name | Stored routine name. |
chistics | New values of stored routine attributes to write. |
false | Success. |
true | Error. |
void sp_update_stmt_used_routines | ( | THD * | thd, |
Query_tables_list * | prelocking_ctx, | ||
malloc_unordered_map< std::string, Sroutine_hash_entry * > * | src, | ||
Table_ref * | belong_to_view | ||
) |
Add contents of hash representing set of routines to the set of routines used by statement.
thd | Thread context |
prelocking_ctx | Prelocking context of the statement |
src | Hash representing set from which routines will be added |
belong_to_view | Uppermost view which uses these routines, 0 if none |
void sp_update_stmt_used_routines | ( | THD * | thd, |
Query_tables_list * | prelocking_ctx, | ||
SQL_I_List< Sroutine_hash_entry > * | src, | ||
Table_ref * | belong_to_view | ||
) |
Add contents of list representing set of routines to the set of routines used by statement.
thd | Thread context |
prelocking_ctx | Prelocking context of the statement |
src | List representing set from which routines will be added |
belong_to_view | Uppermost view which uses these routines, 0 if none |
|
static |