diff options
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r-- | sql/sql_class.h | 614 |
1 files changed, 430 insertions, 184 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 9ae1e5cf23b..986cb1c4793 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 "sql_digest_stream.h" // sql_digest_state @@ -44,6 +46,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, @@ -176,7 +179,7 @@ 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); @@ -225,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; @@ -255,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; @@ -270,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 @@ -342,8 +352,6 @@ class Foreign_key: public Key { public: enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL, FK_MATCH_PARTIAL, FK_MATCH_SIMPLE}; - enum fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE, - FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT}; LEX_STRING ref_db; LEX_STRING ref_table; @@ -470,16 +478,22 @@ 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, + }; extern int killed_errno(killed_state killed); @@ -503,8 +517,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 { /* @@ -558,6 +570,7 @@ typedef struct system_variables 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; @@ -628,6 +641,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; @@ -658,7 +672,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; @@ -681,6 +695,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; /** @@ -695,6 +715,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; @@ -771,6 +792,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 */ ulonglong master_gtid_wait_timeouts; /* Number of timeouts */ @@ -819,8 +841,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); @@ -1053,7 +1074,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) { @@ -1203,7 +1227,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 */ @@ -1267,6 +1292,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 @@ -1296,15 +1376,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 @@ -1382,8 +1472,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; @@ -1431,9 +1525,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; @@ -1451,8 +1545,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 * @@ -1467,7 +1561,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; @@ -1480,6 +1574,7 @@ show_system_thread(enum_thread_type thread) Internal error handlers are exception handlers used by the server implementation. */ + class Internal_error_handler { protected: @@ -1517,7 +1612,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; @@ -1538,7 +1633,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) { @@ -1565,7 +1660,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); @@ -1574,6 +1669,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 @@ -1910,6 +2029,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; @@ -1983,6 +2115,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 @@ -2065,7 +2204,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; @@ -2107,7 +2246,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; @@ -2365,6 +2504,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. @@ -2661,7 +2802,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; @@ -2773,7 +2914,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; @@ -2915,7 +3056,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(); @@ -2935,6 +3076,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 @@ -2942,7 +3085,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() @@ -3107,6 +3249,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 @@ -3116,7 +3264,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; } @@ -3333,6 +3481,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() @@ -3348,6 +3502,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) { @@ -3539,13 +3709,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; @@ -3665,7 +3835,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); @@ -3925,11 +4095,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. @@ -3946,26 +4115,88 @@ public: */ rpl_gtid last_commit_gtid; - inline void lock_temporary_tables() + LF_PINS *tdc_hash_pins; + LF_PINS *xid_hash_pins; + bool fix_xid_hash_pins(); + +/* Members related to temporary tables. */ +public: + 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); + TABLE *find_temporary_table(const TABLE_LIST *tl); + + 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); + +private: + /* Whether a lock has been acquired? */ + bool m_tmp_tables_locked; + + /* Opened table states. */ + enum Temporary_table_state { + TMP_TABLE_IN_USE, + TMP_TABLE_NOT_IN_USE, + TMP_TABLE_ANY + }; + + 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) { - if (rgi_slave) - rgi_lock_temporary_tables(); + return uint4korr(share->table_cache_key.str + + share->table_cache_key.length - 4); } - inline void unlock_temporary_tables(bool clear) - { - if (rgi_slave) - rgi_unlock_temporary_tables(clear); - } - inline bool have_temporary_tables() + + inline TMP_TABLE_SHARE *tmp_table_share(TABLE *table) { - return (temporary_tables || - (rgi_slave && unlikely(rgi_have_temporary_tables()))); + DBUG_ASSERT(table->s->tmp_table); + return static_cast<TMP_TABLE_SHARE *>(table->s); } - LF_PINS *tdc_hash_pins; - LF_PINS *xid_hash_pins; - bool fix_xid_hash_pins(); - +public: inline ulong wsrep_binlog_format() const { return WSREP_FORMAT(variables.binlog_format); @@ -4048,8 +4279,41 @@ public: { main_lex.restore_set_statement_var(); } + + /* + 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(). */ @@ -4069,6 +4333,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) \ @@ -4147,12 +4413,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. @@ -4209,6 +4476,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; @@ -4442,6 +4712,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, @@ -4449,12 +4720,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); @@ -4500,16 +4773,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; @@ -4544,7 +4810,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. */ @@ -4574,9 +4846,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() { @@ -4588,17 +4861,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: @@ -4636,6 +4905,30 @@ 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; + + select_union_recursive(THD *thd_arg): + select_union(thd_arg), + incr_table(0), first_rec_table_to_update(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. @@ -4912,16 +5205,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 { @@ -4999,85 +5295,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; - ulonglong max_in_memory_size; - IO_CACHE file; - TREE tree; - uchar *record_pointers; - ulong filtered_out_elems; - bool flush(); - uint size; - uint full_size; - uint min_dupl_count; /* 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) - { - register ulonglong max_elems_in_tree= - max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); - 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 { @@ -5105,13 +5323,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(); }; @@ -5155,16 +5371,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 { @@ -5324,6 +5535,15 @@ public: */ #define CF_UPDATES_DATA (1U << 18) +/** + SP Bulk execution safe +*/ +#define CF_SP_BULK_SAFE (1U << 19) +/** + SP Bulk execution optimized +*/ +#define CF_SP_BULK_OPTIMIZED (1U << 20) + /* Bits in server_command_flags */ /** @@ -5345,6 +5565,10 @@ public: Do not check that wsrep snapshot is ready before allowing this command */ #define CF_SKIP_WSREP_CHECK (1U << 2) +/** + Do not allow it for COM_MULTI batch +*/ +#define CF_NO_COM_MULTI (1U << 3) /* Inline functions */ @@ -5491,6 +5715,28 @@ 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. +}; + #endif /* MYSQL_SERVER */ #endif /* SQL_CLASS_INCLUDED */ |