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.h706
1 files changed, 549 insertions, 157 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7570211f586..7aac98eccb2 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -75,14 +75,15 @@ void set_thd_stage_info(void *thd,
#include "wsrep_condition_variable.h"
class Wsrep_applier_service;
-
#endif /* WITH_WSREP */
+
class Reprepare_observer;
class Relay_log_info;
struct rpl_group_info;
class Rpl_filter;
class Query_log_event;
class Load_log_event;
+class Log_event_writer;
class sp_rcontext;
class sp_cache;
class Lex_input_stream;
@@ -106,7 +107,8 @@ enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
SLAVE_EXEC_MODE_LAST_BIT };
enum enum_slave_run_triggers_for_rbr { SLAVE_RUN_TRIGGERS_FOR_RBR_NO,
SLAVE_RUN_TRIGGERS_FOR_RBR_YES,
- SLAVE_RUN_TRIGGERS_FOR_RBR_LOGGING};
+ SLAVE_RUN_TRIGGERS_FOR_RBR_LOGGING,
+ SLAVE_RUN_TRIGGERS_FOR_RBR_ENFORCE};
enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY,
SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY};
@@ -193,7 +195,16 @@ extern char empty_c_string[1];
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd);
+extern "C" unsigned long long thd_query_id(const MYSQL_THD thd);
extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
+extern "C" const char *thd_priv_user(MYSQL_THD thd, size_t *length);
+extern "C" const char *thd_priv_host(MYSQL_THD thd, size_t *length);
+extern "C" const char *thd_user_name(MYSQL_THD thd);
+extern "C" const char *thd_client_host(MYSQL_THD thd);
+extern "C" const char *thd_client_ip(MYSQL_THD thd);
+extern "C" LEX_CSTRING *thd_current_db(MYSQL_THD thd);
+extern "C" int thd_current_status(MYSQL_THD thd);
+extern "C" enum enum_server_command thd_current_command(MYSQL_THD thd);
/**
@class CSET_STRING
@@ -291,6 +302,17 @@ public:
*/
Key_part_spec *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Key_part_spec(*this); }
+ bool check_key_for_blob(const class handler *file) const;
+ bool check_key_length_for_blob() const;
+ bool check_primary_key_for_blob(const class handler *file) const
+ {
+ return check_key_for_blob(file) || check_key_length_for_blob();
+ }
+ bool check_foreign_key_for_blob(const class handler *file) const
+ {
+ return check_key_for_blob(file) || check_key_length_for_blob();
+ }
+ bool init_multiple_key_for_blob(const class handler *file);
};
@@ -323,17 +345,41 @@ public:
class Alter_column :public Sql_alloc {
public:
- const char *name;
+ LEX_CSTRING name;
+ LEX_CSTRING new_name;
Virtual_column_info *default_value;
bool alter_if_exists;
- Alter_column(const char *par_name, Virtual_column_info *expr, bool par_exists)
- :name(par_name), default_value(expr), alter_if_exists(par_exists) {}
+ Alter_column(LEX_CSTRING par_name, Virtual_column_info *expr, bool par_exists)
+ :name(par_name), new_name{NULL, 0}, default_value(expr), alter_if_exists(par_exists) {}
+ Alter_column(LEX_CSTRING par_name, LEX_CSTRING _new_name, bool exists)
+ :name(par_name), new_name(_new_name), default_value(NULL), alter_if_exists(exists) {}
/**
Used to make a clone of this object for ALTER/CREATE TABLE
@sa comment for Key_part_spec::clone
*/
Alter_column *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Alter_column(*this); }
+ bool is_rename()
+ {
+ DBUG_ASSERT(!new_name.str || !default_value);
+ return new_name.str;
+ }
+};
+
+
+class Alter_rename_key : public Sql_alloc
+{
+public:
+ LEX_CSTRING old_name;
+ LEX_CSTRING new_name;
+ bool alter_if_exists;
+
+ Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg, bool exists)
+ : old_name(old_name_arg), new_name(new_name_arg), alter_if_exists(exists) {}
+
+ Alter_rename_key *clone(MEM_ROOT *mem_root) const
+ { return new (mem_root) Alter_rename_key(*this); }
+
};
@@ -347,13 +393,15 @@ public:
engine_option_value *option_list;
bool generated;
bool invisible;
+ bool without_overlaps;
+ Lex_ident period;
Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
ha_key_alg algorithm_arg, bool generated_arg, DDL_options_st ddl_options)
:DDL_options(ddl_options),
type(type_par), key_create_info(default_key_create_info),
name(*name_arg), option_list(NULL), generated(generated_arg),
- invisible(false)
+ invisible(false), without_overlaps(false)
{
key_create_info.algorithm= algorithm_arg;
}
@@ -364,7 +412,7 @@ public:
:DDL_options(ddl_options),
type(type_par), key_create_info(*key_info_arg), columns(*cols),
name(*name_arg), option_list(create_opt), generated(generated_arg),
- invisible(false)
+ invisible(false), without_overlaps(false)
{}
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
@@ -383,12 +431,14 @@ class Foreign_key: public Key {
public:
enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
+ LEX_CSTRING constraint_name;
LEX_CSTRING ref_db;
LEX_CSTRING ref_table;
List<Key_part_spec> ref_columns;
enum enum_fk_option delete_opt, update_opt;
enum fk_match_opt match_opt;
Foreign_key(const LEX_CSTRING *name_arg, List<Key_part_spec> *cols,
+ const LEX_CSTRING *constraint_name_arg,
const LEX_CSTRING *ref_db_arg, const LEX_CSTRING *ref_table_arg,
List<Key_part_spec> *ref_cols,
enum_fk_option delete_opt_arg, enum_fk_option update_opt_arg,
@@ -396,6 +446,7 @@ public:
DDL_options ddl_options)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL,
ddl_options),
+ constraint_name(*constraint_name_arg),
ref_db(*ref_db_arg), ref_table(*ref_table_arg), ref_columns(*ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
@@ -427,8 +478,8 @@ class LEX_COLUMN : public Sql_alloc
{
public:
String column;
- uint rights;
- LEX_COLUMN (const String& x,const uint& y ): column (x),rights (y) {}
+ privilege_t rights;
+ LEX_COLUMN (const String& x,const privilege_t & y ): column (x),rights (y) {}
};
class MY_LOCALE;
@@ -616,6 +667,7 @@ typedef struct system_variables
*/
ulong saved_auto_increment_increment, saved_auto_increment_offset;
ulong saved_lock_wait_timeout;
+ ulonglong wsrep_gtid_seq_no;
#endif /* WITH_WSREP */
uint eq_range_index_dive_limit;
ulong column_compression_zlib_strategy;
@@ -629,7 +681,6 @@ typedef struct system_variables
ulong max_tmp_tables;
ulong max_insert_delayed_threads;
ulong min_examined_row_limit;
- ulong multi_range_count;
ulong net_buffer_length;
ulong net_interactive_timeout;
ulong net_read_timeout;
@@ -702,11 +753,6 @@ typedef struct system_variables
my_bool query_cache_strip_comments;
my_bool sql_log_slow;
my_bool sql_log_bin;
- /*
- A flag to help detect whether binary logging was temporarily disabled
- (see tmp_disable_binlog(A) macro).
- */
- my_bool sql_log_bin_off;
my_bool binlog_annotate_row_events;
my_bool binlog_direct_non_trans_update;
my_bool column_compression_zlib_wrap;
@@ -759,6 +805,9 @@ typedef struct system_variables
ulong session_track_transaction_info;
my_bool session_track_schema;
my_bool session_track_state_change;
+#ifdef USER_VAR_TRACKING
+ my_bool session_track_user_variables;
+#endif // USER_VAR_TRACKING
my_bool tcp_nodelay;
ulong threadpool_priority;
@@ -769,6 +818,7 @@ typedef struct system_variables
uint column_compression_threshold;
uint column_compression_zlib_level;
uint in_subquery_conversion_threshold;
+ ulong optimizer_max_sel_arg_weight;
ulonglong max_rowid_filter_size;
vers_asof_timestamp_t vers_asof_timestamp;
@@ -870,6 +920,7 @@ typedef struct system_status_var
ulong feature_system_versioning; /* +1 opening a table WITH SYSTEM VERSIONING */
ulong feature_application_time_periods;
/* +1 opening a table with application-time period */
+ ulong feature_insert_returning; /* +1 when INSERT...RETURNING is used */
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 */
@@ -923,6 +974,11 @@ typedef struct system_status_var
#define last_system_status_var questions
#define last_cleared_system_status_var local_memory_used
+/** Number of contiguous global status variables */
+constexpr int COUNT_GLOBAL_STATUS_VARS= int(offsetof(STATUS_VAR,
+ last_system_status_var) /
+ sizeof(ulong)) + 1;
+
/*
Global status variables
*/
@@ -993,6 +1049,39 @@ static inline bool is_supported_parser_charset(CHARSET_INFO *cs)
return MY_TEST(cs->mbminlen == 1 && cs->number != 17 /* filename */);
}
+/** THD registry */
+class THD_list_iterator
+{
+protected:
+ I_List<THD> threads;
+ mutable mysql_rwlock_t lock;
+
+public:
+
+ /**
+ Iterates registered threads.
+
+ @param action called for every element
+ @param argument opque argument passed to action
+
+ @return
+ @retval 0 iteration completed successfully
+ @retval 1 iteration was interrupted (action returned 1)
+ */
+ template <typename T> int iterate(my_bool (*action)(THD *thd, T *arg), T *arg= 0)
+ {
+ int res= 0;
+ mysql_rwlock_rdlock(&lock);
+ I_List_iterator<THD> it(threads);
+ while (auto tmp= it++)
+ if ((res= action(tmp, arg)))
+ break;
+ mysql_rwlock_unlock(&lock);
+ return res;
+ }
+ static THD_list_iterator *iterator();
+};
+
/**
A counter of THDs
@@ -1319,7 +1408,10 @@ struct st_savepoint {
class Security_context {
public:
- Security_context() {} /* Remove gcc warning */
+ Security_context()
+ :master_access(NO_ACL),
+ db_access(NO_ACL)
+ {} /* Remove gcc warning */
/*
host - host of the client
user - user of the client, set to NULL until the user has been read from
@@ -1339,8 +1431,8 @@ public:
char *external_user;
/* points to host if host is available, otherwise points to ip */
const char *host_or_ip;
- ulong master_access; /* Global privileges from mysql.user */
- ulong db_access; /* Privileges for current db */
+ privilege_t master_access; /* Global privileges from mysql.user */
+ privilege_t db_access; /* Privileges for current db */
bool password_expired;
@@ -1373,7 +1465,7 @@ public:
* privileges.
@return True if the security context fulfills the access requirements.
*/
- bool check_access(ulong want_access, bool match_any = false);
+ bool check_access(const privilege_t want_access, bool match_any = false);
bool is_priv_user(const char *user, const char *host);
};
@@ -1922,12 +2014,11 @@ public:
m_locked_tables_count(0),
some_table_marked_for_reopen(0)
{
- init_sql_alloc(&m_locked_tables_root, "Locked_tables_list",
- MEM_ROOT_BLOCK_SIZE, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_locked_table_list, &m_locked_tables_root,
+ MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
}
- void unlock_locked_tables(THD *thd);
- void unlock_locked_table(THD *thd, MDL_ticket *mdl_ticket);
+ int unlock_locked_tables(THD *thd);
+ int unlock_locked_table(THD *thd, MDL_ticket *mdl_ticket);
~Locked_tables_list()
{
reset();
@@ -1976,6 +2067,14 @@ struct Ha_data
*/
plugin_ref lock;
Ha_data() :ha_ptr(NULL) {}
+
+ void reset()
+ {
+ ha_ptr= nullptr;
+ for (auto &info : ha_info)
+ info.reset();
+ lock= nullptr;
+ }
};
/**
@@ -2172,6 +2271,22 @@ struct wait_for_commit
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
+class Gap_time_tracker;
+
+/*
+ Thread context for Gap_time_tracker class.
+*/
+class Gap_time_tracker_data
+{
+public:
+ Gap_time_tracker_data(): bill_to(NULL) {}
+
+ Gap_time_tracker *bill_to;
+ ulonglong start_time;
+
+ void init() { bill_to = NULL; }
+};
+
/**
@class THD
For each client connection we create a separate thread with THD serving as
@@ -2337,9 +2452,22 @@ public:
*/
const char *proc_info;
+ void set_psi(PSI_thread *psi)
+ {
+ my_atomic_storeptr((void*volatile*)&m_psi, psi);
+ }
+
+ PSI_thread* get_psi()
+ {
+ return static_cast<PSI_thread*>(my_atomic_loadptr((void*volatile*)&m_psi));
+ }
+
private:
unsigned int m_current_stage_key;
+ /** Performance schema thread instrumentation for this session. */
+ PSI_thread *m_psi;
+
public:
void enter_stage(const PSI_stage_info *stage,
const char *calling_func,
@@ -2356,7 +2484,7 @@ public:
calling_line);
#endif
#ifdef HAVE_PSI_THREAD_INTERFACE
- MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line);
+ m_stage_progress_psi= MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line);
#endif
}
@@ -2416,7 +2544,8 @@ public:
// track down slow pthread_create
ulonglong prior_thr_create_utime, thr_create_utime;
ulonglong start_utime, utime_after_lock, utime_after_query;
-
+ /* This can be used by handlers to send signals to the SQL level */
+ ulonglong replication_flags;
// Process indicator
struct {
/*
@@ -2491,14 +2620,17 @@ public:
*/
void binlog_start_trans_and_stmt();
void binlog_set_stmt_begin();
- int binlog_write_table_map(TABLE *table, bool is_transactional,
- my_bool *with_annotate= 0);
int binlog_write_row(TABLE* table, bool is_transactional,
const uchar *buf);
int binlog_delete_row(TABLE* table, bool is_transactional,
const uchar *buf);
int binlog_update_row(TABLE* table, bool is_transactional,
const uchar *old_data, const uchar *new_data);
+ bool prepare_handlers_for_update(uint flag);
+ bool binlog_write_annotated_row(Log_event_writer *writer);
+ void binlog_prepare_for_row_logging();
+ bool binlog_write_table_maps();
+ bool binlog_write_table_map(TABLE *table, bool with_annotate);
static void binlog_prepare_row_images(TABLE* table);
void set_server_id(uint32 sid) { variables.server_id = sid; }
@@ -2592,22 +2724,21 @@ private:
*/
enum_binlog_format current_stmt_binlog_format;
- /*
- Number of outstanding table maps, i.e., table maps in the
- transaction cache.
- */
- uint binlog_table_maps;
public:
+
+ /* 1 if binlog table maps has been written */
+ bool binlog_table_maps;
+
void issue_unsafe_warnings();
void reset_unsafe_warnings()
{ binlog_unsafe_warning_flags= 0; }
- uint get_binlog_table_maps() const {
- return binlog_table_maps;
- }
- void clear_binlog_table_maps() {
+ void reset_binlog_for_next_statement()
+ {
binlog_table_maps= 0;
}
+ bool binlog_table_should_be_logged(const LEX_CSTRING *db);
+
#endif /* MYSQL_CLIENT */
public:
@@ -2647,6 +2778,10 @@ public:
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
DBUG_VOID_RETURN;
}
+ void free()
+ {
+ free_root(&mem_root,MYF(0));
+ }
bool is_active()
{
return (all.ha_list != NULL);
@@ -2659,11 +2794,10 @@ public:
{
bzero((char*)this, sizeof(*this));
implicit_xid.null();
- init_sql_alloc(&mem_root, "THD::transactions",
- ALLOC_ROOT_MIN_BLOCK_SIZE, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_thd_transactions, &mem_root,
+ ALLOC_ROOT_MIN_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
}
- } transaction;
+ } default_transaction, *transaction;
Global_read_lock global_read_lock;
Field *dup_field;
#ifndef __WIN__
@@ -2959,6 +3093,8 @@ public:
PROFILING profiling;
#endif
+ /** Current stage progress instrumentation. */
+ PSI_stage_progress *m_stage_progress_psi;
/** Current statement digest. */
sql_digest_state *m_digest;
/** Current statement digest token array. */
@@ -2972,6 +3108,14 @@ public:
/** Current statement instrumentation state. */
PSI_statement_locker_state m_statement_state;
#endif /* HAVE_PSI_STATEMENT_INTERFACE */
+
+ /** Current transaction instrumentation. */
+ PSI_transaction_locker *m_transaction_psi;
+#ifdef HAVE_PSI_TRANSACTION_INTERFACE
+ /** Current transaction instrumentation state. */
+ PSI_transaction_locker_state m_transaction_state;
+#endif /* HAVE_PSI_TRANSACTION_INTERFACE */
+
/** Idle instrumentation. */
PSI_idle_locker *m_idle_psi;
#ifdef HAVE_PSI_IDLE_INTERFACE
@@ -2988,7 +3132,7 @@ public:
update auto-updatable fields (like auto_increment and timestamp).
*/
query_id_t query_id;
- ulong col_access;
+ privilege_t col_access;
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
@@ -3099,7 +3243,6 @@ public:
uint8 password; /* 0, 1 or 2 */
uint8 failed_com_change_user;
bool slave_thread;
- bool extra_port; /* If extra connection */
bool no_errors;
/**
@@ -3303,7 +3446,7 @@ public:
void cleanup_after_query();
void free_connection();
void reset_for_reuse();
- bool store_globals();
+ void store_globals();
void reset_globals();
bool trace_started()
{
@@ -3349,6 +3492,7 @@ public:
*/
Apc_target apc_target;
+ Gap_time_tracker_data gap_tracker_data;
#ifndef MYSQL_CLIENT
enum enum_binlog_query_type {
/* The query can be logged in row format or in statement format. */
@@ -3364,6 +3508,7 @@ public:
char const *query, ulong query_len, bool is_trans,
bool direct, bool suppress_use,
int errcode);
+ bool binlog_current_query_unfiltered();
#endif
inline void
@@ -3488,8 +3633,8 @@ public:
timeval transaction_time()
{
if (!in_multi_stmt_transaction_mode())
- transaction.start_time.reset(this);
- return transaction.start_time;
+ transaction->start_time.reset(this);
+ return transaction->start_time;
}
inline void set_start_time()
@@ -3643,6 +3788,8 @@ public:
{
return server_status & SERVER_STATUS_IN_TRANS;
}
+ /* Commit both statement and full transaction */
+ int commit_whole_transaction_and_close_tables();
void give_protection_error();
/*
Give an error if any of the following is true for this connection
@@ -3665,7 +3812,19 @@ public:
}
inline void* trans_alloc(size_t size)
{
- return alloc_root(&transaction.mem_root,size);
+ return alloc_root(&transaction->mem_root,size);
+ }
+
+ LEX_CSTRING strmake_lex_cstring(const char *str, size_t length)
+ {
+ const char *tmp= strmake_root(mem_root, str, length);
+ if (!tmp)
+ return {0,0};
+ return {tmp, length};
+ }
+ LEX_CSTRING strmake_lex_cstring(const LEX_CSTRING &from)
+ {
+ return strmake_lex_cstring(from.str, from.length);
}
LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, size_t length)
@@ -3777,7 +3936,7 @@ public:
const char *src, size_t src_length);
/*
If either "dstcs" or "srccs" is &my_charset_bin,
- then performs native copying using cs->cset->copy_fix().
+ then performs native copying using copy_fix().
Otherwise, performs Unicode conversion using convert_fix().
*/
bool copy_fix(CHARSET_INFO *dstcs, LEX_STRING *dst,
@@ -3811,10 +3970,10 @@ public:
@param repertoire - the repertoire of the string
*/
Item_basic_constant *make_string_literal(const char *str, size_t length,
- uint repertoire);
+ my_repertoire_t repertoire);
Item_basic_constant *make_string_literal(const Lex_string_with_metadata_st &str)
{
- uint repertoire= str.repertoire(variables.character_set_client);
+ my_repertoire_t repertoire= str.repertoire(variables.character_set_client);
return make_string_literal(str.str, str.length, repertoire);
}
Item_basic_constant *make_string_literal_nchar(const Lex_string_with_metadata_st &str);
@@ -4076,7 +4235,7 @@ public:
inline bool really_abort_on_warning()
{
return (abort_on_warning &&
- (!transaction.stmt.modified_non_trans_table ||
+ (!transaction->stmt.modified_non_trans_table ||
(variables.sql_mode & MODE_STRICT_ALL_TABLES)));
}
void set_status_var_init();
@@ -4589,7 +4748,7 @@ public:
information to decide the logging format. So that cases we call decide_logging_format_2
at later stages in execution.
One example would be binlog format for IODKU but column with unique key is not inserted.
- We dont have inserted columns info when we call decide_logging_format so on later stage we call
+ We don't have inserted columns info when we call decide_logging_format so on later stage we call
decide_logging_format_low
@returns 0 if no format is changed
@@ -4666,6 +4825,7 @@ public:
}
void mark_transaction_to_rollback(bool all);
+ bool internal_transaction() { return transaction != &default_transaction; }
private:
/** The current internal error handler for this thread, or NULL. */
@@ -4710,9 +4870,7 @@ private:
AUTHID invoker;
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.
@@ -4739,6 +4897,17 @@ public:
LF_PINS *xid_hash_pins;
bool fix_xid_hash_pins();
+ const XID *get_xid() const
+ {
+#ifdef WITH_WSREP
+ if (!wsrep_xid.is_null())
+ return &wsrep_xid;
+#endif /* WITH_WSREP */
+ return (transaction->xid_state.is_explicit_XA() ?
+ transaction->xid_state.get_xid() :
+ &transaction->implicit_xid);
+ }
+
/* Members related to temporary tables. */
public:
/* Opened table states. */
@@ -4748,6 +4917,7 @@ public:
TMP_TABLE_ANY
};
bool has_thd_temporary_tables();
+ bool has_temporary_tables();
TABLE *create_and_open_tmp_table(LEX_CUSTRING *frm,
const char *path,
@@ -4786,7 +4956,6 @@ 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(LEX_CUSTRING *frm,
@@ -4872,17 +5041,13 @@ public:
size_t wsrep_TOI_pre_query_len;
wsrep_po_handle_t wsrep_po_handle;
size_t wsrep_po_cnt;
-#ifdef GTID_SUPPORT
- my_bool wsrep_po_in_trans;
- rpl_sid wsrep_po_sid;
-#endif /* GTID_SUPPORT */
void *wsrep_apply_format;
uchar* wsrep_rbr_buf;
wsrep_gtid_t wsrep_sync_wait_gtid;
- // wsrep_gtid_t wsrep_last_written_gtid;
+ uint64 wsrep_last_written_gtid_seqno;
+ uint64 wsrep_current_gtid_seqno;
ulong wsrep_affected_rows;
bool wsrep_has_ignored_error;
- bool wsrep_replicate_GTID;
/*
When enabled, do not replicate/binlog updates from the current table that's
@@ -4985,10 +5150,10 @@ public:
/* Copy relevant `stmt` transaction flags to `all` transaction. */
void merge_unsafe_rollback_flags()
{
- if (transaction.stmt.modified_non_trans_table)
- transaction.all.modified_non_trans_table= TRUE;
- transaction.all.m_unsafe_rollback_flags|=
- (transaction.stmt.m_unsafe_rollback_flags &
+ if (transaction->stmt.modified_non_trans_table)
+ transaction->all.modified_non_trans_table= TRUE;
+ transaction->all.m_unsafe_rollback_flags|=
+ (transaction->stmt.m_unsafe_rollback_flags &
(THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE |
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL |
THD_TRANS::EXECUTED_TABLE_ADMIN_CMD));
@@ -4998,7 +5163,7 @@ public:
{
if (in_active_multi_stmt_transaction())
{
- if (transaction.all.is_trx_read_write())
+ if (transaction->all.is_trx_read_write())
{
if (variables.idle_write_transaction_timeout > 0)
return variables.idle_write_transaction_timeout;
@@ -5049,6 +5214,41 @@ public:
};
+
+/*
+ Start a new independent transaction for the THD.
+ The old one is stored in this object and restored when calling
+ restore_old_transaction() or when the object is freed
+*/
+
+class start_new_trans
+{
+ /* container for handler's private per-connection data */
+ Ha_data old_ha_data[MAX_HA];
+ struct THD::st_transactions *old_transaction, new_transaction;
+ Open_tables_backup open_tables_state_backup;
+ MDL_savepoint mdl_savepoint;
+ PSI_transaction_locker *m_transaction_psi;
+ THD *org_thd;
+ uint in_sub_stmt;
+ uint server_status;
+ my_bool wsrep_on;
+
+public:
+ start_new_trans(THD *thd);
+ ~start_new_trans()
+ {
+ destroy();
+ }
+ void destroy()
+ {
+ if (org_thd) // Safety
+ restore_old_transaction();
+ new_transaction.free();
+ }
+ void restore_old_transaction();
+};
+
/** A short cut for thd->get_stmt_da()->set_ok_status(). */
inline void
@@ -5075,11 +5275,10 @@ my_eof(THD *thd)
#define tmp_disable_binlog(A) \
{ulonglong tmp_disable_binlog__save_options= (A)->variables.option_bits; \
(A)->variables.option_bits&= ~OPTION_BIN_LOG; \
- (A)->variables.sql_log_bin_off= 1;
+ (A)->variables.option_bits|= OPTION_BIN_TMP_LOG_OFF;
#define reenable_binlog(A) \
- (A)->variables.option_bits= tmp_disable_binlog__save_options; \
- (A)->variables.sql_log_bin_off= 0;}
+ (A)->variables.option_bits= tmp_disable_binlog__save_options; }
inline date_conv_mode_t sql_mode_for_dates(THD *thd)
@@ -5129,6 +5328,18 @@ class select_result_sink: public Sql_alloc
public:
THD *thd;
select_result_sink(THD *thd_arg): thd(thd_arg) {}
+ inline int send_data_with_check(List<Item> &items,
+ SELECT_LEX_UNIT *u,
+ ha_rows sent)
+ {
+ if (u->lim.check_offset(sent))
+ return 0;
+
+ if (u->thd->killed == ABORT_QUERY)
+ return 0;
+
+ return send_data(items);
+ }
/*
send_data returns 0 on ok, 1 on error and -1 if data was ignored, for
example for a duplicate row entry written to a temp table.
@@ -5164,7 +5375,7 @@ protected:
/* Something used only by the parser: */
public:
ha_rows est_records; /* estimated number of records in the result */
- select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {}
+ select_result(THD *thd_arg): select_result_sink(thd_arg), est_records(0) {}
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
virtual ~select_result() {};
/**
@@ -5230,9 +5441,9 @@ public:
/* 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()
+ void remove_offset_limit()
{
- unit->offset_limit_cnt= 0;
+ unit->lim.remove_offset();
}
/*
@@ -5258,7 +5469,7 @@ public:
It is aimed at capturing SHOW EXPLAIN output, so:
- Unlike select_result class, we don't assume that the sent data is an
- output of a SELECT_LEX_UNIT (and so we dont apply "LIMIT x,y" from the
+ output of a SELECT_LEX_UNIT (and so we don't apply "LIMIT x,y" from the
unit)
- We don't try to convert the target table to MyISAM
*/
@@ -5539,16 +5750,17 @@ public:
class select_insert :public select_result_interceptor {
public:
+ select_result *sel_result;
TABLE_LIST *table_list;
TABLE *table;
List<Item> *fields;
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
COPY_INFO info;
bool insert_into_view;
- select_insert(THD *thd_arg, TABLE_LIST *table_list_par,
- TABLE *table_par, List<Item> *fields_par,
- List<Item> *update_fields, List<Item> *update_values,
- enum_duplicates duplic, bool ignore);
+ select_insert(THD *thd_arg, TABLE_LIST *table_list_par, TABLE *table_par,
+ List<Item> *fields_par, List<Item> *update_fields,
+ List<Item> *update_values, enum_duplicates duplic,
+ bool ignore, select_result *sel_ret_list);
~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
virtual int prepare2(JOIN *join);
@@ -5584,7 +5796,7 @@ public:
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
TABLE_LIST *select_tables_arg):
select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic,
- ignore),
+ ignore, NULL),
create_table(table_arg),
create_info(create_info_par),
select_tables(select_tables_arg),
@@ -5594,7 +5806,6 @@ public:
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- int binlog_show_create_table(TABLE **tables, uint count);
void store_values(List<Item> &values);
bool send_eof();
virtual void abort_result_set();
@@ -5739,17 +5950,18 @@ public:
class select_unit :public select_result_interceptor
{
+protected:
uint curr_step, prev_step, curr_sel;
enum sub_select_type step;
public:
- Item_int *intersect_mark;
TMP_TABLE_PARAM tmp_table_param;
+ /* Number of additional (hidden) field of the used temporary table */
+ int addon_cnt;
int write_err; /* Error code from the last send_data->ha_write_row call. */
TABLE *table;
select_unit(THD *thd_arg):
- select_result_interceptor(thd_arg),
- intersect_mark(0), table(0)
+ select_result_interceptor(thd_arg), addon_cnt(0), table(0)
{
init();
tmp_table_param.init();
@@ -5766,6 +5978,9 @@ public:
virtual bool postponed_prepare(List<Item> &types)
{ return false; }
int send_data(List<Item> &items);
+ int write_record();
+ int update_counter(Field *counter, longlong value);
+ int delete_record();
bool send_eof();
virtual bool flush();
void cleanup();
@@ -5784,7 +5999,148 @@ public:
step= UNION_TYPE;
write_err= 0;
}
+ virtual void change_select();
+ virtual bool force_enable_index_if_needed() { return false; }
+};
+
+
+/**
+ @class select_unit_ext
+
+ The class used when processing rows produced by operands of query expressions
+ containing INTERSECT ALL and/or EXCEPT all operations. One or two extra fields
+ of the temporary to store the rows of the partial and final result can be employed.
+ Both of them contain counters. The second additional field is used only when
+ the processed query expression contains INTERSECT ALL.
+
+ Consider how these extra fields are used.
+
+ Let
+ table t1 (f char(8))
+ table t2 (f char(8))
+ table t3 (f char(8))
+ contain the following sets:
+ ("b"),("a"),("d"),("c"),("b"),("a"),("c"),("a")
+ ("c"),("b"),("c"),("c"),("a"),("b"),("g")
+ ("c"),("a"),("b"),("d"),("b"),("e")
+
+ - Let's demonstrate how the the set operation INTERSECT ALL is proceesed
+ for the query
+ SELECT f FROM t1 INTERSECT ALL SELECT f FROM t2
+
+ When send_data() is called for the rows of the first operand we put
+ the processed record into the temporary table if there was no such record
+ setting dup_cnt field to 1 and add_cnt field to 0 and increment the
+ counter in the dup_cnt field by one otherwise. We get
+
+ |add_cnt|dup_cnt| f |
+ |0 |2 |b |
+ |0 |3 |a |
+ |0 |1 |d |
+ |0 |2 |c |
+
+ The call of send_eof() for the first operand swaps the values stored in
+ dup_cnt and add_cnt. After this, we'll see the following rows in the
+ temporary table
+
+ |add_cnt|dup_cnt| f |
+ |2 |0 |b |
+ |3 |0 |a |
+ |1 |0 |d |
+ |2 |0 |c |
+
+ When send_data() is called for the rows of the second operand we increment
+ the counter in dup_cnt if the processed row is found in the table and do
+ nothing otherwise. As a result we get
+
+ |add_cnt|dup_cnt| f |
+ |2 |2 |b |
+ |3 |1 |a |
+ |1 |0 |d |
+ |2 |3 |c |
+
+ At the call of send_eof() for the second operand first we disable index.
+ Then for each record, the minimum of counters from dup_cnt and add_cnt m is
+ taken. If m == 0 then the record is deleted. Otherwise record is replaced
+ with m copies of it. Yet the counter in this copies are set to 1 for
+ dup_cnt and to 0 for add_cnt
+
+ |add_cnt|dup_cnt| f |
+ |0 |1 |b |
+ |0 |1 |b |
+ |0 |1 |a |
+ |0 |1 |c |
+ |0 |1 |c |
+
+ - Let's demonstrate how the the set operation EXCEPT ALL is proceesed
+ for the query
+ SELECT f FROM t1 EXCEPT ALL SELECT f FROM t3
+
+ Only one additional counter field dup_cnt is used for EXCEPT ALL.
+ After the first operand has been processed we have in the temporary table
+
+ |dup_cnt| f |
+ |2 |b |
+ |3 |a |
+ |1 |d |
+ |2 |c |
+
+ When send_data() is called for the rows of the second operand we decrement
+ the counter in dup_cnt if the processed row is found in the table and do
+ nothing otherwise. If the counter becomes 0 we delete the record
+
+ |dup_cnt| f |
+ |2 |a |
+ |1 |c |
+
+ Finally at the call of send_eof() for the second operand we disable index
+ unfold rows adding duplicates
+
+ |dup_cnt| f |
+ |1 |a |
+ |1 |a |
+ |1 |c |
+ */
+
+class select_unit_ext :public select_unit
+{
+public:
+ select_unit_ext(THD *thd_arg):
+ select_unit(thd_arg), increment(0), is_index_enabled(TRUE),
+ curr_op_type(UNSPECIFIED)
+ {
+ };
+ int send_data(List<Item> &items);
void change_select();
+ int unfold_record(ha_rows cnt);
+ bool send_eof();
+ bool force_enable_index_if_needed()
+ {
+ is_index_enabled= true;
+ return true;
+ }
+ bool disable_index_if_needed(SELECT_LEX *curr_sl);
+
+ /*
+ How to change increment/decrement the counter in duplicate_cnt field
+ when processing a record produced by the current operand in send_data().
+ The value can be 1 or -1
+ */
+ int increment;
+ /* TRUE <=> the index of the result temporary table is enabled */
+ bool is_index_enabled;
+ /* The type of the set operation currently executed */
+ enum set_op_type curr_op_type;
+ /*
+ Points to the extra field of the temporary table where
+ duplicate counters are stored
+ */
+ Field *duplicate_cnt;
+ /*
+ Points to the extra field of the temporary table where additional
+ counters used only for INTERSECT ALL operations are stored
+ */
+ Field *additional_cnt;
};
class select_union_recursive :public select_unit
@@ -5904,7 +6260,7 @@ public:
*/
DBUG_ASSERT(false); /* purecov: inspected */
}
- void reset_offset_limit_cnt()
+ void remove_offset_limit()
{
// EXPLAIN should never output to a select_union_direct
DBUG_ASSERT(false); /* purecov: inspected */
@@ -6106,8 +6462,53 @@ public:
/* Structs used when sorting */
struct SORT_FIELD_ATTR
{
- uint length; /* Length of sort field */
- uint suffix_length; /* Length suffix (0-4) */
+ /*
+ If using mem-comparable fixed-size keys:
+ length of the mem-comparable image of the field, in bytes.
+
+ If using packed keys: still the same? Not clear what is the use of it.
+ */
+ uint length;
+
+ /*
+ For most datatypes, this is 0.
+ The exception are the VARBINARY columns.
+ For those columns, the comparison actually compares
+
+ (value_prefix(N), suffix=length(value))
+
+ Here value_prefix is either the whole value or its prefix if it was too
+ long, and the suffix is the length of the original value.
+ (this way, for values X and Y: if X=prefix(Y) then X compares as less
+ than Y
+ */
+ uint suffix_length;
+
+ /*
+ If using packed keys, number of bytes that are used to store the length
+ of the packed key.
+
+ */
+ uint length_bytes;
+
+ /* Max. length of the original value, in bytes */
+ uint original_length;
+ enum Type { FIXED_SIZE, VARIABLE_SIZE } type;
+ /*
+ TRUE : if the item or field is NULLABLE
+ FALSE : otherwise
+ */
+ bool maybe_null;
+ CHARSET_INFO *cs;
+ uint pack_sort_string(uchar *to, const Binary_string *str,
+ CHARSET_INFO *cs) const;
+ int compare_packed_fixed_size_vals(uchar *a, size_t *a_len,
+ uchar *b, size_t *b_len);
+ int compare_packed_varstrings(uchar *a, size_t *a_len,
+ uchar *b, size_t *b_len);
+ bool check_if_packing_possible(THD *thd) const;
+ bool is_variable_sized() { return type == VARIABLE_SIZE; }
+ void set_length_and_original_length(THD *thd, uint length_arg);
};
@@ -6214,7 +6615,7 @@ class user_var_entry
double val_real(bool *null_value);
longlong val_int(bool *null_value) const;
- String *val_str(bool *null_value, String *str, uint decimals);
+ String *val_str(bool *null_value, String *str, uint decimals) const;
my_decimal *val_decimal(bool *null_value, my_decimal *result);
CHARSET_INFO *charset() const { return m_charset; }
void set_charset(CHARSET_INFO *cs) { m_charset= cs; }
@@ -6650,8 +7051,8 @@ inline int handler::ha_write_tmp_row(uchar *buf)
int error;
MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
increment_statistics(&SSV::ha_tmp_write_count);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,
- { error= write_row(buf); })
+ TABLE_IO_WAIT(tracker, PSI_TABLE_WRITE_ROW, MAX_KEY, error,
+ { error= write_row(buf); })
MYSQL_INSERT_ROW_DONE(error);
return error;
}
@@ -6661,7 +7062,7 @@ inline int handler::ha_delete_tmp_row(uchar *buf)
int error;
MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
increment_statistics(&SSV::ha_tmp_delete_count);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_DELETE_ROW, MAX_KEY, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, MAX_KEY, error,
{ error= delete_row(buf); })
MYSQL_DELETE_ROW_DONE(error);
return error;
@@ -6672,12 +7073,16 @@ inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data)
int error;
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
increment_statistics(&SSV::ha_tmp_update_count);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0,
- { error= update_row(old_data, new_data);})
+ TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, error,
+ { error= update_row(old_data, new_data);})
MYSQL_UPDATE_ROW_DONE(error);
return error;
}
+inline bool handler::has_long_unique()
+{
+ return table->s->long_unique_table;
+}
extern pthread_attr_t *get_connection_attrib(void);
@@ -6748,22 +7153,6 @@ class Sql_mode_save
sql_mode_t old_mode; // SQL mode saved at construction time.
};
-class Abort_on_warning_instant_set
-{
- THD *m_thd;
- bool m_save_abort_on_warning;
-public:
- Abort_on_warning_instant_set(THD *thd, bool temporary_value)
- :m_thd(thd), m_save_abort_on_warning(thd->abort_on_warning)
- {
- thd->abort_on_warning= temporary_value;
- }
- ~Abort_on_warning_instant_set()
- {
- m_thd->abort_on_warning= m_save_abort_on_warning;
- }
-};
-
class Switch_to_definer_security_ctx
{
public:
@@ -6781,6 +7170,45 @@ class Switch_to_definer_security_ctx
};
+class Sql_mode_instant_set: public Sql_mode_save
+{
+public:
+ Sql_mode_instant_set(THD *thd, sql_mode_t temporary_value)
+ :Sql_mode_save(thd)
+ {
+ thd->variables.sql_mode= temporary_value;
+ }
+};
+
+
+class Sql_mode_instant_remove: public Sql_mode_save
+{
+public:
+ Sql_mode_instant_remove(THD *thd, sql_mode_t temporary_remove_flags)
+ :Sql_mode_save(thd)
+ {
+ thd->variables.sql_mode&= ~temporary_remove_flags;
+ }
+};
+
+
+class Abort_on_warning_instant_set
+{
+ THD *m_thd;
+ bool m_save_abort_on_warning;
+public:
+ Abort_on_warning_instant_set(THD *thd, bool temporary_value)
+ :m_thd(thd), m_save_abort_on_warning(thd->abort_on_warning)
+ {
+ thd->abort_on_warning= temporary_value;
+ }
+ ~Abort_on_warning_instant_set()
+ {
+ m_thd->abort_on_warning= m_save_abort_on_warning;
+ }
+};
+
+
class Check_level_instant_set
{
THD *m_thd;
@@ -6825,17 +7253,15 @@ public:
bool eq(const Database_qualified_name *other) const
{
CHARSET_INFO *cs= lower_case_table_names ?
- &my_charset_utf8_general_ci :
- &my_charset_utf8_bin;
+ &my_charset_utf8mb3_general_ci :
+ &my_charset_utf8mb3_bin;
return
m_db.length == other->m_db.length &&
m_name.length == other->m_name.length &&
- !my_strnncoll(cs,
- (const uchar *) m_db.str, m_db.length,
- (const uchar *) other->m_db.str, other->m_db.length) &&
- !my_strnncoll(cs,
- (const uchar *) m_name.str, m_name.length,
- (const uchar *) other->m_name.str, other->m_name.length);
+ !cs->strnncoll(m_db.str, m_db.length,
+ other->m_db.str, other->m_db.length) &&
+ !cs->strnncoll(m_name.str, m_name.length,
+ other->m_name.str, other->m_name.length);
}
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
const LEX_CSTRING &name);
@@ -6911,10 +7337,9 @@ public:
class Type_holder: public Sql_alloc,
public Item_args,
public Type_handler_hybrid_field_type,
- public Type_all_attributes,
- public Type_geometry_attributes
+ public Type_all_attributes
{
- TYPELIB *m_typelib;
+ const TYPELIB *m_typelib;
bool m_maybe_null;
public:
Type_holder()
@@ -6937,19 +7362,11 @@ public:
DBUG_ASSERT(0);
return 0;
}
- void set_geometry_type(uint type)
- {
- Type_geometry_attributes::set_geometry_type(type);
- }
- uint uint_geometry_type() const
- {
- return Type_geometry_attributes::get_geometry_type();
- }
- void set_typelib(TYPELIB *typelib)
+ void set_typelib(const TYPELIB *typelib)
{
m_typelib= typelib;
}
- TYPELIB *get_typelib() const
+ const TYPELIB *get_typelib() const
{
return m_typelib;
}
@@ -6982,13 +7399,13 @@ class Sp_eval_expr_state
{
m_thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
m_thd->abort_on_warning= m_thd->is_strict_mode();
- m_thd->transaction.stmt.modified_non_trans_table= false;
+ m_thd->transaction->stmt.modified_non_trans_table= false;
}
void stop()
{
m_thd->count_cuted_fields= m_count_cuted_fields;
m_thd->abort_on_warning= m_abort_on_warning;
- m_thd->transaction.stmt.modified_non_trans_table=
+ m_thd->transaction->stmt.modified_non_trans_table=
m_stmt_modified_non_trans_table;
}
public:
@@ -6996,7 +7413,7 @@ public:
:m_thd(thd),
m_count_cuted_fields(thd->count_cuted_fields),
m_abort_on_warning(thd->abort_on_warning),
- m_stmt_modified_non_trans_table(thd->transaction.stmt.
+ m_stmt_modified_non_trans_table(thd->transaction->stmt.
modified_non_trans_table)
{
start();
@@ -7034,11 +7451,8 @@ private:
/** THD registry */
-class THD_list
+class THD_list: public THD_list_iterator
{
- I_List<THD> threads;
- mutable mysql_rwlock_t lock;
-
public:
/**
Constructor replacement.
@@ -7086,28 +7500,6 @@ public:
thd->unlink();
mysql_rwlock_unlock(&lock);
}
-
- /**
- Iterates registered threads.
-
- @param action called for every element
- @param argument opque argument passed to action
-
- @return
- @retval 0 iteration completed successfully
- @retval 1 iteration was interrupted (action returned 1)
- */
- template <typename T> int iterate(my_bool (*action)(THD *thd, T *arg), T *arg= 0)
- {
- int res= 0;
- mysql_rwlock_rdlock(&lock);
- I_List_iterator<THD> it(threads);
- while (auto tmp= it++)
- if ((res= action(tmp, arg)))
- break;
- mysql_rwlock_unlock(&lock);
- return res;
- }
};
extern THD_list server_threads;