diff options
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r-- | sql/sql_class.h | 620 |
1 files changed, 410 insertions, 210 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 9cca3c17..c832cf77 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -23,6 +23,8 @@ #include "dur_prop.h" #include <waiting_threads.h> #include "sql_const.h" +#include "lex_ident.h" +#include "sql_used.h" #include <mysql/plugin_audit.h> #include "log.h" #include "rpl_tblmap.h" @@ -70,6 +72,7 @@ void set_thd_stage_info(void *thd, #include "wsrep_on.h" #ifdef WITH_WSREP #include <inttypes.h> +#include <ilist.h> /* wsrep-lib */ #include "wsrep_client_service.h" #include "wsrep_client_state.h" @@ -90,7 +93,6 @@ struct rpl_group_info; struct rpl_parallel_thread; class Rpl_filter; class Query_log_event; -class Load_log_event; class Log_event_writer; class sp_rcontext; class sp_cache; @@ -146,7 +148,9 @@ enum enum_binlog_row_image { /** Whenever possible, before and after image contain all columns except blobs. */ BINLOG_ROW_IMAGE_NOBLOB= 1, /** All columns in both before and after image. */ - BINLOG_ROW_IMAGE_FULL= 2 + BINLOG_ROW_IMAGE_FULL= 2, + /** All columns in before image, but only updated columns in after image */ + BINLOG_ROW_IMAGE_FULL_NODUP= 3 }; @@ -194,13 +198,18 @@ enum enum_binlog_row_image { /* Bits for different old style modes */ -#define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) -#define OLD_MODE_NO_PROGRESS_INFO (1 << 1) +#define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) +#define OLD_MODE_NO_PROGRESS_INFO (1 << 1) #define OLD_MODE_ZERO_DATE_TIME_CAST (1 << 2) #define OLD_MODE_UTF8_IS_UTF8MB3 (1 << 3) #define OLD_MODE_IGNORE_INDEX_ONLY_FOR_JOIN (1 << 4) #define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5) #define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6) +#define OLD_MODE_LOCK_ALTER_TABLE_COPY (1 << 7) + +#define OLD_MODE_DEFAULT_VALUE OLD_MODE_UTF8_IS_UTF8MB3 + +void old_mode_deprecated_warnings(THD *thd, ulonglong v); extern char internal_table_name[2]; extern char empty_c_string[1]; @@ -694,7 +703,7 @@ typedef struct system_variables char* dynamic_variables_ptr; uint dynamic_variables_head; /* largest valid variable offset */ uint dynamic_variables_size; /* how many bytes are in use */ - + ulonglong max_heap_table_size; ulonglong tmp_memory_table_size; ulonglong tmp_disk_table_size; @@ -716,11 +725,7 @@ typedef struct system_variables ulonglong sortbuff_size; ulonglong default_regex_flags; ulonglong max_mem_used; - /* - A bitmap of OPTIMIZER_ADJ_* flags (defined in sql_priv.h). - See sys_vars.cc:adjust_secondary_key_cost for symbolic names. - */ - ulonglong optimizer_adjust_secondary_key_costs; + ulonglong max_rowid_filter_size; /** Place holders to store Multi-source variables in sys_var.cc during @@ -729,10 +734,14 @@ typedef struct system_variables ulonglong slave_skip_counter; ulonglong max_relay_log_size; + double optimizer_where_cost, optimizer_scan_setup_cost; + double long_query_time_double, max_statement_time_double; + double sample_percentage; + ha_rows select_limit; ha_rows max_join_size; ha_rows expensive_subquery_limit; - ulong auto_increment_increment, auto_increment_offset; + #ifdef WITH_WSREP /* Stored values of the auto_increment_increment and auto_increment_offset @@ -741,11 +750,12 @@ typedef struct system_variables original values (which are set by the user) by calculated ones (which are based on the cluster size): */ + ulonglong wsrep_gtid_seq_no; 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 auto_increment_increment, auto_increment_offset; ulong column_compression_zlib_strategy; ulong lock_wait_timeout; ulong join_cache_level; @@ -754,7 +764,6 @@ typedef struct system_variables ulong max_length_for_sort_data; ulong max_recursive_iterations; ulong max_sort_length; - ulong max_tmp_tables; ulong max_insert_delayed_threads; ulong min_examined_row_limit; ulong net_buffer_length; @@ -771,8 +780,8 @@ typedef struct system_variables ulong optimizer_max_sel_arg_weight; ulong optimizer_max_sel_args; ulong optimizer_trace_max_mem_size; + ulong optimizer_adjust_secondary_key_costs; ulong use_stat_tables; - double sample_percentage; ulong histogram_size; ulong histogram_type; ulong preload_buff_size; @@ -792,6 +801,7 @@ typedef struct system_variables ulong trans_alloc_block_size; ulong trans_prealloc_size; ulong log_warnings; + ulong block_encryption_mode; ulong log_slow_max_warnings; /* Flags for slow log filtering */ ulong log_slow_rate_limit; @@ -803,8 +813,15 @@ typedef struct system_variables ulong tx_isolation; ulong updatable_views_with_limit; ulong alter_algorithm; - int max_user_connections; ulong server_id; + ulong session_track_transaction_info; + ulong threadpool_priority; + ulong vers_alter_history; + + /* deadlock detection */ + ulong wt_timeout_short, wt_deadlock_search_depth_short; + ulong wt_timeout_long, wt_deadlock_search_depth_long; + /** In slave thread we need to know in behalf of which thread the query is being run to replicate temp tables properly @@ -814,10 +831,18 @@ typedef struct system_variables When replicating an event group with GTID, keep these values around so slave binlog can receive the same GTID as the original. */ - uint32 gtid_domain_id; uint64 gtid_seq_no; + uint32 gtid_domain_id; uint group_concat_max_len; + uint eq_range_index_dive_limit; + uint idle_transaction_timeout; + uint idle_readonly_transaction_timeout; + uint idle_write_transaction_timeout; + uint column_compression_threshold; + uint column_compression_zlib_level; + uint in_subquery_conversion_threshold; + int max_user_connections; /** Default transaction access mode. READ ONLY (true) or READ WRITE (false). @@ -837,7 +862,16 @@ typedef struct system_variables my_bool binlog_annotate_row_events; my_bool binlog_direct_non_trans_update; my_bool column_compression_zlib_wrap; - + my_bool sysdate_is_now; + my_bool wsrep_on; + my_bool wsrep_dirty_reads; + my_bool pseudo_slave_mode; + 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; plugin_ref table_plugin; plugin_ref tmp_table_plugin; plugin_ref enforced_table_plugin; @@ -863,48 +897,20 @@ typedef struct system_variables MY_LOCALE *lc_time_names; Time_zone *time_zone; + char *session_track_system_variables; + char *redirect_url; - my_bool sysdate_is_now; - - /* deadlock detection */ - ulong wt_timeout_short, wt_deadlock_search_depth_short; - ulong wt_timeout_long, wt_deadlock_search_depth_long; - - my_bool wsrep_on; - my_bool wsrep_causal_reads; - uint wsrep_sync_wait; - ulong wsrep_retry_autocommit; + /* Some wsrep variables */ ulonglong wsrep_trx_fragment_size; + ulong wsrep_retry_autocommit; ulong wsrep_trx_fragment_unit; ulong wsrep_OSU_method; - my_bool wsrep_dirty_reads; - double long_query_time_double, max_statement_time_double; - - 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; -#ifdef USER_VAR_TRACKING - my_bool session_track_user_variables; -#endif // USER_VAR_TRACKING - my_bool tcp_nodelay; - - ulong threadpool_priority; - - uint idle_transaction_timeout; - uint idle_readonly_transaction_timeout; - uint idle_write_transaction_timeout; - uint column_compression_threshold; - uint column_compression_zlib_level; - uint in_subquery_conversion_threshold; - - ulonglong max_rowid_filter_size; + uint wsrep_sync_wait; vers_asof_timestamp_t vers_asof_timestamp; - ulong vers_alter_history; my_bool binlog_alter_two_phase; + + Charset_collation_map_st character_set_collations; } SV; /** @@ -994,19 +1000,21 @@ typedef struct system_status_var functions are used */ ulong feature_dynamic_columns; /* +1 when creating a dynamic column */ ulong feature_fulltext; /* +1 when MATCH is used */ - ulong feature_gis; /* +1 opening a table with GIS features */ - ulong feature_invisible_columns; /* +1 opening a table with invisible column */ - ulong feature_json; /* +1 when JSON function appears in the statement */ + ulong feature_gis; /* +1 opening table with GIS features */ + ulong feature_invisible_columns; /* +1 opening table with invisible column */ + ulong feature_json; /* +1 when JSON function is used */ ulong feature_locale; /* +1 when LOCALE is set */ ulong feature_subquery; /* +1 when subqueries are used */ - ulong feature_system_versioning; /* +1 opening a table WITH SYSTEM VERSIONING */ + ulong feature_system_versioning; /* +1 opening 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_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 */ ulong feature_window_functions; /* +1 when window functions are used */ + ulong feature_into_outfile; /* +1 when INTO OUTFILE is used */ + ulong feature_into_variable; /* +1 when INTO VARIABLE is used */ /* From MASTER_GTID_WAIT usage */ ulong master_gtid_wait_timeouts; /* Number of timeouts */ @@ -1242,21 +1250,31 @@ public: inline bool is_conventional() const { return state == STMT_CONVENTIONAL_EXECUTION; } - inline void* alloc(size_t size) { return alloc_root(mem_root,size); } - inline void* calloc(size_t size) + inline void* alloc(size_t size) const { return alloc_root(mem_root,size); } + inline void* calloc(size_t size) const { void *ptr; if (likely((ptr=alloc_root(mem_root,size)))) bzero(ptr, size); return ptr; } - inline char *strdup(const char *str) + inline char *strdup(const char *str) const { return strdup_root(mem_root,str); } - inline char *strmake(const char *str, size_t size) + inline char *strmake(const char *str, size_t size) const { return strmake_root(mem_root,str,size); } - inline void *memdup(const void *str, size_t size) + inline LEX_CSTRING strcat(const LEX_CSTRING &a, const LEX_CSTRING &b) const + { + char *buf= (char*)alloc(a.length + b.length + 1); + if (unlikely(!buf)) + return null_clex_str; + memcpy(buf, a.str, a.length); + memcpy(buf + a.length, b.str, b.length); + buf[a.length + b.length] = 0; + return {buf, a.length + b.length}; + } + inline void *memdup(const void *str, size_t size) const { return memdup_root(mem_root,str,size); } - inline void *memdup_w_gap(const void *str, size_t size, size_t gap) + inline void *memdup_w_gap(const void *str, size_t size, size_t gap) const { void *ptr; if (likely((ptr= alloc_root(mem_root,size+gap)))) @@ -1264,6 +1282,151 @@ public: return ptr; } + /* + Methods to copy a string to the memory root + and return the value as a LEX_CSTRING. + */ + LEX_CSTRING strmake_lex_cstring(const char *str, size_t length) const + { + 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) const + { + return strmake_lex_cstring(from.str, from.length); + } + LEX_CSTRING strmake_lex_cstring_trim_whitespace(const LEX_CSTRING &from, + CHARSET_INFO *cs) + { + return strmake_lex_cstring(Lex_cstring(from).trim_whitespace(cs)); + } + + /* + Methods to copy a string to memory root, + write the result to the out parameter, + and return as a LEX_STRING/LEX_CSTRING pointer. + */ + LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, + size_t length) const + { + if (!(lex_str->str= strmake_root(mem_root, str, length))) + { + lex_str->length= 0; + return 0; + } + lex_str->length= length; + return lex_str; + } + LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str, const char* str, + size_t length) const + { + if (!(lex_str->str= strmake_root(mem_root, str, length))) + { + lex_str->length= 0; + return 0; + } + lex_str->length= length; + return lex_str; + } + + /* + Methods to copy a string value on memory root, + but also allocate on memory root LEX_CSTRING itself + and return a pointer to it. + */ + LEX_CSTRING *make_clex_string(const char* str, size_t length) const + { + LEX_CSTRING *lex_str; + char *tmp; + if (unlikely(!(lex_str= (LEX_CSTRING *)alloc_root(mem_root, + sizeof(LEX_CSTRING) + + length+1)))) + return 0; + tmp= (char*) (lex_str+1); + lex_str->str= tmp; + memcpy(tmp, str, length); + tmp[length]= 0; + lex_str->length= length; + return lex_str; + } + LEX_CSTRING *make_clex_string(const LEX_CSTRING from) const + { + return make_clex_string(from.str, from.length); + } + + // Allocate LEX_STRING for character set conversion + bool alloc_lex_string(LEX_STRING *dst, size_t length) const + { + if (likely((dst->str= (char*) alloc(length)))) + return false; + dst->length= 0; // Safety + return true; // EOM + } + + // Remove double quotes: aaa""bbb -> aaa"bbb + bool quote_unescape(LEX_CSTRING *dst, const LEX_CSTRING *src, + char quote) const + { + const char *tmp= src->str; + const char *tmpend= src->str + src->length; + char *to; + if (!(dst->str= to= (char *) alloc(src->length + 1))) + { + dst->length= 0; // Safety + return true; + } + for ( ; tmp < tmpend; ) + { + if ((*to++= *tmp++) == quote) + tmp++; // Skip double quotes + } + *to= 0; // End null for safety + dst->length= to - dst->str; + return false; + } + + /* + Make a lower-cased copy of an identifier on mem_root. + + @param src - The original identifier (usually coming from the parser) + @return - {NULL,0} in case of EOM, or a non-NULL LEX_STRING + with the lower-cased identifier copy. + */ + LEX_STRING make_ident_casedn(const LEX_CSTRING &src) + { + return lex_string_casedn_root(mem_root, &my_charset_utf8mb3_general_ci, + src.str, src.length); + } + + /* + Make an exact copy or a lower-cased copy of an identifier on mem_root. + + @param src - The original identifier (usually coming from the parser) + @param casedn - If the name should be converted to lower case + @return - {NULL,0} in case of EOM, + or a non-NULL LEX_STRING with the identifier copy. + */ + LEX_STRING make_ident_opt_casedn(const LEX_CSTRING &src, bool casedn) + { + return casedn ? make_ident_casedn(src) : + lex_string_strmake_root(mem_root, src.str, src.length); + } + + /* + Convert a LEX_CSTRING to a valid internal database name: + - validated with Lex_ident_fs::check_db_name() + - optionally lower-cased when lower_case_table_names==1 + The lower-cased copy is created on Query_arena::mem_root, when needed. + + @param name - The name to normalize. Must not be {NULL,0}. + @return - {NULL,0} on EOM or a bad database name + (with an errror is raised, + or a good database name otherwise. + */ + Lex_ident_db to_ident_db_internal_with_error(const LEX_CSTRING &name); + void set_query_arena(Query_arena *set); void free_items(); @@ -1334,6 +1497,8 @@ struct send_column_info_state } }; +extern uint sql_command_flags[]; + /** @class Statement @@ -1414,6 +1579,10 @@ public: { set_query_inner(CSET_STRING()); } + ulong sql_command_flags() const + { + return ::sql_command_flags[lex->sql_command]; + } /** Name of the current (default) database. @@ -1883,6 +2052,7 @@ public: ulonglong tmp_tables_size; ulonglong client_capabilities; ulonglong cuted_fields, sent_row_count, examined_row_count; + ulonglong sent_row_count_for_statement, examined_row_count_for_statement; ulonglong affected_rows; ulonglong bytes_sent_old; ha_handler_stats handler_stats; @@ -1893,6 +2063,7 @@ public: uint in_sub_stmt; /* 0, SUB_STMT_TRIGGER or SUB_STMT_FUNCTION */ bool enable_slow_log; bool last_insert_id_used; + bool in_stored_procedure; enum enum_check_fields count_cuted_fields; }; @@ -2659,6 +2830,7 @@ struct thd_async_state */ class THD: public THD_count, /* this must be first */ + public Sql_used, public Statement, /* This is to track items changed during execution of a prepared @@ -2743,7 +2915,7 @@ public: Protocol_binary protocol_binary; // Binary protocol HASH user_vars; // hash for user variables String packet; // dynamic buffer for network I/O - String convert_buffer; // buffer for charset conversions + String convert_buffer; // buffer for charset conversions struct my_rnd_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars @@ -2751,6 +2923,7 @@ public: struct system_status_var *initial_status_var; /* used by show status */ ha_handler_stats handler_stats; // Handler statistics THR_LOCK_INFO lock_info; // Locking info of this thread + /** Protects THD data accessed from other threads: - thd->query and thd->query_length (used by SHOW ENGINE @@ -2987,12 +3160,6 @@ public: */ uint32 binlog_unsafe_warning_flags; - typedef uint used_t; - enum { RAND_USED=1, TIME_ZONE_USED=2, QUERY_START_SEC_PART_USED=4, - THREAD_SPECIFIC_USED=8 }; - - used_t used; - #ifndef MYSQL_CLIENT binlog_cache_mngr * binlog_setup_trx_data(); /* @@ -3006,43 +3173,44 @@ public: */ void binlog_start_trans_and_stmt(); void binlog_set_stmt_begin(); - int binlog_write_row(TABLE* table, bool is_transactional, + int binlog_write_row(TABLE* table, Event_log *bin_log, + binlog_cache_data *cache_data, 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, + int binlog_delete_row(TABLE* table, Event_log *bin_log, + binlog_cache_data *cache_data, bool is_transactional, + enum_binlog_row_image row_image, const uchar *buf); + int binlog_update_row(TABLE* table, Event_log *bin_log, + binlog_cache_data *cache_data, bool is_transactional, + enum_binlog_row_image row_image, 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; } /* Member functions to handle pending event for row-level logging. */ - template <class RowsEventT> Rows_log_event* - binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, - size_t needed, - bool is_transactional, - RowsEventT* hint); - Rows_log_event* binlog_get_pending_rows_event(bool is_transactional) const; - void binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional); + binlog_cache_mngr *binlog_get_cache_mngr() const; inline int binlog_flush_pending_rows_event(bool stmt_end) { return (binlog_flush_pending_rows_event(stmt_end, FALSE) || binlog_flush_pending_rows_event(stmt_end, TRUE)); } int binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional); - int binlog_remove_pending_rows_event(bool clear_maps, bool is_transactional); bool binlog_need_stmt_format(bool is_transactional) const { - return log_current_statement() && - !binlog_get_pending_rows_event(is_transactional); + if (!log_current_statement()) + return false; + auto *cache_mngr= binlog_get_cache_mngr(); + if (!cache_mngr) + return true; + return !binlog_get_pending_rows_event(cache_mngr, + use_trans_cache(this, + is_transactional)); } bool binlog_for_noop_dml(bool transactional_table); @@ -3448,12 +3616,13 @@ public: ha_rows cuted_fields; -private: /* number of rows we actually sent to the client, including "synthetic" rows in ROLLUP etc. */ ha_rows m_sent_row_count; + /* Number of rows for the total statement */ + ha_rows sent_row_count_for_statement; /** Number of rows read and/or evaluated for a statement. Used for @@ -3466,8 +3635,9 @@ private: filesort() before reading it for e.g. update. */ ha_rows m_examined_row_count; + /* Number of rows for the top level query */ + ha_rows examined_row_count_for_statement; -public: ha_rows get_sent_row_count() const { return m_sent_row_count; } @@ -3482,10 +3652,25 @@ public: { return affected_rows; } void set_sent_row_count(ha_rows count); - void set_examined_row_count(ha_rows count); - void inc_sent_row_count(ha_rows count); - void inc_examined_row_count(ha_rows count); + inline void inc_sent_row_count(ha_rows count) + { + m_sent_row_count+= count; + sent_row_count_for_statement+= count; + MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count); + } + inline void inc_examined_row_count_fast(ha_rows count= 1) + { + m_examined_row_count+= count; + examined_row_count_for_statement+= count; + } + inline void inc_examined_row_count(ha_rows count= 1) + { + inc_examined_row_count_fast(); + MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count); + } + + void ps_report_examined_row_count(); void inc_status_created_tmp_disk_tables(); void inc_status_created_tmp_files(); @@ -3512,7 +3697,7 @@ public: Check if the number of rows accessed by a statement exceeded LIMIT ROWS EXAMINED. If so, signal the query engine to stop execution. */ - void check_limit_rows_examined() + inline void check_limit_rows_examined() { if (++accessed_rows_and_keys > lex->limit_rows_examined_cnt) set_killed(ABORT_QUERY); @@ -3592,15 +3777,15 @@ public: /* Current or next transaction isolation level. When a connection is established, the value is taken from - @@session.tx_isolation (default transaction isolation for - the session), which is in turn taken from @@global.tx_isolation - (the global value). + @@session.transaction_isolation (default transaction isolation + for the session), which is in turn taken from + @@global.transaction_isolation (the global value). If there is no transaction started, this variable holds the value of the next transaction's isolation level. When a transaction starts, the value stored in this variable becomes "actual". At transaction commit or rollback, we assign this variable - again from @@session.tx_isolation. + again from @@session.transaction_isolation. The only statement that can otherwise change the value of this variable is SET TRANSACTION ISOLATION LEVEL. Its purpose is to effect the isolation level of the next @@ -3610,13 +3795,13 @@ public: transaction, this assignment (naturally) only affects the upcoming transaction. At the end of the current active transaction the value is - be reset again from @@session.tx_isolation, as described + be reset again from @@session.transaction_isolation, as described above. */ enum_tx_isolation tx_isolation; /* Current or next transaction access mode. - See comment above regarding tx_isolation. + See comment above regarding transaction_isolation. */ bool tx_read_only; enum_check_fields count_cuted_fields; @@ -3670,7 +3855,6 @@ public: This is used for taging error messages in the log files. */ LEX_CSTRING connection_name; - char default_master_connection_buff[MAX_CONNECTION_NAME+1]; uint8 password; /* 0, 1 or 2 */ uint8 failed_com_change_user; bool slave_thread; @@ -4133,6 +4317,8 @@ public: utime_after_query= current_utime(); } + Timeval_null safe_timeval_replacement_for_nonzero_datetime(const Datetime &); + /** Update server status after execution of a top level statement. Currently only checks if a query was slow, and assigns @@ -4236,104 +4422,23 @@ public: { return !stmt_arena->is_stmt_prepare(); } - inline void* trans_alloc(size_t size) + inline void* trans_alloc(size_t size) const { 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_CSTRING strmake_lex_cstring_trim_whitespace(const LEX_CSTRING &from) { - return strmake_lex_cstring(Lex_cstring(from).trim_whitespace(charset())); - } - - LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, size_t length) - { - if (!(lex_str->str= strmake_root(mem_root, str, length))) - { - lex_str->length= 0; - return 0; - } - lex_str->length= length; - return lex_str; - } - LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str, const char* str, size_t length) - { - if (!(lex_str->str= strmake_root(mem_root, str, length))) - { - lex_str->length= 0; - return 0; - } - lex_str->length= length; - return lex_str; - } - // Remove double quotes: aaa""bbb -> aaa"bbb - bool quote_unescape(LEX_CSTRING *dst, const LEX_CSTRING *src, char quote) - { - const char *tmp= src->str; - const char *tmpend= src->str + src->length; - char *to; - if (!(dst->str= to= (char *) alloc(src->length + 1))) - { - dst->length= 0; // Safety - return true; - } - for ( ; tmp < tmpend; ) - { - if ((*to++= *tmp++) == quote) - tmp++; // Skip double quotes - } - *to= 0; // End null for safety - dst->length= to - dst->str; - return false; - } - - LEX_CSTRING *make_clex_string(const char* str, size_t length) - { - LEX_CSTRING *lex_str; - char *tmp; - if (unlikely(!(lex_str= (LEX_CSTRING *)alloc_root(mem_root, - sizeof(LEX_CSTRING) + - length+1)))) - return 0; - tmp= (char*) (lex_str+1); - lex_str->str= tmp; - memcpy(tmp, str, length); - tmp[length]= 0; - lex_str->length= length; - return lex_str; - } - LEX_CSTRING *make_clex_string(const LEX_CSTRING from) - { - return make_clex_string(from.str, from.length); - } - - // Allocate LEX_STRING for character set conversion - bool alloc_lex_string(LEX_STRING *dst, size_t length) - { - if (likely((dst->str= (char*) alloc(length)))) - return false; - dst->length= 0; // Safety - return true; // EOM + return Query_arena::strmake_lex_cstring_trim_whitespace(from, charset()); } bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, const char *from, size_t from_length, - CHARSET_INFO *from_cs); + CHARSET_INFO *from_cs) const; bool reinterpret_string_from_binary(LEX_CSTRING *to, CHARSET_INFO *to_cs, - const char *from, size_t from_length); + const char *from, size_t from_length) + const; bool convert_string(LEX_CSTRING *to, CHARSET_INFO *to_cs, const char *from, size_t from_length, - CHARSET_INFO *from_cs) + CHARSET_INFO *from_cs) const { LEX_STRING tmp; bool rc= convert_string(&tmp, to_cs, from, from_length, from_cs); @@ -4343,7 +4448,7 @@ public: } bool convert_string(LEX_CSTRING *to, CHARSET_INFO *tocs, const LEX_CSTRING *from, CHARSET_INFO *fromcs, - bool simple_copy_is_possible) + bool simple_copy_is_possible) const { if (!simple_copy_is_possible) return unlikely(convert_string(to, tocs, from->str, from->length, fromcs)); @@ -4359,7 +4464,7 @@ public: */ bool convert_fix(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length, - String_copier *status); + String_copier *status) const; /* Same as above, but additionally sends ER_INVALID_CHARACTER_STRING @@ -4367,7 +4472,7 @@ public: */ bool convert_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, - const char *src, size_t src_length); + const char *src, size_t src_length) const; /* If either "dstcs" or "srccs" is &my_charset_bin, then performs native copying using copy_fix(). @@ -4375,16 +4480,18 @@ public: */ bool copy_fix(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length, - String_copier *status); + String_copier *status) const; /* Same as above, but additionally sends ER_INVALID_CHARACTER_STRING in case of bad byte sequences or Unicode conversion problems. */ bool copy_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst, - CHARSET_INFO *srccs, const char *src, size_t src_length); + CHARSET_INFO *srccs, const char *src, size_t src_length) + const; - bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs); + bool convert_string(String *s, CHARSET_INFO *from_cs, + CHARSET_INFO *to_cs); /* Check if the string is wellformed, raise an error if not wellformed. @@ -4395,7 +4502,8 @@ public: size_t length, CHARSET_INFO *cs) const; - bool to_ident_sys_alloc(Lex_ident_sys_st *to, const Lex_ident_cli_st *from); + bool to_ident_sys_alloc(Lex_ident_sys_st *to, + const Lex_ident_cli_st *from) const; /* Create a string literal with optional client->connection conversion. @@ -4405,7 +4513,8 @@ public: */ Item_basic_constant *make_string_literal(const char *str, size_t length, my_repertoire_t repertoire); - Item_basic_constant *make_string_literal(const Lex_string_with_metadata_st &str) + Item_basic_constant * + make_string_literal(const Lex_string_with_metadata_st &str) { my_repertoire_t repertoire= str.repertoire(variables.character_set_client); return make_string_literal(str.str, str.length, repertoire); @@ -4691,7 +4800,7 @@ public: void reset_sub_statement_state(Sub_statement_state *backup, uint new_state); void restore_sub_statement_state(Sub_statement_state *backup); void store_slow_query_state(Sub_statement_state *backup); - void reset_slow_query_state(); + void reset_slow_query_state(Sub_statement_state *backup); void add_slow_query_state(Sub_statement_state *backup); void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup); @@ -5461,6 +5570,8 @@ public: bool is_binlog_dump_thread(); #endif + bool check_slave_ignored_db_with_error(const Lex_ident_db &db) const; + inline ulong wsrep_binlog_format(ulong binlog_format) const { #ifdef WITH_WSREP @@ -5783,6 +5894,15 @@ public: return false; return !is_set_timestamp_forbidden(this); } + /* + Return true if we are in stored procedure, not in a function or + trigger. + */ + bool in_stored_procedure() + { + return (lex->sphead != 0 && + !(in_sub_stmt & (SUB_STMT_FUNCTION | SUB_STMT_TRIGGER))); + } }; @@ -6139,6 +6259,8 @@ public: }; +class sp_instr_cpush; + /* A mediator between stored procedures and server side cursors */ class sp_lex_keeper; class sp_cursor: public sp_cursor_statistics @@ -6175,19 +6297,17 @@ private: public: sp_cursor() :result(NULL, false), - m_lex_keeper(NULL), server_side_cursor(NULL) { } - sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, bool view_structure_only) + sp_cursor(THD *thd_arg, bool view_structure_only) :result(thd_arg, view_structure_only), - m_lex_keeper(lex_keeper), server_side_cursor(NULL) {} virtual ~sp_cursor() { destroy(); } - sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; } + virtual sp_lex_keeper *get_lex_keeper() { return nullptr; } int open(THD *thd); @@ -6200,17 +6320,16 @@ public: bool export_structure(THD *thd, Row_definition_list *list); - void reset(THD *thd_arg, sp_lex_keeper *lex_keeper) + void reset(THD *thd_arg) { sp_cursor_statistics::reset(); result.reset(thd_arg); - m_lex_keeper= lex_keeper; server_side_cursor= NULL; } + virtual sp_instr_cpush *get_push_instr() { return nullptr; } private: Select_fetch_into_spvars result; - sp_lex_keeper *m_lex_keeper; Server_side_cursor *server_side_cursor; void destroy(); }; @@ -6436,6 +6555,7 @@ public: Item **items_to_copy; /* Fields in tmp table */ TMP_ENGINE_COLUMNDEF *recinfo, *start_recinfo; KEY *keyinfo; + ulong *rec_per_key; ha_rows end_write_records; /** Number of normal fields in the query, including those referred to @@ -7011,13 +7131,13 @@ public: /* Cost to materialize - execute the sub-join and write rows into temp.table */ - Cost_estimate materialization_cost; + double materialization_cost; /* Cost to make one lookup in the temptable */ - Cost_estimate lookup_cost; + double lookup_cost; /* Cost of scanning the materialized table */ - Cost_estimate scan_cost; + double scan_cost; /* --- Execution structures ---------- */ @@ -7162,6 +7282,16 @@ public: } bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs); bool append_to(THD *thd, String *to) const; + /* + Convert Table_ident::m_db to a valid internal database name: + - validated with Lex_ident_fs::check_db_name() + - optionally lower-cased when lower_case_table_names==1 + + @param arena - the arena to allocate the lower-cased copy on, when needed. + @return {NULL,0} in case of EOM or invalid database name, + or a good identifier otherwise. + */ + Lex_ident_db to_ident_db_internal_with_error(Query_arena *arena) const; }; @@ -7185,7 +7315,7 @@ public: :Table_ident(thd, db, table, false), m_column(*column) { } - bool resolve_type_ref(THD *thd, Column_definition *def); + bool resolve_type_ref(THD *thd, Column_definition *def) const; bool append_to(THD *thd, String *to) const; }; @@ -7294,6 +7424,7 @@ public: enum_duplicates handle_duplicates, bool ignore); ~multi_update(); bool init(THD *thd); + bool init_for_single_table(THD *thd); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int send_data(List<Item> &items); bool initialize_tables (JOIN *join); @@ -7302,6 +7433,8 @@ public: bool send_eof(); inline ha_rows num_found() const { return found; } inline ha_rows num_updated() const { return updated; } + inline void set_found (ha_rows n) { found= n; } + inline void set_updated (ha_rows n) { updated= n; } virtual void abort_result_set(); void update_used_tables(); void prepare_to_read_rows(); @@ -7604,11 +7737,38 @@ inline void handler::increment_statistics(ulong SSV::*offset) const table->in_use->check_limit_rows_examined(); } +inline void handler::fast_increment_statistics(ulong SSV::*offset) const +{ + status_var_increment(table->in_use->status_var.*offset); +} + inline void handler::decrement_statistics(ulong SSV::*offset) const { status_var_decrement(table->in_use->status_var.*offset); } +/* Update references in the handler to the table */ + +inline void handler::set_table(TABLE* table_arg) +{ + table= table_arg; + costs= &table_arg->s->optimizer_costs; +} + +inline bool handler::pk_is_clustering_key(uint index) const +{ + /* + We have to check for MAX_INDEX as table->s->primary_key can be + MAX_KEY in the case where there is no primary key. + */ + return index != MAX_KEY && is_clustering_key(index); +} + +inline bool handler::is_clustering_key(uint index) const +{ + DBUG_ASSERT(index != MAX_KEY); + return table->is_clustering_key(index); +} inline int handler::ha_ft_read(uchar *buf) { @@ -7679,6 +7839,22 @@ inline bool handler::has_long_unique() return table->s->long_unique_table; } +/** + Return whether the handler is root. + @return false if table is maintained by different handlerton, true otherwise. + @note The implementation supposes that the same handler can't be found as both + root and non-root. + + There are two known cases when it's non-root: + 1. under partition's ha_write_row() (also true for copy_partitions()) + 2. under ha_mroonga::wrapper_write_row(); + same applies for ha_delete_row/ha_update_row. +*/ +inline bool handler::is_root_handler() const +{ + return ht == table->file->ht; +} + extern pthread_attr_t *get_connection_attrib(void); /** @@ -7732,6 +7908,8 @@ inline bool binlog_should_compress(size_t len) len >= opt_bin_log_compress_min_len; } +void binlog_prepare_row_images(TABLE* table, + enum_binlog_row_image row_image); /** Save thd sql_mode on instantiation. @@ -7977,8 +8155,13 @@ public: !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); + /* + Make copies of "db" and "name" on the memory root in internal format: + - Lower-case "db" if lower-case-table-names==1. + - Preserve "name" as is. + */ + bool copy_sp_name_internal(MEM_ROOT *mem_root, const LEX_CSTRING &db, + const LEX_CSTRING &name); // Export db and name as a qualified name string: 'db.name' size_t make_qname(char *dst, size_t dstlen, bool casedn_name) const @@ -7988,7 +8171,6 @@ public: // Export db and name as a qualified name string, allocate on mem_root. LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_name) const { - DBUG_SLOW_ASSERT(ok_for_lower_case_names(m_db.str)); return Identifier_chain2(m_db, m_name).make_qname(mem_root, casedn_name); } @@ -8249,5 +8431,23 @@ public: } }; + +/** + Make a new string allocated on THD's mem-root. + + @param thd thread handler. + @param start_ptr start of the new string. + @param end_ptr end of the new string. + + @return LEX_CSTRING object, containing a pointer to a newly + constructed/allocated string, and its length. The data member + LEX_CSTRING::str has the value nullptr in case of out-of-memory error. +*/ + +LEX_CSTRING make_string(THD *thd, const char *start_ptr, + const char *end_ptr); + +#include "deprecation.h" + #endif /* MYSQL_SERVER */ #endif /* SQL_CLASS_INCLUDED */ |