summaryrefslogtreecommitdiff
path: root/sql/sql_class.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r--sql/sql_class.h783
1 files changed, 561 insertions, 222 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 4d14b42b065..1e4f0225397 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2016, MariaDB
+ Copyright (c) 2009, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
/* Classes in mysql */
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
+#include "dur_prop.h"
#include <waiting_threads.h>
#include "sql_const.h"
#include <mysql/plugin_audit.h>
@@ -36,6 +37,7 @@
#include "violite.h" /* vio_is_connected */
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA, THR_LOCK_INFO */
#include "thr_timer.h"
+#include "thr_malloc.h"
#include <my_tree.h>
#include "sql_digest_stream.h" // sql_digest_state
@@ -45,6 +47,7 @@
#include <mysql/psi/mysql_idle.h>
#include <mysql/psi/mysql_table.h>
#include <mysql_com_server.h>
+#include "session_tracker.h"
extern "C"
void set_thd_stage_info(void *thd,
@@ -151,7 +154,7 @@ extern MYSQL_PLUGIN_IMPORT const char **errmesg;
extern bool volatile shutdown_in_progress;
extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd);
-extern "C" char **thd_query(MYSQL_THD thd);
+extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
/**
@class CSET_STRING
@@ -177,11 +180,10 @@ public:
}
inline char *str() const { return string.str; }
- inline uint32 length() const { return string.length; }
+ inline size_t length() const { return string.length; }
CHARSET_INFO *charset() const { return cs; }
friend LEX_STRING * thd_query_string (MYSQL_THD thd);
- friend char **thd_query(MYSQL_THD thd);
};
@@ -226,6 +228,7 @@ typedef struct st_copy_info {
List<Item> *update_values;
/* for VIEW ... WITH CHECK OPTION */
TABLE_LIST *view;
+ TABLE_LIST *table_list; /* Normal table */
} COPY_INFO;
@@ -256,7 +259,7 @@ public:
class Alter_drop :public Sql_alloc {
public:
- enum drop_type {KEY, COLUMN, FOREIGN_KEY };
+ enum drop_type {KEY, COLUMN, FOREIGN_KEY, CHECK_CONSTRAINT };
const char *name;
enum drop_type type;
bool drop_if_exists;
@@ -271,15 +274,21 @@ public:
*/
Alter_drop *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Alter_drop(*this); }
+ const char *type_name()
+ {
+ return type == COLUMN ? "COLUMN" :
+ type == CHECK_CONSTRAINT ? "CONSTRAINT" :
+ type == KEY ? "INDEX" : "FOREIGN KEY";
+ }
};
class Alter_column :public Sql_alloc {
public:
const char *name;
- Item *def;
- Alter_column(const char *par_name,Item *literal)
- :name(par_name), def(literal) {}
+ Virtual_column_info *default_value;
+ Alter_column(const char *par_name, Virtual_column_info *expr)
+ :name(par_name), default_value(expr) {}
/**
Used to make a clone of this object for ALTER/CREATE TABLE
@sa comment for Key_part_spec::clone
@@ -469,16 +478,27 @@ enum killed_state
KILL_TIMEOUT= 8,
KILL_TIMEOUT_HARD= 9,
/*
+ When binlog reading thread connects to the server it kills
+ all the binlog threads with the same ID.
+ */
+ KILL_SLAVE_SAME_ID= 10,
+ /*
All of the following killed states will kill the connection
KILL_CONNECTION must be the first of these and it must start with
an even number (becasue of HARD bit)!
*/
- KILL_CONNECTION= 10,
- KILL_CONNECTION_HARD= 11,
- KILL_SYSTEM_THREAD= 12,
- KILL_SYSTEM_THREAD_HARD= 13,
- KILL_SERVER= 14,
- KILL_SERVER_HARD= 15
+ KILL_CONNECTION= 12,
+ KILL_CONNECTION_HARD= 13,
+ KILL_SYSTEM_THREAD= 14,
+ KILL_SYSTEM_THREAD_HARD= 15,
+ KILL_SERVER= 16,
+ KILL_SERVER_HARD= 17,
+ /*
+ Used in threadpool to signal wait timeout.
+ */
+ KILL_WAIT_TIMEOUT= 18,
+ KILL_WAIT_TIMEOUT_HARD= 19
+
};
#define killed_mask_hard(killed) ((killed_state) ((killed) & ~KILL_HARD_BIT))
@@ -501,8 +521,6 @@ class Time_zone;
#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)
-typedef ulonglong sql_mode_t;
-
typedef struct system_variables
{
/*
@@ -523,7 +541,8 @@ typedef struct system_variables
uint dynamic_variables_size; /* how many bytes are in use */
ulonglong max_heap_table_size;
- ulonglong tmp_table_size;
+ ulonglong tmp_memory_table_size;
+ ulonglong tmp_disk_table_size;
ulonglong long_query_time;
ulonglong max_statement_time;
ulonglong optimizer_switch;
@@ -561,11 +580,13 @@ typedef struct system_variables
*/
ulong saved_auto_increment_increment, saved_auto_increment_offset;
#endif /* WITH_WSREP */
+ uint eq_range_index_dive_limit;
ulong lock_wait_timeout;
ulong join_cache_level;
ulong max_allowed_packet;
ulong max_error_count;
ulong max_length_for_sort_data;
+ ulong max_recursive_iterations;
ulong max_sort_length;
ulong max_tmp_tables;
ulong max_insert_delayed_threads;
@@ -636,6 +657,7 @@ typedef struct system_variables
my_bool old_alter_table;
my_bool old_passwords;
my_bool big_tables;
+ my_bool only_standard_compliant_cte;
my_bool query_cache_strip_comments;
my_bool sql_log_slow;
my_bool sql_log_bin;
@@ -666,7 +688,7 @@ typedef struct system_variables
/* Error messages */
MY_LOCALE *lc_messages;
- const char **errmsgs; /* lc_messages->errmsg->errmsgs */
+ const char ***errmsgs; /* lc_messages->errmsg->errmsgs */
/* Locale Support */
MY_LOCALE *lc_time_names;
@@ -689,6 +711,12 @@ typedef struct system_variables
my_bool pseudo_slave_mode;
+ char *session_track_system_variables;
+ ulong session_track_transaction_info;
+ my_bool session_track_schema;
+ my_bool session_track_state_change;
+
+ ulong threadpool_priority;
} SV;
/**
@@ -703,6 +731,7 @@ typedef struct system_status_var
ulong com_create_tmp_table;
ulong com_drop_tmp_table;
ulong com_other;
+ ulong com_multi;
ulong com_stmt_prepare;
ulong com_stmt_reprepare;
@@ -779,6 +808,7 @@ typedef struct system_status_var
ulong feature_timezone; /* +1 when XPATH is used */
ulong feature_trigger; /* +1 opening a table with triggers */
ulong feature_xml; /* +1 when XPATH is used */
+ ulong feature_window_functions; /* +1 when window functions are used */
/* From MASTER_GTID_WAIT usage */
ulong master_gtid_wait_timeouts; /* Number of timeouts */
@@ -827,8 +857,7 @@ typedef struct system_status_var
Global status variables
*/
-extern ulong feature_files_opened_with_delayed_keys;
-
+extern ulong feature_files_opened_with_delayed_keys, feature_check_constraint;
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
@@ -1061,7 +1090,10 @@ public:
inline char *query() const { return query_string.str(); }
- inline uint32 query_length() const { return query_string.length(); }
+ inline uint32 query_length() const
+ {
+ return static_cast<uint32>(query_string.length());
+ }
CHARSET_INFO *query_charset() const { return query_string.charset(); }
void set_query_inner(const CSET_STRING &string_arg)
{
@@ -1234,7 +1266,8 @@ public:
priv_user - The user privilege we are using. May be "" for anonymous user.
ip - client IP
*/
- char *host, *user, *ip;
+ const char *host;
+ char *user, *ip;
char priv_user[USERNAME_LENGTH];
char proxy_user[USERNAME_LENGTH + MAX_HOSTNAME + 5];
/* The host privilege we are using */
@@ -1281,7 +1314,40 @@ public:
*/
struct Item_change_record;
-typedef I_List<Item_change_record> Item_change_list;
+class Item_change_list
+{
+ I_List<Item_change_record> change_list;
+public:
+ void nocheck_register_item_tree_change(Item **place, Item *old_value,
+ MEM_ROOT *runtime_memroot);
+ void check_and_register_item_tree_change(Item **place, Item **new_value,
+ MEM_ROOT *runtime_memroot);
+ void rollback_item_tree_changes();
+ void move_elements_to(Item_change_list *to)
+ {
+ change_list.move_elements_to(&to->change_list);
+ }
+ bool is_empty() { return change_list.is_empty(); }
+};
+
+
+class Item_change_list_savepoint: public Item_change_list
+{
+public:
+ Item_change_list_savepoint(Item_change_list *list)
+ {
+ list->move_elements_to(this);
+ }
+ void rollback(Item_change_list *list)
+ {
+ list->rollback_item_tree_changes();
+ move_elements_to(list);
+ }
+ ~Item_change_list_savepoint()
+ {
+ DBUG_ASSERT(is_empty());
+ }
+};
/**
@@ -1298,6 +1364,61 @@ enum enum_locked_tables_mode
LTM_always_last
};
+/**
+ The following structure is an extension to TABLE_SHARE and is
+ exclusively for temporary tables.
+
+ @note:
+ Although, TDC_element has data members (like next, prev &
+ all_tables) to store the list of TABLE_SHARE & TABLE objects
+ related to a particular TABLE_SHARE, they cannot be moved to
+ TABLE_SHARE in order to be reused for temporary tables. This
+ is because, as concurrent threads iterating through hash of
+ TDC_element's may need access to all_tables, but if all_tables
+ is made part of TABLE_SHARE, then TDC_element->share->all_tables
+ is not always guaranteed to be valid, as TDC_element can live
+ longer than TABLE_SHARE.
+*/
+struct TMP_TABLE_SHARE : public TABLE_SHARE
+{
+private:
+ /*
+ Link to all temporary table shares. Declared as private to
+ avoid direct manipulation with those objects. One should
+ use methods of I_P_List template instead.
+ */
+ TMP_TABLE_SHARE *tmp_next;
+ TMP_TABLE_SHARE **tmp_prev;
+
+ friend struct All_tmp_table_shares;
+
+public:
+ /*
+ Doubly-linked (back-linked) lists of used and unused TABLE objects
+ for this share.
+ */
+ All_share_tables_list all_tmp_tables;
+};
+
+/**
+ Helper class which specifies which members of TMP_TABLE_SHARE are
+ used for participation in the list of temporary tables.
+*/
+
+struct All_tmp_table_shares
+{
+ static inline TMP_TABLE_SHARE **next_ptr(TMP_TABLE_SHARE *l)
+ {
+ return &l->tmp_next;
+ }
+ static inline TMP_TABLE_SHARE ***prev_ptr(TMP_TABLE_SHARE *l)
+ {
+ return &l->tmp_prev;
+ }
+};
+
+/* Also used in rpl_rli.h. */
+typedef I_P_List <TMP_TABLE_SHARE, All_tmp_table_shares> All_tmp_tables_list;
/**
Class that holds information about tables which were opened and locked
@@ -1327,15 +1448,25 @@ public:
base tables that were opened with @see open_tables().
*/
TABLE *open_tables;
+
/**
- List of temporary tables used by this thread. Contains user-level
- temporary tables, created with CREATE TEMPORARY TABLE, and
- internal temporary tables, created, e.g., to resolve a SELECT,
+ A list of temporary tables used by this thread. This includes
+ user-level temporary tables, created with CREATE TEMPORARY TABLE,
+ and internal temporary tables, created, e.g., to resolve a SELECT,
or for an intermediate table used in ALTER.
- XXX Why are internal temporary tables added to this list?
*/
- TABLE *temporary_tables;
+ All_tmp_tables_list *temporary_tables;
+
+ /*
+ Derived tables.
+ */
TABLE *derived_tables;
+
+ /*
+ Temporary tables created for recursive table references.
+ */
+ TABLE *rec_tables;
+
/*
During a MySQL session, one can lock tables in two modes: automatic
or manual. In automatic mode all necessary tables are locked just before
@@ -1413,8 +1544,12 @@ public:
void reset_open_tables_state(THD *thd)
{
- open_tables= temporary_tables= derived_tables= 0;
- extra_lock= lock= 0;
+ open_tables= 0;
+ temporary_tables= 0;
+ derived_tables= 0;
+ rec_tables= 0;
+ extra_lock= 0;
+ lock= 0;
locked_tables_mode= LTM_NONE;
state_flags= 0U;
m_reprepare_observer= NULL;
@@ -1466,9 +1601,9 @@ public:
Discrete_intervals_list auto_inc_intervals_forced;
ulonglong limit_found_rows;
ha_rows cuted_fields, sent_row_count, examined_row_count;
- ulong client_capabilities;
+ ulonglong client_capabilities;
ulong query_plan_flags;
- uint in_sub_stmt;
+ uint in_sub_stmt; /* 0, SUB_STMT_TRIGGER or SUB_STMT_FUNCTION */
bool enable_slow_log;
bool last_insert_id_used;
SAVEPOINT *savepoints;
@@ -1486,8 +1621,8 @@ enum enum_thread_type
SYSTEM_THREAD_EVENT_SCHEDULER= 8,
SYSTEM_THREAD_EVENT_WORKER= 16,
SYSTEM_THREAD_BINLOG_BACKGROUND= 32,
- SYSTEM_THREAD_SLAVE_INIT= 64,
- SYSTEM_THREAD_SLAVE_BACKGROUND= 128
+ SYSTEM_THREAD_SLAVE_BACKGROUND= 64,
+ SYSTEM_THREAD_GENERIC= 128
};
inline char const *
@@ -1502,7 +1637,7 @@ show_system_thread(enum_thread_type thread)
RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_SQL);
RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_SCHEDULER);
RETURN_NAME_AS_STRING(SYSTEM_THREAD_EVENT_WORKER);
- RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_INIT);
+ RETURN_NAME_AS_STRING(SYSTEM_THREAD_SLAVE_BACKGROUND);
default:
sprintf(buf, "<UNKNOWN SYSTEM THREAD: %d>", thread);
return buf;
@@ -1515,6 +1650,7 @@ show_system_thread(enum_thread_type thread)
Internal error handlers are exception handlers used by the server
implementation.
*/
+
class Internal_error_handler
{
protected:
@@ -1552,7 +1688,7 @@ public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ Sql_condition::enum_warning_level *level,
const char* msg,
Sql_condition ** cond_hdl) = 0;
@@ -1573,7 +1709,7 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ Sql_condition::enum_warning_level *level,
const char* msg,
Sql_condition ** cond_hdl)
{
@@ -1595,11 +1731,11 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ Sql_condition::enum_warning_level *level,
const char* msg,
Sql_condition ** cond_hdl)
{
- if (level == Sql_condition::WARN_LEVEL_ERROR)
+ if (*level == Sql_condition::WARN_LEVEL_ERROR)
errors++;
return false;
}
@@ -1623,7 +1759,7 @@ public:
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ Sql_condition::enum_warning_level *level,
const char* msg,
Sql_condition ** cond_hdl);
@@ -1632,6 +1768,30 @@ private:
/**
+ Internal error handler to process an error from MDL_context::upgrade_lock()
+ and mysql_lock_tables(). Used by implementations of HANDLER READ and
+ LOCK TABLES LOCAL.
+*/
+
+class MDL_deadlock_and_lock_abort_error_handler: public Internal_error_handler
+{
+public:
+ virtual
+ bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char *sqlstate,
+ Sql_condition::enum_warning_level *level,
+ const char* msg,
+ Sql_condition **cond_hdl);
+
+ bool need_reopen() const { return m_need_reopen; };
+ void init() { m_need_reopen= FALSE; };
+private:
+ bool m_need_reopen;
+};
+
+
+/**
Tables that were locked with LOCK TABLES statement.
Encapsulates a list of TABLE_LIST instances for tables
@@ -1663,20 +1823,23 @@ private:
TABLE_LIST *m_locked_tables;
TABLE_LIST **m_locked_tables_last;
/** An auxiliary array used only in reopen_tables(). */
- TABLE **m_reopen_array;
+ TABLE_LIST **m_reopen_array;
/**
Count the number of tables in m_locked_tables list. We can't
rely on thd->lock->table_count because it excludes
non-transactional temporary tables. We need to know
an exact number of TABLE objects.
*/
- size_t m_locked_tables_count;
+ uint m_locked_tables_count;
public:
+ bool some_table_marked_for_reopen;
+
Locked_tables_list()
:m_locked_tables(NULL),
m_locked_tables_last(&m_locked_tables),
m_reopen_array(NULL),
- m_locked_tables_count(0)
+ m_locked_tables_count(0),
+ some_table_marked_for_reopen(0)
{
init_sql_alloc(&m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0,
MYF(MY_THREAD_SPECIFIC));
@@ -1699,6 +1862,7 @@ public:
bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table,
MYSQL_LOCK *lock);
void add_back_last_deleted_lock(TABLE_LIST *dst_table_list);
+ void mark_table_for_reopen(THD *thd, TABLE *table);
};
@@ -1952,6 +2116,14 @@ void dbug_serve_apcs(THD *thd, int n_calls);
*/
class THD :public Statement,
+ /*
+ This is to track items changed during execution of a prepared
+ statement/stored procedure. It's created by
+ nocheck_register_item_tree_change() in memory root of THD,
+ and freed in rollback_item_tree_changes().
+ For conventional execution it's always empty.
+ */
+ public Item_change_list,
public MDL_context_owner,
public Open_tables_state
{
@@ -1968,6 +2140,19 @@ private:
inline bool is_conventional() const
{ DBUG_ASSERT(0); return Statement::is_conventional(); }
+ void dec_thread_count(void)
+ {
+ DBUG_ASSERT(thread_count > 0);
+ thread_safe_decrement32(&thread_count);
+ signal_thd_deleted();
+ }
+
+
+ void inc_thread_count(void)
+ {
+ thread_safe_increment32(&thread_count);
+ }
+
public:
MDL_context mdl_context;
@@ -2043,6 +2228,13 @@ public:
/* all prepared statements and cursors of this connection */
Statement_map stmt_map;
+
+ /* Last created prepared statement */
+ Statement *last_stmt;
+ inline void set_last_stmt(Statement *stmt)
+ { last_stmt= (is_error() ? NULL : stmt); }
+ inline void clear_last_stmt() { last_stmt= NULL; }
+
/*
A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
@@ -2125,7 +2317,7 @@ public:
/* Needed by MariaDB semi sync replication */
Trans_binlog_info *semisync_info;
- ulong client_capabilities; /* What the client supports */
+ ulonglong client_capabilities; /* What the client supports */
ulong max_client_packet_length;
HASH handler_tables_hash;
@@ -2139,6 +2331,9 @@ public:
uint dbug_sentry; // watch out for memory corruption
#endif
struct st_my_thread_var *mysys_var;
+
+ /* Original charset number from the first client packet, or COM_CHANGE_USER*/
+ CHARSET_INFO *org_charset;
private:
/*
Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from
@@ -2167,7 +2362,7 @@ public:
bool report_to_client;
/*
true, if we will send progress report packets to a client
- (client has requested them, see CLIENT_PROGRESS; report_to_client
+ (client has requested them, see MARIADB_CLIENT_PROGRESS; report_to_client
is true; not in sub-statement)
*/
bool report;
@@ -2402,14 +2597,6 @@ public:
#ifdef SIGNAL_WITH_VIO_CLOSE
Vio* active_vio;
#endif
- /*
- This is to track items changed during execution of a prepared
- statement/stored procedure. It's created by
- nocheck_register_item_tree_change() in memory root of THD, and freed in
- rollback_item_tree_changes(). For conventional execution it's always
- empty.
- */
- Item_change_list change_list;
/*
A permanent memory area of the statement. For conventional
@@ -2425,6 +2612,8 @@ public:
*/
Query_arena *stmt_arena;
+ void *bulk_param;
+
/*
map for tables that will be updated for a multi-table update query
statement, for other query statements, this will be zero.
@@ -2721,7 +2910,7 @@ public:
ulong query_plan_flags;
ulong query_plan_fsort_passes;
pthread_t real_id; /* For debugging */
- my_thread_id thread_id;
+ my_thread_id thread_id, thread_dbug_id;
uint32 os_thread_id;
uint tmp_table, global_disable_checkpoint;
uint server_status,open_options;
@@ -2842,7 +3031,7 @@ public:
/* for IS NULL => = last_insert_id() fix in remove_eq_conds() */
bool substitute_null_with_insert_id;
bool in_lock_tables;
- bool bootstrap, cleanup_done;
+ bool bootstrap, cleanup_done, free_connection_done;
/** is set if some thread specific value(s) used in a statement. */
bool thread_specific_used;
@@ -2986,7 +3175,7 @@ public:
/* Debug Sync facility. See debug_sync.cc. */
struct st_debug_sync_control *debug_sync_control;
#endif /* defined(ENABLED_DEBUG_SYNC) */
- THD(bool is_wsrep_applier= false);
+ THD(my_thread_id id, bool is_wsrep_applier= false);
~THD();
@@ -3006,6 +3195,8 @@ public:
void change_user(void);
void cleanup(void);
void cleanup_after_query();
+ void free_connection();
+ void reset_for_reuse();
bool store_globals();
void reset_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -3013,7 +3204,6 @@ public:
{
mysql_mutex_lock(&LOCK_thd_data);
active_vio = vio;
- vio_set_thread_id(vio, pthread_self());
mysql_mutex_unlock(&LOCK_thd_data);
}
inline void clear_active_vio()
@@ -3178,6 +3368,12 @@ public:
}
ulonglong current_utime() { return microsecond_interval_timer(); }
+ /* Tell SHOW PROCESSLIST to show time from this point */
+ inline void set_time_for_next_stage()
+ {
+ utime_after_query= current_utime();
+ }
+
/**
Update server status after execution of a top level statement.
Currently only checks if a query was slow, and assigns
@@ -3187,7 +3383,7 @@ public:
*/
void update_server_status()
{
- utime_after_query= current_utime();
+ set_time_for_next_stage();
if (utime_after_query > utime_after_lock + variables.long_query_time)
server_status|= SERVER_QUERY_WAS_SLOW;
}
@@ -3406,6 +3602,12 @@ public:
To raise this flag, use my_error().
*/
inline bool is_error() const { return m_stmt_da->is_error(); }
+ void set_bulk_execution(void *bulk)
+ {
+ bulk_param= bulk;
+ m_stmt_da->set_bulk_execution(MY_TEST(bulk));
+ }
+ bool is_bulk_op() const { return MY_TEST(bulk_param); }
/// Returns Diagnostics-area for the current statement.
Diagnostics_area *get_stmt_da() const
@@ -3417,6 +3619,22 @@ public:
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
+ void update_charset(CHARSET_INFO *character_set_client,
+ CHARSET_INFO *collation_connection)
+ {
+ variables.character_set_client= character_set_client;
+ variables.collation_connection= collation_connection;
+ update_charset();
+ }
+ void update_charset(CHARSET_INFO *character_set_client,
+ CHARSET_INFO *collation_connection,
+ CHARSET_INFO *character_set_results)
+ {
+ variables.character_set_client= character_set_client;
+ variables.collation_connection= collation_connection;
+ variables.character_set_results= character_set_results;
+ update_charset();
+ }
inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup)
{
@@ -3463,11 +3681,6 @@ public:
*/
memcpy((char*) place, new_value, sizeof(*new_value));
}
- void nocheck_register_item_tree_change(Item **place, Item *old_value,
- MEM_ROOT *runtime_memroot);
- void check_and_register_item_tree_change(Item **place, Item **new_value,
- MEM_ROOT *runtime_memroot);
- void rollback_item_tree_changes();
/*
Cleanup statement parse state (parse tree, lex) and execution
@@ -3512,7 +3725,8 @@ public:
The worst things that can happen is that we get
a suboptimal error message.
*/
- if ((killed_err= (err_info*) alloc(sizeof(*killed_err))))
+ killed_err= (err_info*) alloc_root(&main_mem_root, sizeof(*killed_err));
+ if (killed_err)
{
killed_err->no= killed_errno_arg;
::strmake((char*) killed_err->msg, killed_err_msg_arg,
@@ -3664,13 +3878,13 @@ public:
*/
DBUG_PRINT("debug",
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
- YESNO(temporary_tables), YESNO(in_sub_stmt),
+ YESNO(has_thd_temporary_tables()), YESNO(in_sub_stmt),
show_system_thread(system_thread)));
if (in_sub_stmt == 0)
{
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
set_current_stmt_binlog_format_row();
- else if (temporary_tables == NULL)
+ else if (!has_thd_temporary_tables())
set_current_stmt_binlog_format_stmt();
}
DBUG_VOID_RETURN;
@@ -3721,7 +3935,7 @@ public:
mysql_mutex_unlock(&LOCK_thd_data);
#ifdef HAVE_PSI_THREAD_INTERFACE
if (result)
- PSI_THREAD_CALL(set_thread_db)(new_db, new_db_len);
+ PSI_THREAD_CALL(set_thread_db)(new_db, (int) new_db_len);
#endif
return result;
}
@@ -3746,7 +3960,7 @@ public:
db_length= new_db_len;
mysql_mutex_unlock(&LOCK_thd_data);
#ifdef HAVE_PSI_THREAD_INTERFACE
- PSI_THREAD_CALL(set_thread_db)(new_db, new_db_len);
+ PSI_THREAD_CALL(set_thread_db)(new_db, (int) new_db_len);
#endif
}
}
@@ -3759,11 +3973,28 @@ public:
{
if (db == NULL)
{
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- return TRUE;
+ /*
+ No default database is set. In this case if it's guaranteed that
+ no CTE can be used in the statement then we can throw an error right
+ now at the parser stage. Otherwise the decision about throwing such
+ a message must be postponed until a post-parser stage when we are able
+ to resolve all CTE names as we don't need this message to be thrown
+ for any CTE references.
+ */
+ if (!lex->with_clauses_list)
+ {
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ return TRUE;
+ }
+ /* This will allow to throw an error later for non-CTE references */
+ *p_db= NULL;
+ *p_db_length= 0;
+ }
+ else
+ {
+ *p_db= strmake(db, db_length);
+ *p_db_length= db_length;
}
- *p_db= strmake(db, db_length);
- *p_db_length= db_length;
return FALSE;
}
thd_scheduler event_scheduler;
@@ -3790,7 +4021,7 @@ private:
*/
bool handle_condition(uint sql_errno,
const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ Sql_condition::enum_warning_level *level,
const char* msg,
Sql_condition ** cond_hdl);
@@ -4062,11 +4293,10 @@ private:
LEX_STRING invoker_user;
LEX_STRING invoker_host;
- /* Protect against add/delete of temporary tables in parallel replication */
- void rgi_lock_temporary_tables();
- void rgi_unlock_temporary_tables(bool clear);
- bool rgi_have_temporary_tables();
public:
+#ifndef EMBEDDED_LIBRARY
+ Session_tracker session_tracker;
+#endif //EMBEDDED_LIBRARY
/*
Flag, mutex and condition for a thread to wait for a signal from another
thread.
@@ -4081,28 +4311,98 @@ public:
The GTID assigned to the last commit. If no GTID was assigned to any commit
so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
- rpl_gtid last_commit_gtid;
+private:
+ rpl_gtid m_last_commit_gtid;
+
+public:
+ rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; }
+ void set_last_commit_gtid(rpl_gtid &gtid);
- inline void lock_temporary_tables()
- {
- if (rgi_slave)
- rgi_lock_temporary_tables();
- }
- inline void unlock_temporary_tables(bool clear)
- {
- if (rgi_slave)
- rgi_unlock_temporary_tables(clear);
- }
- inline bool have_temporary_tables()
- {
- return (temporary_tables ||
- (rgi_slave && unlikely(rgi_have_temporary_tables())));
- }
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
bool fix_xid_hash_pins();
+/* Members related to temporary tables. */
+public:
+ /* Opened table states. */
+ enum Temporary_table_state {
+ TMP_TABLE_IN_USE,
+ TMP_TABLE_NOT_IN_USE,
+ TMP_TABLE_ANY
+ };
+ bool has_thd_temporary_tables();
+
+ TABLE *create_and_open_tmp_table(handlerton *hton,
+ LEX_CUSTRING *frm,
+ const char *path,
+ const char *db,
+ const char *table_name,
+ bool open_in_engine);
+
+ TABLE *find_temporary_table(const char *db, const char *table_name,
+ Temporary_table_state state= TMP_TABLE_IN_USE);
+ TABLE *find_temporary_table(const TABLE_LIST *tl,
+ Temporary_table_state state= TMP_TABLE_IN_USE);
+
+ TMP_TABLE_SHARE *find_tmp_table_share_w_base_key(const char *key,
+ uint key_length);
+ TMP_TABLE_SHARE *find_tmp_table_share(const char *db,
+ const char *table_name);
+ TMP_TABLE_SHARE *find_tmp_table_share(const TABLE_LIST *tl);
+ TMP_TABLE_SHARE *find_tmp_table_share(const char *key, uint key_length);
+
+ bool open_temporary_table(TABLE_LIST *tl);
+ bool open_temporary_tables(TABLE_LIST *tl);
+
+ bool close_temporary_tables();
+ bool rename_temporary_table(TABLE *table, const char *db,
+ const char *table_name);
+ bool drop_temporary_table(TABLE *table, bool *is_trans, bool delete_table);
+ bool rm_temporary_table(handlerton *hton, const char *path);
+ void mark_tmp_tables_as_free_for_reuse();
+ void mark_tmp_table_as_free_for_reuse(TABLE *table);
+
+ TMP_TABLE_SHARE* save_tmp_table_share(TABLE *table);
+ void restore_tmp_table_share(TMP_TABLE_SHARE *share);
+ void close_unused_temporary_table_instances(const TABLE_LIST *tl);
+
+private:
+ /* Whether a lock has been acquired? */
+ bool m_tmp_tables_locked;
+
+ bool has_temporary_tables();
+ uint create_tmp_table_def_key(char *key, const char *db,
+ const char *table_name);
+ TMP_TABLE_SHARE *create_temporary_table(handlerton *hton, LEX_CUSTRING *frm,
+ const char *path, const char *db,
+ const char *table_name);
+ TABLE *find_temporary_table(const char *key, uint key_length,
+ Temporary_table_state state);
+ TABLE *open_temporary_table(TMP_TABLE_SHARE *share, const char *alias,
+ bool open_in_engine);
+ bool find_and_use_tmp_table(const TABLE_LIST *tl, TABLE **out_table);
+ bool use_temporary_table(TABLE *table, TABLE **out_table);
+ void close_temporary_table(TABLE *table);
+ bool log_events_and_free_tmp_shares();
+ void free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table);
+ void free_temporary_table(TABLE *table);
+ bool lock_temporary_tables();
+ void unlock_temporary_tables();
+
+ inline uint tmpkeyval(TMP_TABLE_SHARE *share)
+ {
+ return uint4korr(share->table_cache_key.str +
+ share->table_cache_key.length - 4);
+ }
+
+ inline TMP_TABLE_SHARE *tmp_table_share(TABLE *table)
+ {
+ DBUG_ASSERT(table->s->tmp_table);
+ return static_cast<TMP_TABLE_SHARE *>(table->s);
+ }
+
+public:
inline ulong wsrep_binlog_format() const
{
return WSREP_FORMAT(variables.binlog_format);
@@ -4151,6 +4451,14 @@ public:
ulong wsrep_affected_rows;
bool wsrep_replicate_GTID;
bool wsrep_skip_wsrep_GTID;
+ /* This flag is set when innodb do an intermediate commit to
+ processing the LOAD DATA INFILE statement by splitting it into 10K
+ rows chunks. If flag is set, then binlog rotation is not performed
+ while intermediate transaction try to commit, because in this case
+ rotation causes unregistration of innodb handler. Later innodb handler
+ registered again, but replication of last chunk of rows is skipped
+ by the innodb engine: */
+ bool wsrep_split_flag;
#endif /* WITH_WSREP */
/* Handling of timeouts for commands */
@@ -4196,8 +4504,40 @@ public:
(THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE |
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL));
}
+ /*
+ Reset current_linfo
+ Setting current_linfo to 0 needs to be done with LOCK_thread_count to
+ ensure that adjust_linfo_offsets doesn't use a structure that may
+ be deleted.
+ */
+ inline void reset_current_linfo()
+ {
+ mysql_mutex_lock(&LOCK_thread_count);
+ current_linfo= 0;
+ mysql_mutex_unlock(&LOCK_thread_count);
+ }
};
+inline void add_to_active_threads(THD *thd)
+{
+ mysql_mutex_lock(&LOCK_thread_count);
+ threads.append(thd);
+ mysql_mutex_unlock(&LOCK_thread_count);
+}
+
+/*
+ This should be called when you want to delete a thd that was not
+ running any queries.
+ This function will assert that the THD is linked.
+*/
+
+inline void unlink_not_visible_thd(THD *thd)
+{
+ thd->assert_linked();
+ mysql_mutex_lock(&LOCK_thread_count);
+ thd->unlink();
+ mysql_mutex_unlock(&LOCK_thread_count);
+}
/** A short cut for thd->get_stmt_da()->set_ok_status(). */
@@ -4217,6 +4557,8 @@ my_eof(THD *thd)
{
thd->set_row_count_func(-1);
thd->get_stmt_da()->set_eof_status(thd);
+
+ TRANSACT_TRACKER(add_trx_state(thd, TX_RESULT_SET));
}
#define tmp_disable_binlog(A) \
@@ -4296,12 +4638,13 @@ protected:
/*
All descendant classes have their send_data() skip the first
unit->offset_limit_cnt rows sent. Select_materialize
- also uses unit->get_unit_column_types().
+ also uses unit->get_column_types().
*/
SELECT_LEX_UNIT *unit;
/* Something used only by the parser: */
public:
select_result(THD *thd_arg): select_result_sink(thd_arg) {}
+ void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
virtual ~select_result() {};
/**
Change wrapped select_result.
@@ -4358,6 +4701,9 @@ public:
#endif
virtual void update_used_tables() {}
+ /* this method is called just before the first row of the table can be read */
+ virtual void prepare_to_read_rows() {}
+
void reset_offset_limit()
{
unit->offset_limit_cnt= 0;
@@ -4589,6 +4935,7 @@ class select_create: public select_insert {
/* m_lock or thd->extra_lock */
MYSQL_LOCK **m_plock;
bool exit_done;
+ TMP_TABLE_SHARE *saved_tmp_table_share;
public:
select_create(THD *thd_arg, TABLE_LIST *table_arg,
@@ -4596,12 +4943,14 @@ public:
Alter_info *alter_info_arg,
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
TABLE_LIST *select_tables_arg):
- select_insert(thd_arg, NULL, NULL, &select_fields, 0, 0, duplic, ignore),
+ select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic,
+ ignore),
create_table(table_arg),
create_info(create_info_par),
select_tables(select_tables_arg),
alter_info(alter_info_arg),
- m_plock(NULL), exit_done(0)
+ m_plock(NULL), exit_done(0),
+ saved_tmp_table_share(0)
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
@@ -4647,16 +4996,9 @@ inline uint tmp_table_max_key_parts() { return MI_MAX_KEY_SEG; }
class TMP_TABLE_PARAM :public Sql_alloc
{
-private:
- /* Prevent use of these (not safe because of lists and copy_field) */
- TMP_TABLE_PARAM(const TMP_TABLE_PARAM &);
- void operator=(TMP_TABLE_PARAM &);
-
public:
List<Item> copy_funcs;
- List<Item> save_copy_funcs;
Copy_field *copy_field, *copy_field_end;
- Copy_field *save_copy_field, *save_copy_field_end;
uchar *group_buff;
Item **items_to_copy; /* Fields in tmp table */
TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo;
@@ -4691,7 +5033,13 @@ public:
uint hidden_field_count;
uint group_parts,group_length,group_null_parts;
uint quick_group;
- bool using_indirect_summary_function;
+ /**
+ Enabled when we have atleast one outer_sum_func. Needed when used
+ along with distinct.
+
+ @see create_tmp_table
+ */
+ bool using_outer_summary_function;
CHARSET_INFO *table_charset;
bool schema_table;
/* TRUE if the temp table is created for subquery materialization. */
@@ -4721,9 +5069,10 @@ public:
TMP_TABLE_PARAM()
:copy_field(0), group_parts(0),
group_length(0), group_null_parts(0),
- schema_table(0), materialized_subquery(0), force_not_null_cols(0),
- precomputed_group_by(0),
- force_copy_fields(0), bit_fields_as_long(0), skip_create_table(0)
+ using_outer_summary_function(0),
+ schema_table(0), materialized_subquery(0), force_not_null_cols(0),
+ precomputed_group_by(0),
+ force_copy_fields(0), bit_fields_as_long(0), skip_create_table(0)
{}
~TMP_TABLE_PARAM()
{
@@ -4735,17 +5084,13 @@ public:
if (copy_field) /* Fix for Intel compiler */
{
delete [] copy_field;
- save_copy_field= copy_field= NULL;
- save_copy_field_end= copy_field_end= NULL;
+ copy_field= NULL;
+ copy_field_end= NULL;
}
}
- void free_copy_field_data()
- {
- for (Copy_field *ptr= copy_field ; ptr != copy_field_end ; ptr++)
- ptr->tmp.free();
- }
};
+
class select_union :public select_result_interceptor
{
public:
@@ -4783,6 +5128,36 @@ public:
};
+class select_union_recursive :public select_union
+{
+ public:
+ /* The temporary table with the new records generated by one iterative step */
+ TABLE *incr_table;
+ /* One of tables from the list rec_tables (determined dynamically) */
+ TABLE *first_rec_table_to_update;
+ /* The temporary tables used for recursive table references */
+ List<TABLE> rec_tables;
+ /*
+ The count of how many times cleanup() was called with cleaned==false
+ for the unit specifying the recursive CTE for which this object was created
+ or for the unit specifying a CTE that mutually recursive with this CTE.
+ */
+ uint cleanup_count;
+
+ select_union_recursive(THD *thd_arg):
+ select_union(thd_arg),
+ incr_table(0), first_rec_table_to_update(0), cleanup_count(0) {};
+
+ int send_data(List<Item> &items);
+ bool create_result_table(THD *thd, List<Item> *column_types,
+ bool is_distinct, ulonglong options,
+ const char *alias,
+ bool bit_fields_as_long,
+ bool create_table,
+ bool keep_row_order= FALSE);
+ void cleanup();
+};
+
/**
UNION result that is passed directly to the receiving select_result
without filling a temporary table.
@@ -5059,16 +5434,19 @@ public:
/* Structs used when sorting */
+struct SORT_FIELD_ATTR
+{
+ uint length; /* Length of sort field */
+ uint suffix_length; /* Length suffix (0-4) */
+};
+
-typedef struct st_sort_field {
+struct SORT_FIELD: public SORT_FIELD_ATTR
+{
Field *field; /* Field to sort */
Item *item; /* Item if not sorting fields */
- uint length; /* Length of sort field */
- uint suffix_length; /* Length suffix (0-4) */
- Item_result result_type; /* Type of item */
bool reverse; /* if descending sort */
- bool need_strxnfrm; /* If we have to use strxnfrm() */
-} SORT_FIELD;
+};
typedef struct st_sort_buffer {
@@ -5146,94 +5524,7 @@ class user_var_entry
user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
bool create_if_not_exists);
-/*
- Unique -- class for unique (removing of duplicates).
- Puts all values to the TREE. If the tree becomes too big,
- it's dumped to the file. User can request sorted values, or
- just iterate through them. In the last case tree merging is performed in
- memory simultaneously with iteration, so it should be ~2-3x faster.
- */
-
-class Unique :public Sql_alloc
-{
- DYNAMIC_ARRAY file_ptrs;
- ulong max_elements; /* Total number of elements that will be stored in-memory */
- ulonglong max_in_memory_size;
- IO_CACHE file;
- TREE tree;
- uchar *record_pointers;
- /* Number of elements filtered out due to min_dupl_count when storing results
- to table. See Unique::get */
- ulong filtered_out_elems;
- bool flush();
- uint size;
- uint full_size; /* Size of element + space needed to store the number of
- duplicates found for the element. */
- uint min_dupl_count; /* Minimum number of occurences of element required for
- it to be written to record_pointers.
- always 0 for unions, > 0 for intersections */
- bool with_counters;
-
- bool merge(TABLE *table, uchar *buff, bool without_last_merge);
-
-public:
- ulong elements;
- Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
- uint size_arg, ulonglong max_in_memory_size_arg,
- uint min_dupl_count_arg= 0);
- ~Unique();
- ulong elements_in_tree() { return tree.elements_in_tree; }
- inline bool unique_add(void *ptr)
- {
- DBUG_ENTER("unique_add");
- DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements));
- if (!(tree.flag & TREE_ONLY_DUPS) &&
- tree.elements_in_tree >= max_elements && flush())
- DBUG_RETURN(1);
- DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg));
- }
-
- bool is_in_memory() { return (my_b_tell(&file) == 0); }
- void close_for_expansion() { tree.flag= TREE_ONLY_DUPS; }
-
- bool get(TABLE *table);
-
- /* Cost of searching for an element in the tree */
- inline static double get_search_cost(ulonglong tree_elems, uint compare_factor)
- {
- return log((double) tree_elems) / (compare_factor * M_LN2);
- }
-
- static double get_use_cost(uint *buffer, size_t nkeys, uint key_size,
- ulonglong max_in_memory_size, uint compare_factor,
- bool intersect_fl, bool *in_memory);
- inline static int get_cost_calc_buff_size(size_t nkeys, uint key_size,
- ulonglong max_in_memory_size)
- {
- ulonglong max_elems_in_tree=
- max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size);
-
- if (max_elems_in_tree == 0)
- max_elems_in_tree= 1;
- return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree));
- }
-
- void reset();
- bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg);
-
- uint get_size() const { return size; }
- ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
-
- friend int unique_write_to_file(uchar* key, element_count count, Unique *unique);
- friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique);
-
- friend int unique_write_to_file_with_count(uchar* key, element_count count,
- Unique *unique);
- friend int unique_intersect_write_to_ptrs(uchar* key, element_count count,
- Unique *unique);
-};
-
-
+class SORT_INFO;
class multi_delete :public select_result_interceptor
{
TABLE_LIST *delete_tables, *table_being_deleted;
@@ -5260,13 +5551,11 @@ public:
int send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
int do_deletes();
- int do_table_deletes(TABLE *table, bool ignore);
+ int do_table_deletes(TABLE *table, SORT_INFO *sort_info, bool ignore);
bool send_eof();
- inline ha_rows num_deleted()
- {
- return deleted;
- }
+ inline ha_rows num_deleted() const { return deleted; }
virtual void abort_result_set();
+ void prepare_to_read_rows();
};
@@ -5310,16 +5599,11 @@ public:
bool initialize_tables (JOIN *join);
int do_updates();
bool send_eof();
- inline ha_rows num_found()
- {
- return found;
- }
- inline ha_rows num_updated()
- {
- return updated;
- }
+ inline ha_rows num_found() const { return found; }
+ inline ha_rows num_updated() const { return updated; }
virtual void abort_result_set();
void update_used_tables();
+ void prepare_to_read_rows();
};
class my_var : public Sql_alloc {
@@ -5484,6 +5768,15 @@ public:
*/
#define CF_ADMIN_COMMAND (1U << 19)
+/**
+ SP Bulk execution safe
+*/
+#define CF_SP_BULK_SAFE (1U << 20)
+/**
+ SP Bulk execution optimized
+*/
+#define CF_SP_BULK_OPTIMIZED (1U << 21)
+
/* Bits in server_command_flags */
/**
@@ -5500,11 +5793,19 @@ public:
sent by the user (ie: stored procedure).
*/
#define CF_SKIP_QUESTIONS (1U << 1)
-
+#ifdef WITH_WSREP
/**
Do not check that wsrep snapshot is ready before allowing this command
*/
#define CF_SKIP_WSREP_CHECK (1U << 2)
+#else
+#define CF_SKIP_WSREP_CHECK 0
+#endif /* WITH_WSREP */
+
+/**
+ Do not allow it for COM_MULTI batch
+*/
+#define CF_NO_COM_MULTI (1U << 3)
/* Inline functions */
@@ -5649,6 +5950,44 @@ void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage,
#define THD_EXIT_COND(P1, P2) \
thd_exit_cond(P1, P2, __func__, __FILE__, __LINE__)
+inline bool binlog_should_compress(ulong len)
+{
+ return opt_bin_log_compress &&
+ len >= opt_bin_log_compress_min_len;
+}
+
+
+/**
+ Save thd sql_mode on instantiation.
+ On destruction it resets the mode to the previously stored value.
+*/
+class Sql_mode_save
+{
+ public:
+ Sql_mode_save(THD *thd) : thd(thd), old_mode(thd->variables.sql_mode) {}
+ ~Sql_mode_save() { thd->variables.sql_mode = old_mode; }
+
+ private:
+ THD *thd;
+ sql_mode_t old_mode; // SQL mode saved at construction time.
+};
+
+class Switch_to_definer_security_ctx
+{
+ public:
+ Switch_to_definer_security_ctx(THD *thd, TABLE_LIST *table) :
+ m_thd(thd), m_sctx(thd->security_ctx)
+ {
+ if (table->security_ctx)
+ thd->security_ctx= table->security_ctx;
+ }
+ ~Switch_to_definer_security_ctx() { m_thd->security_ctx = m_sctx; }
+
+ private:
+ THD *m_thd;
+ Security_context *m_sctx;
+};
+
#endif /* MYSQL_SERVER */
#endif /* SQL_CLASS_INCLUDED */