MySQL  8.0.19
Source Code Documentation
sql_prepare.cc File Reference
#include "sql/sql_prepare.h"
#include "my_config.h"
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <atomic>
#include <memory>
#include <unordered_map>
#include <utility>
#include "decimal.h"
#include "field_types.h"
#include "m_ctype.h"
#include "m_string.h"
#include "map_helpers.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/plugin_audit.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/psi/mysql_ps.h"
#include "mysql/udf_registration_types.h"
#include "mysql_com.h"
#include "mysql_time.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/derror.h"
#include "sql/field.h"
#include "sql/handler.h"
#include "sql/item.h"
#include "sql/item_func.h"
#include "sql/log.h"
#include "sql/mdl.h"
#include "sql/my_decimal.h"
#include "sql/mysqld.h"
#include "sql/opt_trace.h"
#include "sql/protocol.h"
#include "sql/protocol_classic.h"
#include "sql/psi_memory_key.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_const.h"
#include "sql/sql_cursor.h"
#include "sql/sql_db.h"
#include "sql/sql_digest_stream.h"
#include "sql/sql_handler.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/system_variables.h"
#include "sql/table.h"
#include "sql/thr_malloc.h"
#include "sql/transaction.h"
#include "sql/window.h"
#include "sql_string.h"
#include "violite.h"

Classes

class  Protocol_local
 Protocol_local: a helper class to intercept the result of the data written to the network. More...
 
class  Statement_backup
 

Namespaces

 resourcegroups
 

Functions

static void rewrite_query_if_needed (THD *thd)
 Rewrite the current query (to obfuscate passwords etc.) if needed (i.e. More...
 
static 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 bool send_statement (THD *thd, const Prepared_statement *stmt, uint no_columns, Query_result *result, List< Item > *types)
 
static void set_param_tiny (Item_param *param, uchar **pos, ulong len)
 Data conversion routines. More...
 
static void set_param_short (Item_param *param, uchar **pos, ulong len)
 
static void set_param_int32 (Item_param *param, uchar **pos, ulong len)
 
static void set_param_int64 (Item_param *param, uchar **pos, ulong len)
 
static void set_param_float (Item_param *param, uchar **pos, ulong len)
 
static void set_param_double (Item_param *param, uchar **pos, ulong len)
 
static void set_param_decimal (Item_param *param, uchar **pos, ulong len)
 
static void set_param_time (Item_param *param, uchar **pos, ulong len)
 
static void set_param_datetime (Item_param *param, uchar **pos, ulong len)
 
static void set_param_date (Item_param *param, uchar **pos, ulong len)
 
static void set_param_str (Item_param *param, uchar **pos, ulong len)
 
static bool setup_one_conversion_function (THD *thd, Item_param *param, enum enum_field_types param_type)
 
bool is_param_long_data_type (Item_param *param)
 Check whether this parameter data type is compatible with long data. More...
 
static bool setup_conversion_functions (Prepared_statement *stmt, PS_PARAM *parameters)
 
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...
 
bool mysql_test_show (Prepared_statement *stmt, TABLE_LIST *tables)
 Validate SHOW statement. More...
 
static bool mysql_test_set_fields (Prepared_statement *stmt, TABLE_LIST *tables, List< set_var_base > *var_list)
 Validate and prepare for execution SET statement expressions. More...
 
static bool select_like_stmt_test (THD *thd)
 Check internal SELECT of the prepared command. More...
 
static bool mysql_test_create_view (Prepared_statement *stmt)
 Validate and prepare for execution CREATE VIEW statement. More...
 
static bool check_prepared_statement (Prepared_statement *stmt)
 Perform semantic analysis of the parsed tree and send a response packet to the client. More...
 
static bool init_param_array (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...
 
bool reinit_stmt_before_use (THD *thd, LEX *lex)
 Reinit prepared statement/stored procedure before execution. More...
 
static void reset_stmt_params (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...
 
static bool disable_general_log (THD *thd)
 Disables the general log for the current session by setting the OPTION_LOG_OFF bit in thd->variables.option_bits. More...
 

Detailed Description

This file contains the implementation of prepared statements.

When one prepares a statement:

  • Server gets the query from client with command 'COM_STMT_PREPARE'; in the following format: [COM_STMT_PREPARE:1] [query]
  • Parse the query and recognize any parameter markers '?' and store its information list in lex->param_list
  • Allocate a new statement for this prepare; and keep this in 'thd->stmt_map'.
  • Without executing the query, return back to client the total number of parameters along with result-set metadata information (if any) in the following format:
        [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:

  • Server gets the command 'COM_STMT_EXECUTE' to execute the previously prepared query. If there are any parameter markers, then the client will send the data in the following format:
        [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)
  • If it is a first execute or types of parameters were altered by client, then setup the conversion routines.
  • Assign parameter items from the supplied data.
  • Execute the query without re-parsing and send back the results to client

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:

  • Server gets the long data in pieces with command type 'COM_STMT_SEND_LONG_DATA'.
  • The packet received will have the format as: [COM_STMT_SEND_LONG_DATA:1][STMT_ID:4][parameter_number:2][data]
  • data from the packet is appended to the long data value buffer for this placeholder.
  • It's up to the client to stop supplying data chunks at any point. The server doesn't care; also, the server doesn't notify the client whether it got the data or not; if there is any error, then it will be returned at statement execute.

Function Documentation

◆ check_prepared_statement()

static bool check_prepared_statement ( Prepared_statement stmt)
static

Perform semantic analysis of the parsed tree and send a response packet to the client.

This function

  • opens all tables and checks access rights
  • validates semantics of statement columns and SQL functions by calling fix_fields.
Parameters
stmtprepared statement
Return values
falsesuccess, statement metadata is sent to client
trueerror, error message is set in THD (but not sent)

◆ disable_general_log()

static bool disable_general_log ( THD thd)
static

Disables the general log for the current session by setting the OPTION_LOG_OFF bit in thd->variables.option_bits.

Parameters
thdthe session
Returns
whether the setting was changed
Return values
falseif the general log was already disabled for this session
trueif the general log was enabled for the session and is now disabled

◆ get_dynamic_sql_string()

static const char* get_dynamic_sql_string ( LEX lex,
size_t *  query_len 
)
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.

Parameters
[in]lexmain lex
[out]query_lenlength of the SQL statement (is set only in case of success)
Return values
non-zerosuccess
0in case of error (out of memory)

◆ init_param_array()

static bool init_param_array ( Prepared_statement stmt)
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.

◆ is_param_long_data_type()

bool is_param_long_data_type ( Item_param param)
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.

◆ log_execute_line()

static void log_execute_line ( THD thd)
inlinestatic

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.

Parameters
thdthread handle

◆ mysql_sql_stmt_close()

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.

◆ mysql_sql_stmt_execute()

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.

Parameters
thdthread handle

◆ mysql_sql_stmt_prepare()

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.

Parameters
thdthread handle

◆ mysql_stmt_get_longdata()

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).

Parameters
thdThread handle
stmtPointer to Prepared_statement
param_numberNumber of parameters
strString to append
lengthLength of string (including end \0)

◆ mysql_stmt_precheck()

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.

Parameters
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

◆ mysql_test_create_view()

static bool mysql_test_create_view ( Prepared_statement stmt)
static

Validate and prepare for execution CREATE VIEW statement.

Parameters
stmtprepared statement
Note
This function handles create view commands.
Return values
falseOperation was a success.
trueAn error occurred.

◆ mysql_test_set_fields()

static bool mysql_test_set_fields ( Prepared_statement stmt,
TABLE_LIST tables,
List< set_var_base > *  var_list 
)
static

Validate and prepare for execution SET statement expressions.

Parameters
stmtprepared statement
tableslist of tables used in this query
var_listlist of expressions
Return values
falsesuccess
trueerror, error message is set in THD

◆ mysql_test_show()

bool mysql_test_show ( Prepared_statement stmt,
TABLE_LIST tables 
)

Validate SHOW statement.

In case of success, if this query is not EXPLAIN, send column list info back to the client.

Parameters
stmtprepared statement
tableslist of tables used in the query
Returns
false on succes and true on error

◆ mysqld_stmt_close()

void mysqld_stmt_close ( THD thd,
Prepared_statement stmt 
)

Delete a prepared statement from memory.

Note
we don't send any reply to this command.

◆ mysqld_stmt_execute()

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.

Parameters
thdcurrent thread
stmtprepared statement
has_new_typestrue if parsed parameters have data types defined
execute_flagsflag used to decide if a cursor should be used
parametersprepared statement's parsed parameters

◆ mysqld_stmt_fetch()

void mysqld_stmt_fetch ( THD thd,
Prepared_statement stmt,
ulong  num_rows 
)

COM_STMT_FETCH handler: fetches requested amount of rows from cursor.

Parameters
thdThread handle.
stmtPointer to the prepared statement.
num_rowsNumber of rows to fetch.

◆ mysqld_stmt_prepare()

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.

Parameters
thdthread handle
queryquery to be prepared
lengthquery string length, including ignored trailing NULL or quote char.
stmtPrepared_statement to be used for preparation.
Note
This function parses the query and sends the total number of parameters and resultset metadata information back to client (if any), without executing the query i.e. without any log/disk writes. This allows the queries to be re-executed without re-parsing during execute.

◆ mysqld_stmt_reset()

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:

  • clear an error happened during mysqld_stmt_send_long_data
  • cancel long data stream for all placeholders without having to call mysqld_stmt_execute.
  • close an open cursor Sends 'OK' packet in case of success (statement was reset) or 'ERROR' packet (unrecoverable error/statement not found/etc).
Parameters
thdThread handle
stmtPointer to the Prepared_statement

◆ reinit_stmt_before_use()

bool reinit_stmt_before_use ( THD thd,
LEX lex 
)

Reinit prepared statement/stored procedure before execution.

Resets the LEX object.

Return values
falseOK.
trueError.

◆ reset_stmt_params()

static void reset_stmt_params ( Prepared_statement stmt)
static

Clears parameters from data left from previous execution or long data.

Parameters
stmtprepared statement for which parameters should be reset

◆ rewrite_query_if_needed()

static void rewrite_query_if_needed ( THD thd)
inlinestatic

Rewrite the current query (to obfuscate passwords etc.) if needed (i.e.

only if we'll be writing the query to any of our logs).

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.

Parameters
thdthread handle

◆ select_like_stmt_test()

static bool select_like_stmt_test ( THD thd)
static

Check internal SELECT of the prepared command.

Note
Old version. Will be replaced with select_like_stmt_cmd_test() after the parser refactoring.
Parameters
thdThread handle.
Note
This function won't directly open tables used in select. They should be opened either by calling function (and in this case you probably should use select_like_stmt_test_with_open()) or by "specific_prepare" call (like this happens in case of multi-update).
Return values
falsesuccess
trueerror, error message is set in THD

◆ send_statement()

bool send_statement ( THD thd,
const Prepared_statement stmt,
uint  no_columns,
Query_result result,
List< Item > *  types 
)
static

◆ set_param_date()

static void set_param_date ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_datetime()

static void set_param_datetime ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_decimal()

static void set_param_decimal ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_double()

static void set_param_double ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_float()

static void set_param_float ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_int32()

static void set_param_int32 ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_int64()

static void set_param_int64 ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_short()

static void set_param_short ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_str()

static void set_param_str ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_time()

static void set_param_time ( Item_param param,
uchar **  pos,
ulong  len 
)
static

◆ set_param_tiny()

static void set_param_tiny ( Item_param param,
uchar **  pos,
ulong  len 
)
static

Data conversion routines.

All these functions read the data from pos, convert it to requested type and assign to param; pos is advanced to predefined length.

Make a note that the NULL handling is examined at first execution (i.e. when input types altered) and for all subsequent executions we don't read any values for this.

Parameters
paramparameter item
posinput data buffer
lenlength of data in the buffer

◆ setup_conversion_functions()

static bool setup_conversion_functions ( Prepared_statement stmt,
PS_PARAM parameters 
)
static

◆ setup_one_conversion_function()

static bool setup_one_conversion_function ( THD thd,
Item_param param,
enum enum_field_types  param_type 
)
static

◆ swap_parameter_array()

static void swap_parameter_array ( Item_param **  param_array_dst,
Item_param **  param_array_src,
uint  param_count 
)
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.

Parameters
[out]param_array_dstparameter markers of the new statement
[in]param_array_srcparameter markers of the original statement
[in]param_counttotal number of parameters. Is the same in src and dst arrays, since the statement query is the same