MySQL 9.1.0
Source Code Documentation
|
This file contains the implementation of prepared statements. More...
#include "sql/sql_prepare.h"
#include "my_config.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <unordered_map>
#include <utility>
#include "decimal.h"
#include "event_parse_data.h"
#include "field_types.h"
#include "map_helpers.h"
#include "mem_root_deque.h"
#include "my_alloc.h"
#include "my_byteorder.h"
#include "my_command.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_sqlcommand.h"
#include "my_sys.h"
#include "my_time.h"
#include "mysql/com_data.h"
#include "mysql/components/services/log_shared.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/psi/mysql_ps.h"
#include "mysql/psi/mysql_statement.h"
#include "mysql/psi/mysql_thread.h"
#include "mysql/strings/dtoa.h"
#include "mysql/strings/int2str.h"
#include "mysql/strings/m_ctype.h"
#include "mysql/udf_registration_types.h"
#include "mysql_com.h"
#include "mysql_time.h"
#include "mysqld_error.h"
#include "nulls.h"
#include "scope_guard.h"
#include "sp_head.h"
#include "sql-common/my_decimal.h"
#include "sql/aggregated_stats.h"
#include "sql/aggregated_stats_buffer.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/current_thd.h"
#include "sql/debug_sync.h"
#include "sql/derror.h"
#include "sql/handler.h"
#include "sql/item.h"
#include "sql/item_func.h"
#include "sql/log.h"
#include "sql/mdl.h"
#include "sql/mysqld.h"
#include "sql/opt_hints.h"
#include "sql/opt_trace.h"
#include "sql/protocol.h"
#include "sql/protocol_classic.h"
#include "sql/psi_memory_key.h"
#include "sql/query_options.h"
#include "sql/query_result.h"
#include "sql/resourcegroups/resource_group_basic_types.h"
#include "sql/resourcegroups/resource_group_mgr.h"
#include "sql/session_tracker.h"
#include "sql/set_var.h"
#include "sql/sp_cache.h"
#include "sql/sql_audit.h"
#include "sql/sql_base.h"
#include "sql/sql_class.h"
#include "sql/sql_cmd.h"
#include "sql/sql_cmd_ddl_table.h"
#include "sql/sql_cmd_dml.h"
#include "sql/sql_const.h"
#include "sql/sql_cursor.h"
#include "sql/sql_db.h"
#include "sql/sql_digest.h"
#include "sql/sql_digest_stream.h"
#include "sql/sql_error.h"
#include "sql/sql_handler.h"
#include "sql/sql_insert.h"
#include "sql/sql_lex.h"
#include "sql/sql_list.h"
#include "sql/sql_parse.h"
#include "sql/sql_profile.h"
#include "sql/sql_query_rewrite.h"
#include "sql/sql_rewrite.h"
#include "sql/sql_view.h"
#include "sql/statement/statement_runnable.h"
#include "sql/system_variables.h"
#include "sql/table.h"
#include "sql/thd_raii.h"
#include "sql/transaction.h"
#include "sql_string.h"
#include "string_with_len.h"
#include "template_utils.h"
Classes | |
class | anonymous_namespace{sql_prepare.cc}::Query_fetch_protocol_binary |
A result class used to send cursor rows using the binary protocol. More... | |
class | Statement_backup |
Namespaces | |
namespace | resourcegroups |
namespace | anonymous_namespace{sql_prepare.cc} |
Functions | |
void | rewrite_query (THD *thd) |
Rewrite the current query (to obfuscate passwords etc.). More... | |
void | log_execute_line (THD *thd) |
Unless we're doing dynamic SQL, write the current query to the general query log if it's open. More... | |
static void | set_parameter_type (Item_param *param, enum enum_field_types type, bool unsigned_type, const CHARSET_INFO *cs_source) |
Set source parameter type based on information from protocol buffer. More... | |
static bool | set_parameter_value (Item_param *param, const uchar **pos, ulong len, enum Prepared_statement::enum_param_pack_type pack_type) |
Set parameter value from protocol buffer. More... | |
bool | is_param_long_data_type (Item_param *param) |
Check whether this parameter data type is compatible with long data. More... | |
static void | swap_parameter_array (Item_param **param_array_dst, Item_param **param_array_src, uint param_count) |
Setup data conversion routines using an array of parameter markers from the original prepared statement. More... | |
static bool | send_statement (THD *thd, const Prepared_statement *stmt, uint no_columns, Query_result *result, const mem_root_deque< Item * > *types) |
static bool | mysql_test_set_fields (THD *thd, Prepared_statement *stmt, Table_ref *tables, List< set_var_base > *var_list) |
Validate and prepare for execution SET statement expressions. More... | |
static bool | select_like_stmt_test (THD *thd, Query_result *result, ulonglong added_options) |
static bool | mysql_test_create_view (THD *thd, Prepared_statement *stmt) |
Validate and prepare for execution CREATE VIEW statement. More... | |
const char * | fieldtype2str (enum enum_field_types type) |
Returns a string for a mysql field type. More... | |
static bool | init_param_array (THD *thd, Prepared_statement *stmt) |
Initialize array of parameters in statement from LEX. More... | |
void | mysqld_stmt_prepare (THD *thd, const char *query, uint length, Prepared_statement *stmt) |
COM_STMT_PREPARE handler. More... | |
bool | mysql_stmt_precheck (THD *thd, const COM_DATA *com_data, enum enum_server_command cmd, Prepared_statement **stmt) |
Searches for the statement with the specified id and validates it. More... | |
static const char * | get_dynamic_sql_string (LEX *lex, size_t *query_len) |
Get an SQL statement text from a user variable or from plain text. More... | |
void | mysql_sql_stmt_prepare (THD *thd) |
SQLCOM_PREPARE implementation. More... | |
void | reset_stmt_parameters (Prepared_statement *stmt) |
Clears parameters from data left from previous execution or long data. More... | |
void | mysqld_stmt_execute (THD *thd, Prepared_statement *stmt, bool has_new_types, ulong execute_flags, PS_PARAM *parameters) |
COM_STMT_EXECUTE handler: execute a previously prepared statement. More... | |
void | mysql_sql_stmt_execute (THD *thd) |
SQLCOM_EXECUTE implementation. More... | |
void | mysqld_stmt_fetch (THD *thd, Prepared_statement *stmt, ulong num_rows) |
COM_STMT_FETCH handler: fetches requested amount of rows from cursor. More... | |
void | mysqld_stmt_reset (THD *thd, Prepared_statement *stmt) |
Reset a prepared statement in case there was a recoverable error. More... | |
void | mysqld_stmt_close (THD *thd, Prepared_statement *stmt) |
Delete a prepared statement from memory. More... | |
void | mysql_sql_stmt_close (THD *thd) |
SQLCOM_DEALLOCATE implementation. More... | |
void | mysql_stmt_get_longdata (THD *thd, Prepared_statement *stmt, uint param_number, uchar *str, ulong length) |
Handle long data in pieces from client. More... | |
bool | ask_to_reprepare (THD *thd) |
Requests for repreparation of statement. More... | |
This file contains the implementation of prepared statements.
When one prepares a statement:
[STMT_ID:4] [Column_count:2] [Param_count:2] [Params meta info (stubs only for now)] (if Param_count > 0) [Columns meta info] (if Column_count > 0)
During prepare the tables used in a statement are opened, but no locks are acquired. Table opening will block any DDL during the operation, and we do not need any locks as we neither read nor modify any data during prepare. Tables are closed after prepare finishes.
When one executes a statement:
[COM_STMT_EXECUTE:1] [STMT_ID:4] [NULL_BITS:(param_count+7)/8)] [TYPES_SUPPLIED_BY_CLIENT(0/1):1] [[length]data] [[length]data] .. [[length]data].(Note: Except for string/binary types; all other types will not be supplied with length field)
During execution of prepared statement tables are opened and locked the same way they would for normal (non-prepared) statement execution. Tables are unlocked and closed after the execution.
When one supplies long data for a placeholder:
bool ask_to_reprepare | ( | THD * | thd | ) |
Requests for repreparation of statement.
const char * fieldtype2str | ( | enum enum_field_types | type | ) |
Returns a string for a mysql field type.
type | the type of the field. |
|
static |
Get an SQL statement text from a user variable or from plain text.
If the statement is plain text, just assign the pointers, otherwise allocate memory in thd->mem_root and copy the contents of the variable, possibly with character set conversion.
[in] | lex | main lex |
[out] | query_len | length of the SQL statement (is set only in case of success) |
non-zero | success |
0 | in case of error (out of memory) |
|
static |
Initialize array of parameters in statement from LEX.
(We need to have quick access to items by number in mysql_stmt_get_longdata). This is to avoid using malloc/realloc in the parser.
|
inline |
Check whether this parameter data type is compatible with long data.
Used to detect whether a long data stream has been supplied to a incompatible data type. Notice that VARCHAR type is MYSQL_TYPE_STRING, not MYSQL_TYPE_VARCHAR, when sent on protocol between client and server.
void log_execute_line | ( | THD * | thd | ) |
Unless we're doing dynamic SQL, write the current query to the general query log if it's open.
If we have a rewritten version of the query, use that instead of the "raw" one.
Side-effect: query may be written to general log if it's open.
thd | thread handle |
void mysql_sql_stmt_close | ( | THD * | thd | ) |
SQLCOM_DEALLOCATE implementation.
Close an SQL prepared statement. As this can be called from Dynamic SQL, we should be careful to not close a statement that is currently being executed.
OK packet is sent in case of success, otherwise an error message is set in THD.
void mysql_sql_stmt_execute | ( | THD * | thd | ) |
SQLCOM_EXECUTE implementation.
Execute prepared statement using parameter values from lex->prepared_stmt_params and send result to the client using text protocol. This is called from mysql_execute_command and therefore should behave like an ordinary query (e.g. not change global THD data, such as warning count, server status, etc). This function uses text protocol to send a possible result set.
In case of success, OK (or result set) packet is sent to the client, otherwise an error is set in THD.
thd | thread handle |
void mysql_sql_stmt_prepare | ( | THD * | thd | ) |
SQLCOM_PREPARE implementation.
Prepare an SQL prepared statement. This is called from mysql_execute_command and should therefore behave like an ordinary query (e.g. should not reset any global THD data).
In case of success, OK packet is sent to the client, otherwise an error message is set in THD.
thd | thread handle |
void mysql_stmt_get_longdata | ( | THD * | thd, |
Prepared_statement * | stmt, | ||
uint | param_number, | ||
uchar * | str, | ||
ulong | length | ||
) |
Handle long data in pieces from client.
Get a part of a long data. To make the protocol efficient, we are not sending any return packets here. If something goes wrong, then we will send the error on 'execute' We assume that the client takes care of checking that all parts are sent to the server. (No checking that we get a 'end of column' in the server is performed).
thd | Thread handle |
stmt | Pointer to Prepared_statement |
param_number | Number of parameters |
str | String to append |
length | Length of string (including end \0) |
bool mysql_stmt_precheck | ( | THD * | thd, |
const COM_DATA * | com_data, | ||
enum enum_server_command | cmd, | ||
Prepared_statement ** | stmt | ||
) |
Searches for the statement with the specified id and validates it.
thd | [in] thread handle |
com_data | [in] command data |
cmd | [in] command type to be executed |
stmt | [out] pointer to Prepared_statement to store it if found |
|
static |
Validate and prepare for execution CREATE VIEW statement.
thd | current thread |
stmt | prepared statement |
false | Operation was a success. |
true | An error occurred. |
|
static |
Validate and prepare for execution SET statement expressions.
thd | current thread |
stmt | prepared statement |
tables | list of tables used in this query |
var_list | list of expressions |
void mysqld_stmt_close | ( | THD * | thd, |
Prepared_statement * | stmt | ||
) |
Delete a prepared statement from memory.
void mysqld_stmt_execute | ( | THD * | thd, |
Prepared_statement * | stmt, | ||
bool | has_new_types, | ||
ulong | execute_flags, | ||
PS_PARAM * | parameters | ||
) |
COM_STMT_EXECUTE handler: execute a previously prepared statement.
If there are any parameters, then replace parameter markers with the data supplied from the client, and then execute the statement. This function uses binary protocol to send a possible result set to the client.
In case of success OK packet or a result set is sent to the client, otherwise an error message is set in THD.
thd | current thread |
stmt | prepared statement |
has_new_types | true if parsed parameters have data types defined, otherwise types from last execution will be used |
execute_flags | flag used to decide if a cursor should be used |
parameters | prepared statement's parsed parameters |
void mysqld_stmt_fetch | ( | THD * | thd, |
Prepared_statement * | stmt, | ||
ulong | num_rows | ||
) |
COM_STMT_FETCH handler: fetches requested amount of rows from cursor.
thd | Thread handle. |
stmt | Pointer to the prepared statement. |
num_rows | Number of rows to fetch. |
void mysqld_stmt_prepare | ( | THD * | thd, |
const char * | query, | ||
uint | length, | ||
Prepared_statement * | stmt | ||
) |
COM_STMT_PREPARE handler.
Given a query string with parameter markers, create a prepared statement from it and send PS info back to the client.
If parameter markers are found in the query, then store the information using Item_param along with maintaining a list in lex->param_array, so that a fast and direct retrieval can be made without going through all field items.
In case of success a new statement id and metadata is sent to the client, otherwise an error message is set in THD.
thd | thread handle |
query | query to be prepared |
length | query string length, including ignored trailing NULL or quote char. |
stmt | Prepared_statement to be used for preparation. |
void mysqld_stmt_reset | ( | THD * | thd, |
Prepared_statement * | stmt | ||
) |
Reset a prepared statement in case there was a recoverable error.
This function resets statement to the state it was right after prepare. It can be used to:
thd | Thread handle |
stmt | Pointer to the Prepared_statement |
void reset_stmt_parameters | ( | Prepared_statement * | stmt | ) |
Clears parameters from data left from previous execution or long data.
stmt | prepared statement for which parameters should be reset |
void rewrite_query | ( | THD * | thd | ) |
Rewrite the current query (to obfuscate passwords etc.).
Side-effect: thd->rewritten_query() may be populated with a rewritten query. If the query is not of a rewritable type, thd->rewritten_query() will be empty.
thd | thread handle |
|
static |
thd | thread handler |
result | query result sink |
added_options | options added to query block before preparation |
|
static |
|
static |
Set source parameter type based on information from protocol buffer.
param | Parameter to set source type for |
type | Field type |
unsigned_type | true if type is unsigned (applicable for numeric types) |
cs_source | The source collation for non-binary string parameters |
If parameter metadata is invalid, set source data type MYSQL_TYPE_INVALID.
|
static |
Set parameter value from protocol buffer.
param | Parameter to set a value for |
pos | Pointer to parameter value in protocol buffer |
len | Length of parameter value |
The function reads a binary valuefrom pos, converts it to the requested type and assigns it to the paramameter.
|
static |
Setup data conversion routines using an array of parameter markers from the original prepared statement.
Swap the parameter data of the original prepared statement to the new one.
Used only when we re-prepare a prepared statement. There are two reasons for this function to exist:
1) In the binary client/server protocol, parameter metadata is sent only at first execute. Consequently, if we need to reprepare a prepared statement at a subsequent execution, we may not have metadata information in the packet. In that case we use the parameter array of the original prepared statement to setup parameter types of the new prepared statement.
2) In the binary client/server protocol, we may supply long data in pieces. When the last piece is supplied, we assemble the pieces and convert them from client character set to the connection character set. After that the parameter value is only available inside the parameter, the original pieces are lost, and thus we can only assign the corresponding parameter of the reprepared statement from the original value.
[out] | param_array_dst | parameter markers of the new statement |
[in] | param_array_src | parameter markers of the original statement |
[in] | param_count | total number of parameters. Is the same in src and dst arrays, since the statement query is the same |