summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt26
-rw-r--r--sql/backup.cc3
-rw-r--r--sql/bounded_queue.h8
-rw-r--r--sql/create_options.cc2
-rw-r--r--sql/datadict.cc2
-rw-r--r--sql/debug_sync.cc30
-rw-r--r--sql/derror.cc8
-rw-r--r--sql/discover.cc3
-rw-r--r--sql/event_data_objects.cc47
-rw-r--r--sql/event_data_objects.h13
-rw-r--r--sql/event_db_repository.cc3
-rw-r--r--sql/event_queue.cc6
-rw-r--r--sql/event_scheduler.cc21
-rw-r--r--sql/events.cc28
-rw-r--r--sql/events.h2
-rw-r--r--sql/field.cc122
-rw-r--r--sql/field.h80
-rw-r--r--sql/filesort.cc1043
-rw-r--r--sql/filesort.h15
-rw-r--r--sql/filesort_utils.cc19
-rw-r--r--sql/filesort_utils.h4
-rw-r--r--sql/gcalc_slicescan.cc2
-rw-r--r--sql/gstream.cc4
-rw-r--r--sql/ha_partition.cc87
-rw-r--r--sql/handle_connections_win.cc2
-rw-r--r--sql/handler.cc171
-rw-r--r--sql/handler.h138
-rw-r--r--sql/hash_filo.h29
-rw-r--r--sql/hostname.cc13
-rw-r--r--sql/item.cc14
-rw-r--r--sql/item.h22
-rw-r--r--sql/item_cmpfunc.cc15
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_create.cc47
-rw-r--r--sql/item_func.cc50
-rw-r--r--sql/item_func.h66
-rw-r--r--sql/item_jsonfunc.h11
-rw-r--r--sql/item_strfunc.cc3
-rw-r--r--sql/item_subselect.cc15
-rw-r--r--sql/keycaches.cc10
-rw-r--r--sql/lex.h2
-rw-r--r--sql/lock.cc31
-rw-r--r--sql/log.cc58
-rw-r--r--sql/log.h16
-rw-r--r--sql/log_event.cc61
-rw-r--r--sql/log_event.h14
-rw-r--r--sql/log_event_client.cc20
-rw-r--r--sql/log_event_old.cc18
-rw-r--r--sql/log_event_server.cc55
-rw-r--r--sql/mdl.cc75
-rw-r--r--sql/mdl.h36
-rw-r--r--sql/mysqld.cc394
-rw-r--r--sql/mysqld.h140
-rw-r--r--sql/net_serv.cc25
-rw-r--r--sql/opt_range.cc51
-rw-r--r--sql/opt_split.cc12
-rw-r--r--sql/opt_subselect.cc4
-rw-r--r--sql/opt_trace.cc2
-rw-r--r--sql/partition_info.cc3
-rw-r--r--sql/privilege.h201
-rw-r--r--sql/protocol.cc51
-rw-r--r--sql/proxy_protocol.cc3
-rw-r--r--sql/records.cc38
-rw-r--r--sql/repl_failsafe.cc7
-rw-r--r--sql/rpl_filter.cc23
-rw-r--r--sql/rpl_gtid.cc60
-rw-r--r--sql/rpl_gtid.h2
-rw-r--r--sql/rpl_injector.cc3
-rw-r--r--sql/rpl_mi.cc16
-rw-r--r--sql/rpl_parallel.cc10
-rw-r--r--sql/rpl_rli.cc18
-rw-r--r--sql/rpl_tblmap.cc13
-rw-r--r--sql/rpl_utility.cc3
-rw-r--r--sql/rpl_utility_server.cc2
-rw-r--r--sql/scheduler.h11
-rw-r--r--sql/select_handler.cc26
-rw-r--r--sql/semisync_master.cc4
-rw-r--r--sql/semisync_master.h2
-rw-r--r--sql/semisync_master_ack_receiver.cc2
-rw-r--r--sql/session_tracker.cc10
-rw-r--r--sql/session_tracker.h14
-rw-r--r--sql/set_var.cc38
-rw-r--r--sql/set_var.h2
-rw-r--r--sql/share/errmsg-utf8.txt5
-rw-r--r--sql/signal_handler.cc18
-rw-r--r--sql/slave.cc21
-rw-r--r--sql/sp.cc68
-rw-r--r--sql/sp.h46
-rw-r--r--sql/sp_cache.cc2
-rw-r--r--sql/sp_head.cc210
-rw-r--r--sql/sp_head.h98
-rw-r--r--sql/sp_pcontext.cc6
-rw-r--r--sql/sp_rcontext.cc1
-rw-r--r--sql/sql_acl.cc267
-rw-r--r--sql/sql_acl.h2
-rw-r--r--sql/sql_admin.cc17
-rw-r--r--sql/sql_alter.cc2
-rw-r--r--sql/sql_alter.h4
-rw-r--r--sql/sql_analyze_stmt.cc23
-rw-r--r--sql/sql_analyze_stmt.h20
-rw-r--r--sql/sql_array.h24
-rw-r--r--sql/sql_audit.cc2
-rw-r--r--sql/sql_base.cc40
-rw-r--r--sql/sql_binlog.cc7
-rw-r--r--sql/sql_cache.cc16
-rw-r--r--sql/sql_class.cc78
-rw-r--r--sql/sql_class.h201
-rw-r--r--sql/sql_cmd.h2
-rw-r--r--sql/sql_connect.cc52
-rw-r--r--sql/sql_const.h2
-rw-r--r--sql/sql_cte.cc136
-rw-r--r--sql/sql_cte.h11
-rw-r--r--sql/sql_db.cc23
-rw-r--r--sql/sql_delete.cc1
-rw-r--r--sql/sql_derived.cc4
-rw-r--r--sql/sql_error.cc2
-rw-r--r--sql/sql_explain.h2
-rw-r--r--sql/sql_handler.cc17
-rw-r--r--sql/sql_hset.h11
-rw-r--r--sql/sql_insert.cc18
-rw-r--r--sql/sql_join_cache.cc20
-rw-r--r--sql/sql_lex.cc93
-rw-r--r--sql/sql_lex.h12
-rw-r--r--sql/sql_list.h3
-rw-r--r--sql/sql_manager.cc3
-rw-r--r--sql/sql_parse.cc126
-rw-r--r--sql/sql_partition.cc7
-rw-r--r--sql/sql_partition.h1
-rw-r--r--sql/sql_plugin.cc72
-rw-r--r--sql/sql_prepare.cc56
-rw-r--r--sql/sql_profile.cc5
-rw-r--r--sql/sql_profile.h4
-rw-r--r--sql/sql_repl.cc18
-rw-r--r--sql/sql_select.cc260
-rw-r--r--sql/sql_select.h10
-rw-r--r--sql/sql_sequence.cc7
-rw-r--r--sql/sql_servers.cc16
-rw-r--r--sql/sql_show.cc175
-rw-r--r--sql/sql_show.h7
-rw-r--r--sql/sql_sort.h350
-rw-r--r--sql/sql_statistics.cc2
-rw-r--r--sql/sql_string.cc30
-rw-r--r--sql/sql_string.h31
-rw-r--r--sql/sql_table.cc155
-rw-r--r--sql/sql_test.cc3
-rw-r--r--sql/sql_time.cc3
-rw-r--r--sql/sql_trigger.cc28
-rw-r--r--sql/sql_type.h175
-rw-r--r--sql/sql_type_geom.cc8
-rw-r--r--sql/sql_type_geom.h10
-rw-r--r--sql/sql_udf.cc15
-rw-r--r--sql/sql_union.cc4
-rw-r--r--sql/sql_update.cc1
-rw-r--r--sql/sql_view.cc11
-rw-r--r--sql/sql_window.cc6
-rw-r--r--sql/sql_yacc.yy77
-rw-r--r--sql/sys_vars.cc202
-rw-r--r--sql/sys_vars.ic3
-rw-r--r--sql/table.cc38
-rw-r--r--sql/table.h17
-rw-r--r--sql/table_cache.cc8
-rw-r--r--sql/temporary_tables.cc9
-rw-r--r--sql/thr_malloc.cc7
-rw-r--r--sql/thr_malloc.h4
-rw-r--r--sql/threadpool_common.cc18
-rw-r--r--sql/threadpool_generic.cc3
-rw-r--r--sql/transaction.cc49
-rw-r--r--sql/tztime.cc26
-rw-r--r--sql/uniques.cc18
-rw-r--r--sql/unireg.cc4
-rw-r--r--sql/wsrep_binlog.cc2
-rw-r--r--sql/wsrep_mysqld.cc6
-rw-r--r--sql/wsrep_sst.cc14
-rw-r--r--sql/wsrep_var.cc30
-rw-r--r--sql/xa.cc63
175 files changed, 5613 insertions, 1932 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index da046d0ec3a..d0a3e8a437a 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -433,16 +433,9 @@ ADD_CUSTOM_TARGET(distclean
VERBATIM
)
-IF(INSTALL_LAYOUT STREQUAL "STANDALONE")
-
-# Copy db.opt into data/test/
-SET(DBOPT_FILE ${CMAKE_SOURCE_DIR}/support-files/db.opt )
-INSTALL(FILES ${DBOPT_FILE} DESTINATION data/test COMPONENT DataFiles)
-
-# Install initial database on windows
-IF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
-
- IF(MSVC_IDE OR CMAKE_GENERATOR MATCHES "Xcode")
+# Install initial database (default on windows, optional target elsewhere)
+IF(TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
+ IF(GENERATOR_IS_MULTI_CONFIG)
SET (CONFIG_PARAM -DCONFIG=${CMAKE_CFG_INTDIR})
ENDIF()
MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/data)
@@ -461,15 +454,16 @@ IF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS mysqld
)
+ IF(WIN32)
+ SET(ALL_ON_WINDOWS ALL)
+ ELSE()
+ SET(ALL_ON_WINDOWS)
+ ENDIF()
ADD_CUSTOM_TARGET(initial_database
- ALL
+ ${ALL_ON_WINDOWS}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
)
-ELSE()
- # Not windows or cross compiling, just install an empty directory
- INSTALL(FILES ${DUMMY_FILE} DESTINATION data/mysql COMPONENT DataFiles)
-ENDIF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
-ENDIF(INSTALL_LAYOUT STREQUAL "STANDALONE")
+ENDIF()
IF(WIN32)
SET(my_bootstrap_sql ${CMAKE_CURRENT_BINARY_DIR}/my_bootstrap.sql)
diff --git a/sql/backup.cc b/sql/backup.cc
index 1a0341ad9a4..40791e27416 100644
--- a/sql/backup.cc
+++ b/sql/backup.cc
@@ -161,7 +161,8 @@ static bool backup_start(THD *thd)
DBUG_RETURN(1);
}
- mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_START, MDL_EXPLICIT);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_START,
+ MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
DBUG_RETURN(1);
diff --git a/sql/bounded_queue.h b/sql/bounded_queue.h
index cd710d835aa..07ab6dbaab9 100644
--- a/sql/bounded_queue.h
+++ b/sql/bounded_queue.h
@@ -59,7 +59,8 @@ public:
*/
typedef uint (*keymaker_function)(Sort_param *param,
Key_type *to,
- Element_type *from);
+ Element_type *from,
+ bool packing_keys);
/**
Function for comparing two keys.
@@ -181,11 +182,12 @@ void Bounded_queue<Element_type, Key_type>::push(Element_type *element)
{
// Replace top element with new key, and re-order the queue.
Key_type **pq_top= reinterpret_cast<Key_type **>(queue_top(&m_queue));
- (void)(*m_keymaker)(m_sort_param, *pq_top, element);
+ (void)(*m_keymaker)(m_sort_param, *pq_top, element, false);
queue_replace_top(&m_queue);
} else {
// Insert new key into the queue.
- (*m_keymaker)(m_sort_param, m_sort_keys[m_queue.elements], element);
+ (*m_keymaker)(m_sort_param, m_sort_keys[m_queue.elements],
+ element, false);
queue_insert(&m_queue,
reinterpret_cast<uchar*>(&m_sort_keys[m_queue.elements]));
}
diff --git a/sql/create_options.cc b/sql/create_options.cc
index 817c4ba46e0..04469120db1 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -407,7 +407,7 @@ static bool resolve_sysvars(handlerton *hton, ha_create_table_option *rules)
return 1;
}
DBUG_ASSERT(str.length());
- opt->values= my_strndup(str.ptr(), str.length()-1, MYF(MY_WME));
+ opt->values= my_strndup(PSI_INSTRUMENT_ME, str.ptr(), str.length()-1, MYF(MY_WME));
if (!opt->values)
return 1;
break;
diff --git a/sql/datadict.cc b/sql/datadict.cc
index da8376d8b1a..5cfda166b2b 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -25,7 +25,7 @@ static int read_string(File file, uchar**to, size_t length)
DBUG_ENTER("read_string");
/* This can't use MY_THREAD_SPECIFIC as it's used on server start */
- if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) ||
+ if (!(*to= (uchar*) my_malloc(PSI_INSTRUMENT_ME, length+1,MYF(MY_WME))) ||
mysql_file_read(file, *to, length, MYF(MY_NABP)))
{
my_free(*to);
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index af541b1bb32..fdca2c47dbc 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -122,6 +122,25 @@ static void init_debug_sync_psi_keys(void)
/**
+ Set the THD::proc_info without instrumentation.
+ This method is private to DEBUG_SYNC,
+ and on purpose avoid any use of:
+ - the SHOW PROFILE instrumentation
+ - the PERFORMANCE_SCHEMA instrumentation
+ so that using DEBUG_SYNC() in the server code
+ does not cause the instrumentations to record
+ spurious data.
+*/
+static const char*
+debug_sync_thd_proc_info(THD *thd, const char* info)
+{
+ const char* old_proc_info= thd->proc_info;
+ thd->proc_info= info;
+ return old_proc_info;
+}
+
+
+/**
Initialize the debug sync facility at server start.
@return status
@@ -236,7 +255,8 @@ void debug_sync_init_thread(THD *thd)
if (opt_debug_sync_timeout)
{
thd->debug_sync_control= (st_debug_sync_control*)
- my_malloc(sizeof(st_debug_sync_control),
+ my_malloc(PSI_NOT_INSTRUMENTED,
+ sizeof(st_debug_sync_control),
MYF(MY_WME | MY_ZEROFILL | MY_THREAD_SPECIFIC));
if (!thd->debug_sync_control)
{
@@ -657,7 +677,7 @@ static st_debug_sync_action *debug_sync_get_action(THD *thd,
if (ds_control->ds_active > ds_control->ds_allocated)
{
uint new_alloc= ds_control->ds_active + 3;
- void *new_action= my_realloc(ds_control->ds_action,
+ void *new_action= my_realloc(PSI_NOT_INSTRUMENTED, ds_control->ds_action,
new_alloc * sizeof(st_debug_sync_action),
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (!new_action)
@@ -1364,7 +1384,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
strxnmov(ds_control->ds_proc_info, sizeof(ds_control->ds_proc_info)-1,
"debug sync point: ", action->sync_point.c_ptr(), NullS);
old_proc_info= thd->proc_info;
- thd_proc_info(thd, ds_control->ds_proc_info);
+ debug_sync_thd_proc_info(thd, ds_control->ds_proc_info);
}
/*
@@ -1482,11 +1502,11 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
mysql_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= old_mutex;
thd->mysys_var->current_cond= old_cond;
- thd_proc_info(thd, old_proc_info);
+ debug_sync_thd_proc_info(thd, old_proc_info);
mysql_mutex_unlock(&thd->mysys_var->mutex);
}
else
- thd_proc_info(thd, old_proc_info);
+ debug_sync_thd_proc_info(thd, old_proc_info);
}
else
{
diff --git a/sql/derror.cc b/sql/derror.cc
index 7a79833c26c..1c10bdfdd92 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -120,8 +120,9 @@ bool init_errmessage(void)
all_errors+= errors_per_range[i];
if (!(original_error_messages= (const char***)
- my_malloc((all_errors + MAX_ERROR_RANGES)* sizeof(void*),
- MYF(MY_ZEROFILL))))
+ my_malloc(PSI_NOT_INSTRUMENTED,
+ (all_errors + MAX_ERROR_RANGES)*sizeof(void*),
+ MYF(MY_ZEROFILL))))
DBUG_RETURN(TRUE);
errmsgs= (const char**)(original_error_messages + MAX_ERROR_RANGES);
@@ -315,7 +316,8 @@ bool read_texts(const char *file_name, const char *language,
DBUG_RETURN(1);
if (!(*data= (const char***)
- my_malloc((size_t) ((MAX_ERROR_RANGES+1) * sizeof(char**) +
+ my_malloc(key_memory_errmsgs,
+ (size_t) ((MAX_ERROR_RANGES+1) * sizeof(char**) +
MY_MAX(msg_file.text_length, msg_file.errors * 2)+
msg_file.errors * sizeof(char*)),
MYF(MY_WME))))
diff --git a/sql/discover.cc b/sql/discover.cc
index 3e41388ed51..e49a2a3b0c0 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -76,7 +76,8 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len)
// Read whole frm file
error= 3;
- if (!(read_data= (uchar*)my_malloc(read_len, MYF(MY_WME))))
+ if (!(read_data= (uchar*)my_malloc(key_memory_frm_string, read_len,
+ MYF(MY_WME))))
goto err;
if (mysql_file_read(file, read_data, read_len, MYF(MY_NABP)))
{
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 5ea8300b7e4..bd457fba4fa 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -25,13 +25,13 @@
// date_add_interval,
// calc_time_diff
#include "tztime.h" // my_tz_find, my_tz_OFFSET0, struct Time_zone
-#include "sql_acl.h" // EVENT_ACL, SUPER_ACL
#include "sp.h" // load_charset, load_collation
#include "events.h"
#include "event_data_objects.h"
#include "event_db_repository.h"
#include "sp_head.h"
#include "sql_show.h" // append_definer, append_identifier
+#include "mysql/psi/mysql_sp.h"
#ifdef WITH_WSREP
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
@@ -40,6 +40,18 @@
@{
*/
+#ifdef HAVE_PSI_INTERFACE
+void init_scheduler_psi_keys()
+{
+ const char *category= "scheduler";
+
+ PSI_server->register_statement(category, & Event_queue_element_for_exec::psi_info, 1);
+}
+
+PSI_statement_info Event_queue_element_for_exec::psi_info=
+{ 0, "event", 0};
+#endif
+
/*************************************************************************/
/**
@@ -173,11 +185,13 @@ Event_creation_ctx::load_from_db(THD *thd,
*/
bool
-Event_queue_element_for_exec::init(const LEX_CSTRING *db, const LEX_CSTRING *n)
+Event_queue_element_for_exec::init(const LEX_CSTRING &db, const LEX_CSTRING &n)
{
- if (!(dbname.str= my_strndup(db->str, dbname.length= db->length, MYF(MY_WME))))
+ if (!(dbname.str= my_strndup(key_memory_Event_queue_element_for_exec_names,
+ db.str, dbname.length= db.length, MYF(MY_WME))))
return TRUE;
- if (!(name.str= my_strndup(n->str, name.length= n->length, MYF(MY_WME))))
+ if (!(name.str= my_strndup(key_memory_Event_queue_element_for_exec_names,
+ n.str, name.length= n.length, MYF(MY_WME))))
{
my_free(const_cast<char*>(dbname.str));
return TRUE;
@@ -211,7 +225,7 @@ Event_basic::Event_basic()
{
DBUG_ENTER("Event_basic::Event_basic");
/* init memory root */
- init_sql_alloc(&mem_root, "Event_basic", 256, 512, MYF(0));
+ init_sql_alloc(key_memory_event_basic_root, &mem_root, 256, 512, MYF(0));
dbname.str= name.str= NULL;
dbname.length= name.length= 0;
time_zone= NULL;
@@ -1425,15 +1439,23 @@ Event_job_data::execute(THD *thd, bool drop)
{
Parser_state parser_state;
+ sql_digest_state *parent_digest= thd->m_digest;
+ PSI_statement_locker *parent_locker= thd->m_statement_psi;
+ bool res;
+
if (parser_state.init(thd, thd->query(), thd->query_length()))
goto end;
- if (parse_sql(thd, & parser_state, creation_ctx))
+ thd->m_digest= NULL;
+ thd->m_statement_psi= NULL;
+ res= parse_sql(thd, & parser_state, creation_ctx);
+ thd->m_digest= parent_digest;
+ thd->m_statement_psi= parent_locker;
+
+ if (res)
{
- sql_print_error("Event Scheduler: "
- "%serror during compilation of %s.%s",
- thd->is_fatal_error ? "fatal " : "",
- (const char *) dbname.str, (const char *) name.str);
+ sql_print_error("Event Scheduler: %serror during compilation of %s.%s",
+ thd->is_fatal_error ? "fatal " : "", dbname.str, name.str);
goto end;
}
}
@@ -1456,6 +1478,9 @@ Event_job_data::execute(THD *thd, bool drop)
sphead->set_creation_ctx(creation_ctx);
sphead->optimize();
+ sphead->m_sp_share= MYSQL_GET_SP_SHARE(SP_TYPE_EVENT,
+ dbname.str, static_cast<uint>(dbname.length),
+ name.str, static_cast<uint>(name.length));
ret= sphead->execute_procedure(thd, &empty_item_list);
/*
There is no pre-locking and therefore there should be no
@@ -1492,7 +1517,7 @@ end:
*/
privilege_t saved_master_access(thd->security_ctx->master_access);
- thd->security_ctx->master_access |= SUPER_ACL;
+ thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
bool save_tx_read_only= thd->tx_read_only;
thd->tx_read_only= false;
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index e5e3e4eb087..c20a8c31425 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -30,6 +30,8 @@ class THD;
class Time_zone;
struct TABLE;
+void init_scheduler_psi_keys(void);
+
class Event_queue_element_for_exec
{
public:
@@ -37,7 +39,7 @@ public:
~Event_queue_element_for_exec();
bool
- init(const LEX_CSTRING *dbname, const LEX_CSTRING *name);
+ init(const LEX_CSTRING &dbname, const LEX_CSTRING &name);
LEX_CSTRING dbname;
LEX_CSTRING name;
@@ -48,6 +50,15 @@ private:
/* Prevent use of these */
Event_queue_element_for_exec(const Event_queue_element_for_exec &);
void operator=(Event_queue_element_for_exec &);
+#ifdef HAVE_PSI_INTERFACE
+public:
+ PSI_statement_info* get_psi_info()
+ {
+ return & psi_info;
+ }
+
+ static PSI_statement_info psi_info;
+#endif
};
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 6783338ab10..af43d92dea7 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -24,7 +24,6 @@
#include "sql_db.h" // get_default_db_collation
#include "sql_time.h" // interval_type_to_name
#include "tztime.h" // struct Time_zone
-#include "sql_acl.h" // SUPER_ACL, MYSQL_DB_FIELD_COUNT, mysql_db_table_fields
#include "records.h" // init_read_record, end_read_record
#include "sp_head.h"
#include "event_data_objects.h"
@@ -1128,7 +1127,7 @@ update_timing_fields_for_event(THD *thd,
*/
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
- DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL);
+ DBUG_ASSERT(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY);
if (open_event_table(thd, TL_WRITE, &table))
goto end;
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 6b3f5777df3..71d1d2c68ee 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -24,6 +24,7 @@
#include "tztime.h" // my_tz_find, my_tz_OFFSET0, struct Time_zone
#include "log.h" // sql_print_error
#include "sql_class.h" // struct THD
+#include "mysql/psi/mysql_sp.h"
/**
@addtogroup Event_Scheduler
@@ -351,6 +352,9 @@ Event_queue::drop_matching_events(THD *thd, const LEX_CSTRING *pattern,
is ok.
*/
queue_remove(&queue, i);
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(SP_TYPE_EVENT, et->dbname.str, static_cast<uint>(et->dbname.length),
+ et->name.str, static_cast<uint>(et->name.length));
delete et;
}
else
@@ -637,7 +641,7 @@ Event_queue::get_top_for_execution_if_time(THD *thd,
}
if (!(*event_name= new Event_queue_element_for_exec()) ||
- (*event_name)->init(&top->dbname, &top->name))
+ (*event_name)->init(top->dbname, top->name))
{
ret= TRUE;
break;
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 9a8869e2fb3..0e8e4826939 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -22,7 +22,7 @@
#include "event_queue.h"
#include "event_db_repository.h"
#include "sql_connect.h" // init_new_connection_handler_thread
-#include "sql_acl.h" // SUPER_ACL
+#include "sql_class.h"
/**
@addtogroup Event_Scheduler
@@ -291,6 +291,15 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
DBUG_ASSERT(thd->m_digest == NULL);
DBUG_ASSERT(thd->m_statement_psi == NULL);
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
+ PSI_statement_locker_state state;
+ thd->m_statement_psi= MYSQL_START_STATEMENT(& state,
+ event->get_psi_info()->m_key,
+ event->dbname.str,
+ event->dbname.length,
+ thd->charset(), NULL);
+#endif
+
thd->thread_stack= &my_stack; // remember where our stack is
res= post_init_event_thread(thd);
@@ -319,7 +328,10 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
job_data.definer.str,
job_data.dbname.str, job_data.name.str);
end:
- DBUG_ASSERT(thd->m_statement_psi == NULL);
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
+ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->m_statement_psi= NULL;
+#endif
DBUG_ASSERT(thd->m_digest == NULL);
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
event->name.str));
@@ -405,13 +417,14 @@ Event_scheduler::start(int *err_no)
Same goes for transaction access mode. Set it to read-write for this thd.
*/
- new_thd->security_ctx->master_access |= SUPER_ACL;
+ new_thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
new_thd->variables.tx_read_only= false;
new_thd->tx_read_only= false;
/* This should not be marked with MY_THREAD_SPECIFIC */
scheduler_param_value=
- (struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0));
+ (struct scheduler_param *)my_malloc(key_memory_Event_scheduler_scheduler_param,
+ sizeof(struct scheduler_param), MYF(0));
scheduler_param_value->thd= new_thd;
scheduler_param_value->scheduler= this;
diff --git a/sql/events.cc b/sql/events.cc
index 68e013adfae..3bed25e20c3 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -34,6 +34,7 @@
#include "sp_head.h" // for Stored_program_creation_ctx
#include "set_var.h"
#include "lock.h" // lock_object_name
+#include "mysql/psi/mysql_sp.h"
/**
@addtogroup Event_Scheduler
@@ -620,6 +621,9 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
/* Binlog the drop event. */
DBUG_ASSERT(thd->query() && thd->query_length());
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(SP_TYPE_EVENT,
+ dbname->str, static_cast<uint>(dbname->length), name->str, static_cast<uint>(name->length));
}
thd->restore_stmt_binlog_format(save_binlog_format);
@@ -832,13 +836,12 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
*/
if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS)
{
- DBUG_ASSERT(thd->lex->first_select_lex()->db.str);
- if (!is_infoschema_db(&thd->lex->first_select_lex()->db) && // There is no events in I_S
- check_access(thd, EVENT_ACL, thd->lex->first_select_lex()->db.str,
- NULL, NULL, 0, 0))
+ LEX_CSTRING *lexdb= &thd->lex->first_select_lex()->db;
+ DBUG_ASSERT(lexdb);
+ if (!is_infoschema_db(lexdb) && !is_perfschema_db(lexdb) &&
+ check_access(thd, EVENT_ACL, lexdb->str, NULL, NULL, 0, 0))
DBUG_RETURN(1);
- db= normalize_db_name(thd->lex->first_select_lex()->db.str,
- db_tmp, sizeof(db_tmp));
+ db= normalize_db_name(lexdb->str, db_tmp, sizeof(db_tmp));
}
ret= db_repository->fill_schema_events(thd, tables, db);
@@ -1028,6 +1031,8 @@ PSI_stage_info stage_waiting_on_empty_queue= { 0, "Waiting on empty queue", 0};
PSI_stage_info stage_waiting_for_next_activation= { 0, "Waiting for next activation", 0};
PSI_stage_info stage_waiting_for_scheduler_to_stop= { 0, "Waiting for the scheduler to stop", 0};
+PSI_memory_key key_memory_event_basic_root;
+
#ifdef HAVE_PSI_INTERFACE
PSI_stage_info *all_events_stages[]=
{
@@ -1036,6 +1041,11 @@ PSI_stage_info *all_events_stages[]=
& stage_waiting_for_scheduler_to_stop
};
+static PSI_memory_info all_events_memory[]=
+{
+ { &key_memory_event_basic_root, "Event_basic::mem_root", PSI_FLAG_GLOBAL}
+};
+
static void init_events_psi_keys(void)
{
const char* category= "sql";
@@ -1053,6 +1063,10 @@ static void init_events_psi_keys(void)
count= array_elements(all_events_stages);
mysql_stage_register(category, all_events_stages, count);
+ count= array_elements(all_events_memory);
+ mysql_memory_register(category, all_events_memory, count);
+
+ init_scheduler_psi_keys();
}
#endif /* HAVE_PSI_INTERFACE */
@@ -1158,7 +1172,7 @@ Events::load_events_from_db(THD *thd)
*/
privilege_t saved_master_access(thd->security_ctx->master_access);
- thd->security_ctx->master_access |= SUPER_ACL;
+ thd->security_ctx->master_access |= PRIV_IGNORE_READ_ONLY;
bool save_tx_read_only= thd->tx_read_only;
thd->tx_read_only= false;
diff --git a/sql/events.h b/sql/events.h
index 9e1651c767a..2fb13d7c807 100644
--- a/sql/events.h
+++ b/sql/events.h
@@ -31,6 +31,8 @@ extern PSI_cond_key key_event_scheduler_COND_state;
extern PSI_thread_key key_thread_event_scheduler, key_thread_event_worker;
#endif /* HAVE_PSI_INTERFACE */
+extern PSI_memory_key key_memory_event_basic_root;
+
/* Always defined, for SHOW PROCESSLIST. */
extern PSI_stage_info stage_waiting_on_empty_queue;
extern PSI_stage_info stage_waiting_for_next_activation;
diff --git a/sql/field.cc b/sql/field.cc
index 1ce49b0bdfa..460c26fbfd2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1013,8 +1013,15 @@ CPP_UNNAMED_NS_END
Static help functions
*****************************************************************************/
+/*
+ @brief
+ Create a fixed size sort key part
+
+ @param buff buffer where values are written
+ @param length fixed size of the sort column
+*/
-void Field::make_sort_key(uchar *buff,uint length)
+void Field::make_sort_key_part(uchar *buff,uint length)
{
if (maybe_null())
{
@@ -1029,6 +1036,62 @@ void Field::make_sort_key(uchar *buff,uint length)
}
+/*
+ @brief
+ Create a packed sort key part
+
+ @param buff buffer where values are written
+ @param sort_field sort column structure
+
+ @retval
+ length of the bytes written, does not include the NULL bytes
+*/
+uint
+Field::make_packed_sort_key_part(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field)
+{
+ if (maybe_null())
+ {
+ if (is_null())
+ {
+ *buff++= 0;
+ return 0; // For NULL values don't write any data
+ }
+ *buff++=1;
+ }
+ sort_string(buff, sort_field->original_length);
+ return sort_field->original_length;
+}
+
+
+uint
+Field_longstr::make_packed_sort_key_part(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field)
+{
+ if (maybe_null())
+ {
+ if (is_null())
+ {
+ *buff++= 0;
+ return 0; // For NULL values don't write any data
+ }
+ *buff++=1;
+ }
+ uchar *end= pack_sort_string(buff, sort_field);
+ return static_cast<int>(end-buff);
+}
+
+
+uchar*
+Field_longstr::pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field)
+{
+ String buf;
+ val_str(&buf, &buf);
+ return to + sort_field->pack_sort_string(to, buf.lex_cstring(),
+ field_charset());
+}
+
+
/**
@brief
Determine the relative position of the field value in a numeric interval
@@ -5395,29 +5458,6 @@ static longlong read_native(const uchar *from, uint bytes)
}
#endif
-static void store_lowendian(ulonglong num, uchar *to, uint bytes)
-{
- switch(bytes) {
- case 1: *to= (uchar)num; break;
- case 2: int2store(to, num); break;
- case 3: int3store(to, num); break;
- case 4: int4store(to, num); break;
- case 8: int8store(to, num); break;
- default: DBUG_ASSERT(0);
- }
-}
-
-static longlong read_lowendian(const uchar *from, uint bytes)
-{
- switch(bytes) {
- case 1: return from[0];
- case 2: return uint2korr(from);
- case 3: return uint3korr(from);
- case 4: return uint4korr(from);
- case 8: return sint8korr(from);
- default: DBUG_ASSERT(0); return 0;
- }
-}
void Field_timestamp_hires::store_TIMEVAL(const timeval &tv)
{
@@ -7030,6 +7070,27 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end,
}
+/*
+ This is JSON specific.
+ We should eventually add Field_json_varchar and Field_json_blob
+ and move make_send_field() to the new classes.
+*/
+void Field_longstr::make_send_field(Send_field *field)
+{
+ Field_str::make_send_field(field);
+ if (check_constraint)
+ {
+ /*
+ Append the format that is implicitly implied by the CHECK CONSTRAINT.
+ For example:
+ CREATE TABLE t1 (js longtext DEFAULT NULL CHECK (json_valid(a)));
+ SELECT j FROM t1;
+ will add "format=json" to the extended type info metadata for t1.js.
+ */
+ check_constraint->expr->set_format_by_check_constraint(field);
+ }
+}
+
/* Copy a string and fill with space */
int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs)
@@ -8013,7 +8074,7 @@ int Field_longstr::compress(char *to, uint to_length,
max_length < length)
{
set_if_smaller(max_length, static_cast<ulonglong>(mbmaxlen()) * length + 1);
- if (!(buf= (char*) my_malloc(max_length, MYF(MY_WME))))
+ if (!(buf= (char*) my_malloc(PSI_INSTRUMENT_ME, max_length, MYF(MY_WME))))
{
*out_length= 0;
return -1;
@@ -8526,8 +8587,15 @@ Binlog_type_info Field_blob::binlog_type_info() const
uint32 Field_blob::sort_length() const
{
- return (uint32) (get_thd()->variables.max_sort_length +
- (field_charset() == &my_charset_bin ? 0 : packlength));
+ return packlength == 4 ?
+ UINT_MAX32 :
+ (uint32) field_length + sort_suffix_length();
+}
+
+
+uint32 Field_blob::sort_suffix_length() const
+{
+ return field_charset() == &my_charset_bin ? packlength : 0;
}
diff --git a/sql/field.h b/sql/field.h
index 4a8eec35b05..425f9f5292c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -51,6 +51,8 @@ class Table_ident;
class SEL_ARG;
class RANGE_OPT_PARAM;
struct KEY_PART;
+struct SORT_FIELD;
+struct SORT_FIELD_ATTR;
enum enum_check_fields
{
@@ -1075,6 +1077,12 @@ public:
virtual uint32 data_length() { return pack_length(); }
virtual uint32 sort_length() const { return pack_length(); }
+ /*
+ sort_suffix_length() return the length bytes needed to store the length
+ for binary charset
+ */
+ virtual uint32 sort_suffix_length() const { return 0; }
+
/*
Get the number bytes occupied by the value in the field.
CHAR values are stripped of trailing spaces.
@@ -1410,7 +1418,18 @@ public:
return bytes;
}
- void make_sort_key(uchar *buff, uint length);
+ /*
+ Create mem-comparable sort key part for a sort key
+ */
+ void make_sort_key_part(uchar *buff, uint length);
+
+ /*
+ create a compact sort key which can be compared with a comparison
+ function. They are called packed sort keys
+ */
+ virtual uint make_packed_sort_key_part(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field);
+
virtual void make_send_field(Send_field *);
virtual void sort_string(uchar *buff,uint length)=0;
virtual bool optimize_range(uint idx, uint part) const;
@@ -1527,7 +1546,7 @@ public:
{ return length;}
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual bool is_packable() { return false; }
+ virtual bool is_packable() const { return false; }
uint offset(const uchar *record) const
{
@@ -2120,11 +2139,12 @@ public:
{}
enum_conv_type rpl_conv_type_from(const Conv_source &source,
const Relay_log_info *rli,
- const Conv_param &param) const;
- int store_decimal(const my_decimal *d);
- uint32 max_data_length() const;
+ const Conv_param &param) const override;
+ int store_decimal(const my_decimal *d) override;
+ uint32 max_data_length() const override;
+ void make_send_field(Send_field *) override;
- bool is_varchar_and_in_write_set() const
+ bool is_varchar_and_in_write_set() const override
{
DBUG_ASSERT(table && table->write_set);
return bitmap_is_set(table->write_set, field_index);
@@ -2132,15 +2152,18 @@ public:
bool match_collation_to_optimize_range() const { return true; }
bool can_optimize_keypart_ref(const Item_bool_func *cond,
- const Item *item) const;
+ const Item *item) const override;
bool can_optimize_hash_join(const Item_bool_func *cond,
- const Item *item) const;
+ const Item *item) const override;
bool can_optimize_group_min_max(const Item_bool_func *cond,
- const Item *const_item) const;
+ const Item *const_item) const override;
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
- bool is_eq_func) const;
- bool is_packable() { return true; }
+ bool is_eq_func) const override;
+ bool is_packable() const override { return true; }
+ uint make_packed_sort_key_part(uchar *buff,
+ const SORT_FIELD_ATTR *sort_field)override;
+ uchar* pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field);
};
/* base class for float and double and decimal (old one) */
@@ -4042,8 +4065,11 @@ public:
uint32 key_length() const override { return (uint32) field_length; }
uint32 sort_length() const override
{
- return (uint32) field_length + (field_charset() == &my_charset_bin ?
- length_bytes : 0);
+ return (uint32) field_length + sort_suffix_length();
+ }
+ virtual uint32 sort_suffix_length() const override
+ {
+ return (field_charset() == &my_charset_bin ? length_bytes : 0);
}
Copy_func *get_copy_func(const Field *from) const override;
bool memcpy_field_possible(const Field *from) const override;
@@ -4187,6 +4213,30 @@ static inline longlong read_bigendian(const uchar *from, uint bytes)
}
}
+static inline void store_lowendian(ulonglong num, uchar *to, uint bytes)
+{
+ switch(bytes) {
+ case 1: *to= (uchar)num; break;
+ case 2: int2store(to, num); break;
+ case 3: int3store(to, num); break;
+ case 4: int4store(to, num); break;
+ case 8: int8store(to, num); break;
+ default: DBUG_ASSERT(0);
+ }
+}
+
+static inline longlong read_lowendian(const uchar *from, uint bytes)
+{
+ switch(bytes) {
+ case 1: return from[0];
+ case 2: return uint2korr(from);
+ case 3: return uint3korr(from);
+ case 4: return uint4korr(from);
+ case 8: return sint8korr(from);
+ default: DBUG_ASSERT(0); return 0;
+ }
+}
+
extern LEX_CSTRING temp_lex_str;
@@ -4353,6 +4403,7 @@ public:
{ return (uint32) (packlength); }
uint row_pack_length() const override { return pack_length_no_ptr(); }
uint32 sort_length() const override;
+ uint32 sort_suffix_length() const override;
uint32 value_length() override { return get_length(); }
virtual uint32 max_data_length() const override
{
@@ -5461,7 +5512,8 @@ public:
*/
class Send_field :public Sql_alloc,
- public Type_handler_hybrid_field_type
+ public Type_handler_hybrid_field_type,
+ public Send_field_extended_metadata
{
public:
LEX_CSTRING db_name;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 763f9f59246..1e19d492220 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -48,13 +48,18 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
ha_rows *found_rows);
static bool write_keys(Sort_param *param, SORT_INFO *fs_info,
uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
-static uint make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos);
+static uint make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos,
+ bool using_packed_sortkeys= false);
+static uint make_sortkey(Sort_param *param, uchar *to);
+static uint make_packed_sortkey(Sort_param *param, uchar *to);
+
static void register_used_fields(Sort_param *param);
static bool save_index(Sort_param *param, uint count,
SORT_INFO *table_sort);
static uint suffix_length(ulong string_length);
-static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
- bool *multi_byte_charset);
+static uint sortlength(THD *thd, Sort_keys *sortorder,
+ bool *multi_byte_charset,
+ bool *allow_packing_for_sortkeys);
static Addon_fields *get_addon_fields(TABLE *table, uint sortlength,
uint *addon_length,
uint *m_packable_length);
@@ -63,6 +68,31 @@ static bool check_if_pq_applicable(Sort_param *param, SORT_INFO *info,
TABLE *table,
ha_rows records, size_t memory_available);
+static void store_key_part_length(uint32 num, uchar *to, uint bytes)
+{
+ switch(bytes) {
+ case 1: *to= (uchar)num; break;
+ case 2: int2store(to, num); break;
+ case 3: int3store(to, num); break;
+ case 4: int4store(to, num); break;
+ default: DBUG_ASSERT(0);
+ }
+}
+
+
+static uint32 read_keypart_length(const uchar *from, uint bytes)
+{
+ switch(bytes) {
+ case 1: return from[0];
+ case 2: return uint2korr(from);
+ case 3: return uint3korr(from);
+ case 4: return uint4korr(from);
+ default: DBUG_ASSERT(0); return 0;
+ }
+}
+
+
+// @param sortlen [Maximum] length of the sort key
void Sort_param::init_for_filesort(uint sortlen, TABLE *table,
ha_rows maxrows, bool sort_positions)
{
@@ -108,7 +138,7 @@ void Sort_param::try_to_pack_addons(ulong max_length_for_sort_data)
if (!Addon_fields::can_pack_addon_fields(res_length))
return;
- const uint sz= Addon_fields::size_of_length_field;;
+ const uint sz= Addon_fields::size_of_length_field;
if (rec_length + sz > max_length_for_sort_data)
return;
@@ -125,6 +155,7 @@ void Sort_param::try_to_pack_addons(ulong max_length_for_sort_data)
addon_fields->set_using_packed_addons(true);
m_using_packed_addons= true;
+ m_packed_format= true;
addon_length+= sz;
res_length+= sz;
@@ -171,18 +202,21 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
ha_rows num_rows= HA_POS_ERROR;
IO_CACHE tempfile, buffpek_pointers, *outfile;
Sort_param param;
- bool multi_byte_charset;
+ bool multi_byte_charset, allow_packing_for_sortkeys;
Bounded_queue<uchar, uchar> pq;
SQL_SELECT *const select= filesort->select;
ha_rows max_rows= filesort->limit;
uint s_length= 0;
+ Sort_keys *sort_keys;
DBUG_ENTER("filesort");
- if (!(s_length= filesort->make_sortorder(thd, join, first_table_bit)))
+ if (!(sort_keys= filesort->make_sortorder(thd, join, first_table_bit)))
DBUG_RETURN(NULL); /* purecov: inspected */
- DBUG_EXECUTE("info",TEST_filesort(filesort->sortorder,s_length););
+ s_length= static_cast<uint>(sort_keys->size());
+
+ DBUG_EXECUTE("info",TEST_filesort(filesort->sortorder, s_length););
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
@@ -215,16 +249,14 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
error= 1;
sort->found_rows= HA_POS_ERROR;
- param.init_for_filesort(sortlength(thd, filesort->sortorder, s_length,
- &multi_byte_charset),
- table, max_rows, filesort->sort_positions);
+ param.sort_keys= sort_keys;
+ uint sort_len= sortlength(thd, sort_keys, &multi_byte_charset,
+ &allow_packing_for_sortkeys);
- sort->addon_fields= param.addon_fields;
+ param.init_for_filesort(sort_len, table, max_rows, filesort->sort_positions);
- if (multi_byte_charset &&
- !(param.tmp_buffer= (char*) my_malloc(param.sort_length,
- MYF(MY_WME | MY_THREAD_SPECIFIC))))
- goto err;
+ sort->addon_fields= param.addon_fields;
+ sort->sort_keys= param.sort_keys;
if (select && select->quick)
thd->inc_status_sort_range();
@@ -245,6 +277,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
tracker->incr_pq_used();
param.using_pq= true;
const size_t compare_length= param.sort_length;
+ DBUG_ASSERT(param.using_packed_sortkeys() == false);
/*
For PQ queries (with limit) we know exactly how many pointers/records
we have in the buffer, so to simplify things, we initialize
@@ -271,9 +304,19 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
{
DBUG_PRINT("info", ("filesort PQ is not applicable"));
+ if (allow_packing_for_sortkeys)
+ param.try_to_pack_sortkeys();
+
param.try_to_pack_addons(thd->variables.max_length_for_sort_data);
+ tracker->report_sort_keys_format(param.using_packed_sortkeys());
param.using_pq= false;
+ if ((multi_byte_charset || param.using_packed_sortkeys()) &&
+ !(param.tmp_buffer= (char*) my_malloc(key_memory_Sort_param_tmp_buffer, param.sort_length,
+ MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ goto err;
+
+
size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY,
param.sort_length*MERGEBUFF2);
set_if_bigger(min_sort_memory, sizeof(Merge_chunk*)*MERGEBUFF2);
@@ -298,6 +341,12 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
tracker->report_sort_buffer_size(sort->sort_buffer_size());
}
+ if (param.using_addon_fields())
+ {
+ // report information whether addon fields are packed or not
+ tracker->report_addon_fields_format(param.using_packed_addons());
+ }
+
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
DISK_BUFFER_SIZE, MYF(MY_WME)))
goto err;
@@ -479,24 +528,42 @@ void Filesort::cleanup()
}
-uint Filesort::make_sortorder(THD *thd, JOIN *join, table_map first_table_bit)
+/*
+ Create the Sort_keys array and fill the sort_keys[i]->{item|field}.
+
+ This indicates which field/item values will be used as sort keys.
+ Attributes like lengths are not filled yet.
+*/
+
+Sort_keys*
+Filesort::make_sortorder(THD *thd, JOIN *join, table_map first_table_bit)
{
uint count;
SORT_FIELD *sort,*pos;
ORDER *ord;
DBUG_ENTER("make_sortorder");
-
count=0;
for (ord = order; ord; ord= ord->next)
count++;
- if (!sortorder)
- sortorder= (SORT_FIELD*) thd->alloc(sizeof(SORT_FIELD) * (count + 1));
+
+ if (sortorder)
+ DBUG_RETURN(sort_keys);
+
+ DBUG_ASSERT(sort_keys == NULL);
+
+ sortorder= (SORT_FIELD*) thd->alloc(sizeof(SORT_FIELD) * count);
pos= sort= sortorder;
if (!pos)
DBUG_RETURN(0);
+ sort_keys= new Sort_keys(sortorder, count);
+
+ if (!sort_keys)
+ DBUG_RETURN(0);
+
+ pos= sort_keys->begin();
for (ord= order; ord; ord= ord->next, pos++)
{
Item *first= ord->item[0];
@@ -537,7 +604,7 @@ uint Filesort::make_sortorder(THD *thd, JOIN *join, table_map first_table_bit)
pos->reverse= (ord->direction == ORDER::ORDER_DESC);
DBUG_ASSERT(pos->field != NULL || pos->item != NULL);
}
- DBUG_RETURN(count);
+ DBUG_RETURN(sort_keys);
}
@@ -552,7 +619,8 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
if (count > UINT_MAX/sizeof(Merge_chunk))
return 0; /* sizeof(BUFFPEK)*count will overflow */
if (!tmp)
- tmp= (uchar *)my_malloc(length, MYF(MY_WME | MY_THREAD_SPECIFIC));
+ tmp= (uchar *)my_malloc(key_memory_Filesort_info_merge, length,
+ MYF(MY_WME | MY_THREAD_SPECIFIC));
if (tmp)
{
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
@@ -746,7 +814,7 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
SORT_INFO *fs_info,
- IO_CACHE *buffpek_pointers,
+ IO_CACHE *buffpek_pointers,
IO_CACHE *tempfile,
Bounded_queue<uchar, uchar> *pq,
ha_rows *found_rows)
@@ -759,7 +827,9 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
MY_BITMAP *save_read_set, *save_write_set;
Item *sort_cond;
ha_rows num_records= 0;
- const bool packed_addon_fields= param->using_packed_addons();
+ const bool packed_format= param->is_packed_format();
+ const bool using_packed_sortkeys= param->using_packed_sortkeys();
+
DBUG_ENTER("find_all_keys");
DBUG_PRINT("info",("using: %s",
(select ? select->quick ? "ranges" : "where":
@@ -815,6 +885,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
}
DEBUG_SYNC(thd, "after_index_merge_phase1");
+
for (;;)
{
if (quick_select)
@@ -882,8 +953,9 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
fs_info->init_next_record_pointer();
uchar *start_of_rec= fs_info->get_next_record_pointer();
- const uint rec_sz= make_sortkey(param, start_of_rec, ref_pos);
- if (packed_addon_fields && rec_sz != param->rec_length)
+ const uint rec_sz= make_sortkey(param, start_of_rec,
+ ref_pos, using_packed_sortkeys);
+ if (packed_format && rec_sz != param->rec_length)
fs_info->adjust_next_record_pointer(rec_sz);
idx++;
}
@@ -964,12 +1036,9 @@ static bool
write_keys(Sort_param *param, SORT_INFO *fs_info, uint count,
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
{
- size_t rec_length;
Merge_chunk buffpek;
DBUG_ENTER("write_keys");
- rec_length= param->rec_length;
-
fs_info->sort_buffer(param, count);
if (!my_b_inited(tempfile) &&
@@ -985,19 +1054,12 @@ write_keys(Sort_param *param, SORT_INFO *fs_info, uint count,
count=(uint) param->max_rows; /* purecov: inspected */
buffpek.set_rowcount(static_cast<ha_rows>(count));
- const bool packed_addon_fields= param->using_packed_addons();
for (uint ix= 0; ix < count; ++ix)
{
uchar *record= fs_info->get_sorted_record(ix);
- if (packed_addon_fields)
- {
- rec_length= param->sort_length +
- Addon_fields::read_addon_length(record + param->sort_length);
- }
- else
- rec_length= param->rec_length;
- if (my_b_write(tempfile, record, rec_length))
+
+ if (my_b_write(tempfile, record, param->get_record_length(record)))
DBUG_RETURN(1); /* purecov: inspected */
}
@@ -1010,10 +1072,9 @@ write_keys(Sort_param *param, SORT_INFO *fs_info, uint count,
/**
- Store length as suffix in high-byte-first order.
+ Store length in high-byte-first order.
*/
-
-static inline void store_length(uchar *to, uint length, uint pack_length)
+void store_length(uchar *to, uint length, uint pack_length)
{
switch (pack_length) {
case 1:
@@ -1033,9 +1094,9 @@ static inline void store_length(uchar *to, uint length, uint pack_length)
void
-Type_handler_string_result::make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+Type_handler_string_result::make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
{
CHARSET_INFO *cs= item->collation.collation;
bool maybe_null= item->maybe_null;
@@ -1105,9 +1166,9 @@ Type_handler_string_result::make_sort_key(uchar *to, Item *item,
void
-Type_handler_int_result::make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+Type_handler_int_result::make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
{
longlong value= item->val_int_result();
make_sort_key_longlong(to, item->maybe_null, item->null_value,
@@ -1116,7 +1177,7 @@ Type_handler_int_result::make_sort_key(uchar *to, Item *item,
void
-Type_handler_temporal_result::make_sort_key(uchar *to, Item *item,
+Type_handler_temporal_result::make_sort_key_part(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const
{
@@ -1138,7 +1199,7 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item,
void
-Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item,
+Type_handler_timestamp_common::make_sort_key_part(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const
{
@@ -1171,6 +1232,24 @@ Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item,
void
+Type_handler::store_sort_key_longlong(uchar *to, bool unsigned_flag,
+ longlong value) const
+{
+ to[7]= (uchar) value;
+ to[6]= (uchar) (value >> 8);
+ to[5]= (uchar) (value >> 16);
+ to[4]= (uchar) (value >> 24);
+ to[3]= (uchar) (value >> 32);
+ to[2]= (uchar) (value >> 40);
+ to[1]= (uchar) (value >> 48);
+ if (unsigned_flag) /* Fix sign */
+ to[0]= (uchar) (value >> 56);
+ else
+ to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
+}
+
+
+void
Type_handler::make_sort_key_longlong(uchar *to,
bool maybe_null,
bool null_value,
@@ -1187,24 +1266,35 @@ Type_handler::make_sort_key_longlong(uchar *to,
}
*to++= 1;
}
- to[7]= (uchar) value;
- to[6]= (uchar) (value >> 8);
- to[5]= (uchar) (value >> 16);
- to[4]= (uchar) (value >> 24);
- to[3]= (uchar) (value >> 32);
- to[2]= (uchar) (value >> 40);
- to[1]= (uchar) (value >> 48);
- if (unsigned_flag) /* Fix sign */
- to[0]= (uchar) (value >> 56);
- else
- to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
+ store_sort_key_longlong(to, unsigned_flag, value);
+}
+
+
+uint
+Type_handler::make_packed_sort_key_longlong(uchar *to, bool maybe_null,
+ bool null_value, bool unsigned_flag,
+ longlong value,
+ const SORT_FIELD_ATTR *sort_field) const
+{
+ if (maybe_null)
+ {
+ if (null_value)
+ {
+ *to++= 0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ store_sort_key_longlong(to, unsigned_flag, value);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
}
void
-Type_handler_decimal_result::make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+Type_handler_decimal_result::make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
{
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
if (item->maybe_null)
@@ -1222,9 +1312,9 @@ Type_handler_decimal_result::make_sort_key(uchar *to, Item *item,
void
-Type_handler_real_result::make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+Type_handler_real_result::make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
{
double value= item->val_result();
if (item->maybe_null)
@@ -1242,48 +1332,14 @@ Type_handler_real_result::make_sort_key(uchar *to, Item *item,
/** Make a sort-key from record. */
-static uint make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos)
+static uint make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos,
+ bool using_packed_sortkeys)
{
- Field *field;
- SORT_FIELD *sort_field;
- uint length;
uchar *orig_to= to;
- for (sort_field=param->local_sortorder.begin() ;
- sort_field != param->local_sortorder.end() ;
- sort_field++)
- {
- bool maybe_null=0;
- if ((field=sort_field->field))
- { // Field
- field->make_sort_key(to, sort_field->length);
- if ((maybe_null = field->maybe_null()))
- to++;
- }
- else
- { // Item
- sort_field->item->type_handler()->make_sort_key(to, sort_field->item,
- sort_field, param);
- if ((maybe_null= sort_field->item->maybe_null))
- to++;
- }
- if (sort_field->reverse)
- { /* Revers key */
- if (maybe_null && (to[-1]= !to[-1]))
- {
- to+= sort_field->length; // don't waste the time reversing all 0's
- continue;
- }
- length=sort_field->length;
- while (length--)
- {
- *to = (uchar) (~ *to);
- to++;
- }
- }
- else
- to+= sort_field->length;
- }
+ to+= using_packed_sortkeys ?
+ make_packed_sortkey(param, to) :
+ make_sortkey(param, to);
if (param->using_addon_fields())
{
@@ -1379,7 +1435,7 @@ static void register_used_fields(Sort_param *param)
static bool save_index(Sort_param *param, uint count,
SORT_INFO *table_sort)
{
- uint offset,res_length;
+ uint offset,res_length, length;
uchar *to;
DBUG_ENTER("save_index");
DBUG_ASSERT(table_sort->record_pointers == 0);
@@ -1393,16 +1449,21 @@ static bool save_index(Sort_param *param, uint count,
DBUG_RETURN(0);
}
+ bool using_packed_sortkeys= param->using_packed_sortkeys();
res_length= param->res_length;
offset= param->rec_length-res_length;
if (!(to= table_sort->record_pointers=
- (uchar*) my_malloc(res_length*count,
- MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ (uchar*) my_malloc(key_memory_Filesort_info_record_pointers,
+ res_length*count, MYF(MY_WME | MY_THREAD_SPECIFIC))))
DBUG_RETURN(1); /* purecov: inspected */
for (uint ix= 0; ix < count; ++ix)
{
uchar *record= table_sort->get_sorted_record(ix);
- memcpy(to, record + offset, res_length);
+
+ length= using_packed_sortkeys ?
+ Sort_keys::read_sortkey_length(record) : offset;
+
+ memcpy(to, record + length, res_length);
to+= res_length;
}
DBUG_RETURN(0);
@@ -1605,7 +1666,7 @@ cleanup:
*/
ulong read_to_buffer(IO_CACHE *fromfile, Merge_chunk *buffpek,
- Sort_param *param)
+ Sort_param *param, bool packed_format)
{
ha_rows count;
uint rec_length= param->rec_length;
@@ -1613,7 +1674,7 @@ ulong read_to_buffer(IO_CACHE *fromfile, Merge_chunk *buffpek,
if ((count= MY_MIN(buffpek->max_keys(),buffpek->rowcount())))
{
size_t bytes_to_read;
- if (param->using_packed_addons())
+ if (packed_format)
{
count= buffpek->rowcount();
bytes_to_read= MY_MIN(buffpek->buffer_size(),
@@ -1628,26 +1689,43 @@ ulong read_to_buffer(IO_CACHE *fromfile, Merge_chunk *buffpek,
return ((ulong) -1);
size_t num_bytes_read;
- if (param->using_packed_addons())
+
+ if (packed_format)
{
/*
The last record read is most likely not complete here.
We need to loop through all the records, reading the length fields,
and then "chop off" the final incomplete record.
- */
+ */
uchar *record= buffpek->buffer_start();
uint ix= 0;
+ uint size_of_addon_length= param->using_packed_addons() ?
+ Addon_fields::size_of_length_field : 0;
+
+ uint size_of_sort_length= param->using_packed_sortkeys() ?
+ Sort_keys::size_of_length_field : 0;
+
for (; ix < count; ++ix)
{
- if (record + param->sort_length + Addon_fields::size_of_length_field >
+ if (record + size_of_sort_length > buffpek->buffer_end())
+ break;
+ uint sort_length= param->using_packed_sortkeys() ?
+ Sort_keys::read_sortkey_length(record) :
+ param->sort_length;
+
+ DBUG_ASSERT(sort_length <= param->sort_length);
+
+ if (record + sort_length + size_of_addon_length >
buffpek->buffer_end())
break; // Incomplete record.
- uchar *plen= record + param->sort_length;
- uint res_length= Addon_fields::read_addon_length(plen);
+
+ uchar *plen= record + sort_length;
+ uint res_length= param->get_result_length(plen);
if (plen + res_length > buffpek->buffer_end())
break; // Incomplete record.
DBUG_ASSERT(res_length > 0);
- record+= param->sort_length;
+ DBUG_ASSERT(sort_length + res_length <= param->rec_length);
+ record+= sort_length;
record+= res_length;
}
DBUG_ASSERT(ix > 0);
@@ -1704,7 +1782,10 @@ void reuse_freed_buff(QUEUE *queue, Merge_chunk *reuse, uint key_length)
@param lastbuff OUT Store here BUFFPEK describing data written to to_file
@param Fb First element in source BUFFPEKs array
@param Tb Last element in source BUFFPEKs array
- @param flag
+ @param flag 0 <=> write {sort_key, addon_fields} pairs as further
+ sorting will be performed
+ 1 <=> write just addon_fields as this is the final
+ merge pass
@retval
0 OK
@@ -1748,6 +1829,11 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
(flag && min_dupl_count ? sizeof(dupl_count) : 0)-res_length);
uint wr_len= flag ? res_length : rec_length;
uint wr_offset= flag ? offset : 0;
+
+ const bool using_packed_sortkeys= param->using_packed_sortkeys();
+ bool offset_for_packing= (flag == 1 && using_packed_sortkeys);
+ const bool packed_format= param->is_packed_format();
+
maxcount= (ulong) (param->max_keys_per_buffer/((uint) (Tb-Fb) +1));
to_start_filepos= my_b_tell(to_file);
strpos= sort_buffer.array();
@@ -1762,8 +1848,8 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
}
else
{
- cmp= get_ptr_compare(sort_length);
- first_cmp_arg= (void*) &sort_length;
+ cmp= param->get_compare_function();
+ first_cmp_arg= param->get_compare_argument(&sort_length);
}
if (unlikely(init_queue(&queue, (uint) (Tb-Fb)+1,
offsetof(Merge_chunk,m_current_key), 0,
@@ -1775,7 +1861,7 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
strpos + (sort_buffer.size()/((uint) (Tb-Fb) +1)));
buffpek->set_max_keys(maxcount);
- bytes_read= read_to_buffer(from_file, buffpek, param);
+ bytes_read= read_to_buffer(from_file, buffpek, param, packed_format);
if (unlikely(bytes_read == (ulong) -1))
goto err; /* purecov: inspected */
strpos+= bytes_read;
@@ -1802,7 +1888,7 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
if (buffpek->mem_count() == 0)
{
if (unlikely(!(bytes_read= read_to_buffer(from_file, buffpek,
- param))))
+ param, packed_format))))
{
(void) queue_remove_top(&queue);
reuse_freed_buff(&queue, buffpek, rec_length);
@@ -1860,7 +1946,11 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
*/
if (!check_dupl_count || dupl_count >= min_dupl_count)
{
- if (my_b_write(to_file, src + wr_offset, bytes_to_write))
+ if(my_b_write(to_file,
+ src + (offset_for_packing ?
+ rec_length - res_length : // sort length
+ wr_offset),
+ bytes_to_write))
goto err; /* purecov: inspected */
}
if (cmp)
@@ -1883,7 +1973,7 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
if (buffpek->mem_count() == 0)
{
if (unlikely(!(bytes_read= read_to_buffer(from_file, buffpek,
- param))))
+ param, packed_format))))
{
(void) queue_remove_top(&queue);
reuse_freed_buff(&queue, buffpek, rec_length);
@@ -1943,7 +2033,8 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
max_rows-= buffpek->mem_count();
for (uint ix= 0; ix < buffpek->mem_count(); ++ix)
{
- param->get_rec_and_res_len(buffpek->current_key(),
+ uchar *src= buffpek->current_key();
+ param->get_rec_and_res_len(src,
&rec_length, &res_length);
const uint bytes_to_write= (flag == 0) ? rec_length : res_length;
if (check_dupl_count)
@@ -1954,15 +2045,18 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
if (dupl_count < min_dupl_count)
continue;
}
- if (my_b_write(to_file, buffpek->current_key() + wr_offset,
- bytes_to_write))
+ if(my_b_write(to_file,
+ src + (offset_for_packing ?
+ rec_length - res_length : // sort length
+ wr_offset),
+ bytes_to_write))
goto err;
buffpek->advance_current_key(rec_length);
}
}
while (likely(!(error=
- (bytes_read= read_to_buffer(from_file, buffpek,
- param)) == (ulong) -1)) &&
+ (bytes_read= read_to_buffer(from_file, buffpek, param,
+ packed_format)) == (ulong) -1)) &&
bytes_read != 0);
end:
@@ -2007,13 +2101,14 @@ static uint suffix_length(ulong string_length)
void
-Type_handler_string_result::sortlength(THD *thd,
+Type_handler_string_result::sort_length(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *sortorder) const
{
CHARSET_INFO *cs;
sortorder->length= item->max_length;
- set_if_smaller(sortorder->length, thd->variables.max_sort_length);
+ sortorder->original_length= item->max_length;
+
if (use_strnxfrm((cs= item->collation.collation)))
{
sortorder->length= (uint) cs->strnxfrmlen(sortorder->length);
@@ -2023,54 +2118,57 @@ Type_handler_string_result::sortlength(THD *thd,
/* Store length last to be able to sort blob/varbinary */
sortorder->suffix_length= suffix_length(sortorder->length);
sortorder->length+= sortorder->suffix_length;
+ sortorder->original_length+= sortorder->suffix_length;
}
}
void
-Type_handler_temporal_result::sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *sortorder) const
+Type_handler_temporal_result::sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *sortorder) const
{
- sortorder->length= 8; // Sizof intern longlong
+ sortorder->original_length= sortorder->length= 8; // Sizof intern longlong
}
void
-Type_handler_timestamp_common::sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *sortorder) const
+Type_handler_timestamp_common::sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *sortorder) const
{
sortorder->length= my_timestamp_binary_length(item->decimals);
+ sortorder->original_length= sortorder->length;
}
void
-Type_handler_int_result::sortlength(THD *thd,
+Type_handler_int_result::sort_length(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *sortorder) const
{
- sortorder->length= 8; // Sizof intern longlong
+ sortorder->original_length= sortorder->length= 8; // Sizof intern longlong
}
void
-Type_handler_real_result::sortlength(THD *thd,
+Type_handler_real_result::sort_length(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *sortorder) const
{
- sortorder->length= sizeof(double);
+ sortorder->original_length= sortorder->length= sizeof(double);
}
void
-Type_handler_decimal_result::sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *sortorder) const
+Type_handler_decimal_result::sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *sortorder) const
{
sortorder->length=
my_decimal_get_binary_size(item->max_length - (item->decimals ? 1 : 0),
item->decimals);
+ sortorder->original_length= sortorder->length;
}
@@ -2082,54 +2180,100 @@ Type_handler_decimal_result::sortlength(THD *thd,
@param s_length Number of items to sort
@param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
(In which case we have to use strxnfrm())
+ @param allow_packing_for_sortkeys [out] set to false if packing sort keys is not
+ allowed
@note
- sortorder->length is updated for each sort item.
+ * sortorder->length and other members are updated for each sort item.
+ * TODO what is the meaning of this value if some fields are using packing while
+ others are not?
@return
Total length of sort buffer in bytes
*/
static uint
-sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
- bool *multi_byte_charset)
+sortlength(THD *thd, Sort_keys *sort_keys, bool *multi_byte_charset,
+ bool *allow_packing_for_sortkeys)
{
uint length;
*multi_byte_charset= 0;
+ *allow_packing_for_sortkeys= true;
+ bool allow_packing_for_keys= true;
length=0;
- for (; s_length-- ; sortorder++)
+ uint nullable_cols=0;
+
+ for (SORT_FIELD *sortorder= sort_keys->begin();
+ sortorder != sort_keys->end();
+ sortorder++)
{
sortorder->suffix_length= 0;
+ sortorder->length_bytes= 0;
if (sortorder->field)
{
+ Field *field= sortorder->field;
CHARSET_INFO *cs= sortorder->field->sort_charset();
sortorder->length= sortorder->field->sort_length();
+ sortorder->suffix_length= sortorder->field->sort_suffix_length();
+ sortorder->original_length= sortorder->length;
+ sortorder->type= field->is_packable() ?
+ SORT_FIELD_ATTR::VARIABLE_SIZE :
+ SORT_FIELD_ATTR::FIXED_SIZE;
+ sortorder->cs= cs;
+
if (use_strnxfrm((cs=sortorder->field->sort_charset())))
{
*multi_byte_charset= true;
sortorder->length= (uint) cs->strnxfrmlen(sortorder->length);
}
- if (sortorder->field->maybe_null())
- length++; // Place for NULL marker
+ if (sortorder->is_variable_sized() && allow_packing_for_keys)
+ {
+ allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
+ sortorder->length_bytes=
+ number_storage_requirement(MY_MIN(sortorder->original_length,
+ thd->variables.max_sort_length));
+ }
+
+ if ((sortorder->maybe_null= sortorder->field->maybe_null()))
+ nullable_cols++; // Place for NULL marker
}
else
{
- sortorder->item->type_handler()->sortlength(thd, sortorder->item,
- sortorder);
- if (use_strnxfrm(sortorder->item->collation.collation))
+ CHARSET_INFO *cs;
+ sortorder->item->type_handler()->sort_length(thd, sortorder->item,
+ sortorder);
+ sortorder->type= sortorder->item->type_handler()->is_packable() ?
+ SORT_FIELD_ATTR::VARIABLE_SIZE :
+ SORT_FIELD_ATTR::FIXED_SIZE;
+ if (use_strnxfrm((cs=sortorder->item->collation.collation)))
{
*multi_byte_charset= true;
}
- if (sortorder->item->maybe_null)
- length++; // Place for NULL marker
+ sortorder->cs= cs;
+ if (sortorder->is_variable_sized() && allow_packing_for_keys)
+ {
+ allow_packing_for_keys= sortorder->check_if_packing_possible(thd);
+ sortorder->length_bytes=
+ number_storage_requirement(MY_MIN(sortorder->original_length,
+ thd->variables.max_sort_length));
+ }
+
+ if ((sortorder->maybe_null= sortorder->item->maybe_null))
+ nullable_cols++; // Place for NULL marker
}
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
+ set_if_smaller(sortorder->original_length, thd->variables.max_sort_length);
length+=sortorder->length;
+
+ sort_keys->increment_size_of_packable_fields(sortorder->length_bytes);
+ sort_keys->increment_original_sort_length(sortorder->original_length);
}
- sortorder->field= NULL; // end marker
+ // add bytes for nullable_cols
+ sort_keys->increment_original_sort_length(nullable_cols);
+ *allow_packing_for_sortkeys= allow_packing_for_keys;
DBUG_PRINT("info",("sort_length: %d",length));
- return length;
+ return length + nullable_cols;
}
@@ -2237,7 +2381,7 @@ get_addon_fields(TABLE *table, uint sortlength,
if (!filesort_use_addons(table, sortlength, &length, &fields, &null_fields,
&packable_length) ||
- !(my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC),
+ !(my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME | MY_THREAD_SPECIFIC),
&raw_mem, sizeof(Addon_fields),
&raw_mem_addon_field,
sizeof(SORT_ADDON_FIELD) * fields,
@@ -2283,23 +2427,6 @@ get_addon_fields(TABLE *table, uint sortlength,
}
-/**
- Copy (unpack) values appended to sorted fields from a buffer back to
- their regular positions specified by the Field::ptr pointers.
-
- @param addon_field Array of descriptors for appended fields
- @param buff Buffer which to unpack the value from
-
- @note
- The function is supposed to be used only as a callback function
- when getting field values for the sorted result set.
-
- @return
- void.
-*/
-
-
-
/*
** functions to change a double or float to a sortable string
** The following should work for IEEE
@@ -2359,6 +2486,14 @@ void SORT_INFO::free_addon_buff()
addon_fields->free_addon_buff();
}
+/*
+ Check if packed sortkeys are used or not
+*/
+bool SORT_INFO::using_packed_sortkeys()
+{
+ return sort_keys != NULL && sort_keys->using_packed_sortkeys();
+}
+
/**
Free SORT_INFO
*/
@@ -2369,3 +2504,561 @@ SORT_INFO::~SORT_INFO()
free_data();
DBUG_VOID_RETURN;
}
+
+
+void Sort_param::try_to_pack_sortkeys()
+{
+ #ifdef WITHOUT_PACKED_SORT_KEYS
+ return;
+ #endif
+
+ uint size_of_packable_fields= sort_keys->get_size_of_packable_fields();
+
+ /*
+ Disable packing when all fields are fixed-size fields.
+ */
+ if (size_of_packable_fields == 0)
+ return;
+
+ const uint sz= Sort_keys::size_of_length_field;
+ uint sort_len= sort_keys->get_sort_length();
+
+ /*
+ Heuristic introduced, skip packing sort keys if saving less than 128 bytes
+ */
+
+ if (sort_len < 128 + sz + size_of_packable_fields)
+ return;
+
+ sort_keys->set_using_packed_sortkeys(true);
+ m_packed_format= true;
+ m_using_packed_sortkeys= true;
+ sort_length= sort_len + sz + size_of_packable_fields +
+ (using_addon_fields() ? 0 : res_length);
+ /* Only the record length needs to be updated, the res_length does not need
+ to be updated
+ */
+ rec_length= sort_length + addon_length;
+}
+
+
+uint
+Type_handler_string_result::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ CHARSET_INFO *cs= item->collation.collation;
+ bool maybe_null= item->maybe_null;
+
+ if (maybe_null)
+ *to++= 1;
+
+ String tmp(param->tmp_buffer, param->sort_length, cs);
+ String *res= item->str_result(&tmp);
+ if (!res)
+ {
+ if (maybe_null)
+ {
+ *(to-1)= 0;
+ return 0;
+ }
+ else
+ {
+ /* purecov: begin deadcode */
+ /*
+ This should only happen during extreme conditions if we run out
+ of memory or have an item marked not null when it can be null.
+ This code is here mainly to avoid a hard crash in this case.
+ */
+ DBUG_ASSERT(0);
+ DBUG_PRINT("warning",
+ ("Got null on something that shouldn't be null"));
+ memset(to, 0, sort_field->length); // Avoid crash
+ /* purecov: end */
+ return sort_field->original_length;
+ }
+ }
+ return sort_field->pack_sort_string(to, res->lex_cstring(), cs);
+}
+
+
+uint
+Type_handler_int_result::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ longlong value= item->val_int_result();
+ return make_packed_sort_key_longlong(to, item->maybe_null,
+ item->null_value, item->unsigned_flag,
+ value, sort_field);
+}
+
+
+uint
+Type_handler_decimal_result::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
+ if (item->maybe_null)
+ {
+ if (item->null_value)
+ {
+ *to++=0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ dec_val->to_binary(to, item->max_length - (item->decimals ? 1 : 0),
+ item->decimals);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
+}
+
+
+uint
+Type_handler_real_result::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ double value= item->val_result();
+ if (item->maybe_null)
+ {
+ if (item->null_value)
+ {
+ *to++=0;
+ return 0;
+ }
+ *to++= 1;
+ }
+ change_double_for_sort(value, to);
+ DBUG_ASSERT(sort_field->original_length == sort_field->length);
+ return sort_field->original_length;
+}
+
+
+uint
+Type_handler_temporal_result::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ MYSQL_TIME buf;
+ // This is a temporal type. No nanoseconds. Rounding mode is not important.
+ DBUG_ASSERT(item->cmp_type() == TIME_RESULT);
+ static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE);
+ if (item->get_date_result(current_thd, &buf, opt))
+ {
+ DBUG_ASSERT(item->maybe_null);
+ DBUG_ASSERT(item->null_value);
+ return make_packed_sort_key_longlong(to, item->maybe_null, true,
+ item->unsigned_flag, 0, sort_field);
+ }
+ return make_packed_sort_key_longlong(to, item->maybe_null, false,
+ item->unsigned_flag, pack_time(&buf),
+ sort_field);
+}
+
+
+uint
+Type_handler_timestamp_common::make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+{
+ THD *thd= current_thd;
+ uint binlen= my_timestamp_binary_length(item->decimals);
+ Timestamp_or_zero_datetime_native_null native(thd, item);
+ if (native.is_null() || native.is_zero_datetime())
+ {
+ // NULL or '0000-00-00 00:00:00'
+ if (item->maybe_null)
+ {
+ *to++=0;
+ return 0;
+ }
+ else
+ {
+ bzero(to, binlen);
+ return binlen;
+ }
+ }
+ else
+ {
+ if (item->maybe_null)
+ *to++= 1;
+ if (native.length() != binlen)
+ {
+ /*
+ Some items can return native representation with a different
+ number of fractional digits, e.g.: GREATEST(ts_3, ts_4) can
+ return a value with 3 fractional digits, although its fractional
+ precision is 4. Re-pack with a proper precision now.
+ */
+ Timestamp(native).to_native(&native, item->datetime_precision(thd));
+ }
+ DBUG_ASSERT(native.length() == binlen);
+ memcpy((char *) to, native.ptr(), binlen);
+ return binlen;
+ }
+}
+
+
+/*
+ @brief
+ Reverse the key for DESC clause
+ @param to buffer where values are written
+ @param maybe_null nullability of a column
+ @param sort_field Sort field structure
+ @details
+ used for mem-comparable sort keys
+*/
+
+void reverse_key(uchar *to, const SORT_FIELD_ATTR *sort_field)
+{
+ uint length;
+ if (sort_field->maybe_null && (to[-1]= !to[-1]))
+ {
+ to+= sort_field->length; // don't waste the time reversing all 0's
+ return;
+ }
+ length=sort_field->length;
+ while (length--)
+ {
+ *to = (uchar) (~ *to);
+ to++;
+ }
+}
+
+
+/*
+ @brief
+ Check if packing sort keys is allowed
+ @param THD thread structure
+ @retval
+ TRUE packing allowed
+ FALSE packing not allowed
+*/
+bool SORT_FIELD_ATTR::check_if_packing_possible(THD *thd) const
+{
+ /*
+ Packing not allowed when original length is greater than max_sort_length
+ and we have a complex collation because cutting a prefix is not safe in
+ such a case
+ */
+ if (original_length > thd->variables.max_sort_length &&
+ cs->state & MY_CS_NON1TO1)
+ return false;
+ return true;
+}
+
+
+/*
+ Compare function used for packing sort keys
+*/
+
+qsort2_cmp get_packed_keys_compare_ptr()
+{
+ return (qsort2_cmp) compare_packed_sort_keys;
+}
+
+
+/*
+ Compare two varstrings.
+
+ The strings are in this data format:
+
+ [null_byte] [length of string + suffix_bytes] [the string] [suffix_bytes]
+
+ suffix_bytes are used only for binary columns.
+*/
+
+int SORT_FIELD_ATTR::compare_packed_varstrings(uchar *a, size_t *a_len,
+ uchar *b, size_t *b_len)
+{
+ int retval;
+ size_t a_length, b_length;
+ if (maybe_null)
+ {
+ *a_len= *b_len= 1; // NULL bytes are always stored
+ if (*a != *b)
+ {
+ // Note we don't return a proper value in *{a|b}_len for the non-NULL
+ // value but that's ok
+ if (*a == 0)
+ return -1;
+ else
+ return 1;
+ }
+ else
+ {
+ if (*a == 0)
+ return 0;
+ }
+ a++;
+ b++;
+ }
+ else
+ *a_len= *b_len= 0;
+
+ a_length= read_keypart_length(a, length_bytes);
+ b_length= read_keypart_length(b, length_bytes);
+
+ *a_len+= length_bytes + a_length;
+ *b_len+= length_bytes + b_length;
+
+ retval= cs->strnncollsp(a + length_bytes,
+ a_length - suffix_length,
+ b + length_bytes,
+ b_length - suffix_length);
+
+ if (!retval && suffix_length)
+ {
+ DBUG_ASSERT(cs == &my_charset_bin);
+ // comparing the length stored in suffix bytes for binary strings
+ a= a + length_bytes + a_length - suffix_length;
+ b= b + length_bytes + b_length - suffix_length;
+ retval= memcmp(a, b, suffix_length);
+ }
+
+ return retval;
+}
+
+
+/*
+ A value comparison function that has a signature that's suitable for
+ comparing packed values, but actually compares fixed-size values with memcmp.
+
+ This is used for ordering fixed-size columns when the sorting procedure used
+ packed-value format.
+*/
+
+int SORT_FIELD_ATTR::compare_packed_fixed_size_vals(uchar *a, size_t *a_len,
+ uchar *b, size_t *b_len)
+{
+ if (maybe_null)
+ {
+ *a_len=1;
+ *b_len=1;
+ if (*a != *b)
+ {
+ if (*a == 0)
+ return -1;
+ else
+ return 1;
+ }
+ else
+ {
+ if (*a == 0)
+ return 0;
+ }
+ a++;
+ b++;
+ }
+ else
+ *a_len= *b_len= 0;
+
+ *a_len+= length;
+ *b_len+= length;
+ return memcmp(a,b, length);
+}
+
+
+/*
+ @brief
+ Comparison function to compare two packed sort keys
+
+ @param sort_param cmp argument
+ @param a_ptr packed sort key
+ @param b_ptr packed sort key
+
+ @retval
+ >0 key a_ptr greater than b_ptr
+ =0 key a_ptr equal to b_ptr
+ <0 key a_ptr less than b_ptr
+
+*/
+
+int compare_packed_sort_keys(void *sort_param,
+ unsigned char **a_ptr, unsigned char **b_ptr)
+{
+ int retval= 0;
+ size_t a_len, b_len;
+ Sort_param *param= (Sort_param*)sort_param;
+ Sort_keys *sort_keys= param->sort_keys;
+ uchar *a= *a_ptr;
+ uchar *b= *b_ptr;
+
+ a+= Sort_keys::size_of_length_field;
+ b+= Sort_keys::size_of_length_field;
+ for (SORT_FIELD *sort_field= sort_keys->begin();
+ sort_field != sort_keys->end(); sort_field++)
+ {
+ retval= sort_field->is_variable_sized() ?
+ sort_field->compare_packed_varstrings(a, &a_len, b, &b_len) :
+ sort_field->compare_packed_fixed_size_vals(a, &a_len, b, &b_len);
+
+ if (retval)
+ return sort_field->reverse ? -retval : retval;
+
+ a+= a_len;
+ b+= b_len;
+
+ }
+ /*
+ this comparison is done for the case when the sort keys is appended with
+ the ROW_ID pointer. For such cases we don't have addon fields
+ so we can make a memcmp check over both the sort keys
+ */
+ if (!param->using_addon_fields())
+ retval= memcmp(a, b, param->res_length);
+ return retval;
+}
+
+
+/*
+ @brief
+ Store a packed string in the buffer
+
+ @param to buffer
+ @param str packed string value
+ @param cs character set
+
+ @details
+ This function writes to the buffer the packed value of a key_part
+ of the sort key.
+
+ The values written to the buffer are in this order
+ - value for null byte
+ - length of the string
+ - value of the string
+ - suffix length (for binary character set)
+*/
+
+uint
+SORT_FIELD_ATTR::pack_sort_string(uchar *to, const LEX_CSTRING &str,
+ CHARSET_INFO *cs) const
+{
+ uchar *orig_to= to;
+ uint32 length, data_length;
+ DBUG_ASSERT(str.length <= UINT32_MAX);
+ length= (uint32)str.length;
+
+ if (length + suffix_length <= original_length)
+ data_length= length;
+ else
+ data_length= original_length - suffix_length;
+
+ // length stored in lowendian form
+ store_key_part_length(data_length + suffix_length, to, length_bytes);
+ to+= length_bytes;
+ // copying data length bytes to the buffer
+ memcpy(to, (uchar*)str.str, data_length);
+ to+= data_length;
+
+ if (cs == &my_charset_bin && suffix_length)
+ {
+ // suffix length stored in bigendian form
+ store_bigendian(str.length, to, suffix_length);
+ to+= suffix_length;
+ }
+ return static_cast<uint>(to - orig_to);
+}
+
+
+/*
+ @brief
+ Create a mem-comparable sort key
+
+ @param param sort param structure
+ @param to buffer where values are written
+
+ @retval
+ length of the bytes written including the NULL bytes
+*/
+
+static uint make_sortkey(Sort_param *param, uchar *to)
+{
+ Field *field;
+ SORT_FIELD *sort_field;
+ uchar *orig_to= to;
+
+ for (sort_field=param->local_sortorder.begin() ;
+ sort_field != param->local_sortorder.end() ;
+ sort_field++)
+ {
+ bool maybe_null=0;
+ if ((field=sort_field->field))
+ {
+ // Field
+ field->make_sort_key_part(to, sort_field->length);
+ if ((maybe_null= field->maybe_null()))
+ to++;
+ }
+ else
+ { // Item
+ sort_field->item->type_handler()->make_sort_key_part(to,
+ sort_field->item,
+ sort_field, param);
+ if ((maybe_null= sort_field->item->maybe_null))
+ to++;
+ }
+
+ if (sort_field->reverse)
+ reverse_key(to, sort_field);
+ to+= sort_field->length;
+ }
+
+ DBUG_ASSERT(static_cast<uint>(to - orig_to) <= param->sort_length);
+ return static_cast<uint>(to - orig_to);
+}
+
+
+/*
+ @brief
+ create a compact sort key which can be compared with a comparison
+ function. They are called packed sort keys
+
+ @param param sort param structure
+ @param to buffer where values are written
+
+ @retval
+ length of the bytes written including the NULL bytes
+*/
+
+static uint make_packed_sortkey(Sort_param *param, uchar *to)
+{
+ Field *field;
+ SORT_FIELD *sort_field;
+ uint length;
+ uchar *orig_to= to;
+
+ to+= Sort_keys::size_of_length_field;
+
+ for (sort_field=param->local_sortorder.begin() ;
+ sort_field != param->local_sortorder.end() ;
+ sort_field++)
+ {
+ bool maybe_null=0;
+ if ((field=sort_field->field))
+ {
+ // Field
+ length= field->make_packed_sort_key_part(to, sort_field);
+ if ((maybe_null= field->maybe_null()))
+ to++;
+ }
+ else
+ { // Item
+ Item *item= sort_field->item;
+ length= item->type_handler()->make_packed_sort_key_part(to, item,
+ sort_field,
+ param);
+ if ((maybe_null= sort_field->item->maybe_null))
+ to++;
+ }
+ to+= length;
+ }
+
+ length= static_cast<int>(to - orig_to);
+ DBUG_ASSERT(length <= param->sort_length);
+ Sort_keys::store_sortkey_length(orig_to, length);
+ return length;
+}
diff --git a/sql/filesort.h b/sql/filesort.h
index 5102ee2326f..9f71da02c96 100644
--- a/sql/filesort.h
+++ b/sql/filesort.h
@@ -25,9 +25,12 @@ class THD;
struct TABLE;
class Filesort_tracker;
struct SORT_FIELD;
+struct SORT_FIELD_ATTR;
typedef struct st_order ORDER;
class JOIN;
class Addon_fields;
+class Sort_keys;
+
/**
Sorting related info.
@@ -57,6 +60,7 @@ public:
bool sort_positions;
Filesort_tracker *tracker;
+ Sort_keys *sort_keys;
Filesort(ORDER *order_arg, ha_rows limit_arg, bool sort_positions_arg,
SQL_SELECT *select_arg):
@@ -66,14 +70,15 @@ public:
select(select_arg),
own_select(false),
using_pq(false),
- sort_positions(sort_positions_arg)
+ sort_positions(sort_positions_arg),
+ sort_keys(NULL)
{
DBUG_ASSERT(order);
};
~Filesort() { cleanup(); }
/* Prepare ORDER BY list for sorting. */
- uint make_sortorder(THD *thd, JOIN *join, table_map first_table_bit);
+ Sort_keys* make_sortorder(THD *thd, JOIN *join, table_map first_table_bit);
private:
void cleanup();
@@ -88,6 +93,7 @@ class SORT_INFO
public:
SORT_INFO()
:addon_fields(NULL), record_pointers(0),
+ sort_keys(NULL),
sorted_result_in_fsbuf(FALSE)
{
buffpek.str= 0;
@@ -121,6 +127,7 @@ public:
LEX_STRING buffpek; /* Buffer for buffpek structures */
Addon_fields *addon_fields; /* Addon field descriptors */
uchar *record_pointers; /* If sorted in memory */
+ Sort_keys *sort_keys; /* Sort key descriptors*/
/**
If the entire result of filesort fits in memory, we skip the merge phase.
@@ -201,6 +208,7 @@ public:
template<bool Packed_addon_fields>
inline void unpack_addon_fields(uchar *buff);
+ bool using_packed_sortkeys();
friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
Filesort_tracker* tracker, JOIN *join,
@@ -216,5 +224,8 @@ bool filesort_use_addons(TABLE *table, uint sortlength,
uint *m_packable_length);
void change_double_for_sort(double nr,uchar *to);
+void store_length(uchar *to, uint length, uint pack_length);
+void
+reverse_key(uchar *to, const SORT_FIELD_ATTR *sort_field);
#endif /* FILESORT_INCLUDED */
diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc
index 95b9dc51cf8..d178740d24b 100644
--- a/sql/filesort_utils.cc
+++ b/sql/filesort_utils.cc
@@ -20,6 +20,8 @@
#include "table.h"
+PSI_memory_key key_memory_Filesort_buffer_sort_keys;
+
namespace {
/**
A local helper function. See comments for get_merge_buffers_cost().
@@ -128,7 +130,8 @@ uchar *Filesort_buffer::alloc_sort_buffer(uint num_records,
the old values
*/
my_free(m_rawmem);
- if (!(m_rawmem= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC))))
+ if (!(m_rawmem= (uchar*) my_malloc(key_memory_Filesort_buffer_sort_keys,
+ buff_size, MYF(MY_THREAD_SPECIFIC))))
{
m_size_in_bytes= 0;
DBUG_RETURN(0);
@@ -137,7 +140,8 @@ uchar *Filesort_buffer::alloc_sort_buffer(uint num_records,
}
else
{
- if (!(m_rawmem= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC))))
+ if (!(m_rawmem= (uchar*) my_malloc(key_memory_Filesort_buffer_sort_keys,
+ buff_size, MYF(MY_THREAD_SPECIFIC))))
{
m_size_in_bytes= 0;
DBUG_RETURN(0);
@@ -175,14 +179,17 @@ void Filesort_buffer::sort_buffer(const Sort_param *param, uint count)
reverse_record_pointers();
uchar **buffer= NULL;
- if (radixsort_is_appliccable(count, param->sort_length) &&
- (buffer= (uchar**) my_malloc(count*sizeof(char*),
+ if (!param->using_packed_sortkeys() &&
+ radixsort_is_appliccable(count, param->sort_length) &&
+ (buffer= (uchar**) my_malloc(PSI_INSTRUMENT_ME, count*sizeof(char*),
MYF(MY_THREAD_SPECIFIC))))
{
radixsort_for_str_ptr(m_sort_keys, count, param->sort_length, buffer);
my_free(buffer);
return;
}
-
- my_qsort2(m_sort_keys, count, sizeof(uchar*), get_ptr_compare(size), &size);
+
+ my_qsort2(m_sort_keys, count, sizeof(uchar*),
+ param->get_compare_function(),
+ param->get_compare_argument(&size));
}
diff --git a/sql/filesort_utils.h b/sql/filesort_utils.h
index e8b93940abf..1962f149893 100644
--- a/sql/filesort_utils.h
+++ b/sql/filesort_utils.h
@@ -279,4 +279,8 @@ private:
longlong m_idx;
};
+int compare_packed_sort_keys(void *sort_keys, unsigned char **a,
+ unsigned char **b);
+qsort2_cmp get_packed_keys_compare_ptr();
+
#endif // FILESORT_UTILS_INCLUDED
diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc
index 4919e5b959b..6d7ab7e29c3 100644
--- a/sql/gcalc_slicescan.cc
+++ b/sql/gcalc_slicescan.cc
@@ -204,7 +204,7 @@ void Gcalc_dyn_list::format_blk(void* block)
Gcalc_dyn_list::Item *Gcalc_dyn_list::alloc_new_blk()
{
- void *new_block= my_malloc(m_blk_size, MYF(MY_WME));
+ void *new_block= my_malloc(PSI_INSTRUMENT_ME, m_blk_size, MYF(MY_WME));
if (!new_block)
return NULL;
*m_blk_hook= new_block;
diff --git a/sql/gstream.cc b/sql/gstream.cc
index b743140ba59..f8e84e70560 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -23,6 +23,7 @@
#include "sql_priv.h"
#include "gstream.h"
#include "m_string.h" // LEX_STRING
+#include "mysqld.h"
enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
{
@@ -140,6 +141,7 @@ bool Gis_read_stream::check_next_symbol(char symbol)
void Gis_read_stream::set_error_msg(const char *msg)
{
size_t len= strlen(msg); // ok in this context
- m_err_msg= (char *) my_realloc(m_err_msg, (uint) len + 1, MYF(MY_ALLOW_ZERO_PTR));
+ m_err_msg= (char *) my_realloc(key_memory_Gis_read_stream_err_msg,
+ m_err_msg, (uint) len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index d36a58aef20..f30ef6a9688 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -102,22 +102,43 @@ static const char *ha_partition_ext[]=
ha_par_ext, NullS
};
+static PSI_memory_key key_memory_Partition_share;
+static PSI_memory_key key_memory_partition_sort_buffer;
+static PSI_memory_key key_memory_Partition_admin;
+
+static PSI_memory_key key_memory_ha_partition_file;
+//static PSI_memory_key key_memory_ha_partition_engine_array;
+static PSI_memory_key key_memory_ha_partition_part_ids;
#ifdef HAVE_PSI_INTERFACE
PSI_mutex_key key_partition_auto_inc_mutex;
+PSI_file_key key_file_ha_partition_par;
static PSI_mutex_info all_partition_mutexes[]=
{
{ &key_partition_auto_inc_mutex, "Partition_share::auto_inc_mutex", 0}
};
+static PSI_memory_info all_partitioning_memory[]=
+{ { &key_memory_Partition_share, "Partition_share", 0},
+ { &key_memory_partition_sort_buffer, "partition_sort_buffer", 0},
+ { &key_memory_Partition_admin, "Partition_admin", 0},
+ { &key_memory_ha_partition_file, "ha_partition::file", 0},
+// { &key_memory_ha_partition_engine_array, "ha_partition::engine_array", 0},
+ { &key_memory_ha_partition_part_ids, "ha_partition::part_ids", 0} };
+static PSI_file_info all_partition_file[]=
+{ { &key_file_ha_partition_par, "ha_partition::parfile", 0} };
static void init_partition_psi_keys(void)
{
const char* category= "partition";
int count;
+ count= array_elements(all_partitioning_memory);
+ mysql_memory_register(category, all_partitioning_memory, count);
count= array_elements(all_partition_mutexes);
mysql_mutex_register(category, all_partition_mutexes, count);
+ count= array_elements(all_partition_file);
+ mysql_file_register(category, all_partition_file, count);
}
#endif /* HAVE_PSI_INTERFACE */
@@ -244,7 +265,7 @@ ha_partition::ha_partition(handlerton *hton, TABLE_SHARE *share)
void ha_partition::ha_partition_init()
{
- init_alloc_root(&m_mem_root, "ha_partition", 512, 512, MYF(0));
+ init_alloc_root(PSI_INSTRUMENT_ME, &m_mem_root, 512, 512, MYF(0));
init_handler_variables();
}
@@ -649,9 +670,9 @@ int ha_partition::create_partitioning_metadata(const char *path,
strxmov(name, path, ha_par_ext, NullS);
strxmov(old_name, old_path, ha_par_ext, NullS);
if ((action_flag == CHF_DELETE_FLAG &&
- mysql_file_delete(key_file_partition, name, MYF(MY_WME))) ||
+ mysql_file_delete(key_file_ha_partition_par, name, MYF(MY_WME))) ||
(action_flag == CHF_RENAME_FLAG &&
- mysql_file_rename(key_file_partition, old_name, name, MYF(MY_WME))))
+ mysql_file_rename(key_file_ha_partition_par, old_name, name, MYF(MY_WME))))
{
DBUG_RETURN(TRUE);
}
@@ -1333,7 +1354,7 @@ bool print_admin_msg(THD* thd, uint len,
char *msgbuf;
bool error= true;
- if (!(msgbuf= (char*) my_malloc(len, MYF(0))))
+ if (!(msgbuf= (char*) my_malloc(key_memory_Partition_admin, len, MYF(0))))
return true;
va_start(args, fmt);
msg_length= my_vsnprintf(msgbuf, len, fmt, args);
@@ -2749,7 +2770,8 @@ bool ha_partition::create_handler_file(const char *name)
/* 4 static words (tot words, checksum, tot partitions, name length) */
tot_len_words= 4 + tot_partition_words + tot_name_words;
tot_len_byte= PAR_WORD_SIZE * tot_len_words;
- if (!(file_buffer= (uchar *) my_malloc(tot_len_byte, MYF(MY_ZEROFILL))))
+ if (!(file_buffer= (uchar *) my_malloc(key_memory_ha_partition_file,
+ tot_len_byte, MYF(MY_ZEROFILL))))
DBUG_RETURN(TRUE);
engine_array= (file_buffer + PAR_ENGINES_OFFSET);
name_buffer_ptr= (char*) (engine_array + tot_partition_words * PAR_WORD_SIZE
@@ -2804,7 +2826,7 @@ bool ha_partition::create_handler_file(const char *name)
to be used at open, delete_table and rename_table
*/
fn_format(file_name, name, "", ha_par_ext, MY_APPEND_EXT);
- if ((file= mysql_file_create(key_file_partition,
+ if ((file= mysql_file_create(key_file_ha_partition_par,
file_name, CREATE_MODE, O_RDWR | O_TRUNC,
MYF(MY_WME))) >= 0)
{
@@ -2829,7 +2851,7 @@ bool ha_partition::create_handler_file(const char *name)
}
(void) mysql_file_close(file, MYF(0));
if (result)
- mysql_file_delete(key_file_partition, file_name, MYF(MY_WME));
+ mysql_file_delete(key_file_ha_partition_par, file_name, MYF(MY_WME));
}
else
result= TRUE;
@@ -2993,7 +3015,7 @@ bool ha_partition::read_par_file(const char *name)
fn_format(buff, name, "", ha_par_ext, MY_APPEND_EXT);
/* Following could be done with mysql_file_stat to read in whole file */
- if ((file= mysql_file_open(key_file_partition,
+ if ((file= mysql_file_open(key_file_ha_partition_par,
buff, O_RDONLY | O_SHARE, MYF(0))) < 0)
DBUG_RETURN(TRUE);
if (mysql_file_read(file, (uchar *) &buff[0], PAR_WORD_SIZE, MYF(MY_NABP)))
@@ -3219,7 +3241,7 @@ bool ha_partition::insert_partition_name_in_hash(const char *name, uint part_id,
Since we use my_multi_malloc, then my_free(part_def) will also free
part_name, as a part of my_hash_free.
*/
- if (!my_multi_malloc(MY_WME,
+ if (!my_multi_malloc(key_memory_Partition_share, MY_WME,
&part_def, sizeof(PART_NAME_DEF),
&part_name, part_name_length + 1,
NULL))
@@ -3267,10 +3289,10 @@ bool ha_partition::populate_partition_name_hash()
DBUG_RETURN(false);
}
tot_names= m_is_sub_partitioned ? m_tot_parts + num_parts : num_parts;
- if (my_hash_init(&part_share->partition_name_hash,
- system_charset_info, tot_names, 0, 0,
- (my_hash_get_key) get_part_name,
- my_free, HASH_UNIQUE))
+ if (my_hash_init(key_memory_Partition_share,
+ &part_share->partition_name_hash, system_charset_info,
+ tot_names, 0, 0, (my_hash_get_key) get_part_name, my_free,
+ HASH_UNIQUE))
{
unlock_shared_ha_data();
DBUG_RETURN(TRUE);
@@ -3506,7 +3528,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if (!m_part_ids_sorted_by_num_of_records)
{
if (!(m_part_ids_sorted_by_num_of_records=
- (uint32*) my_malloc(m_tot_parts * sizeof(uint32), MYF(MY_WME))))
+ (uint32*) my_malloc(key_memory_ha_partition_part_ids,
+ m_tot_parts * sizeof(uint32), MYF(MY_WME))))
DBUG_RETURN(error);
uint32 i;
/* Initialize it with all partition ids. */
@@ -3524,7 +3547,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
/* Allocate memory used with MMR */
if (!(m_range_info= (void **)
- my_multi_malloc(MYF(MY_WME),
+ my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&m_range_info, sizeof(range_id_t) * m_tot_parts,
&m_stock_range_seq, sizeof(uint) * m_tot_parts,
&m_mrr_buffer, sizeof(HANDLER_BUFFER) * m_tot_parts,
@@ -3535,8 +3558,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
&m_part_mrr_range_current,
sizeof(PARTITION_PART_KEY_MULTI_RANGE *) * m_tot_parts,
&m_partition_part_key_multi_range_hld,
- sizeof(PARTITION_PART_KEY_MULTI_RANGE_HLD) *
- m_tot_parts,
+ sizeof(PARTITION_PART_KEY_MULTI_RANGE_HLD) * m_tot_parts,
NullS)))
goto err_alloc;
@@ -5315,7 +5337,8 @@ bool ha_partition::init_record_priority_queue()
/* Allocate a key for temporary use when setting up the scan. */
alloc_len+= table_share->max_key_length;
- if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
+ if (!(m_ordered_rec_buffer= (uchar*)my_malloc(key_memory_partition_sort_buffer,
+ alloc_len, MYF(MY_WME))))
DBUG_RETURN(true);
/*
@@ -6066,9 +6089,8 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
if (!m_mrr_range_first)
{
if (!(m_mrr_range_first= (PARTITION_KEY_MULTI_RANGE *)
- my_multi_malloc(MYF(MY_WME),
- &m_mrr_range_current,
- sizeof(PARTITION_KEY_MULTI_RANGE),
+ my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
+ &m_mrr_range_current, sizeof(PARTITION_KEY_MULTI_RANGE),
NullS)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -6085,9 +6107,8 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
if (!m_part_mrr_range_first[i])
{
if (!(m_part_mrr_range_first[i]= (PARTITION_PART_KEY_MULTI_RANGE *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &m_part_mrr_range_current[i],
- sizeof(PARTITION_PART_KEY_MULTI_RANGE),
+ my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME | MY_ZEROFILL),
+ &m_part_mrr_range_current[i], sizeof(PARTITION_PART_KEY_MULTI_RANGE),
NullS)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
@@ -6123,7 +6144,7 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
if (m_mrr_range_current->key[0])
my_free(m_mrr_range_current->key[0]);
if (!(m_mrr_range_current->key[0]=
- (uchar *) my_malloc(length, MYF(MY_WME))))
+ (uchar *) my_malloc(PSI_INSTRUMENT_ME, length, MYF(MY_WME))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
m_mrr_range_current->length[0]= length;
}
@@ -6147,7 +6168,7 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
if (m_mrr_range_current->key[1])
my_free(m_mrr_range_current->key[1]);
if (!(m_mrr_range_current->key[1]=
- (uchar *) my_malloc(length, MYF(MY_WME))))
+ (uchar *) my_malloc(PSI_INSTRUMENT_ME, length, MYF(MY_WME))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
m_mrr_range_current->length[1]= length;
}
@@ -6181,7 +6202,7 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
{
PARTITION_PART_KEY_MULTI_RANGE *tmp_part_mrr_range;
if (!(tmp_part_mrr_range= (PARTITION_PART_KEY_MULTI_RANGE *)
- my_malloc(sizeof(PARTITION_PART_KEY_MULTI_RANGE),
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(PARTITION_PART_KEY_MULTI_RANGE),
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -6201,7 +6222,7 @@ int ha_partition::multi_range_key_create_key(RANGE_SEQ_IF *seq,
/* Add end of range sentinel */
PARTITION_KEY_MULTI_RANGE *tmp_mrr_range;
if (!(tmp_mrr_range= (PARTITION_KEY_MULTI_RANGE *)
- my_malloc(sizeof(PARTITION_KEY_MULTI_RANGE), MYF(MY_WME))))
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(PARTITION_KEY_MULTI_RANGE), MYF(MY_WME))))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
tmp_mrr_range->id= m_mrr_range_current->id + 1;
@@ -6472,7 +6493,7 @@ int ha_partition::multi_range_read_init(RANGE_SEQ_IF *seq,
if (m_mrr_full_buffer)
my_free(m_mrr_full_buffer);
if (!(m_mrr_full_buffer=
- (uchar *) my_malloc(m_mrr_new_full_buffer_size, MYF(MY_WME))))
+ (uchar *) my_malloc(PSI_INSTRUMENT_ME, m_mrr_new_full_buffer_size, MYF(MY_WME))))
{
m_mrr_full_buffer_size= 0;
error= HA_ERR_OUT_OF_MEM;
@@ -6870,11 +6891,9 @@ FT_INFO *ha_partition::ft_init_ext(uint flags, uint inx, String *key)
{
FT_INFO **tmp_ft_info;
if (!(ft_target= (st_partition_ft_info *)
- my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
- &ft_target,
- sizeof(st_partition_ft_info),
- &tmp_ft_info,
- sizeof(FT_INFO *) * m_tot_parts,
+ my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME | MY_ZEROFILL),
+ &ft_target, sizeof(st_partition_ft_info),
+ &tmp_ft_info, sizeof(FT_INFO *) * m_tot_parts,
NullS)))
{
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
diff --git a/sql/handle_connections_win.cc b/sql/handle_connections_win.cc
index 5db10c2fada..44ad8ddc865 100644
--- a/sql/handle_connections_win.cc
+++ b/sql/handle_connections_win.cc
@@ -360,7 +360,7 @@ struct Pipe_Listener : public Listener
{
sql_perror("Create named pipe failed");
sql_print_error("Aborting");
- exit(1);
+ unireg_abort(1);
}
first_instance= false;
return pipe_handle;
diff --git a/sql/handler.cc b/sql/handler.cc
index 7d61252eea6..4dd915d8b91 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -30,7 +30,6 @@
#include "key.h" // key_copy, key_unpack, key_cmp_if_same, key_cmp
#include "sql_table.h" // build_table_filename
#include "sql_parse.h" // check_stack_overrun
-#include "sql_acl.h" // SUPER_ACL
#include "sql_base.h" // TDC_element
#include "discover.h" // extension_based_table_discovery, etc
#include "log_event.h" // *_rows_log_event
@@ -40,6 +39,8 @@
#include "myisam.h"
#include "probes_mysql.h"
#include <mysql/psi/mysql_table.h>
+#include <pfs_transaction_provider.h>
+#include <mysql/psi/mysql_transaction.h>
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_audit.h"
#include "ha_sequence.h"
@@ -62,6 +63,39 @@
#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
#endif /* WITH_WSREP */
+/**
+ @def MYSQL_TABLE_LOCK_WAIT
+ Instrumentation helper for table io_waits.
+ @param OP the table operation to be performed
+ @param FLAGS per table operation flags.
+ @param PAYLOAD the code to instrument.
+ @sa MYSQL_END_TABLE_WAIT.
+*/
+#ifdef HAVE_PSI_TABLE_INTERFACE
+ #define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
+ { \
+ if (m_psi != NULL) \
+ { \
+ PSI_table_locker *locker; \
+ PSI_table_locker_state state; \
+ locker= PSI_TABLE_CALL(start_table_lock_wait) \
+ (& state, m_psi, OP, FLAGS, \
+ __FILE__, __LINE__); \
+ PAYLOAD \
+ if (locker != NULL) \
+ PSI_TABLE_CALL(end_table_lock_wait)(locker); \
+ } \
+ else \
+ { \
+ PAYLOAD \
+ } \
+ }
+#else
+ #define MYSQL_TABLE_LOCK_WAIT(OP, FLAGS, PAYLOAD) \
+ PAYLOAD
+#endif
+
+
/*
While we have legacy_db_type, we have this array to
check for dups and to find handlerton from legacy_db_type.
@@ -361,7 +395,8 @@ int ha_init_errors(void)
/* Allocate a pointer array for the error message strings. */
/* Zerofill it to avoid uninitialized gaps. */
- if (! (handler_errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
+ if (! (handler_errmsgs= (const char**) my_malloc(key_memory_handler_errmsgs,
+ HA_ERR_ERRORS * sizeof(char*),
MYF(MY_WME | MY_ZEROFILL))))
return 1;
@@ -531,7 +566,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
DBUG_ENTER("ha_initialize_handlerton");
DBUG_PRINT("plugin", ("initialize plugin: '%s'", plugin->name.str));
- hton= (handlerton *)my_malloc(sizeof(handlerton),
+ hton= (handlerton *)my_malloc(key_memory_handlerton, sizeof(handlerton),
MYF(MY_WME | MY_ZEROFILL));
if (hton == NULL)
{
@@ -1200,7 +1235,7 @@ void ha_pre_shutdown()
times per transaction.
*/
-void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
+void trans_register_ha(THD *thd, bool all, handlerton *ht_arg, ulonglong trxid)
{
THD_TRANS *trans;
Ha_trx_info *ha_info;
@@ -1231,6 +1266,25 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
if (thd->transaction.implicit_xid.is_null())
thd->transaction.implicit_xid.set(thd->query_id);
+/*
+ Register transaction start in performance schema if not done already.
+ By doing this, we handle cases when the transaction is started implicitly in
+ autocommit=0 mode, and cases when we are in normal autocommit=1 mode and the
+ executed statement is a single-statement transaction.
+
+ Explicitly started transactions are handled in trans_begin().
+
+ Do not register transactions in which binary log is the only participating
+ transactional storage engine.
+*/
+ if (thd->m_transaction_psi == NULL && ht_arg->db_type != DB_TYPE_BINLOG)
+ {
+ thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
+ thd->get_xid(), trxid, thd->tx_isolation, thd->tx_read_only,
+ !thd->in_multi_stmt_transaction_mode());
+ DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
+ //gtid_set_performance_schema_values(thd);
+ }
DBUG_VOID_RETURN;
}
@@ -1456,12 +1510,14 @@ int ha_commit_trans(THD *thd, bool all)
Free resources and perform other cleanup even for 'empty' transactions.
*/
if (is_real_trans)
+ {
thd->transaction.cleanup();
+ MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
+ thd->m_transaction_psi= NULL;
+ }
#ifdef WITH_WSREP
if (wsrep_is_active(thd) && is_real_trans && !error)
- {
wsrep_commit_empty(thd, all);
- }
#endif /* WITH_WSREP */
DBUG_RETURN(0);
}
@@ -1490,7 +1546,8 @@ int ha_commit_trans(THD *thd, bool all)
We allow the owner of FTWRL to COMMIT; we assume that it knows
what it does.
*/
- mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
+ MDL_EXPLICIT);
if (!WSREP(thd) &&
thd->mdl_context.acquire_lock(&mdl_request,
@@ -1505,7 +1562,7 @@ int ha_commit_trans(THD *thd, bool all)
if (rw_trans &&
opt_readonly &&
- !(thd->security_ctx->master_access & SUPER_ACL) &&
+ !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
!thd->slave_thread)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
@@ -1651,12 +1708,15 @@ int ha_commit_trans(THD *thd, bool all)
#endif /* WITH_WSREP */
DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE(););
if (tc_log->unlog(cookie, xid))
- {
error= 2; /* Error during commit */
- goto end;
- }
done:
+ if (is_real_trans)
+ {
+ MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
+ thd->m_transaction_psi= NULL;
+ }
+
DBUG_EXECUTE_IF("crash_commit_after", DBUG_SUICIDE(););
mysql_mutex_assert_not_owner(&LOCK_prepare_ordered);
@@ -1694,6 +1754,8 @@ err:
ha_rollback_trans(thd, all);
else
{
+ MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
+ thd->m_transaction_psi= NULL;
WSREP_DEBUG("rollback skipped %p %d",thd->rgi_slave,
thd->rgi_slave->is_parallel_exec);
}
@@ -1913,6 +1975,13 @@ int ha_rollback_trans(THD *thd, bool all)
}
(void) wsrep_after_rollback(thd, all);
#endif /* WITH_WSREP */
+
+ if (all || !thd->in_active_multi_stmt_transaction())
+ {
+ MYSQL_ROLLBACK_TRANSACTION(thd->m_transaction_psi);
+ thd->m_transaction_psi= NULL;
+ }
+
/* Always cleanup. Even if nht==0. There may be savepoints. */
if (is_real_trans)
{
@@ -2218,7 +2287,7 @@ int ha_recover(HASH *commit_list)
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
{
DBUG_EXECUTE_IF("min_xa_len", info.len = 16;);
- info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
+ info.list=(XID *)my_malloc(key_memory_XID, info.len*sizeof(XID), MYF(0));
}
if (!info.list)
{
@@ -2360,6 +2429,10 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
ha_info->reset(); /* keep it conveniently zero-filled */
}
trans->ha_list= sv->ha_list;
+
+ if (thd->m_transaction_psi != NULL)
+ MYSQL_INC_TRANSACTION_ROLLBACK_TO_SAVEPOINT(thd->m_transaction_psi, 1);
+
DBUG_RETURN(error);
}
@@ -2411,6 +2484,9 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv)
*/
sv->ha_list= trans->ha_list;
+ if (!error && thd->m_transaction_psi != NULL)
+ MYSQL_INC_TRANSACTION_SAVEPOINTS(thd->m_transaction_psi, 1);
+
DBUG_RETURN(error);
}
@@ -2435,6 +2511,10 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
error=1;
}
}
+
+ if (thd->m_transaction_psi != NULL)
+ MYSQL_INC_TRANSACTION_RELEASE_SAVEPOINT(thd->m_transaction_psi, 1);
+
DBUG_RETURN(error);
}
@@ -2702,6 +2782,30 @@ void handler::rebind_psi()
}
+void handler::start_psi_batch_mode()
+{
+#ifdef HAVE_PSI_TABLE_INTERFACE
+ DBUG_ASSERT(m_psi_batch_mode == PSI_BATCH_MODE_NONE);
+ DBUG_ASSERT(m_psi_locker == NULL);
+ m_psi_batch_mode= PSI_BATCH_MODE_STARTING;
+ m_psi_numrows= 0;
+#endif
+}
+
+void handler::end_psi_batch_mode()
+{
+#ifdef HAVE_PSI_TABLE_INTERFACE
+ DBUG_ASSERT(m_psi_batch_mode != PSI_BATCH_MODE_NONE);
+ if (m_psi_locker != NULL)
+ {
+ DBUG_ASSERT(m_psi_batch_mode == PSI_BATCH_MODE_STARTED);
+ PSI_TABLE_CALL(end_table_io_wait)(m_psi_locker, m_psi_numrows);
+ m_psi_locker= NULL;
+ }
+ m_psi_batch_mode= PSI_BATCH_MODE_NONE;
+#endif
+}
+
PSI_table_share *handler::ha_table_share_psi() const
{
return table_share->m_psi;
@@ -2791,8 +2895,10 @@ int handler::ha_close(void)
*/
if (table->in_use)
status_var_add(table->in_use->status_var.rows_tmp_read, rows_tmp_read);
- PSI_CALL_close_table(m_psi);
+ PSI_CALL_close_table(table_share, m_psi);
m_psi= NULL; /* instrumentation handle, invalid after close_table() */
+ DBUG_ASSERT(m_psi_batch_mode == PSI_BATCH_MODE_NONE);
+ DBUG_ASSERT(m_psi_locker == NULL);
/* Detach from ANALYZE tracker */
tracker= NULL;
@@ -2813,7 +2919,7 @@ int handler::ha_rnd_next(uchar *buf)
do
{
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, MAX_KEY, result,
{ result= rnd_next(buf); })
if (result != HA_ERR_RECORD_DELETED)
break;
@@ -2845,7 +2951,7 @@ int handler::ha_rnd_pos(uchar *buf, uchar *pos)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited == RND);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, MAX_KEY, result,
{ result= rnd_pos(buf, pos); })
increment_statistics(&SSV::ha_read_rnd_count);
if (result == HA_ERR_RECORD_DELETED)
@@ -2870,7 +2976,7 @@ int handler::ha_index_read_map(uchar *buf, const uchar *key,
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_read_map(buf, key, keypart_map, find_flag); })
increment_statistics(&SSV::ha_read_key_count);
if (!result)
@@ -2898,7 +3004,7 @@ int handler::ha_index_read_idx_map(uchar *buf, uint index, const uchar *key,
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
DBUG_ASSERT(end_range == NULL);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, index, result,
{ result= index_read_idx_map(buf, index, key, keypart_map, find_flag); })
increment_statistics(&SSV::ha_read_key_count);
if (!result)
@@ -2920,7 +3026,7 @@ int handler::ha_index_next(uchar * buf)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_next(buf); })
increment_statistics(&SSV::ha_read_next_count);
if (!result)
@@ -2941,7 +3047,7 @@ int handler::ha_index_prev(uchar * buf)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_prev(buf); })
increment_statistics(&SSV::ha_read_prev_count);
if (!result)
@@ -2961,7 +3067,7 @@ int handler::ha_index_first(uchar * buf)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_first(buf); })
increment_statistics(&SSV::ha_read_first_count);
if (!result)
@@ -2981,7 +3087,7 @@ int handler::ha_index_last(uchar * buf)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_last(buf); })
increment_statistics(&SSV::ha_read_last_count);
if (!result)
@@ -3001,7 +3107,7 @@ int handler::ha_index_next_same(uchar *buf, const uchar *key, uint keylen)
m_lock_type != F_UNLCK);
DBUG_ASSERT(inited==INDEX);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_FETCH_ROW, active_index, result,
{ result= index_next_same(buf, key, keylen); })
increment_statistics(&SSV::ha_read_next_count);
if (!result)
@@ -4585,7 +4691,8 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
ALTER_DROP_CHECK_CONSTRAINT |
ALTER_PARTITIONED |
ALTER_VIRTUAL_GCOL_EXPR |
- ALTER_RENAME;
+ ALTER_RENAME |
+ ALTER_RENAME_INDEX;
/* Is there at least one operation that requires copy algorithm? */
if (ha_alter_info->handler_flags & ~inplace_offline_operations)
@@ -4942,7 +5049,7 @@ void handler::update_global_table_stats()
table->s->table_cache_key.length)))
{
if (!(table_stats = ((TABLE_STATS*)
- my_malloc(sizeof(TABLE_STATS),
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(TABLE_STATS),
MYF(MY_WME | MY_ZEROFILL)))))
{
/* Out of memory error already given */
@@ -5007,7 +5114,7 @@ void handler::update_global_index_stats()
key_length)))
{
if (!(index_stats = ((INDEX_STATS*)
- my_malloc(sizeof(INDEX_STATS),
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(INDEX_STATS),
MYF(MY_WME | MY_ZEROFILL)))))
goto end; // Error is already given
@@ -6389,7 +6496,7 @@ int handler::ha_external_lock(THD *thd, int lock_type)
We cache the table flags if the locking succeeded. Otherwise, we
keep them as they were when they were fetched in ha_open().
*/
- MYSQL_TABLE_LOCK_WAIT(m_psi, PSI_TABLE_EXTERNAL_LOCK, lock_type,
+ MYSQL_TABLE_LOCK_WAIT(PSI_TABLE_EXTERNAL_LOCK, lock_type,
{ error= external_lock(thd, lock_type); })
DBUG_EXECUTE_IF("external_lock_failure", error= HA_ERR_GENERIC;);
@@ -6646,15 +6753,15 @@ int handler::ha_write_row(const uchar *buf)
mark_trx_read_write();
increment_statistics(&SSV::ha_write_count);
- if (table->s->long_unique_table)
+ if (table->s->long_unique_table && this == table->file)
{
- if (this->inited == RND)
+ if (inited == RND)
table->clone_handler_for_update();
handler *h= table->update_handler ? table->update_handler : table->file;
if ((error= check_duplicate_long_entries(table, h, buf)))
DBUG_RETURN(error);
}
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_WRITE_ROW, MAX_KEY, error,
{ error= write_row(buf); })
MYSQL_INSERT_ROW_DONE(error);
@@ -6699,7 +6806,7 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
return error;
}
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, error,
{ error= update_row(old_data, new_data);})
MYSQL_UPDATE_ROW_DONE(error);
@@ -6762,7 +6869,7 @@ int handler::ha_delete_row(const uchar *buf)
mark_trx_read_write();
increment_statistics(&SSV::ha_delete_count);
- TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_DELETE_ROW, active_index, 0,
+ TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, active_index, error,
{ error= delete_row(buf);})
MYSQL_DELETE_ROW_DONE(error);
if (likely(!error))
@@ -7222,7 +7329,7 @@ int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *ta
cache_key_length= db->length + 1 + table->length + 1;
- if(!(cache_key= (uchar *)my_malloc(cache_key_length,
+ if(!(cache_key= (uchar *)my_malloc(PSI_INSTRUMENT_ME, cache_key_length,
MYF(MY_WME | MY_ZEROFILL))))
{
/* Out of memory error already given */
diff --git a/sql/handler.h b/sql/handler.h
index 0a561ec8b3f..f17c303571f 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3115,8 +3115,59 @@ public:
*/
PSI_table *m_psi;
+private:
+ /** Internal state of the batch instrumentation. */
+ enum batch_mode_t
+ {
+ /** Batch mode not used. */
+ PSI_BATCH_MODE_NONE,
+ /** Batch mode used, before first table io. */
+ PSI_BATCH_MODE_STARTING,
+ /** Batch mode used, after first table io. */
+ PSI_BATCH_MODE_STARTED
+ };
+ /**
+ Batch mode state.
+ @sa start_psi_batch_mode.
+ @sa end_psi_batch_mode.
+ */
+ batch_mode_t m_psi_batch_mode;
+ /**
+ The number of rows in the batch.
+ @sa start_psi_batch_mode.
+ @sa end_psi_batch_mode.
+ */
+ ulonglong m_psi_numrows;
+ /**
+ The current event in a batch.
+ @sa start_psi_batch_mode.
+ @sa end_psi_batch_mode.
+ */
+ PSI_table_locker *m_psi_locker;
+ /**
+ Storage for the event in a batch.
+ @sa start_psi_batch_mode.
+ @sa end_psi_batch_mode.
+ */
+ PSI_table_locker_state m_psi_locker_state;
+
+public:
virtual void unbind_psi();
virtual void rebind_psi();
+ /**
+ Put the handler in 'batch' mode when collecting
+ table io instrumented events.
+ When operating in batch mode:
+ - a single start event is generated in the performance schema.
+ - all table io performed between @c start_psi_batch_mode
+ and @c end_psi_batch_mode is not instrumented:
+ the number of rows affected is counted instead in @c m_psi_numrows.
+ - a single end event is generated in the performance schema
+ when the batch mode ends with @c end_psi_batch_mode.
+ */
+ void start_psi_batch_mode();
+ /** End a batch started with @c start_psi_batch_mode. */
+ void end_psi_batch_mode();
bool set_top_table_fields;
struct TABLE *top_table;
@@ -3163,7 +3214,11 @@ public:
pushed_rowid_filter(NULL),
rowid_filter_is_active(0),
auto_inc_intervals_count(0),
- m_psi(NULL), set_top_table_fields(FALSE), top_table(0),
+ m_psi(NULL),
+ m_psi_batch_mode(PSI_BATCH_MODE_NONE),
+ m_psi_numrows(0),
+ m_psi_locker(NULL),
+ set_top_table_fields(FALSE), top_table(0),
top_table_field(0), top_table_fields(0),
m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0)
{
@@ -4036,11 +4091,10 @@ public:
virtual my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
- qc_engine_callback
- *engine_callback,
+ qc_engine_callback *callback,
ulonglong *engine_data)
{
- *engine_callback= 0;
+ *callback= 0;
return TRUE;
}
@@ -5007,7 +5061,8 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal);
#endif
/* these are called by storage engines */
-void trans_register_ha(THD *thd, bool all, handlerton *ht);
+void trans_register_ha(THD *thd, bool all, handlerton *ht,
+ ulonglong trxid);
/*
Storage engine has to assume the transaction will end up with 2pc if
@@ -5032,13 +5087,82 @@ int binlog_log_row(TABLE* table,
const uchar *after_record,
Log_func *log_func);
-#define TABLE_IO_WAIT(TRACKER, PSI, OP, INDEX, FLAGS, PAYLOAD) \
+/**
+ @def MYSQL_TABLE_IO_WAIT
+ Instrumentation helper for table io_waits.
+ Note that this helper is intended to be used from
+ within the handler class only, as it uses members
+ from @c handler
+ Performance schema events are instrumented as follows:
+ - in non batch mode, one event is generated per call
+ - in batch mode, the number of rows affected is saved
+ in @c m_psi_numrows, so that @c end_psi_batch_mode()
+ generates a single event for the batch.
+ @param OP the table operation to be performed
+ @param INDEX the table index used if any, or MAX_KEY.
+ @param PAYLOAD instrumented code to execute
+ @sa handler::end_psi_batch_mode.
+*/
+#ifdef HAVE_PSI_TABLE_INTERFACE
+ #define MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD) \
+ { \
+ if (m_psi != NULL) \
+ { \
+ switch (m_psi_batch_mode) \
+ { \
+ case PSI_BATCH_MODE_NONE: \
+ { \
+ PSI_table_locker *sub_locker= NULL; \
+ PSI_table_locker_state reentrant_safe_state; \
+ sub_locker= PSI_TABLE_CALL(start_table_io_wait) \
+ (& reentrant_safe_state, m_psi, OP, INDEX, \
+ __FILE__, __LINE__); \
+ PAYLOAD \
+ if (sub_locker != NULL) \
+ PSI_TABLE_CALL(end_table_io_wait) \
+ (sub_locker, 1); \
+ break; \
+ } \
+ case PSI_BATCH_MODE_STARTING: \
+ { \
+ m_psi_locker= PSI_TABLE_CALL(start_table_io_wait) \
+ (& m_psi_locker_state, m_psi, OP, INDEX, \
+ __FILE__, __LINE__); \
+ PAYLOAD \
+ if (!RESULT) \
+ m_psi_numrows++; \
+ m_psi_batch_mode= PSI_BATCH_MODE_STARTED; \
+ break; \
+ } \
+ case PSI_BATCH_MODE_STARTED: \
+ default: \
+ { \
+ DBUG_ASSERT(m_psi_batch_mode \
+ == PSI_BATCH_MODE_STARTED); \
+ PAYLOAD \
+ if (!RESULT) \
+ m_psi_numrows++; \
+ break; \
+ } \
+ } \
+ } \
+ else \
+ { \
+ PAYLOAD \
+ } \
+ }
+#else
+ #define MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD) \
+ PAYLOAD
+#endif
+
+#define TABLE_IO_WAIT(TRACKER, OP, INDEX, RESULT, PAYLOAD) \
{ \
Exec_time_tracker *this_tracker; \
if (unlikely((this_tracker= tracker))) \
tracker->start_tracking(table->in_use); \
\
- MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD); \
+ MYSQL_TABLE_IO_WAIT(OP, INDEX, RESULT, PAYLOAD); \
\
if (unlikely(this_tracker)) \
tracker->stop_tracking(table->in_use); \
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index d815c428ac6..ac84e5ccb7b 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -48,6 +48,7 @@ private:
class hash_filo
{
private:
+ PSI_memory_key m_psi_key;
const uint key_offset, key_length;
const my_hash_get_key get_key;
/** Size of this hash table. */
@@ -61,15 +62,13 @@ public:
mysql_mutex_t lock;
HASH cache;
- hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg,
- my_hash_get_key get_key_arg, my_hash_free_key free_element_arg,
- CHARSET_INFO *hash_charset_arg)
- :key_offset(key_offset_arg), key_length(key_length_arg),
- get_key(get_key_arg), m_size(size_arg),
- free_element(free_element_arg),init(0),
- hash_charset(hash_charset_arg),
- first_link(NULL),
- last_link(NULL)
+ hash_filo(PSI_memory_key psi_key, uint size_arg, uint key_offset_arg,
+ uint key_length_arg, my_hash_get_key get_key_arg,
+ my_hash_free_key free_element_arg, CHARSET_INFO *hash_charset_arg)
+ : m_psi_key(psi_key), key_offset(key_offset_arg),
+ key_length(key_length_arg), get_key(get_key_arg), m_size(size_arg),
+ free_element(free_element_arg),init(0), hash_charset(hash_charset_arg),
+ first_link(NULL), last_link(NULL)
{
bzero((char*) &cache,sizeof(cache));
}
@@ -95,8 +94,8 @@ public:
first_link= NULL;
last_link= NULL;
(void) my_hash_free(&cache);
- (void) my_hash_init(&cache,hash_charset,m_size,key_offset,
- key_length, get_key, free_element,0);
+ (void) my_hash_init(m_psi_key, &cache,hash_charset,m_size,key_offset,
+ key_length, get_key, free_element, 0);
if (!locked)
mysql_mutex_unlock(&lock);
}
@@ -202,10 +201,10 @@ public:
template <class T> class Hash_filo: public hash_filo
{
public:
- Hash_filo(uint size_arg, uint key_offset_arg, uint key_length_arg,
- my_hash_get_key get_key_arg, my_hash_free_key free_element_arg,
- CHARSET_INFO *hash_charset_arg) :
- hash_filo(size_arg, key_offset_arg, key_length_arg,
+ Hash_filo(PSI_memory_key psi_key, uint size_arg, uint key_offset_arg, uint
+ key_length_arg, my_hash_get_key get_key_arg, my_hash_free_key
+ free_element_arg, CHARSET_INFO *hash_charset_arg) :
+ hash_filo(psi_key, size_arg, key_offset_arg, key_length_arg,
get_key_arg, free_element_arg, hash_charset_arg) {}
T* first() { return (T*)hash_filo::first(); }
T* last() { return (T*)hash_filo::last(); }
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 968914fd56e..edf31c11081 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -150,10 +150,9 @@ bool hostname_cache_init()
Host_entry tmp;
uint key_offset= (uint) ((char*) (&tmp.ip_key) - (char*) &tmp);
- if (!(hostname_cache= new Hash_filo<Host_entry>(host_cache_size,
- key_offset, HOST_ENTRY_KEY_SIZE,
- NULL, (my_hash_free_key) free,
- &my_charset_bin)))
+ if (!(hostname_cache= new Hash_filo<Host_entry>(key_memory_host_cache_hostname,
+ host_cache_size, key_offset, HOST_ENTRY_KEY_SIZE,
+ NULL, (my_hash_free_key) free, &my_charset_bin)))
return 1;
hostname_cache->clear();
@@ -476,7 +475,8 @@ int ip_to_hostname(struct sockaddr_storage *ip_storage,
if (entry->m_host_validated)
{
if (entry->m_hostname_length)
- *hostname= my_strdup(entry->m_hostname, MYF(0));
+ *hostname= my_strdup(key_memory_host_cache_hostname,
+ entry->m_hostname, MYF(0));
DBUG_PRINT("info",("IP (%s) has been found in the cache. "
"Hostname: '%s'",
@@ -926,7 +926,8 @@ int ip_to_hostname(struct sockaddr_storage *ip_storage,
{
/* Copy host name string to be stored in the cache. */
- *hostname= my_strdup(hostname_buffer, MYF(0));
+ *hostname= my_strdup(key_memory_host_cache_hostname,
+ hostname_buffer, MYF(0));
if (!*hostname)
{
diff --git a/sql/item.cc b/sql/item.cc
index 6b585325439..89e23173b0e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -403,7 +403,7 @@ int Item::save_str_value_in_field(Field *field, String *result)
Item::Item(THD *thd):
is_expensive_cache(-1), rsize(0), name(null_clex_str), orig_name(0),
- is_autogenerated_name(TRUE)
+ common_flags(IS_AUTO_GENERATED_NAME)
{
DBUG_ASSERT(thd);
marker= 0;
@@ -463,7 +463,7 @@ Item::Item(THD *thd, Item *item):
with_param(item->with_param),
with_window_func(item->with_window_func),
with_field(item->with_field),
- is_autogenerated_name(item->is_autogenerated_name)
+ common_flags(item->common_flags)
{
next= thd->free_list; // Put in free list
thd->free_list= this;
@@ -1117,7 +1117,7 @@ void Item::set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs)
str++;
}
}
- if (str != str_start && !is_autogenerated_name)
+ if (str != str_start && !is_autogenerated_name())
{
char buff[SAFE_NAME_LEN];
@@ -2771,7 +2771,8 @@ Item_sp::execute_impl(THD *thd, Item **args, uint arg_count)
(m_sp->agg_type() == NOT_AGGREGATE && !func_ctx));
if (!func_ctx)
{
- init_sql_alloc(&sp_mem_root, "Item_sp", MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_sp_head_call_root, &sp_mem_root,
+ MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
*sp_query_arena= Query_arena(&sp_mem_root,
Query_arena::STMT_INITIALIZED_FOR_SP);
}
@@ -5099,7 +5100,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
/* SELECT list element with explicit alias */
if ((*(cur_group->item))->name.str && !table_name.str &&
- !(*(cur_group->item))->is_autogenerated_name &&
+ !(*(cur_group->item))->is_autogenerated_name() &&
!lex_string_cmp(system_charset_info,
&(*(cur_group->item))->name, &field_name))
{
@@ -6197,6 +6198,9 @@ void Item::init_make_send_field(Send_field *tmp_field,
tmp_field->decimals=decimals;
if (unsigned_flag)
tmp_field->flags |= UNSIGNED_FLAG;
+ static_cast<Send_field_extended_metadata>(*tmp_field)=
+ Send_field_extended_metadata();
+ h->Item_append_extended_type_info(tmp_field, this);
}
void Item::make_send_field(THD *thd, Send_field *tmp_field)
diff --git a/sql/item.h b/sql/item.h
index 6a9d401b101..5eab1d049f0 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -624,6 +624,13 @@ class st_select_lex_unit;
class Item_func_not;
class Item_splocal;
+/* Item::common_flags */
+/* Indicates that name of this Item autogenerated or set by user */
+#define IS_AUTO_GENERATED_NAME 1
+/* Indicates that this item is in CYCLE clause of WITH */
+#define IS_IN_WITH_CYCLE 2
+
+
/**
String_copier that sends Item specific warnings.
*/
@@ -931,8 +938,9 @@ public:
True if any item except Item_sum contains a field. Set during parsing.
*/
bool with_field;
- bool is_autogenerated_name; /* indicate was name of this Item
- autogenerated or set by user */
+ uint8 common_flags;
+ bool is_autogenerated_name()
+ { return (common_flags & IS_AUTO_GENERATED_NAME); }
// alloc & destruct is done as start of select on THD::mem_root
Item(THD *thd);
/*
@@ -1815,6 +1823,15 @@ public:
virtual bool need_parentheses_in_default() { return false; }
virtual void save_in_result_field(bool no_conversions) {}
/*
+ Data type format implied by the CHECK CONSTRAINT,
+ to be sent to the client in the result set metadata.
+ */
+ virtual bool set_format_by_check_constraint(Send_field_extended_metadata *)
+ const
+ {
+ return false;
+ }
+ /*
set value of aggregate function in case of no rows for grouping were found
*/
virtual void no_rows_in_result() {}
@@ -7028,6 +7045,7 @@ public:
name= item->name;
Type_std_attributes::set(*attr);
maybe_null= maybe_null_arg;
+ common_flags= item->common_flags;
}
const Type_handler *type_handler() const
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 6df2b5dbd3a..7fe16848082 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -6481,6 +6481,21 @@ Item *Item_cond_and::neg_transformer(THD *thd) /* NOT(a AND b AND ...) -> */
}
+bool
+Item_cond_and::set_format_by_check_constraint(
+ Send_field_extended_metadata *to) const
+{
+ List_iterator_fast<Item> li(const_cast<List<Item>&>(list));
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->set_format_by_check_constraint(to))
+ return true;
+ }
+ return false;
+}
+
+
Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */
/* NOT a AND NOT b AND ... */
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 9b20fa50214..8d5cfb359ec 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3349,6 +3349,7 @@ public:
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
COND_EQUAL **cond_equal_ref);
+ bool set_format_by_check_constraint(Send_field_extended_metadata *to) const;
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
table_map usable_tables, SARGABLE_PARAM **sargables);
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 486f4fc591e..edf44fc3cd3 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1765,6 +1765,15 @@ protected:
};
+class Create_func_release_all_locks : public Create_func_arg0
+{
+public:
+ virtual Item *create_builder(THD *thd);
+
+ static Create_func_release_all_locks s_singleton;
+};
+
+
class Create_func_release_lock : public Create_func_arg1
{
public:
@@ -2378,7 +2387,7 @@ static bool has_named_parameters(List<Item> *params)
List_iterator<Item> it(*params);
while ((param= it++))
{
- if (! param->is_autogenerated_name)
+ if (! param->is_autogenerated_name())
return true;
}
}
@@ -2624,7 +2633,7 @@ Create_func_arg1::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list
Item *param_1= item_list->pop();
- if (unlikely(! param_1->is_autogenerated_name))
+ if (unlikely(! param_1->is_autogenerated_name()))
{
my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
@@ -2651,8 +2660,8 @@ Create_func_arg2::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
- if (unlikely(!param_1->is_autogenerated_name ||
- !param_2->is_autogenerated_name))
+ if (unlikely(!param_1->is_autogenerated_name() ||
+ !param_2->is_autogenerated_name()))
{
my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
@@ -2680,9 +2689,9 @@ Create_func_arg3::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list
Item *param_2= item_list->pop();
Item *param_3= item_list->pop();
- if (unlikely(!param_1->is_autogenerated_name ||
- !param_2->is_autogenerated_name ||
- !param_3->is_autogenerated_name))
+ if (unlikely(!param_1->is_autogenerated_name() ||
+ !param_2->is_autogenerated_name() ||
+ !param_3->is_autogenerated_name()))
{
my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
@@ -4762,6 +4771,17 @@ Create_func_rand::create_native(THD *thd, LEX_CSTRING *name,
}
+Create_func_release_all_locks Create_func_release_all_locks::s_singleton;
+
+Item*
+Create_func_release_all_locks::create_builder(THD *thd)
+{
+ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ return new (thd->mem_root) Item_func_release_all_locks(thd);
+}
+
+
Create_func_release_lock Create_func_release_lock::s_singleton;
Item*
@@ -5525,6 +5545,8 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("REGEXP_SUBSTR") }, BUILDER(Create_func_regexp_substr)},
{ { STRING_WITH_LEN("RADIANS") }, BUILDER(Create_func_radians)},
{ { STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
+ { { STRING_WITH_LEN("RELEASE_ALL_LOCKS") },
+ BUILDER(Create_func_release_all_locks)},
{ { STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
{ { STRING_WITH_LEN("REPLACE_ORACLE") },
BUILDER(Create_func_replace_oracle)},
@@ -5595,14 +5617,9 @@ int item_create_init()
#ifdef HAVE_SPATIAL
count+= native_func_registry_array_geom.count();
#endif
- if (my_hash_init(& native_functions_hash,
- system_charset_info,
- (ulong) count,
- 0,
- 0,
- (my_hash_get_key) get_native_fct_hash_key,
- NULL, /* Nothing to free */
- MYF(0)))
+ if (my_hash_init(key_memory_native_functions, & native_functions_hash,
+ system_charset_info, (ulong) count, 0, 0, (my_hash_get_key)
+ get_native_fct_hash_key, NULL, MYF(0)))
DBUG_RETURN(1);
if (native_func_registry_array.append_to_hash(&native_functions_hash))
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0419d55cc58..57ef5d6adb9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4019,16 +4019,17 @@ longlong Item_func_get_lock::val_int()
DBUG_PRINT("enter", ("lock: %.*s", res->length(), res->ptr()));
/* HASH entries are of type User_level_lock. */
if (! my_hash_inited(&thd->ull_hash) &&
- my_hash_init(&thd->ull_hash, &my_charset_bin,
- 16 /* small hash */, 0, 0, ull_get_key, NULL, 0))
+ my_hash_init(key_memory_User_level_lock, &thd->ull_hash,
+ &my_charset_bin, 16 /* small hash */, 0, 0, ull_get_key,
+ NULL, 0))
{
DBUG_RETURN(0);
}
MDL_request ull_request;
- ull_request.init(MDL_key::USER_LOCK, res->c_ptr_safe(), "",
+ MDL_REQUEST_INIT(&ull_request, MDL_key::USER_LOCK, res->c_ptr_safe(), "",
MDL_SHARED_NO_WRITE, MDL_EXPLICIT);
- MDL_key *ull_key = &ull_request.key;
+ MDL_key *ull_key= &ull_request.key;
if ((ull= (User_level_lock*)
@@ -4036,7 +4037,7 @@ longlong Item_func_get_lock::val_int()
{
/* Recursive lock */
ull->refs++;
- null_value = 0;
+ null_value= 0;
DBUG_PRINT("info", ("recursive lock, ref-count: %d", (int) ull->refs));
DBUG_RETURN(1);
}
@@ -4052,7 +4053,8 @@ longlong Item_func_get_lock::val_int()
DBUG_RETURN(0);
}
- ull= (User_level_lock*) my_malloc(sizeof(User_level_lock),
+ ull= (User_level_lock*) my_malloc(key_memory_User_level_lock,
+ sizeof(User_level_lock),
MYF(MY_WME|MY_THREAD_SPECIFIC));
if (ull == NULL)
{
@@ -4076,6 +4078,30 @@ longlong Item_func_get_lock::val_int()
/**
+ Release all user level locks.
+ @return
+ - N if N-lock released
+ - 0 if lock wasn't held
+*/
+longlong Item_func_release_all_locks::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ THD *thd= current_thd;
+ ulong num_unlocked= 0;
+ DBUG_ENTER("Item_func_release_all_locks::val_int");
+ for (size_t i= 0; i < thd->ull_hash.records; i++)
+ {
+ auto ull= (User_level_lock *) my_hash_element(&thd->ull_hash, i);
+ thd->mdl_context.release_lock(ull->lock);
+ num_unlocked+= ull->refs;
+ my_free(ull);
+ }
+ my_hash_free(&thd->ull_hash);
+ DBUG_RETURN(num_unlocked);
+}
+
+
+/**
Release a user level lock.
@return
- 1 if lock released
@@ -4275,7 +4301,7 @@ static PSI_mutex_key key_LOCK_item_func_sleep;
static PSI_mutex_info item_func_sleep_mutexes[]=
{
- { &key_LOCK_item_func_sleep, "LOCK_user_locks", PSI_FLAG_GLOBAL}
+ { &key_LOCK_item_func_sleep, "LOCK_item_func_sleep", PSI_FLAG_GLOBAL}
};
@@ -4396,7 +4422,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
size_t size=ALIGN_SIZE(sizeof(user_var_entry))+name->length+1+extra_size;
if (!my_hash_inited(hash))
return 0;
- if (!(entry = (user_var_entry*) my_malloc(size,
+ if (!(entry = (user_var_entry*) my_malloc(key_memory_user_var_entry, size,
MYF(MY_WME | ME_FATAL |
MY_THREAD_SPECIFIC))))
return 0;
@@ -4656,10 +4682,10 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
if (entry->value == pos)
entry->value=0;
- entry->value= (char*) my_realloc(entry->value, length,
+ entry->value= (char*) my_realloc(key_memory_user_var_entry_value,
+ entry->value, length,
MYF(MY_ALLOW_ZERO_PTR | MY_WME |
- ME_FATAL |
- MY_THREAD_SPECIFIC));
+ ME_FATAL | MY_THREAD_SPECIFIC));
if (!entry->value)
return 1;
}
@@ -6770,7 +6796,7 @@ longlong Item_func_nextval::val_int()
if (!(entry= ((SEQUENCE_LAST_VALUE*)
my_hash_search(&thd->sequences, (uchar*) key, length))))
{
- if (!(key= (char*) my_memdup(key, length, MYF(MY_WME))) ||
+ if (!(key= (char*) my_memdup(PSI_INSTRUMENT_ME, key, length, MYF(MY_WME))) ||
!(entry= new SEQUENCE_LAST_VALUE((uchar*) key, length)))
{
/* EOM, error given */
diff --git a/sql/item_func.h b/sql/item_func.h
index dced158bb86..3771992d617 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -2654,19 +2654,13 @@ public:
void mysql_ull_cleanup(THD *thd);
void mysql_ull_set_explicit_lock_duration(THD *thd);
-class Item_func_get_lock :public Item_long_func
+
+class Item_func_lock :public Item_long_func
{
- bool check_arguments() const
- {
- return args[0]->check_type_general_purpose_string(func_name()) ||
- args[1]->check_type_can_return_real(func_name());
- }
- String value;
public:
- Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {}
- longlong val_int();
- const char *func_name() const { return "get_lock"; }
- bool fix_length_and_dec() { max_length=1; maybe_null=1; return FALSE; }
+ Item_func_lock(THD *thd): Item_long_func(thd) { }
+ Item_func_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
+ Item_func_lock(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@ -2677,34 +2671,54 @@ class Item_func_get_lock :public Item_long_func
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
- Item *get_copy(THD *thd)
+};
+
+
+class Item_func_get_lock final :public Item_func_lock
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ args[1]->check_type_can_return_real(func_name());
+ }
+ String value;
+ public:
+ Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_func_lock(thd, a, b) {}
+ longlong val_int() final;
+ const char *func_name() const final { return "get_lock"; }
+ bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
+ Item *get_copy(THD *thd) final
{ return get_item_copy<Item_func_get_lock>(thd, this); }
};
-class Item_func_release_lock :public Item_long_func
+
+class Item_func_release_all_locks final :public Item_func_lock
+{
+public:
+ Item_func_release_all_locks(THD *thd): Item_func_lock(thd)
+ { unsigned_flag= 1; }
+ longlong val_int() final;
+ const char *func_name() const final { return "release_all_locks"; }
+ Item *get_copy(THD *thd) final
+ { return get_item_copy<Item_func_release_all_locks>(thd, this); }
+};
+
+
+class Item_func_release_lock final :public Item_func_lock
{
bool check_arguments() const
{ return args[0]->check_type_general_purpose_string(func_name()); }
String value;
public:
- Item_func_release_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
- longlong val_int();
+ Item_func_release_lock(THD *thd, Item *a): Item_func_lock(thd, a) {}
+ longlong val_int() final;
const char *func_name() const { return "release_lock"; }
bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
- table_map used_tables() const
- {
- return used_tables_cache | RAND_TABLE_BIT;
- }
- bool const_item() const { return 0; }
- bool is_expensive() { return 1; }
- bool check_vcol_func_processor(void *arg)
- {
- return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
- }
- Item *get_copy(THD *thd)
+ Item *get_copy(THD *thd) final
{ return get_item_copy<Item_func_release_lock>(thd, this); }
};
+
/* replication functions */
class Item_master_pos_wait :public Item_longlong_func
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index e61d0875056..44f9e8146c2 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -84,6 +84,11 @@ public:
maybe_null= 1;
return FALSE;
}
+ bool set_format_by_check_constraint(Send_field_extended_metadata *to) const
+ {
+ static const Lex_cstring fmt(STRING_WITH_LEN("json"));
+ return to->set_format_name(fmt);
+ }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_valid>(thd, this); }
};
@@ -118,6 +123,12 @@ public:
Item_json_func(THD *thd, List<Item> &list)
:Item_str_func(thd, list) { }
bool is_json_type() { return true; }
+ void make_send_field(THD *thd, Send_field *tmp_field)
+ {
+ Item_str_func::make_send_field(thd, tmp_field);
+ static const Lex_cstring fmt(STRING_WITH_LEN("json"));
+ tmp_field->set_format_name(fmt);
+ }
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index bee56a607f7..bcc041ae9c6 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -43,7 +43,6 @@
#include "set_var.h"
#include "sql_base.h"
#include "sql_time.h"
-#include "sql_acl.h" // SUPER_ACL
#include "des_key_file.h" // st_des_keyschedule, st_des_keyblock
#include "password.h" // my_make_scrambled_password,
// my_make_scrambled_password_323
@@ -838,7 +837,7 @@ String *Item_func_des_decrypt::val_str(String *str)
{
uint key_number=(uint) (*res)[0] & 127;
// Check if automatic key and that we have privilege to uncompress using it
- if (!(current_thd->security_ctx->master_access & SUPER_ACL) ||
+ if (!(current_thd->security_ctx->master_access & PRIV_DES_DECRYPT_ONE_ARG) ||
key_number > 9)
goto error;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 2d3ea388cc5..e494e9d84e1 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -4434,9 +4434,10 @@ void subselect_single_select_engine::print(String *str,
enum_query_type query_type)
{
With_clause* with_clause= select_lex->get_with_clause();
+ THD *thd= get_thd();
if (with_clause)
- with_clause->print(str, query_type);
- select_lex->print(get_thd(), str, query_type);
+ with_clause->print(thd, str, query_type);
+ select_lex->print(thd, str, query_type);
}
@@ -5807,8 +5808,9 @@ bool Ordered_key::alloc_keys_buffers()
{
DBUG_ASSERT(key_buff_elements > 0);
- if (!(key_buff= (rownum_t*) my_malloc((size_t)(key_buff_elements *
- sizeof(rownum_t)), MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ if (!(key_buff= (rownum_t*) my_malloc(PSI_INSTRUMENT_ME,
+ static_cast<size_t>(key_buff_elements * sizeof(rownum_t)),
+ MYF(MY_WME | MY_THREAD_SPECIFIC))))
return TRUE;
/*
@@ -6239,8 +6241,9 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
sizeof(Ordered_key*))) ||
!(null_bitmaps= (MY_BITMAP**) thd->alloc(merge_keys_count *
sizeof(MY_BITMAP*))) ||
- !(row_num_to_rowid= (uchar*) my_malloc((size_t)(row_count * rowid_length),
- MYF(MY_WME | MY_THREAD_SPECIFIC))))
+ !(row_num_to_rowid= (uchar*) my_malloc(PSI_INSTRUMENT_ME,
+ static_cast<size_t>(row_count * rowid_length),
+ MYF(MY_WME | MY_THREAD_SPECIFIC))))
return TRUE;
/* Create the only non-NULL key if there is any. */
diff --git a/sql/keycaches.cc b/sql/keycaches.cc
index 60049cdd67d..10bec7c1de8 100644
--- a/sql/keycaches.cc
+++ b/sql/keycaches.cc
@@ -23,6 +23,9 @@
NAMED_ILIST key_caches;
NAMED_ILIST rpl_filters;
+extern "C" PSI_memory_key key_memory_KEY_CACHE;
+extern PSI_memory_key key_memory_NAMED_ILINK_name;
+
/**
ilink (intrusive list element) with a name
*/
@@ -37,7 +40,8 @@ public:
size_t name_length_arg, uchar* data_arg)
:name_length(name_length_arg), data(data_arg)
{
- name= my_strndup(name_arg, name_length, MYF(MY_WME));
+ name= my_strndup(key_memory_NAMED_ILINK_name, name_arg, name_length,
+ MYF(MY_WME));
links->push_back(this);
}
inline bool cmp(const char *name_cmp, size_t length)
@@ -118,8 +122,8 @@ KEY_CACHE *create_key_cache(const char *name, size_t length)
DBUG_ENTER("create_key_cache");
DBUG_PRINT("enter",("name: %.*s", (int)length, name));
- if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
- MYF(MY_ZEROFILL | MY_WME))))
+ if ((key_cache= (KEY_CACHE*) my_malloc(key_memory_KEY_CACHE,
+ sizeof(KEY_CACHE), MYF(MY_ZEROFILL | MY_WME))))
{
if (!new NAMED_ILINK(&key_caches, name, length, (uchar*) key_cache))
{
diff --git a/sql/lex.h b/sql/lex.h
index 1cb7ad5d4c8..f36b8258c93 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -239,6 +239,7 @@ static SYMBOL symbols[] = {
{ "FALSE", SYM(FALSE_SYM)},
{ "FAST", SYM(FAST_SYM)},
{ "FAULTS", SYM(FAULTS_SYM)},
+ { "FEDERATED", SYM(FEDERATED_SYM)},
{ "FETCH", SYM(FETCH_SYM)},
{ "FIELDS", SYM(COLUMNS)},
{ "FILE", SYM(FILE_SYM)},
@@ -405,6 +406,7 @@ static SYMBOL symbols[] = {
{ "MODE", SYM(MODE_SYM)},
{ "MODIFIES", SYM(MODIFIES_SYM)},
{ "MODIFY", SYM(MODIFY_SYM)},
+ { "MONITOR", SYM(MONITOR_SYM)},
{ "MONTH", SYM(MONTH_SYM)},
{ "MUTEX", SYM(MUTEX_SYM)},
{ "MYSQL", SYM(MYSQL_SYM)},
diff --git a/sql/lock.cc b/sql/lock.cc
index 6f86c0a38f6..7f69946c35e 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -76,7 +76,6 @@
#include "lock.h"
#include "sql_base.h" // close_tables_for_reopen
#include "sql_parse.h" // is_log_table_write_query
-#include "sql_acl.h" // SUPER_ACL
#include "sql_handler.h"
#include <hash.h>
#include "wsrep_mysqld.h"
@@ -109,12 +108,13 @@ static int
lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
{
uint system_count, i;
- bool is_superuser, log_table_write_query;
+ bool ignore_read_only, log_table_write_query;
DBUG_ENTER("lock_tables_check");
system_count= 0;
- is_superuser= (thd->security_ctx->master_access & SUPER_ACL) != NO_ACL;
+ ignore_read_only=
+ (thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) != NO_ACL;
log_table_write_query= (is_log_table_write_query(thd->lex->sql_command)
|| ((flags & MYSQL_LOCK_LOG_TABLE) != 0));
@@ -179,7 +179,7 @@ lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) && !t->s->tmp_table)
{
if (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE &&
- !is_superuser && opt_readonly && !thd->slave_thread)
+ !ignore_read_only && opt_readonly && !thd->slave_thread)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(1);
@@ -645,7 +645,7 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
a->lock_count, b->lock_count));
if (!(sql_lock= (MYSQL_LOCK*)
- my_malloc(sizeof(*sql_lock)+
+ my_malloc(key_memory_MYSQL_LOCK, sizeof(*sql_lock) +
sizeof(THR_LOCK_DATA*)*((a->lock_count+b->lock_count)*2) +
sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
DBUG_RETURN(0); // Fatal error
@@ -764,7 +764,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
sizeof(table_ptr) * table_count;
if (!(sql_lock= (MYSQL_LOCK*) (flags & GET_LOCK_ON_THD ?
thd->alloc(amount) :
- my_malloc(amount, MYF(0)))))
+ my_malloc(key_memory_MYSQL_LOCK, amount,
+ MYF(0)))))
DBUG_RETURN(0);
locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
to= table_buf= sql_lock->table= (TABLE**) (locks + lock_count * 2);
@@ -858,8 +859,10 @@ bool lock_schema_name(THD *thd, const char *db)
if (thd->has_read_only_protection())
return TRUE;
- global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT);
- mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&global_request, MDL_key::BACKUP, "", "", MDL_BACKUP_DDL,
+ MDL_STATEMENT);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE,
+ MDL_TRANSACTION);
mdl_requests.push_front(&mdl_request);
mdl_requests.push_front(&global_request);
@@ -916,10 +919,12 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type,
if (thd->has_read_only_protection())
return TRUE;
- global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT);
- schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE,
- MDL_TRANSACTION);
- mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&global_request, MDL_key::BACKUP, "", "", MDL_BACKUP_DDL,
+ MDL_STATEMENT);
+ MDL_REQUEST_INIT(&schema_request, MDL_key::SCHEMA, db, "",
+ MDL_INTENTION_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&mdl_request, mdl_type, db, name, MDL_EXCLUSIVE,
+ MDL_TRANSACTION);
mdl_requests.push_front(&mdl_request);
mdl_requests.push_front(&schema_request);
@@ -1040,7 +1045,7 @@ bool Global_read_lock::lock_global_read_lock(THD *thd)
MDL_BACKUP_FTWRL1));
DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "",
MDL_BACKUP_FTWRL2));
- mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_FTWRL1,
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_FTWRL1,
MDL_EXPLICIT);
do
diff --git a/sql/log.cc b/sql/log.cc
index 56e83bf2448..355118dc701 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -34,7 +34,6 @@
#include "sql_parse.h" // command_name
#include "sql_time.h" // calc_time_from_sec, my_time_compare
#include "tztime.h" // my_tz_OFFSET0, struct Time_zone
-#include "sql_acl.h" // SUPER_ACL
#include "log_event.h" // Query_log_event
#include "rpl_filter.h"
#include "rpl_rli.h"
@@ -253,7 +252,7 @@ void make_default_log_name(char **out, const char* log_ext, bool once)
else
{
my_free(*out);
- *out= my_strdup(buff, MYF(MY_WME));
+ *out= my_strdup(PSI_INSTRUMENT_ME, buff, MYF(MY_WME));
}
}
@@ -1723,7 +1722,8 @@ static int binlog_close_connection(handlerton *hton, THD *thd)
if (len > 0) wsrep_dump_rbr_buf(thd, buf, len);
}
#endif /* WITH_WSREP */
- DBUG_ASSERT(cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty());
+ DBUG_ASSERT(cache_mngr->trx_cache.empty());
+ DBUG_ASSERT(cache_mngr->stmt_cache.empty());
cache_mngr->~binlog_cache_mngr();
my_free(cache_mngr);
DBUG_RETURN(0);
@@ -2211,8 +2211,8 @@ void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional)
if (WSREP_EMULATE_BINLOG(thd))
{
if (is_transactional)
- trans_register_ha(thd, TRUE, binlog_hton);
- trans_register_ha(thd, FALSE, binlog_hton);
+ trans_register_ha(thd, TRUE, binlog_hton, 0);
+ trans_register_ha(thd, FALSE, binlog_hton, 0);
}
#endif /* WITH_WSREP */
DBUG_VOID_RETURN;
@@ -2412,8 +2412,8 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
*errmsg = "Could not open log file";
goto err;
}
- if (init_io_cache(log, file, (size_t)binlog_file_cache_size, READ_CACHE, 0, 0,
- MYF(MY_WME|MY_DONT_CHECK_FILESIZE)))
+ if (init_io_cache_ext(log, file, (size_t)binlog_file_cache_size, READ_CACHE,
+ 0, 0, MYF(MY_WME|MY_DONT_CHECK_FILESIZE), key_file_binlog_cache))
{
sql_print_error("Failed to create a cache on log (file '%s')",
log_file_name);
@@ -2652,7 +2652,7 @@ bool MYSQL_LOG::open(
write_error= 0;
- if (!(name= my_strdup(log_name, MYF(MY_WME))))
+ if (!(name= my_strdup(key_memory_MYSQL_LOG_name, log_name, MYF(MY_WME))))
{
name= (char *)log_name; // for the error message
goto err;
@@ -3392,10 +3392,11 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC,
MYF(MY_WME))) < 0 ||
mysql_file_sync(index_file_nr, MYF(MY_WME)) ||
- init_io_cache(&index_file, index_file_nr,
+ init_io_cache_ext(&index_file, index_file_nr,
IO_SIZE, WRITE_CACHE,
mysql_file_seek(index_file_nr, 0L, MY_SEEK_END, MYF(0)),
- 0, MYF(MY_WME | MY_WAIT_IF_FULL)) ||
+ 0, MYF(MY_WME | MY_WAIT_IF_FULL),
+ m_key_file_log_index_cache) ||
DBUG_EVALUATE_IF("fault_injection_openning_index", 1, 0))
{
/*
@@ -4442,14 +4443,16 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
{
rli->last_inuse_relaylog= NULL;
included= 1;
- to_purge_if_included= my_strdup(ir->name, MYF(0));
+ to_purge_if_included= my_strdup(key_memory_Relay_log_info_group_relay_log_name,
+ ir->name, MYF(0));
}
rli->free_inuse_relaylog(ir);
ir= next;
}
rli->inuse_relaylog_list= ir;
if (ir)
- to_purge_if_included= my_strdup(ir->name, MYF(0));
+ to_purge_if_included= my_strdup(key_memory_Relay_log_info_group_relay_log_name,
+ ir->name, MYF(0));
/*
Read the next log file name from the index file and pass it back to
@@ -5588,7 +5591,8 @@ binlog_cache_mngr *THD::binlog_setup_trx_data()
if (cache_mngr)
DBUG_RETURN(cache_mngr); // Already set up
- cache_mngr= (binlog_cache_mngr*) my_malloc(sizeof(binlog_cache_mngr), MYF(MY_ZEROFILL));
+ cache_mngr= (binlog_cache_mngr*) my_malloc(key_memory_binlog_cache_mngr,
+ sizeof(binlog_cache_mngr), MYF(MY_ZEROFILL));
if (!cache_mngr ||
open_cached_file(&cache_mngr->stmt_cache.cache_log, mysql_tmpdir,
LOG_PREFIX, (size_t)binlog_stmt_cache_size, MYF(MY_WME)) ||
@@ -5708,8 +5712,8 @@ THD::binlog_start_trans_and_stmt()
}
#endif
if (mstmt_mode)
- trans_register_ha(this, TRUE, binlog_hton);
- trans_register_ha(this, FALSE, binlog_hton);
+ trans_register_ha(this, TRUE, binlog_hton, 0);
+ trans_register_ha(this, FALSE, binlog_hton, 0);
/*
Mark statement transaction as read/write. We never start
a binary log transaction and keep it read-only,
@@ -5753,7 +5757,7 @@ binlog_start_consistent_snapshot(handlerton *hton, THD *thd)
strmake_buf(cache_mngr->last_commit_pos_file, mysql_bin_log.last_commit_pos_file);
cache_mngr->last_commit_pos_offset= mysql_bin_log.last_commit_pos_offset;
- trans_register_ha(thd, TRUE, hton);
+ trans_register_ha(thd, TRUE, binlog_hton, 0);
DBUG_RETURN(err);
}
@@ -9108,7 +9112,8 @@ int TC_LOG_MMAP::open(const char *opt_name)
npages=(uint)file_length/tc_log_page_size;
if (npages < 3) // to guarantee non-empty pool
goto err;
- if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
+ if (!(pages=(PAGE *)my_malloc(key_memory_TC_LOG_MMAP_pages,
+ npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
goto err;
inited=3;
for (pg=pages, i=0; i < npages; i++, pg++)
@@ -9418,7 +9423,8 @@ int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
{
uint32 size= sizeof(*pending_checkpoint) + sizeof(ulong) * (ncookies - 1);
if (!(pending_checkpoint=
- (pending_cookies *)my_malloc(size, MYF(MY_ZEROFILL))))
+ (pending_cookies *)my_malloc(PSI_INSTRUMENT_ME, size,
+ MYF(MY_ZEROFILL))))
{
my_error(ER_OUTOFMEMORY, MYF(0), size);
mysql_mutex_unlock(&LOCK_pending_checkpoint);
@@ -9557,8 +9563,8 @@ int TC_LOG_MMAP::recover()
goto err1;
}
- if (my_hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
- sizeof(my_xid), 0, 0, MYF(0)))
+ if (my_hash_init(PSI_INSTRUMENT_ME, &xids, &my_charset_bin,
+ tc_log_page_size/3, 0, sizeof(my_xid), 0, 0, MYF(0)))
goto err1;
for ( ; p < end_p ; p++)
@@ -10071,13 +10077,13 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name,
#endif
if (! fdle->is_valid() ||
- (do_xa && my_hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
+ (do_xa && my_hash_init(key_memory_binlog_recover_exec, &xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
sizeof(my_xid), 0, 0, MYF(0))))
goto err1;
if (do_xa)
- init_alloc_root(&mem_root, "TC_LOG_BINLOG", TC_LOG_PAGE_SIZE,
- TC_LOG_PAGE_SIZE, MYF(0));
+ init_alloc_root(key_memory_binlog_recover_exec, &mem_root,
+ TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE, MYF(0));
fdle->flags&= ~LOG_EVENT_BINLOG_IN_USE_F; // abort on the first error
@@ -10489,7 +10495,7 @@ static struct st_mysql_sys_var *binlog_sys_vars[]=
/*
Copy out the non-directory part of binlog position filename for the
`binlog_snapshot_file' status variable, same way as it is done for
- SHOW MASTER STATUS.
+ SHOW BINLOG STATUS.
*/
static void
set_binlog_snapshot_file(const char *src)
@@ -10741,8 +10747,8 @@ void wsrep_register_binlog_handler(THD *thd, bool trx)
Set callbacks in order to be able to call commmit or rollback.
*/
if (trx)
- trans_register_ha(thd, TRUE, binlog_hton);
- trans_register_ha(thd, FALSE, binlog_hton);
+ trans_register_ha(thd, TRUE, binlog_hton, 0);
+ trans_register_ha(thd, FALSE, binlog_hton, 0);
/*
Set the binary log as read/write otherwise callbacks are not called.
diff --git a/sql/log.h b/sql/log.h
index 8684eaba786..e4424778111 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -412,7 +412,6 @@ struct wait_for_commit;
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{
-#ifdef HAVE_PSI_INTERFACE
/** The instrumentation key to use for @ LOCK_index. */
PSI_mutex_key m_key_LOCK_index;
/** The instrumentation key to use for @ COND_relay_log_updated */
@@ -420,14 +419,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
/** The instrumentation key to use for @ COND_bin_log_updated */
PSI_cond_key m_key_bin_log_update;
/** The instrumentation key to use for opening the log file. */
- PSI_file_key m_key_file_log;
+ PSI_file_key m_key_file_log, m_key_file_log_cache;
/** The instrumentation key to use for opening the log index file. */
- PSI_file_key m_key_file_log_index;
+ PSI_file_key m_key_file_log_index, m_key_file_log_index_cache;
- PSI_file_key m_key_COND_queue_busy;
+ PSI_cond_key m_key_COND_queue_busy;
/** The instrumentation key to use for LOCK_binlog_end_pos. */
PSI_mutex_key m_key_LOCK_binlog_end_pos;
-#endif
struct group_commit_entry
{
@@ -587,7 +585,7 @@ public:
:binlog_id(0), xid_count(0), notify_count(0)
{
binlog_name_len= log_file_name_len;
- binlog_name= (char *) my_malloc(binlog_name_len, MYF(MY_ZEROFILL));
+ binlog_name= (char *) my_malloc(PSI_INSTRUMENT_ME, binlog_name_len, MYF(MY_ZEROFILL));
if (binlog_name)
memcpy(binlog_name, log_file_name, binlog_name_len);
}
@@ -674,15 +672,19 @@ public:
PSI_cond_key key_relay_log_update,
PSI_cond_key key_bin_log_update,
PSI_file_key key_file_log,
+ PSI_file_key key_file_log_cache,
PSI_file_key key_file_log_index,
- PSI_file_key key_COND_queue_busy,
+ PSI_file_key key_file_log_index_cache,
+ PSI_cond_key key_COND_queue_busy,
PSI_mutex_key key_LOCK_binlog_end_pos)
{
m_key_LOCK_index= key_LOCK_index;
m_key_relay_log_update= key_relay_log_update;
m_key_bin_log_update= key_bin_log_update;
m_key_file_log= key_file_log;
+ m_key_file_log_cache= key_file_log_cache;
m_key_file_log_index= key_file_log_index;
+ m_key_file_log_index_cache= key_file_log_index_cache;
m_key_COND_queue_busy= key_COND_queue_busy;
m_key_LOCK_binlog_end_pos= key_LOCK_binlog_end_pos;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 4c1c18fffff..7ee38a007d1 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -56,6 +56,10 @@
#define my_b_write_string(A, B) my_b_write((A), (uchar*)(B), (uint) (sizeof(B) - 1))
+PSI_memory_key key_memory_log_event;
+PSI_memory_key key_memory_Incident_log_event_message;
+PSI_memory_key key_memory_Rows_query_log_event_rows_query;
+
/**
BINLOG_CHECKSUM variable.
*/
@@ -410,7 +414,7 @@ query_event_uncompress(const Format_description_log_event *description_event,
}
else
{
- new_dst = (char *)my_malloc(alloc_size, MYF(MY_WME));
+ new_dst = (char *)my_malloc(PSI_INSTRUMENT_ME, alloc_size, MYF(MY_WME));
if (!new_dst)
return 1;
@@ -532,7 +536,7 @@ row_log_event_uncompress(const Format_description_log_event *description_event,
}
else
{
- new_dst = (char *)my_malloc(alloc_size, MYF(MY_WME));
+ new_dst = (char *)my_malloc(PSI_INSTRUMENT_ME, alloc_size, MYF(MY_WME));
if (!new_dst)
return 1;
@@ -873,7 +877,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
*/
sz += MY_AES_BLOCK_SIZE;
#endif
- char *newpkt= (char*)my_malloc(sz, MYF(MY_WME));
+ char *newpkt= (char*)my_malloc(PSI_INSTRUMENT_ME, sz, MYF(MY_WME));
if (!newpkt)
DBUG_RETURN(LOG_READ_MEM);
memcpy(newpkt, packet->ptr(), ev_offset);
@@ -1665,7 +1669,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
*/
#if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
- if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
+ if (!(start= data_buf = (Log_event::Byte*) my_malloc(PSI_INSTRUMENT_ME,
+ catalog_len + 1
+ time_zone_len + 1
+ user.length + 1
+ host.length + 1
@@ -1676,7 +1681,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
+ QUERY_CACHE_FLAGS_SIZE,
MYF(MY_WME))))
#else
- if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
+ if (!(start= data_buf = (Log_event::Byte*) my_malloc(PSI_INSTRUMENT_ME,
+ catalog_len + 1
+ time_zone_len + 1
+ user.length + 1
+ host.length + 1
@@ -1783,8 +1789,8 @@ Query_compressed_log_event::Query_compressed_log_event(const char *buf,
}
/* Reserve one byte for '\0' */
- query_buf = (Log_event::Byte*)my_malloc(ALIGN_SIZE(un_len + 1),
- MYF(MY_WME));
+ query_buf = (Log_event::Byte*)my_malloc(PSI_INSTRUMENT_ME,
+ ALIGN_SIZE(un_len + 1), MYF(MY_WME));
if(query_buf &&
!binlog_buf_uncompress(query, (char *)query_buf, q_len, &un_len))
{
@@ -2033,7 +2039,8 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
common_header_len= LOG_EVENT_HEADER_LEN;
number_of_event_types= LOG_EVENT_TYPES;
/* we'll catch my_malloc() error in is_valid() */
- post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8)
+ post_header_len=(uint8*) my_malloc(PSI_INSTRUMENT_ME,
+ number_of_event_types*sizeof(uint8)
+ BINLOG_CHECKSUM_ALG_DESC_LEN,
MYF(0));
/*
@@ -2159,8 +2166,8 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
make the slave detect less corruptions).
*/
number_of_event_types= FORMAT_DESCRIPTION_EVENT - 1;
- post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8),
- MYF(0));
+ post_header_len=(uint8*) my_malloc(PSI_INSTRUMENT_ME,
+ number_of_event_types*sizeof(uint8), MYF(0));
if (post_header_len)
{
post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
@@ -2228,7 +2235,8 @@ Format_description_log_event(const char* buf,
common_header_len, number_of_event_types));
/* If alloc fails, we'll detect it in is_valid() */
- post_header_len= (uint8*) my_memdup((uchar*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
+ post_header_len= (uint8*) my_memdup(PSI_INSTRUMENT_ME,
+ buf+ST_COMMON_HEADER_LEN_OFFSET+1,
number_of_event_types*
sizeof(*post_header_len),
MYF(0));
@@ -2517,7 +2525,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
ident_len= (uint)(event_len - (LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len));
ident_offset= post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
- new_log_ident= my_strndup(buf + ident_offset, (uint) ident_len, MYF(MY_WME));
+ new_log_ident= my_strndup(PSI_INSTRUMENT_ME, buf + ident_offset, (uint) ident_len, MYF(MY_WME));
DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
DBUG_VOID_RETURN;
}
@@ -2544,7 +2552,7 @@ Binlog_checkpoint_log_event::Binlog_checkpoint_log_event(
binlog_file_len= uint4korr(buf);
if (event_len - (header_size + post_header_len) < binlog_file_len)
return;
- binlog_file_name= my_strndup(buf + post_header_len, binlog_file_len,
+ binlog_file_name= my_strndup(PSI_INSTRUMENT_ME, buf + post_header_len, binlog_file_len,
MYF(MY_WME));
return;
}
@@ -2603,8 +2611,8 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len,
gl_flags= val & ((uint32)0xf << 28);
buf+= 4;
if (event_len - (header_size + post_header_len) < count*element_size ||
- (!(list= (rpl_gtid *)my_malloc(count*sizeof(*list) + (count == 0),
- MYF(MY_WME)))))
+ (!(list= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ count*sizeof(*list) + (count == 0), MYF(MY_WME)))))
return;
for (i= 0; i < count; ++i)
@@ -2621,7 +2629,8 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len,
if ((gl_flags & FLAG_IGN_GTIDS))
{
uint32 i;
- if (!(sub_id_list= (uint64 *)my_malloc(count*sizeof(uint64), MYF(MY_WME))))
+ if (!(sub_id_list= (uint64 *)my_malloc(PSI_INSTRUMENT_ME,
+ count*sizeof(uint64), MYF(MY_WME))))
{
my_free(list);
list= NULL;
@@ -2678,8 +2687,8 @@ Gtid_list_log_event::peek(const char *event_start, size_t event_len,
if (event_len < (uint32)fdev->common_header_len + GTID_LIST_HEADER_LEN +
16 * count)
return true;
- if (!(gtid_list= (rpl_gtid *)my_malloc(sizeof(rpl_gtid)*count + (count == 0),
- MYF(MY_WME))))
+ if (!(gtid_list= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(rpl_gtid)*count + (count == 0), MYF(MY_WME))))
return true;
*out_gtid_list= gtid_list;
*out_list_len= count;
@@ -2886,7 +2895,7 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len,
uint header_len= description_event->common_header_len;
uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1];
uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1];
- if (!(event_buf= (char*) my_memdup(buf, len, MYF(MY_WME))) ||
+ if (!(event_buf= (char*) my_memdup(PSI_INSTRUMENT_ME, buf, len, MYF(MY_WME))) ||
copy_log_event(event_buf,len,
(((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
load_header_len + header_len :
@@ -3188,7 +3197,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
/* Just store/use the first tag of this type, skip others */
if (likely(!m_extra_row_data))
{
- m_extra_row_data= (uchar*) my_malloc(infoLen,
+ m_extra_row_data= (uchar*) my_malloc(PSI_INSTRUMENT_ME, infoLen,
MYF(MY_WME));
if (likely(m_extra_row_data != NULL))
{
@@ -3277,7 +3286,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %lu",
m_table_id, m_flags, m_width, (ulong) data_size));
- m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
+ m_rows_buf= (uchar*) my_malloc(PSI_INSTRUMENT_ME, data_size, MYF(MY_WME));
if (likely((bool)m_rows_buf))
{
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
@@ -3300,7 +3309,7 @@ void Rows_log_event::uncompress_buf()
if (!un_len)
return;
- uchar *new_buf= (uchar*) my_malloc(ALIGN_SIZE(un_len), MYF(MY_WME));
+ uchar *new_buf= (uchar*) my_malloc(PSI_INSTRUMENT_ME, ALIGN_SIZE(un_len), MYF(MY_WME));
if (new_buf)
{
if(!binlog_buf_uncompress((char *)m_rows_buf, (char *)new_buf,
@@ -3535,7 +3544,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
m_colcnt, (long) (ptr_colcnt-(const uchar*)vpart)));
/* Allocate mem for all fields in one go. If fails, caught in is_valid() */
- m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
+ m_memory= (uchar*) my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&m_dbnam, (uint) m_dblen + 1,
&m_tblnam, (uint) m_tbllen + 1,
&m_coltype, (uint) m_colcnt,
@@ -3554,7 +3563,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
if (m_field_metadata_size <= (m_colcnt * 2))
{
uint num_null_bytes= (m_colcnt + 7) / 8;
- m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
+ m_meta_memory= (uchar *)my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&m_null_bits, num_null_bytes,
&m_field_metadata, m_field_metadata_size,
NULL);
@@ -3578,7 +3587,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
{
m_optional_metadata_len= event_len - bytes_read;
m_optional_metadata=
- static_cast<unsigned char*>(my_malloc(m_optional_metadata_len, MYF(MY_WME)));
+ static_cast<unsigned char*>(my_malloc(PSI_INSTRUMENT_ME, m_optional_metadata_len, MYF(MY_WME)));
memcpy(m_optional_metadata, ptr_after_colcnt, m_optional_metadata_len);
}
}
@@ -3958,7 +3967,7 @@ Incident_log_event::Incident_log_event(const char *buf, uint event_len,
m_incident= INCIDENT_NONE;
DBUG_VOID_RETURN;
}
- if (!(m_message.str= (char*) my_malloc(len+1, MYF(MY_WME))))
+ if (!(m_message.str= (char*) my_malloc(key_memory_log_event, len+1, MYF(MY_WME))))
{
/* Mark this event invalid */
m_incident= INCIDENT_NONE;
diff --git a/sql/log_event.h b/sql/log_event.h
index 15442bd5a97..67cf27b60a0 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1357,7 +1357,8 @@ public:
static void *operator new(size_t size)
{
- return (void*) my_malloc((uint)size, MYF(MY_WME|MY_FAE));
+ extern PSI_memory_key key_memory_log_event;
+ return my_malloc(key_memory_log_event, size, MYF(MY_WME|MY_FAE));
}
static void operator delete(void *ptr, size_t)
@@ -4880,6 +4881,12 @@ public:
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
virtual uint8 get_trg_event_map()= 0;
+
+ inline bool do_invoke_trigger()
+ {
+ return (slave_run_triggers_for_rbr && !master_had_triggers) ||
+ slave_run_triggers_for_rbr == SLAVE_RUN_TRIGGERS_FOR_RBR_ENFORCE;
+ }
#endif
protected:
@@ -5362,11 +5369,12 @@ public:
Incident_log_event(THD *thd_arg, Incident incident, const LEX_CSTRING *msg)
: Log_event(thd_arg, 0, FALSE), m_incident(incident)
{
+ extern PSI_memory_key key_memory_Incident_log_event_message;
DBUG_ENTER("Incident_log_event::Incident_log_event");
DBUG_PRINT("enter", ("m_incident: %d", m_incident));
m_message.length= 0;
- if (unlikely(!(m_message.str= (char*) my_malloc(msg->length+1,
- MYF(MY_WME)))))
+ if (!(m_message.str= (char*) my_malloc(key_memory_Incident_log_event_message,
+ msg->length + 1, MYF(MY_WME))))
{
/* Mark this event invalid */
m_incident= INCIDENT_NONE;
diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc
index cae4842355a..6ee5587943d 100644
--- a/sql/log_event_client.cc
+++ b/sql/log_event_client.cc
@@ -1104,7 +1104,7 @@ void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_inf
if (((get_general_type_code() == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end)))
goto end;
- (void) my_init_dynamic_array(&rows_arr, sizeof(LEX_STRING), 8, 8, MYF(0));
+ (void) my_init_dynamic_array(PSI_NOT_INSTRUMENTED, &rows_arr, sizeof(LEX_STRING), 8, 8, MYF(0));
for (uchar *value= m_rows_buf; value < m_rows_end; )
{
@@ -1119,7 +1119,7 @@ void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_inf
}
value+= length1;
- swap_buff1= (uchar *) my_malloc(length1, MYF(0));
+ swap_buff1= (uchar *) my_malloc(PSI_NOT_INSTRUMENTED, length1, MYF(0));
if (!swap_buff1)
{
fprintf(stderr, "\nError: Out of memory. "
@@ -1142,7 +1142,7 @@ void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_inf
}
value+= length2;
- swap_buff2= (uchar *) my_malloc(length2, MYF(0));
+ swap_buff2= (uchar *) my_malloc(PSI_NOT_INSTRUMENTED, length2, MYF(0));
if (!swap_buff2)
{
fprintf(stderr, "\nError: Out of memory. "
@@ -1170,7 +1170,7 @@ void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_inf
LEX_STRING one_row;
one_row.length= length1 + length2;
- one_row.str= (char *) my_malloc(one_row.length, MYF(0));
+ one_row.str= (char *) my_malloc(PSI_NOT_INSTRUMENTED, one_row.length, MYF(0));
memcpy(one_row.str, start_pos, one_row.length);
if (one_row.str == NULL || push_dynamic(&rows_arr, (uchar *) &one_row))
{
@@ -1637,7 +1637,7 @@ bool Log_event::print_base64(IO_CACHE* file,
{
size_t const tmp_str_sz= my_base64_needed_encoded_length((int) size);
char *tmp_str;
- if (!(tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME))))
+ if (!(tmp_str= (char *) my_malloc(PSI_NOT_INSTRUMENTED, tmp_str_sz, MYF(MY_WME))))
goto err;
if (my_base64_encode(ptr, (size_t) size, tmp_str))
@@ -2491,7 +2491,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
bool error;
// 2 hex digits / byte
- hex_str= (char *) my_malloc(2 * val_len + 1 + 3, MYF(MY_WME));
+ hex_str= (char *) my_malloc(PSI_NOT_INSTRUMENTED, 2 * val_len + 1 + 3, MYF(MY_WME));
if (!hex_str)
goto err;
str_to_hex(hex_str, val, val_len);
@@ -2853,7 +2853,7 @@ bool copy_cache_to_string_wrapped(IO_CACHE *cache,
if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE))
goto err;
- if (!(to->str= (char*) my_malloc((size_t)cache->end_of_file + fmt_size,
+ if (!(to->str= (char*) my_malloc(PSI_NOT_INSTRUMENTED, (size_t)cache->end_of_file + fmt_size,
MYF(0))))
{
perror("Out of memory: can't allocate memory in "
@@ -3108,7 +3108,7 @@ int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len,
// Create new temp_buf
ulong event_cur_len= uint4korr(temp_buf + EVENT_LEN_OFFSET);
ulong event_new_len= event_cur_len + len_diff;
- char* new_temp_buf= (char*) my_malloc(event_new_len, MYF(MY_WME));
+ char* new_temp_buf= (char*) my_malloc(PSI_NOT_INSTRUMENTED, event_new_len, MYF(MY_WME));
if (!new_temp_buf)
{
@@ -3150,7 +3150,7 @@ int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len,
char const* tblnam= m_tblnam;
uchar* coltype= m_coltype;
- m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
+ m_memory= (uchar*) my_multi_malloc(PSI_NOT_INSTRUMENTED, MYF(MY_WME),
&m_dbnam, (uint) m_dblen + 1,
&m_tblnam, (uint) m_tbllen + 1,
&m_coltype, (uint) m_colcnt,
@@ -3801,7 +3801,7 @@ bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to)
{
reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE);
if (cache->end_of_file > SIZE_T_MAX ||
- !(to->str= (char*) my_malloc((to->length= (size_t)cache->end_of_file), MYF(0))))
+ !(to->str= (char*) my_malloc(PSI_NOT_INSTRUMENTED, (to->length= (size_t)cache->end_of_file), MYF(0))))
{
perror("Out of memory: can't allocate memory in copy_event_cache_to_string_and_reinit().");
goto err;
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index e01488abbb3..c6ccfc5a2c0 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -32,6 +32,8 @@
#include "rpl_record_old.h"
#include "transaction.h"
+PSI_memory_key key_memory_log_event_old;
+
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
// Old implementation of do_apply_event()
@@ -899,7 +901,7 @@ int Delete_rows_log_event_old::do_before_row_operations(TABLE *table)
if (table->s->keys > 0)
{
- m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
+ m_memory= (uchar*) my_multi_malloc(key_memory_log_event_old, MYF(MY_WME),
&m_after_image,
(uint) table->s->reclength,
&m_key,
@@ -908,7 +910,7 @@ int Delete_rows_log_event_old::do_before_row_operations(TABLE *table)
}
else
{
- m_after_image= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME));
+ m_after_image= (uchar*) my_malloc(key_memory_log_event_old, table->s->reclength, MYF(MY_WME));
m_memory= (uchar*)m_after_image;
m_key= NULL;
}
@@ -997,7 +999,7 @@ int Update_rows_log_event_old::do_before_row_operations(TABLE *table)
if (table->s->keys > 0)
{
- m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
+ m_memory= (uchar*) my_multi_malloc(key_memory_log_event_old, MYF(MY_WME),
&m_after_image,
(uint) table->s->reclength,
&m_key,
@@ -1006,7 +1008,7 @@ int Update_rows_log_event_old::do_before_row_operations(TABLE *table)
}
else
{
- m_after_image= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME));
+ m_after_image= (uchar*) my_malloc(key_memory_log_event_old, table->s->reclength, MYF(MY_WME));
m_memory= m_after_image;
m_key= NULL;
}
@@ -1252,7 +1254,7 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len,
m_table_id, m_flags, m_width, data_size));
DBUG_DUMP("rows_data", (uchar*) ptr_rows_data, data_size);
- m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
+ m_rows_buf= (uchar*) my_malloc(key_memory_log_event_old, data_size, MYF(MY_WME));
if (likely((bool)m_rows_buf))
{
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
@@ -1326,7 +1328,7 @@ int Old_rows_log_event::do_add_row_data(uchar *row_data, size_t length)
my_ptrdiff_t const new_alloc=
block_size * ((cur_size + length + block_size - 1) / block_size);
- uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc,
+ uchar* const new_buf= (uchar*)my_realloc(key_memory_log_event_old, (uchar*)m_rows_buf, (uint) new_alloc,
MYF(MY_ALLOW_ZERO_PTR|MY_WME));
if (unlikely(!new_buf))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2555,7 +2557,7 @@ Delete_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabi
if (m_table->s->keys > 0)
{
// Allocate buffer for key searches
- m_key= (uchar*)my_malloc(m_table->key_info->key_length, MYF(MY_WME));
+ m_key= (uchar*)my_malloc(key_memory_log_event_old, m_table->key_info->key_length, MYF(MY_WME));
if (!m_key)
return HA_ERR_OUT_OF_MEM;
}
@@ -2653,7 +2655,7 @@ Update_rows_log_event_old::do_before_row_operations(const Slave_reporting_capabi
if (m_table->s->keys > 0)
{
// Allocate buffer for key searches
- m_key= (uchar*)my_malloc(m_table->key_info->key_length, MYF(MY_WME));
+ m_key= (uchar*)my_malloc(key_memory_log_event_old, m_table->key_info->key_length, MYF(MY_WME));
if (!m_key)
return HA_ERR_OUT_OF_MEM;
}
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index 202a41c2837..2267f91f0f9 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -1833,8 +1833,8 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
stmt_info_rpl.m_key,
thd->db.str, thd->db.length,
- thd->charset());
- THD_STAGE_INFO(thd, stage_init);
+ thd->charset(), NULL);
+ THD_STAGE_INFO(thd, stage_starting);
MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), thd->query_length());
if (thd->m_digest != NULL)
thd->m_digest->reset(thd->m_token_array, max_digest_length);
@@ -3014,7 +3014,7 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
pos_arg, (ulong) flags));
cache_type= EVENT_NO_CACHE;
if (flags & DUP_NAME)
- new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
+ new_log_ident= my_strndup(PSI_INSTRUMENT_ME, new_log_ident_arg, ident_len, MYF(MY_WME));
if (flags & RELAY_LOG)
set_relay_log_event();
DBUG_VOID_RETURN;
@@ -3170,7 +3170,7 @@ Binlog_checkpoint_log_event::Binlog_checkpoint_log_event(
const char *binlog_file_name_arg,
uint binlog_file_len_arg)
:Log_event(),
- binlog_file_name(my_strndup(binlog_file_name_arg, binlog_file_len_arg,
+ binlog_file_name(my_strndup(PSI_INSTRUMENT_ME, binlog_file_name_arg, binlog_file_len_arg,
MYF(MY_WME))),
binlog_file_len(binlog_file_len_arg)
{
@@ -3443,8 +3443,8 @@ Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set,
cache_type= EVENT_NO_CACHE;
/* Failure to allocate memory will be caught by is_valid() returning false. */
if (count < (1<<28) &&
- (list = (rpl_gtid *)my_malloc(count * sizeof(*list) + (count == 0),
- MYF(MY_WME))))
+ (list = (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ count * sizeof(*list) + (count == 0), MYF(MY_WME))))
gtid_set->get_gtid_list(list, count);
}
@@ -3456,8 +3456,8 @@ Gtid_list_log_event::Gtid_list_log_event(slave_connection_state *gtid_set,
cache_type= EVENT_NO_CACHE;
/* Failure to allocate memory will be caught by is_valid() returning false. */
if (count < (1<<28) &&
- (list = (rpl_gtid *)my_malloc(count * sizeof(*list) + (count == 0),
- MYF(MY_WME))))
+ (list = (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ count * sizeof(*list) + (count == 0), MYF(MY_WME))))
{
gtid_set->get_gtid_list(list, count);
#if defined(HAVE_REPLICATION)
@@ -3465,8 +3465,8 @@ Gtid_list_log_event::Gtid_list_log_event(slave_connection_state *gtid_set,
{
uint32 i;
- if (!(sub_id_list= (uint64 *)my_malloc(count * sizeof(uint64),
- MYF(MY_WME))))
+ if (!(sub_id_list= (uint64 *)my_malloc(PSI_INSTRUMENT_ME,
+ count * sizeof(uint64), MYF(MY_WME))))
{
my_free(list);
list= NULL;
@@ -4691,7 +4691,7 @@ int Execute_load_log_event::do_apply_event(rpl_group_info *rgi)
don't want to overwrite it with the filename.
What we want instead is add the filename to the current error message.
*/
- char *tmp= my_strdup(rli->last_error().message, MYF(MY_WME));
+ char *tmp= my_strdup(PSI_INSTRUMENT_ME, rli->last_error().message, MYF(MY_WME));
if (tmp)
{
rli->report(ERROR_LEVEL, rli->last_error().number, rgi->gtid_info(),
@@ -4823,8 +4823,8 @@ Execute_load_query_log_event::do_apply_event(rpl_group_info *rgi)
int error;
Relay_log_info const *rli= rgi->rli;
- buf= (char*) my_malloc(q_len + 1 - (fn_pos_end - fn_pos_start) +
- (FN_REFLEN + 10) + 10 + 8 + 5, MYF(MY_WME));
+ buf= (char*) my_malloc(PSI_INSTRUMENT_ME, q_len + 1 -
+ (fn_pos_end - fn_pos_start) + (FN_REFLEN + 10) + 10 + 8 + 5, MYF(MY_WME));
DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf); buf= NULL;);
@@ -5036,8 +5036,8 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
size_t const new_alloc=
block_size * ((cur_size + length + block_size - 1) / block_size);
- uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, new_alloc,
- MYF(MY_ALLOW_ZERO_PTR|MY_WME));
+ uchar* const new_buf= (uchar*)my_realloc(PSI_INSTRUMENT_ME, m_rows_buf,
+ new_alloc, MYF(MY_ALLOW_ZERO_PTR|MY_WME));
if (unlikely(!new_buf))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -5990,7 +5990,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
m_flags|= TM_BIT_HAS_TRIGGERS_F;
/* If malloc fails, caught in is_valid() */
- if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME))))
+ if ((m_memory= (uchar*) my_malloc(PSI_INSTRUMENT_ME, m_colcnt, MYF(MY_WME))))
{
m_coltype= reinterpret_cast<uchar*>(m_memory);
for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
@@ -6006,7 +6006,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
*/
uint num_null_bytes= (m_table->s->fields + 7) / 8;
m_data_size+= num_null_bytes;
- m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
+ m_meta_memory= (uchar *)my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&m_null_bits, num_null_bytes,
&m_field_metadata, (m_colcnt * 2),
NULL);
@@ -6158,7 +6158,7 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi)
/* Step the query id to mark what columns that are actually used. */
thd->set_query_id(next_query_id());
- if (!(memory= my_multi_malloc(MYF(MY_WME),
+ if (!(memory= my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&table_list, (uint) sizeof(RPL_TABLE_LIST),
&db_mem, (uint) NAME_LEN + 1,
&tname_mem, (uint) NAME_LEN + 1,
@@ -6809,7 +6809,7 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability
m_table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
}
- if (slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers )
+ if (m_table->triggers && do_invoke_trigger())
m_table->prepare_triggers_for_insert_stmt_or_event();
/* Honor next number column if present */
@@ -6989,8 +6989,7 @@ Rows_log_event::write_row(rpl_group_info *rgi,
TABLE *table= m_table; // pointer to event's table
int error;
int UNINIT_VAR(keynum);
- const bool invoke_triggers=
- slave_run_triggers_for_rbr && !master_had_triggers && table->triggers;
+ const bool invoke_triggers= (m_table->triggers && do_invoke_trigger());
auto_afree_ptr<char> key(NULL);
prepare_record(table, m_width, true);
@@ -7439,7 +7438,7 @@ int Rows_log_event::find_key()
}
// Allocate buffer for key searches
- m_key= (uchar *) my_malloc(best_key->key_length, MYF(MY_WME));
+ m_key= (uchar *) my_malloc(PSI_INSTRUMENT_ME, best_key->key_length, MYF(MY_WME));
if (m_key == NULL)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
m_key_info= best_key;
@@ -7866,7 +7865,7 @@ Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability
*/
return 0;
}
- if (slave_run_triggers_for_rbr && !master_had_triggers)
+ if (do_invoke_trigger())
m_table->prepare_triggers_for_delete_stmt_or_event();
return find_key();
@@ -7889,8 +7888,7 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
int error;
const char *tmp= thd->get_proc_info();
const char *message= "Delete_rows_log_event::find_row()";
- const bool invoke_triggers=
- slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
+ const bool invoke_triggers= (m_table->triggers && do_invoke_trigger());
DBUG_ASSERT(m_table != NULL);
#ifdef WSREP_PROC_INFO
@@ -8016,7 +8014,7 @@ Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability
if ((err= find_key()))
return err;
- if (slave_run_triggers_for_rbr && !master_had_triggers)
+ if (do_invoke_trigger())
m_table->prepare_triggers_for_update_stmt_or_event();
return 0;
@@ -8035,11 +8033,10 @@ Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability
return error;
}
-int
+int
Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
- const bool invoke_triggers=
- slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
+ const bool invoke_triggers= (m_table->triggers && do_invoke_trigger());
const char *tmp= thd->get_proc_info();
const char *message= "Update_rows_log_event::find_row()";
DBUG_ASSERT(m_table != NULL);
diff --git a/sql/mdl.cc b/sql/mdl.cc
index c4d6f89644b..5f229f73b2f 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -25,6 +25,10 @@
#include <mysql/service_thd_wait.h>
#include <mysql/psi/mysql_stage.h>
#include <tpool.h>
+#include <pfs_metadata_provider.h>
+#include <mysql/psi/mysql_mdl.h>
+
+static PSI_memory_key key_memory_MDL_context_acquire_locks;
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
@@ -50,6 +54,11 @@ static PSI_cond_info all_mdl_conds[]=
{ &key_MDL_wait_COND_wait_status, "MDL_context::COND_wait_status", 0}
};
+static PSI_memory_info all_mdl_memory[]=
+{
+ { &key_memory_MDL_context_acquire_locks, "MDL_context::acquire_locks", 0}
+};
+
/**
Initialise all the performance schema instrumentation points
used by the MDL subsystem.
@@ -67,6 +76,9 @@ static void init_mdl_psi_keys(void)
count= array_elements(all_mdl_conds);
mysql_cond_register("sql", all_mdl_conds, count);
+ count= array_elements(all_mdl_memory);
+ mysql_memory_register("sql", all_mdl_memory, count);
+
MDL_key::init_psi_keys();
}
#endif /* HAVE_PSI_INTERFACE */
@@ -955,16 +967,20 @@ bool MDL_context::fix_pins()
@param mdl_type The MDL lock type for the request.
*/
-void MDL_request::init(MDL_key::enum_mdl_namespace mdl_namespace,
+void MDL_request::init_with_source(MDL_key::enum_mdl_namespace mdl_namespace,
const char *db_arg,
const char *name_arg,
enum_mdl_type mdl_type_arg,
- enum_mdl_duration mdl_duration_arg)
+ enum_mdl_duration mdl_duration_arg,
+ const char *src_file,
+ uint src_line)
{
key.mdl_key_init(mdl_namespace, db_arg, name_arg);
type= mdl_type_arg;
duration= mdl_duration_arg;
ticket= NULL;
+ m_src_file= src_file;
+ m_src_line= src_line;
}
@@ -977,14 +993,18 @@ void MDL_request::init(MDL_key::enum_mdl_namespace mdl_namespace,
@param mdl_type_arg The MDL lock type for the request.
*/
-void MDL_request::init(const MDL_key *key_arg,
+void MDL_request::init_by_key_with_source(const MDL_key *key_arg,
enum_mdl_type mdl_type_arg,
- enum_mdl_duration mdl_duration_arg)
+ enum_mdl_duration mdl_duration_arg,
+ const char *src_file,
+ uint src_line)
{
key.mdl_key_init(key_arg);
type= mdl_type_arg;
duration= mdl_duration_arg;
ticket= NULL;
+ m_src_file= src_file;
+ m_src_line= src_line;
}
@@ -1013,6 +1033,9 @@ MDL_ticket *MDL_ticket::create(MDL_context *ctx_arg, enum_mdl_type type_arg
void MDL_ticket::destroy(MDL_ticket *ticket)
{
+ mysql_mdl_destroy(ticket->m_psi);
+ ticket->m_psi= NULL;
+
delete ticket;
}
@@ -2099,6 +2122,15 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
return TRUE;
}
+ DBUG_ASSERT(ticket->m_psi == NULL);
+ ticket->m_psi= mysql_mdl_create(ticket,
+ &mdl_request->key,
+ mdl_request->type,
+ mdl_request->duration,
+ MDL_ticket::PENDING,
+ mdl_request->m_src_file,
+ mdl_request->m_src_line);
+
ticket->m_lock= lock;
if (lock->can_grant_lock(mdl_request->type, this, false))
@@ -2110,6 +2142,8 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
m_tickets[mdl_request->duration].push_front(ticket);
mdl_request->ticket= ticket;
+
+ mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
}
else
*out_ticket= ticket;
@@ -2159,6 +2193,15 @@ MDL_context::clone_ticket(MDL_request *mdl_request)
)))
return TRUE;
+ DBUG_ASSERT(ticket->m_psi == NULL);
+ ticket->m_psi= mysql_mdl_create(ticket,
+ &mdl_request->key,
+ mdl_request->type,
+ mdl_request->duration,
+ MDL_ticket::PENDING,
+ mdl_request->m_src_file,
+ mdl_request->m_src_line);
+
/* clone() is not supposed to be used to get a stronger lock. */
DBUG_ASSERT(mdl_request->ticket->has_stronger_or_equal_type(ticket->m_type));
@@ -2171,6 +2214,8 @@ MDL_context::clone_ticket(MDL_request *mdl_request)
m_tickets[mdl_request->duration].push_front(ticket);
+ mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
+
return FALSE;
}
@@ -2310,6 +2355,12 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
mysql_prlock_unlock(&lock->m_rwlock);
+ PSI_metadata_locker_state state __attribute__((unused));
+ PSI_metadata_locker *locker= NULL;
+
+ if (ticket->m_psi != NULL)
+ locker= PSI_CALL_start_metadata_wait(&state, ticket->m_psi, __FILE__, __LINE__);
+
will_wait_for(ticket);
/* There is a shared or exclusive lock on the object. */
@@ -2355,6 +2406,9 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
done_waiting_for();
+ if (locker != NULL)
+ PSI_CALL_end_metadata_wait(locker, 0);
+
if (wait_status != MDL_wait::GRANTED)
{
lock->remove_ticket(m_pins, &MDL_lock::m_waiting, ticket);
@@ -2390,6 +2444,8 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
mdl_request->ticket= ticket;
+ mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
+
DBUG_RETURN(FALSE);
}
@@ -2435,8 +2491,8 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
DBUG_RETURN(FALSE);
/* Sort requests according to MDL_key. */
- if (! (sort_buf= (MDL_request **)my_malloc(req_count *
- sizeof(MDL_request*),
+ if (! (sort_buf= (MDL_request **)my_malloc(key_memory_MDL_context_acquire_locks,
+ req_count * sizeof(MDL_request*),
MYF(MY_WME))))
DBUG_RETURN(TRUE);
@@ -2521,8 +2577,8 @@ MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
mdl_ticket->get_key()->mdl_namespace() != MDL_key::BACKUP)
DBUG_RETURN(FALSE);
- mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT_BY_KEY(&mdl_xlock_request, &mdl_ticket->m_lock->key,
+ new_type, MDL_TRANSACTION);
if (acquire_lock(&mdl_xlock_request, lock_wait_timeout))
DBUG_RETURN(TRUE);
@@ -2962,7 +3018,8 @@ MDL_context::is_lock_owner(MDL_key::enum_mdl_namespace mdl_namespace,
MDL_request mdl_request;
enum_mdl_duration not_unused;
/* We don't care about exact duration of lock here. */
- mdl_request.init(mdl_namespace, db, name, mdl_type, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&mdl_request, mdl_namespace, db, name, mdl_type,
+ MDL_TRANSACTION);
MDL_ticket *ticket= find_ticket(&mdl_request, &not_unused);
DBUG_ASSERT(ticket == NULL || ticket->m_lock);
diff --git a/sql/mdl.h b/sql/mdl.h
index b084670e5c6..4659238e9f2 100644
--- a/sql/mdl.h
+++ b/sql/mdl.h
@@ -353,7 +353,7 @@ enum enum_mdl_duration {
or "name".
*/
-class MDL_key
+struct MDL_key
{
public:
#ifdef HAVE_PSI_INTERFACE
@@ -535,18 +535,23 @@ public:
/** A lock is requested based on a fully qualified name and type. */
MDL_key key;
+ const char *m_src_file;
+ uint m_src_line;
+
public:
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
{ return alloc_root(mem_root, size); }
static void operator delete(void *, MEM_ROOT *) {}
- void init(MDL_key::enum_mdl_namespace namespace_arg,
+ void init_with_source(MDL_key::enum_mdl_namespace namespace_arg,
const char *db_arg, const char *name_arg,
enum_mdl_type mdl_type_arg,
- enum_mdl_duration mdl_duration_arg);
- void init(const MDL_key *key_arg, enum_mdl_type mdl_type_arg,
- enum_mdl_duration mdl_duration_arg);
+ enum_mdl_duration mdl_duration_arg,
+ const char *src_file, uint src_line);
+ void init_by_key_with_source(const MDL_key *key_arg, enum_mdl_type mdl_type_arg,
+ enum_mdl_duration mdl_duration_arg,
+ const char *src_file, uint src_line);
/** Set type of lock request. Can be only applied to pending locks. */
inline void set_type(enum_mdl_type type_arg)
{
@@ -610,6 +615,12 @@ public:
typedef void (*mdl_cached_object_release_hook)(void *);
+#define MDL_REQUEST_INIT(R, P1, P2, P3, P4, P5) \
+ (*R).init_with_source(P1, P2, P3, P4, P5, __FILE__, __LINE__)
+
+#define MDL_REQUEST_INIT_BY_KEY(R, P1, P2, P3) \
+ (*R).init_by_key_with_source(P1, P2, P3, __FILE__, __LINE__)
+
/**
An abstract class for inspection of a connected
@@ -718,6 +729,11 @@ public:
/** Implement MDL_wait_for_subgraph interface. */
virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor);
virtual uint get_deadlock_weight() const;
+ /**
+ Status of lock request represented by the ticket as reflected in P_S.
+ */
+ enum enum_psi_status { PENDING = 0, GRANTED,
+ PRE_ACQUIRE_NOTIFY, POST_RELEASE_NOTIFY };
private:
friend class MDL_context;
@@ -731,9 +747,15 @@ private:
m_duration(duration_arg),
#endif
m_ctx(ctx_arg),
- m_lock(NULL)
+ m_lock(NULL),
+ m_psi(NULL)
{}
+ virtual ~MDL_ticket()
+ {
+ DBUG_ASSERT(m_psi == NULL);
+ }
+
static MDL_ticket *create(MDL_context *ctx_arg, enum_mdl_type type_arg
#ifndef DBUG_OFF
, enum_mdl_duration duration_arg
@@ -760,6 +782,8 @@ private:
*/
MDL_lock *m_lock;
+ PSI_metadata_lock *m_psi;
+
private:
MDL_ticket(const MDL_ticket &); /* not implemented */
MDL_ticket &operator=(const MDL_ticket &); /* not implemented */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 7aa6d9bfb38..8f1c11a6518 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -113,6 +113,7 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_reload.h" // reload_acl_and_cache
+#include "sp_head.h" // init_sp_psi_keys
#ifdef HAVE_POLL_H
#include <poll.h>
@@ -321,10 +322,6 @@ static PSI_rwlock_key key_rwlock_openssl;
#endif
#endif /* HAVE_PSI_INTERFACE */
-#ifdef HAVE_NPTL
-volatile sig_atomic_t ld_assume_kernel_is_set= 0;
-#endif
-
/**
Statement instrumentation key for replication.
*/
@@ -789,8 +786,8 @@ static struct my_option pfs_early_options[]=
{"performance_schema_consumer_events_statements_current", 0,
"Default startup value for the events_statements_current consumer.",
&pfs_param.m_consumer_events_statements_current_enabled,
- &pfs_param.m_consumer_events_statements_current_enabled, 0,
- GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0},
+ &pfs_param.m_consumer_events_statements_current_enabled, 0, GET_BOOL,
+ OPT_ARG, FALSE, 0, 0, 0, 0, 0},
{"performance_schema_consumer_events_statements_history", 0,
"Default startup value for the events_statements_history consumer.",
&pfs_param.m_consumer_events_statements_history_enabled,
@@ -801,6 +798,21 @@ static struct my_option pfs_early_options[]=
&pfs_param.m_consumer_events_statements_history_long_enabled,
&pfs_param.m_consumer_events_statements_history_long_enabled, 0,
GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
+ {"performance_schema_consumer_events_transactions_current", 0,
+ "Default startup value for the events_transactions_current consumer.",
+ &pfs_param.m_consumer_events_transactions_current_enabled,
+ &pfs_param.m_consumer_events_transactions_current_enabled, 0,
+ GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
+ {"performance_schema_consumer_events_transactions_history", 0,
+ "Default startup value for the events_transactions_history consumer.",
+ &pfs_param.m_consumer_events_transactions_history_enabled,
+ &pfs_param.m_consumer_events_transactions_history_enabled, 0,
+ GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
+ {"performance_schema_consumer_events_transactions_history_long", 0,
+ "Default startup value for the events_transactions_history_long consumer.",
+ &pfs_param.m_consumer_events_transactions_history_long_enabled,
+ &pfs_param.m_consumer_events_transactions_history_long_enabled, 0,
+ GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
{"performance_schema_consumer_events_waits_current", 0,
"Default startup value for the events_waits_current consumer.",
&pfs_param.m_consumer_events_waits_current_enabled,
@@ -838,6 +850,19 @@ static struct my_option pfs_early_options[]=
NO_ARG, 1, 0, 1, 0, 0, 0}
};
+PSI_file_key key_file_binlog, key_file_binlog_cache, key_file_binlog_index,
+ key_file_binlog_index_cache, key_file_casetest,
+ key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
+ key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
+ key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
+ key_file_master_info, key_file_misc, key_file_partition_ddl_log,
+ key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
+ key_file_trg, key_file_trn, key_file_init;
+PSI_file_key key_file_query_log, key_file_slow_log;
+PSI_file_key key_file_relaylog, key_file_relaylog_index,
+ key_file_relaylog_cache, key_file_relaylog_index_cache;
+PSI_file_key key_file_binlog_state;
+
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool,
@@ -1110,17 +1135,6 @@ static PSI_thread_info all_server_threads[]=
PSI_file_key key_file_map;
#endif /* HAVE_MMAP */
-PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
- key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
- key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
- key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
- key_file_master_info, key_file_misc, key_file_partition,
- key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
- key_file_trg, key_file_trn, key_file_init;
-PSI_file_key key_file_query_log, key_file_slow_log;
-PSI_file_key key_file_relaylog, key_file_relaylog_index;
-PSI_file_key key_file_binlog_state;
-
#endif /* HAVE_PSI_INTERFACE */
#ifdef HAVE_PSI_STATEMENT_INTERFACE
@@ -1168,9 +1182,9 @@ void net_after_header_psi(struct st_net *net, void *user_data,
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
stmt_info_new_packet.m_key,
thd->get_db(), thd->db.length,
- thd->charset());
+ thd->charset(), NULL);
- THD_STAGE_INFO(thd, stage_init);
+ THD_STAGE_INFO(thd, stage_starting);
}
/*
@@ -1296,7 +1310,7 @@ private:
void Buffered_logs::init()
{
- init_alloc_root(&m_root, "Buffered_logs", 1024, 0, MYF(0));
+ init_alloc_root(PSI_NOT_INSTRUMENTED, &m_root, 1024, 0, MYF(0));
}
void Buffered_logs::cleanup()
@@ -1676,7 +1690,7 @@ void kill_mysql(THD *thd)
make_user_name(thd, user_host_buff);
- if ((user= my_strdup(user_host_buff, MYF(0))) &&
+ if ((user= my_strdup(PSI_NOT_INSTRUMENTED, user_host_buff, MYF(0))) &&
!shutdown_user.compare_exchange_strong(expected_shutdown_user,
user,
std::memory_order_relaxed,
@@ -2953,8 +2967,7 @@ void init_signals(void)
sa.sa_flags = 0;
sa.sa_handler = print_signal_warning;
sigaction(SIGHUP, &sa, (struct sigaction*) 0);
- if (thd_lib_detected != THD_LIB_LT)
- sigaddset(&set,THR_SERVER_ALARM);
+ sigaddset(&set,THR_SERVER_ALARM);
if (test_flags & TEST_SIGINT)
{
/* Allow SIGINT to break mysqld. This is for debugging with --gdb */
@@ -3211,10 +3224,18 @@ extern "C" void *my_str_malloc_mysqld(size_t size);
void *my_str_malloc_mysqld(size_t size)
{
- return my_malloc(size, MYF(MY_FAE));
+ return my_malloc(key_memory_my_str_malloc, size, MYF(MY_FAE));
}
+#if 0
+extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
+void *my_str_realloc_mysqld(void *ptr, size_t size)
+{
+ return my_realloc(key_memory_my_str_malloc, ptr, size, MYF(MY_FAE));
+}
+#endif
+
#include <mysqld_default_groups.h>
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
@@ -3423,7 +3444,7 @@ SHOW_VAR com_status_vars[]= {
{"show_generic", STMT_STATUS(SQLCOM_SHOW_GENERIC)},
{"show_grants", STMT_STATUS(SQLCOM_SHOW_GRANTS)},
{"show_keys", STMT_STATUS(SQLCOM_SHOW_KEYS)},
- {"show_master_status", STMT_STATUS(SQLCOM_SHOW_MASTER_STAT)},
+ {"show_binlog_status", STMT_STATUS(SQLCOM_SHOW_BINLOG_STAT)},
{"show_open_tables", STMT_STATUS(SQLCOM_SHOW_OPEN_TABLES)},
{"show_package_status", STMT_STATUS(SQLCOM_SHOW_STATUS_PACKAGE)},
#ifndef DBUG_OFF
@@ -3637,10 +3658,8 @@ int json_unescape_json(const char *json_str, const char *json_end,
@returns Pointer to string containing the full file path, or NULL if
it was not possible to create the path.
*/
-static inline const char *
-rpl_make_log_name(const char *opt,
- const char *def,
- const char *ext)
+static const char *rpl_make_log_name(PSI_memory_key key, const char *opt,
+ const char *def, const char *ext)
{
DBUG_ENTER("rpl_make_log_name");
DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt, def, ext));
@@ -3658,7 +3677,7 @@ rpl_make_log_name(const char *opt,
mysql_real_data_home_ptr= mysql_real_data_home;
if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
- DBUG_RETURN(my_strdup(buff, MYF(MY_WME)));
+ DBUG_RETURN(my_strdup(key, buff, MYF(MY_WME)));
else
DBUG_RETURN(NULL);
}
@@ -3794,7 +3813,9 @@ static int init_common_variables()
key_BINLOG_COND_relay_log_updated,
key_BINLOG_COND_bin_log_updated,
key_file_binlog,
+ key_file_binlog_cache,
key_file_binlog_index,
+ key_file_binlog_index_cache,
key_BINLOG_COND_queue_busy,
key_LOCK_binlog_end_pos);
#endif
@@ -4981,10 +5002,12 @@ static int init_server_components()
}
log_bin_basename=
- rpl_make_log_name(opt_bin_logname, pidfile_name,
+ rpl_make_log_name(key_memory_MYSQL_BIN_LOG_basename,
+ opt_bin_logname, pidfile_name,
opt_bin_logname ? "" : "-bin");
log_bin_index=
- rpl_make_log_name(opt_binlog_index_name, log_bin_basename, ".index");
+ rpl_make_log_name(key_memory_MYSQL_BIN_LOG_index,
+ opt_binlog_index_name, log_bin_basename, ".index");
if (log_bin_basename == NULL || log_bin_index == NULL)
{
sql_print_error("Unable to create replication path names:"
@@ -5002,10 +5025,12 @@ static int init_server_components()
if (opt_relay_logname)
{
relay_log_basename=
- rpl_make_log_name(opt_relay_logname, pidfile_name,
+ rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_basename,
+ opt_relay_logname, pidfile_name,
opt_relay_logname ? "" : "-relay-bin");
relay_log_index=
- rpl_make_log_name(opt_relaylog_index_name, relay_log_basename, ".index");
+ rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_index,
+ opt_relaylog_index_name, relay_log_basename, ".index");
if (relay_log_basename == NULL || relay_log_index == NULL)
{
sql_print_error("Unable to create replication path names:"
@@ -5351,10 +5376,10 @@ int mysqld_main(int argc, char **argv)
if (init_early_variables())
exit(1);
-#ifdef HAVE_NPTL
- ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
-#endif
#ifndef _WIN32
+#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
+ pre_initialize_performance_schema();
+#endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
// For windows, my_init() is called from the win specific mysqld_main
if (my_init()) // init my_sys library & pthreads
{
@@ -5454,6 +5479,7 @@ int mysqld_main(int argc, char **argv)
init_server_psi_keys();
/* Instrument the main thread */
PSI_thread *psi= PSI_CALL_new_thread(key_thread_main, NULL, 0);
+ PSI_CALL_set_thread_os_id(psi);
PSI_CALL_set_thread(psi);
/*
@@ -5733,7 +5759,7 @@ int mysqld_main(int argc, char **argv)
mysql_cond_broadcast(&COND_server_started);
mysql_mutex_unlock(&LOCK_server_started);
- MYSQL_SET_STAGE(0 ,__FILE__, __LINE__);
+ (void)MYSQL_SET_STAGE(0 ,__FILE__, __LINE__);
/* Memory used when everything is setup */
start_memory_used= global_status_var.global_memory_used;
@@ -5918,6 +5944,10 @@ int mysqld_main(int argc, char **argv)
/* Must be initialized early for comparison of service name */
system_charset_info= &my_charset_utf8mb3_general_ci;
+#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
+ pre_initialize_performance_schema();
+#endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
+
if (my_init())
{
fprintf(stderr, "my_init() failed.");
@@ -6381,7 +6411,8 @@ int handle_early_options()
my_getopt_skip_unknown= TRUE;
/* prepare all_early_options array */
- my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25, MYF(0));
+ my_init_dynamic_array(PSI_NOT_INSTRUMENTED, &all_early_options,
+ sizeof(my_option), 100, 25, MYF(0));
add_many_options(&all_early_options, pfs_early_options,
array_elements(pfs_early_options));
sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
@@ -7700,7 +7731,7 @@ static int option_cmp(my_option *a, my_option *b)
static void print_help()
{
MEM_ROOT mem_root;
- init_alloc_root(&mem_root, "help", 4096, 4096, MYF(0));
+ init_alloc_root(PSI_NOT_INSTRUMENTED, &mem_root, 4096, 4096, MYF(0));
pop_dynamic(&all_options);
add_many_options(&all_options, pfs_early_options,
@@ -8555,7 +8586,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
my_getopt_error_reporter= option_error_reporter;
/* prepare all_options array */
- my_init_dynamic_array(&all_options, sizeof(my_option),
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &all_options, sizeof(my_option),
array_elements(my_long_options) + sys_var_elements(),
array_elements(my_long_options)/4, MYF(0));
add_many_options(&all_options, my_long_options, array_elements(my_long_options));
@@ -8987,7 +9018,7 @@ static int fix_paths(void)
sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
DBUG_RETURN(1);
}
- char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
+ char *secure_file_real_path= (char *)my_malloc(PSI_INSTRUMENT_ME, FN_REFLEN, MYF(MY_FAE));
convert_dirname(secure_file_real_path, buff, NullS);
my_free(opt_secure_file_priv);
opt_secure_file_priv= secure_file_real_path;
@@ -9088,6 +9119,11 @@ void refresh_status(THD *thd)
{
mysql_mutex_lock(&LOCK_status);
+#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
+ /* Reset aggregated status counters. */
+ reset_pfs_status_stats();
+#endif
+
/* Add thread's status variabes to global status */
add_to_status(&global_status_var, &thd->status_var);
@@ -9125,9 +9161,14 @@ static PSI_file_info all_server_files[]=
{ &key_file_map, "map", 0},
#endif /* HAVE_MMAP */
{ &key_file_binlog, "binlog", 0},
+ { &key_file_binlog_cache, "binlog_cache", 0},
{ &key_file_binlog_index, "binlog_index", 0},
+ { &key_file_binlog_index_cache, "binlog_index_cache", 0},
{ &key_file_relaylog, "relaylog", 0},
+ { &key_file_relaylog_cache, "relaylog_cache", 0},
{ &key_file_relaylog_index, "relaylog_index", 0},
+ { &key_file_relaylog_index_cache, "relaylog_index_cache", 0},
+ { &key_file_io_cache, "io_cache", 0},
{ &key_file_casetest, "casetest", 0},
{ &key_file_dbopt, "dbopt", 0},
{ &key_file_des_key_file, "des_key_file", 0},
@@ -9142,7 +9183,7 @@ static PSI_file_info all_server_files[]=
{ &key_file_log_event_info, "log_event_info", 0},
{ &key_file_master_info, "master_info", 0},
{ &key_file_misc, "misc", 0},
- { &key_file_partition, "partition", 0},
+ { &key_file_partition_ddl_log, "partition_ddl_log", 0},
{ &key_file_pid, "pid", 0},
{ &key_file_query_log, "query_log", 0},
{ &key_file_relay_log_info, "relay_log_info", 0},
@@ -9161,25 +9202,25 @@ PSI_stage_info stage_after_create= { 0, "After create", 0};
PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0};
PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0};
PSI_stage_info stage_allocating_local_table= { 0, "Allocating local table", 0};
-PSI_stage_info stage_alter_inplace_prepare= { 0, "Preparing for alter table", 0};
-PSI_stage_info stage_alter_inplace= { 0, "Altering table", 0};
+PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
+PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
PSI_stage_info stage_alter_inplace_commit= { 0, "Committing alter table to storage engine", 0};
PSI_stage_info stage_apply_event= { 0, "Apply log event", 0};
PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
-PSI_stage_info stage_checking_permissions= { 0, "Checking permissions", 0};
-PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "Checking privileges on cached query", 0};
+PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0};
+PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "checking privileges on cached query", 0};
PSI_stage_info stage_checking_query_cache_for_query= { 0, "Checking query cache for query", 0};
PSI_stage_info stage_cleaning_up= { 0, "Reset for next command", 0};
-PSI_stage_info stage_closing_tables= { 0, "Closing tables", 0};
+PSI_stage_info stage_closing_tables= { 0, "closing tables", 0};
PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0};
PSI_stage_info stage_converting_heap_to_myisam= { 0, "Converting HEAP to " TMP_ENGINE_NAME, 0};
PSI_stage_info stage_copying_to_group_table= { 0, "Copying to group table", 0};
PSI_stage_info stage_copying_to_tmp_table= { 0, "Copying to tmp table", 0};
-PSI_stage_info stage_copy_to_tmp_table= { 0, "Copy to tmp table", 0};
+PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", PSI_FLAG_STAGE_PROGRESS};
PSI_stage_info stage_creating_delayed_handler= { 0, "Creating delayed handler", 0};
PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0};
-PSI_stage_info stage_creating_table= { 0, "Creating table", 0};
+PSI_stage_info stage_creating_table= { 0, "creating table", 0};
PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0};
PSI_stage_info stage_deleting_from_main_table= { 0, "Deleting from main table", 0};
PSI_stage_info stage_deleting_from_reference_tables= { 0, "Deleting from reference tables", 0};
@@ -9197,17 +9238,17 @@ PSI_stage_info stage_freeing_items= { 0, "Freeing items", 0};
PSI_stage_info stage_fulltext_initialization= { 0, "Fulltext initialization", 0};
PSI_stage_info stage_got_handler_lock= { 0, "Got handler lock", 0};
PSI_stage_info stage_got_old_table= { 0, "Got old table", 0};
-PSI_stage_info stage_init= { 0, "Init", 0};
-PSI_stage_info stage_init_update= { 0, "Init for update", 0};
+PSI_stage_info stage_init= { 0, "init", 0};
+PSI_stage_info stage_init_update= { 0, "init for update", 0};
PSI_stage_info stage_insert= { 0, "Insert", 0};
PSI_stage_info stage_invalidating_query_cache_entries_table= { 0, "Invalidating query cache entries (table)", 0};
PSI_stage_info stage_invalidating_query_cache_entries_table_list= { 0, "Invalidating query cache entries (table list)", 0};
PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0};
PSI_stage_info stage_logging_slow_query= { 0, "Logging slow query", 0};
-PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE.", 0};
-PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE.", 0};
+PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE", 0};
+PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE", 0};
PSI_stage_info stage_manage_keys= { 0, "Manage keys", 0};
-PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for binlog to be updated", 0};
+PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for more updates", 0};
PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0};
PSI_stage_info stage_optimizing= { 0, "Optimizing", 0};
PSI_stage_info stage_preparing= { 0, "Preparing", 0};
@@ -9217,7 +9258,7 @@ PSI_stage_info stage_starting_cleanup= { 0, "Starting cleanup", 0};
PSI_stage_info stage_rollback= { 0, "Rollback", 0};
PSI_stage_info stage_rollback_implicit= { 0, "Rollback_implicit", 0};
PSI_stage_info stage_commit= { 0, "Commit", 0};
-PSI_stage_info stage_commit_implicit= { 0, "Commit_implicit", 0};
+PSI_stage_info stage_commit_implicit= { 0, "Commit implicit", 0};
PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0};
PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0};
PSI_stage_info stage_recreating_table= { 0, "Recreating table", 0};
@@ -9232,9 +9273,9 @@ PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update"
PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0};
PSI_stage_info stage_sending_cached_result_to_client= { 0, "Sending cached result to client", 0};
PSI_stage_info stage_sending_data= { 0, "Sending data", 0};
-PSI_stage_info stage_setup= { 0, "Setup", 0};
+PSI_stage_info stage_setup= { 0, "setup", 0};
PSI_stage_info stage_show_explain= { 0, "Show explain", 0};
-PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for the slave I/O thread to update it", 0};
+PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for more updates", 0};
PSI_stage_info stage_sorting= { 0, "Sorting", 0};
PSI_stage_info stage_sorting_for_group= { 0, "Sorting for group", 0};
PSI_stage_info stage_sorting_for_order= { 0, "Sorting for order", 0};
@@ -9245,7 +9286,7 @@ PSI_stage_info stage_storing_result_in_query_cache= { 0, "Storing result in quer
PSI_stage_info stage_storing_row_into_queue= { 0, "Storing row into queue", 0};
PSI_stage_info stage_system_lock= { 0, "System lock", 0};
PSI_stage_info stage_unlocking_tables= { 0, "Unlocking tables", 0};
-PSI_stage_info stage_table_lock= { 0, "Table lock", 0};
+PSI_stage_info stage_table_lock= { 0, "table lock", 0};
PSI_stage_info stage_filling_schema_table= { 0, "Filling schema table", 0};
PSI_stage_info stage_update= { 0, "Update", 0};
PSI_stage_info stage_updating= { 0, "Updating", 0};
@@ -9275,14 +9316,13 @@ PSI_stage_info stage_waiting_for_query_cache_lock= { 0, "Waiting for query cache
PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0};
PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0};
PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0};
-PSI_stage_info stage_waiting_to_get_readlock= { 0, "Waiting to get readlock", 0};
PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0};
PSI_stage_info stage_binlog_write= { 0, "Writing to binlog", 0};
PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0};
PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0};
PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0};
PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to commit", 0};
-PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0};
+PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit", 0};
PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0};
PSI_stage_info stage_waiting_for_workers_idle= { 0, "Waiting for worker threads to be idle", 0};
PSI_stage_info stage_waiting_for_ftwrl= { 0, "Waiting due to global read lock", 0};
@@ -9290,10 +9330,92 @@ PSI_stage_info stage_waiting_for_ftwrl_threads_to_pause= { 0, "Waiting for worke
PSI_stage_info stage_waiting_for_rpl_thread_pool= { 0, "Waiting while replication worker thread pool is busy", 0};
PSI_stage_info stage_master_gtid_wait_primary= { 0, "Waiting in MASTER_GTID_WAIT() (primary waiter)", 0};
PSI_stage_info stage_master_gtid_wait= { 0, "Waiting in MASTER_GTID_WAIT()", 0};
-PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process GTID received on multiple master connections", 0};
+PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process the same GTID", 0};
PSI_stage_info stage_slave_background_process_request= { 0, "Processing requests", 0};
PSI_stage_info stage_slave_background_wait_request= { 0, "Waiting for requests", 0};
PSI_stage_info stage_waiting_for_deadlock_kill= { 0, "Waiting for parallel replication deadlock handling to complete", 0};
+PSI_stage_info stage_starting= { 0, "starting", 0};
+
+PSI_memory_key key_memory_DATE_TIME_FORMAT;
+PSI_memory_key key_memory_DDL_LOG_MEMORY_ENTRY;
+PSI_memory_key key_memory_Event_queue_element_for_exec_names;
+PSI_memory_key key_memory_Event_scheduler_scheduler_param;
+PSI_memory_key key_memory_Filesort_info_merge;
+PSI_memory_key key_memory_Filesort_info_record_pointers;
+PSI_memory_key key_memory_Gis_read_stream_err_msg;
+PSI_memory_key key_memory_JOIN_CACHE;
+PSI_memory_key key_memory_MPVIO_EXT_auth_info;
+PSI_memory_key key_memory_MYSQL_BIN_LOG_basename;
+PSI_memory_key key_memory_MYSQL_BIN_LOG_index;
+PSI_memory_key key_memory_MYSQL_LOCK;
+PSI_memory_key key_memory_MYSQL_LOG_name;
+PSI_memory_key key_memory_MYSQL_RELAY_LOG_basename;
+PSI_memory_key key_memory_MYSQL_RELAY_LOG_index;
+PSI_memory_key key_memory_NAMED_ILINK_name;
+PSI_memory_key key_memory_PROFILE;
+PSI_memory_key key_memory_QUICK_RANGE_SELECT_mrr_buf_desc;
+PSI_memory_key key_memory_Query_cache;
+PSI_memory_key key_memory_Relay_log_info_group_relay_log_name;
+PSI_memory_key key_memory_Row_data_memory_memory;
+PSI_memory_key key_memory_Rpl_info_file_buffer;
+PSI_memory_key key_memory_SLAVE_INFO;
+PSI_memory_key key_memory_ST_SCHEMA_TABLE;
+PSI_memory_key key_memory_Sort_param_tmp_buffer;
+PSI_memory_key key_memory_Sys_var_charptr_value;
+PSI_memory_key key_memory_TABLE;
+PSI_memory_key key_memory_TABLE_RULE_ENT;
+PSI_memory_key key_memory_TC_LOG_MMAP_pages;
+PSI_memory_key key_memory_THD_db;
+PSI_memory_key key_memory_THD_handler_tables_hash;
+PSI_memory_key key_memory_THD_variables;
+PSI_memory_key key_memory_Table_trigger_dispatcher;
+PSI_memory_key key_memory_Unique_merge_buffer;
+PSI_memory_key key_memory_Unique_sort_buffer;
+PSI_memory_key key_memory_User_level_lock;
+PSI_memory_key key_memory_XID;
+PSI_memory_key key_memory_acl_cache;
+PSI_memory_key key_memory_acl_mem;
+PSI_memory_key key_memory_acl_memex;
+PSI_memory_key key_memory_binlog_cache_mngr;
+PSI_memory_key key_memory_binlog_pos;
+PSI_memory_key key_memory_binlog_recover_exec;
+PSI_memory_key key_memory_binlog_statement_buffer;
+PSI_memory_key key_memory_binlog_ver_1_event;
+PSI_memory_key key_memory_bison_stack;
+PSI_memory_key key_memory_blob_mem_storage;
+PSI_memory_key key_memory_dboptions_hash;
+PSI_memory_key key_memory_errmsgs;
+PSI_memory_key key_memory_frm_string;
+PSI_memory_key key_memory_gdl;
+PSI_memory_key key_memory_global_system_variables;
+PSI_memory_key key_memory_handler_errmsgs;
+PSI_memory_key key_memory_handlerton;
+PSI_memory_key key_memory_hash_index_key_buffer;
+PSI_memory_key key_memory_host_cache_hostname;
+PSI_memory_key key_memory_ignored_db;
+PSI_memory_key key_memory_locked_table_list;
+PSI_memory_key key_memory_locked_thread_list;
+PSI_memory_key key_memory_my_str_malloc;
+PSI_memory_key key_memory_native_functions;
+PSI_memory_key key_memory_prepared_statement_main_mem_root;
+PSI_memory_key key_memory_prepared_statement_map;
+PSI_memory_key key_memory_queue_item;
+PSI_memory_key key_memory_quick_range_select_root;
+PSI_memory_key key_memory_rpl_filter;
+PSI_memory_key key_memory_sp_cache;
+PSI_memory_key key_memory_sp_head_call_root;
+PSI_memory_key key_memory_sp_head_execute_root;
+PSI_memory_key key_memory_sp_head_main_root;
+PSI_memory_key key_memory_table_mapping_root;
+PSI_memory_key key_memory_table_share;
+PSI_memory_key key_memory_table_triggers_list;
+PSI_memory_key key_memory_thd_main_mem_root;
+PSI_memory_key key_memory_thd_transactions;
+PSI_memory_key key_memory_user_conn;
+PSI_memory_key key_memory_user_var_entry;
+PSI_memory_key key_memory_user_var_entry_value;
+
+PSI_memory_key key_memory_String_value;
#ifdef HAVE_PSI_INTERFACE
@@ -9422,7 +9544,6 @@ PSI_stage_info *all_server_stages[]=
& stage_waiting_for_the_slave_thread_to_advance_position,
& stage_waiting_for_work_from_sql_thread,
& stage_waiting_to_finalize_termination,
- & stage_waiting_to_get_readlock,
& stage_master_gtid_wait_primary,
& stage_master_gtid_wait,
& stage_gtid_wait_other_connection,
@@ -9431,7 +9552,8 @@ PSI_stage_info *all_server_stages[]=
& stage_waiting_for_semi_sync_ack_from_slave,
& stage_waiting_for_semi_sync_slave,
& stage_reading_semi_sync_ack,
- & stage_waiting_for_deadlock_kill
+ & stage_waiting_for_deadlock_kill,
+ & stage_starting
};
PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;
@@ -9443,6 +9565,145 @@ static PSI_socket_info all_server_sockets[]=
{ &key_socket_client_connection, "client_connection", 0}
};
+static PSI_memory_info all_server_memory[]=
+{
+ { &key_memory_locked_table_list, "Locked_tables_list::m_locked_tables_root", 0},
+ { &key_memory_locked_thread_list, "display_table_locks", PSI_FLAG_THREAD},
+ { &key_memory_thd_transactions, "THD::transactions::mem_root", PSI_FLAG_THREAD},
+// { &key_memory_delegate, "Delegate::memroot", 0},
+ { &key_memory_acl_mem, "sql_acl_mem", PSI_FLAG_GLOBAL},
+ { &key_memory_acl_memex, "sql_acl_memex", PSI_FLAG_GLOBAL},
+ { &key_memory_acl_cache, "acl_cache", PSI_FLAG_GLOBAL},
+ { &key_memory_thd_main_mem_root, "thd::main_mem_root", PSI_FLAG_THREAD},
+// { &key_memory_help, "help", 0},
+// { &key_memory_new_frm_mem, "new_frm_mem", 0},
+ { &key_memory_table_share, "TABLE_SHARE::mem_root", PSI_FLAG_GLOBAL}, /* table definition cache */
+ { &key_memory_gdl, "gdl", 0},
+ { &key_memory_table_triggers_list, "Table_triggers_list", 0},
+// { &key_memory_servers, "servers", 0},
+ { &key_memory_prepared_statement_map, "Prepared_statement_map", PSI_FLAG_THREAD},
+ { &key_memory_prepared_statement_main_mem_root, "Prepared_statement::main_mem_root", PSI_FLAG_THREAD},
+// { &key_memory_protocol_rset_root, "Protocol_local::m_rset_root", PSI_FLAG_THREAD},
+// { &key_memory_warning_info_warn_root, "Warning_info::m_warn_root", PSI_FLAG_THREAD},
+ { &key_memory_sp_cache, "THD::sp_cache", 0},
+ { &key_memory_sp_head_main_root, "sp_head::main_mem_root", 0},
+ { &key_memory_sp_head_execute_root, "sp_head::execute_mem_root", PSI_FLAG_THREAD},
+ { &key_memory_sp_head_call_root, "sp_head::call_mem_root", PSI_FLAG_THREAD},
+ { &key_memory_table_mapping_root, "table_mapping::m_mem_root", 0},
+ { &key_memory_quick_range_select_root, "QUICK_RANGE_SELECT::alloc", PSI_FLAG_THREAD},
+// { &key_memory_quick_index_merge_root, "QUICK_INDEX_MERGE_SELECT::alloc", PSI_FLAG_THREAD},
+// { &key_memory_quick_ror_intersect_select_root, "QUICK_ROR_INTERSECT_SELECT::alloc", PSI_FLAG_THREAD},
+// { &key_memory_quick_ror_union_select_root, "QUICK_ROR_UNION_SELECT::alloc", PSI_FLAG_THREAD},
+// { &key_memory_quick_group_min_max_select_root, "QUICK_GROUP_MIN_MAX_SELECT::alloc", PSI_FLAG_THREAD},
+// { &key_memory_test_quick_select_exec, "test_quick_select", PSI_FLAG_THREAD},
+// { &key_memory_prune_partitions_exec, "prune_partitions::exec", 0},
+ { &key_memory_binlog_recover_exec, "MYSQL_BIN_LOG::recover", 0},
+ { &key_memory_blob_mem_storage, "Blob_mem_storage::storage", 0},
+ { &key_memory_NAMED_ILINK_name, "NAMED_ILINK::name", 0},
+ { &key_memory_String_value, "String::value", 0},
+ { &key_memory_Sys_var_charptr_value, "Sys_var_charptr::value", 0},
+ { &key_memory_queue_item, "Queue::queue_item", 0},
+ { &key_memory_THD_db, "THD::db", 0},
+ { &key_memory_user_var_entry, "user_var_entry", 0},
+// { &key_memory_Slave_job_group_group_relay_log_name, "Slave_job_group::group_relay_log_name", 0},
+ { &key_memory_Relay_log_info_group_relay_log_name, "Relay_log_info::group_relay_log_name", 0},
+ { &key_memory_binlog_cache_mngr, "binlog_cache_mngr", 0},
+ { &key_memory_Row_data_memory_memory, "Row_data_memory::memory", 0},
+// { &key_memory_Gtid_set_to_string, "Gtid_set::to_string", 0},
+// { &key_memory_Gtid_state_to_string, "Gtid_state::to_string", 0},
+// { &key_memory_Owned_gtids_to_string, "Owned_gtids::to_string", 0},
+// { &key_memory_log_event, "Log_event", 0},
+// { &key_memory_Incident_log_event_message, "Incident_log_event::message", 0},
+// { &key_memory_Rows_query_log_event_rows_query, "Rows_query_log_event::rows_query", 0},
+ { &key_memory_Sort_param_tmp_buffer, "Sort_param::tmp_buffer", 0},
+ { &key_memory_Filesort_info_merge, "Filesort_info::merge", 0},
+ { &key_memory_Filesort_info_record_pointers, "Filesort_info::record_pointers", 0},
+// { &key_memory_Filesort_buffer_sort_keys, "Filesort_buffer::sort_keys", 0},
+ { &key_memory_handler_errmsgs, "handler::errmsgs", 0},
+ { &key_memory_handlerton, "handlerton", 0},
+ { &key_memory_XID, "XID", 0},
+ { &key_memory_host_cache_hostname, "host_cache::hostname", 0},
+ { &key_memory_user_var_entry_value, "user_var_entry::value", 0},
+ { &key_memory_User_level_lock, "User_level_lock", 0},
+ { &key_memory_MYSQL_LOG_name, "MYSQL_LOG::name", 0},
+ { &key_memory_TC_LOG_MMAP_pages, "TC_LOG_MMAP::pages", 0},
+// { &key_memory_my_bitmap_map, "my_bitmap_map", 0},
+ { &key_memory_QUICK_RANGE_SELECT_mrr_buf_desc, "QUICK_RANGE_SELECT::mrr_buf_desc", 0},
+ { &key_memory_Event_queue_element_for_exec_names, "Event_queue_element_for_exec::names", 0},
+ { &key_memory_my_str_malloc, "my_str_malloc", 0},
+ { &key_memory_MYSQL_BIN_LOG_basename, "MYSQL_BIN_LOG::basename", 0},
+ { &key_memory_MYSQL_BIN_LOG_index, "MYSQL_BIN_LOG::index", 0},
+ { &key_memory_MYSQL_RELAY_LOG_basename, "MYSQL_RELAY_LOG::basename", 0},
+ { &key_memory_MYSQL_RELAY_LOG_index, "MYSQL_RELAY_LOG::index", 0},
+ { &key_memory_rpl_filter, "rpl_filter memory", 0},
+ { &key_memory_errmsgs, "errmsgs", 0},
+ { &key_memory_Gis_read_stream_err_msg, "Gis_read_stream::err_msg", 0},
+// { &key_memory_Geometry_objects_data, "Geometry::ptr_and_wkb_data", 0},
+ { &key_memory_MYSQL_LOCK, "MYSQL_LOCK", 0},
+// { &key_memory_NET_buff, "NET::buff", 0},
+// { &key_memory_NET_compress_packet, "NET::compress_packet", 0},
+ { &key_memory_Event_scheduler_scheduler_param, "Event_scheduler::scheduler_param", 0},
+// { &key_memory_Gtid_set_Interval_chunk, "Gtid_set::Interval_chunk", 0},
+// { &key_memory_Owned_gtids_sidno_to_hash, "Owned_gtids::sidno_to_hash", 0},
+// { &key_memory_Sid_map_Node, "Sid_map::Node", 0},
+// { &key_memory_Gtid_state_group_commit_sidno, "Gtid_state::group_commit_sidno_locks", 0},
+// { &key_memory_Mutex_cond_array_Mutex_cond, "Mutex_cond_array::Mutex_cond", 0},
+ { &key_memory_TABLE_RULE_ENT, "TABLE_RULE_ENT", 0},
+// { &key_memory_Rpl_info_table, "Rpl_info_table", 0},
+ { &key_memory_Rpl_info_file_buffer, "Rpl_info_file::buffer", 0},
+// { &key_memory_db_worker_hash_entry, "db_worker_hash_entry", 0},
+// { &key_memory_rpl_slave_check_temp_dir, "rpl_slave::check_temp_dir", 0},
+// { &key_memory_rpl_slave_command_buffer, "rpl_slave::command_buffer", 0},
+ { &key_memory_binlog_ver_1_event, "binlog_ver_1_event", 0},
+ { &key_memory_SLAVE_INFO, "SLAVE_INFO", 0},
+ { &key_memory_binlog_pos, "binlog_pos", 0},
+// { &key_memory_HASH_ROW_ENTRY, "HASH_ROW_ENTRY", 0},
+ { &key_memory_binlog_statement_buffer, "binlog_statement_buffer", 0},
+// { &key_memory_partition_syntax_buffer, "partition_syntax_buffer", 0},
+// { &key_memory_READ_INFO, "READ_INFO", 0},
+ { &key_memory_JOIN_CACHE, "JOIN_CACHE", 0},
+// { &key_memory_TABLE_sort_io_cache, "TABLE::sort_io_cache", 0},
+// { &key_memory_frm, "frm", 0},
+ { &key_memory_Unique_sort_buffer, "Unique::sort_buffer", 0},
+ { &key_memory_Unique_merge_buffer, "Unique::merge_buffer", 0},
+ { &key_memory_TABLE, "TABLE", PSI_FLAG_GLOBAL}, /* Table cache */
+// { &key_memory_frm_extra_segment_buff, "frm::extra_segment_buff", 0},
+// { &key_memory_frm_form_pos, "frm::form_pos", 0},
+ { &key_memory_frm_string, "frm::string", 0},
+// { &key_memory_LOG_name, "LOG_name", 0},
+ { &key_memory_DATE_TIME_FORMAT, "DATE_TIME_FORMAT", 0},
+ { &key_memory_DDL_LOG_MEMORY_ENTRY, "DDL_LOG_MEMORY_ENTRY", 0},
+ { &key_memory_ST_SCHEMA_TABLE, "ST_SCHEMA_TABLE", 0},
+ { &key_memory_ignored_db, "ignored_db", 0},
+ { &key_memory_PROFILE, "PROFILE", 0},
+ { &key_memory_global_system_variables, "global_system_variables", 0},
+ { &key_memory_THD_variables, "THD::variables", 0},
+// { &key_memory_Security_context, "Security_context", 0},
+// { &key_memory_shared_memory_name, "Shared_memory_name", 0},
+ { &key_memory_bison_stack, "bison_stack", 0},
+ { &key_memory_THD_handler_tables_hash, "THD::handler_tables_hash", 0},
+ { &key_memory_hash_index_key_buffer, "hash_index_key_buffer", 0},
+ { &key_memory_dboptions_hash, "dboptions_hash", 0},
+ { &key_memory_user_conn, "user_conn", 0},
+// { &key_memory_LOG_POS_COORD, "LOG_POS_COORD", 0},
+// { &key_memory_XID_STATE, "XID_STATE", 0},
+ { &key_memory_MPVIO_EXT_auth_info, "MPVIO_EXT::auth_info", 0},
+// { &key_memory_opt_bin_logname, "opt_bin_logname", 0},
+ { &key_memory_Query_cache, "Query_cache", PSI_FLAG_GLOBAL},
+// { &key_memory_READ_RECORD_cache, "READ_RECORD_cache", 0},
+// { &key_memory_Quick_ranges, "Quick_ranges", 0},
+// { &key_memory_File_query_log_name, "File_query_log::name", 0},
+ { &key_memory_Table_trigger_dispatcher, "Table_trigger_dispatcher::m_mem_root", 0},
+// { &key_memory_thd_timer, "thd_timer", 0},
+// { &key_memory_THD_Session_tracker, "THD::Session_tracker", 0},
+// { &key_memory_THD_Session_sysvar_resource_manager, "THD::Session_sysvar_resource_manager", 0},
+// { &key_memory_show_slave_status_io_gtid_set, "show_slave_status_io_gtid_set", 0},
+// { &key_memory_write_set_extraction, "write_set_extraction", 0},
+// { &key_memory_get_all_tables, "get_all_tables", 0},
+// { &key_memory_fill_schema_schemata, "fill_schema_schemata", 0},
+ { &key_memory_native_functions, "native_functions", PSI_FLAG_GLOBAL},
+};
+
/**
Initialise all the performance schema instrumentation points
used by the server.
@@ -9473,11 +9734,16 @@ void init_server_psi_keys(void)
count= array_elements(all_server_sockets);
mysql_socket_register(category, all_server_sockets, count);
+ count= array_elements(all_server_memory);
+ mysql_memory_register(category, all_server_memory, count);
+
#ifdef HAVE_PSI_STATEMENT_INTERFACE
init_sql_statement_info();
count= array_elements(sql_statement_info);
mysql_statement_register(category, sql_statement_info, count);
+ init_sp_psi_keys();
+
category= "com";
init_com_statement_info();
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 7261b25cab0..018c8cdcaf5 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -306,7 +306,6 @@ extern my_bool disconnect_on_expired_password;
enum secure_timestamp { SECTIME_NO, SECTIME_SUPER, SECTIME_REPL, SECTIME_YES };
-#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active,
key_LOCK_pool, key_LOCK_pending_checkpoint;
@@ -391,22 +390,153 @@ extern PSI_thread_key key_thread_delayed_insert,
key_thread_one_connection, key_thread_signal_hand,
key_thread_slave_background, key_rpl_parallel_thread;
-extern PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
+extern PSI_file_key key_file_binlog, key_file_binlog_cache,
+ key_file_binlog_index, key_file_binlog_index_cache, key_file_casetest,
key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
- key_file_master_info, key_file_misc, key_file_partition,
+ key_file_master_info, key_file_misc, key_file_partition_ddl_log,
key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
key_file_trg, key_file_trn, key_file_init;
extern PSI_file_key key_file_query_log, key_file_slow_log;
-extern PSI_file_key key_file_relaylog, key_file_relaylog_index;
+extern PSI_file_key key_file_relaylog, key_file_relaylog_index,
+ key_file_relaylog_cache, key_file_relaylog_index_cache;
extern PSI_socket_key key_socket_tcpip, key_socket_unix,
key_socket_client_connection;
extern PSI_file_key key_file_binlog_state;
+#ifdef HAVE_PSI_INTERFACE
void init_server_psi_keys();
#endif /* HAVE_PSI_INTERFACE */
+extern PSI_memory_key key_memory_locked_table_list;
+extern PSI_memory_key key_memory_locked_thread_list;
+extern PSI_memory_key key_memory_thd_transactions;
+extern PSI_memory_key key_memory_delegate;
+extern PSI_memory_key key_memory_acl_mem;
+extern PSI_memory_key key_memory_acl_memex;
+extern PSI_memory_key key_memory_acl_cache;
+extern PSI_memory_key key_memory_thd_main_mem_root;
+extern PSI_memory_key key_memory_help;
+extern PSI_memory_key key_memory_frm;
+extern PSI_memory_key key_memory_table_share;
+extern PSI_memory_key key_memory_gdl;
+extern PSI_memory_key key_memory_table_triggers_list;
+extern PSI_memory_key key_memory_prepared_statement_map;
+extern PSI_memory_key key_memory_prepared_statement_main_mem_root;
+extern PSI_memory_key key_memory_protocol_rset_root;
+extern PSI_memory_key key_memory_warning_info_warn_root;
+extern PSI_memory_key key_memory_sp_cache;
+extern PSI_memory_key key_memory_sp_head_main_root;
+extern PSI_memory_key key_memory_sp_head_execute_root;
+extern PSI_memory_key key_memory_sp_head_call_root;
+extern PSI_memory_key key_memory_table_mapping_root;
+extern PSI_memory_key key_memory_quick_range_select_root;
+extern PSI_memory_key key_memory_quick_index_merge_root;
+extern PSI_memory_key key_memory_quick_ror_intersect_select_root;
+extern PSI_memory_key key_memory_quick_ror_union_select_root;
+extern PSI_memory_key key_memory_quick_group_min_max_select_root;
+extern PSI_memory_key key_memory_test_quick_select_exec;
+extern PSI_memory_key key_memory_prune_partitions_exec;
+extern PSI_memory_key key_memory_binlog_recover_exec;
+extern PSI_memory_key key_memory_blob_mem_storage;
+
+extern PSI_memory_key key_memory_Sys_var_charptr_value;
+extern PSI_memory_key key_memory_THD_db;
+extern PSI_memory_key key_memory_user_var_entry;
+extern PSI_memory_key key_memory_user_var_entry_value;
+extern PSI_memory_key key_memory_Slave_job_group_group_relay_log_name;
+extern PSI_memory_key key_memory_Relay_log_info_group_relay_log_name;
+extern PSI_memory_key key_memory_binlog_cache_mngr;
+extern PSI_memory_key key_memory_Row_data_memory_memory;
+extern PSI_memory_key key_memory_errmsgs;
+extern PSI_memory_key key_memory_Event_queue_element_for_exec_names;
+extern PSI_memory_key key_memory_Event_scheduler_scheduler_param;
+extern PSI_memory_key key_memory_Gis_read_stream_err_msg;
+extern PSI_memory_key key_memory_Geometry_objects_data;
+extern PSI_memory_key key_memory_host_cache_hostname;
+extern PSI_memory_key key_memory_User_level_lock;
+extern PSI_memory_key key_memory_Filesort_info_record_pointers;
+extern PSI_memory_key key_memory_Sort_param_tmp_buffer;
+extern PSI_memory_key key_memory_Filesort_info_merge;
+extern PSI_memory_key key_memory_Filesort_buffer_sort_keys;
+extern PSI_memory_key key_memory_handler_errmsgs;
+extern PSI_memory_key key_memory_handlerton;
+extern PSI_memory_key key_memory_XID;
+extern PSI_memory_key key_memory_MYSQL_LOCK;
+extern PSI_memory_key key_memory_MYSQL_LOG_name;
+extern PSI_memory_key key_memory_TC_LOG_MMAP_pages;
+extern PSI_memory_key key_memory_my_str_malloc;
+extern PSI_memory_key key_memory_MYSQL_BIN_LOG_basename;
+extern PSI_memory_key key_memory_MYSQL_BIN_LOG_index;
+extern PSI_memory_key key_memory_MYSQL_RELAY_LOG_basename;
+extern PSI_memory_key key_memory_MYSQL_RELAY_LOG_index;
+extern PSI_memory_key key_memory_rpl_filter;
+extern PSI_memory_key key_memory_Security_context;
+extern PSI_memory_key key_memory_NET_buff;
+extern PSI_memory_key key_memory_NET_compress_packet;
+extern PSI_memory_key key_memory_my_bitmap_map;
+extern PSI_memory_key key_memory_QUICK_RANGE_SELECT_mrr_buf_desc;
+extern PSI_memory_key key_memory_TABLE_RULE_ENT;
+extern PSI_memory_key key_memory_Mutex_cond_array_Mutex_cond;
+extern PSI_memory_key key_memory_Owned_gtids_sidno_to_hash;
+extern PSI_memory_key key_memory_Sid_map_Node;
+extern PSI_memory_key key_memory_bison_stack;
+extern PSI_memory_key key_memory_TABLE_sort_io_cache;
+extern PSI_memory_key key_memory_DATE_TIME_FORMAT;
+extern PSI_memory_key key_memory_DDL_LOG_MEMORY_ENTRY;
+extern PSI_memory_key key_memory_ST_SCHEMA_TABLE;
+extern PSI_memory_key key_memory_ignored_db;
+extern PSI_memory_key key_memory_SLAVE_INFO;
+extern PSI_memory_key key_memory_log_event_old;
+extern PSI_memory_key key_memory_HASH_ROW_ENTRY;
+extern PSI_memory_key key_memory_table_def_memory;
+extern PSI_memory_key key_memory_MPVIO_EXT_auth_info;
+extern PSI_memory_key key_memory_LOG_POS_COORD;
+extern PSI_memory_key key_memory_XID_STATE;
+extern PSI_memory_key key_memory_Rpl_info_file_buffer;
+extern PSI_memory_key key_memory_Rpl_info_table;
+extern PSI_memory_key key_memory_binlog_pos;
+extern PSI_memory_key key_memory_db_worker_hash_entry;
+extern PSI_memory_key key_memory_rpl_slave_command_buffer;
+extern PSI_memory_key key_memory_binlog_ver_1_event;
+extern PSI_memory_key key_memory_rpl_slave_check_temp_dir;
+extern PSI_memory_key key_memory_TABLE;
+extern PSI_memory_key key_memory_binlog_statement_buffer;
+extern PSI_memory_key key_memory_user_conn;
+extern PSI_memory_key key_memory_dboptions_hash;
+extern PSI_memory_key key_memory_hash_index_key_buffer;
+extern PSI_memory_key key_memory_THD_handler_tables_hash;
+extern PSI_memory_key key_memory_JOIN_CACHE;
+extern PSI_memory_key key_memory_READ_INFO;
+extern PSI_memory_key key_memory_partition_syntax_buffer;
+extern PSI_memory_key key_memory_global_system_variables;
+extern PSI_memory_key key_memory_THD_variables;
+extern PSI_memory_key key_memory_PROFILE;
+extern PSI_memory_key key_memory_LOG_name;
+extern PSI_memory_key key_memory_string_iterator;
+extern PSI_memory_key key_memory_frm_extra_segment_buff;
+extern PSI_memory_key key_memory_frm_form_pos;
+extern PSI_memory_key key_memory_frm_string;
+extern PSI_memory_key key_memory_Unique_sort_buffer;
+extern PSI_memory_key key_memory_Unique_merge_buffer;
+extern PSI_memory_key key_memory_shared_memory_name;
+extern PSI_memory_key key_memory_opt_bin_logname;
+extern PSI_memory_key key_memory_Query_cache;
+extern PSI_memory_key key_memory_READ_RECORD_cache;
+extern PSI_memory_key key_memory_Quick_ranges;
+extern PSI_memory_key key_memory_File_query_log_name;
+extern PSI_memory_key key_memory_Table_trigger_dispatcher;
+extern PSI_memory_key key_memory_show_slave_status_io_gtid_set;
+extern PSI_memory_key key_memory_write_set_extraction;
+extern PSI_memory_key key_memory_thd_timer;
+extern PSI_memory_key key_memory_THD_Session_tracker;
+extern PSI_memory_key key_memory_THD_Session_sysvar_resource_manager;
+extern PSI_memory_key key_memory_get_all_tables;
+extern PSI_memory_key key_memory_fill_schema_schemata;
+extern PSI_memory_key key_memory_native_functions;
+extern PSI_memory_key key_memory_JSON;
+
/*
MAINTAINER: Please keep this list in order, to limit merge collisions.
Hint: grep PSI_stage_info | sort -u
@@ -526,7 +656,6 @@ extern PSI_stage_info stage_waiting_for_table_flush;
extern PSI_stage_info stage_waiting_for_the_next_event_in_relay_log;
extern PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position;
extern PSI_stage_info stage_waiting_to_finalize_termination;
-extern PSI_stage_info stage_waiting_to_get_readlock;
extern PSI_stage_info stage_binlog_waiting_background_tasks;
extern PSI_stage_info stage_binlog_write;
extern PSI_stage_info stage_binlog_processing_checkpoint_notify;
@@ -545,6 +674,7 @@ extern PSI_stage_info stage_gtid_wait_other_connection;
extern PSI_stage_info stage_slave_background_process_request;
extern PSI_stage_info stage_slave_background_wait_request;
extern PSI_stage_info stage_waiting_for_deadlock_kill;
+extern PSI_stage_info stage_starting;
#ifdef HAVE_PSI_STATEMENT_INTERFACE
/**
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 4fecf8bffd0..840593cd2db 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -47,6 +47,9 @@
#include "probes_mysql.h"
#include "proxy_protocol.h"
+PSI_memory_key key_memory_NET_buff;
+PSI_memory_key key_memory_NET_compress_packet;
+
#ifdef EMBEDDED_LIBRARY
#undef MYSQL_SERVER
#undef MYSQL_CLIENT
@@ -176,8 +179,9 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags)
my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags)
{
DBUG_ENTER("net_allocate_new_packet");
- if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+
- NET_HEADER_SIZE + COMP_HEADER_SIZE +1,
+ if (!(net->buff=(uchar*) my_malloc(key_memory_NET_buff,
+ (size_t) net->max_packet +
+ NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
MYF(MY_WME | my_flags))))
DBUG_RETURN(1);
net->buff_end=net->buff+net->max_packet;
@@ -221,11 +225,11 @@ my_bool net_realloc(NET *net, size_t length)
my_real_read() may actually read 4 bytes depending on build flags and
platform.
*/
- if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
+ if (!(buff= (uchar*) my_realloc(key_memory_NET_buff,
+ (char*) net->buff, pkt_length +
NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
- MYF(MY_WME |
- (net->thread_specific_malloc ?
- MY_THREAD_SPECIFIC : 0)))))
+ MYF(MY_WME | (net->thread_specific_malloc
+ ? MY_THREAD_SPECIFIC : 0)))))
{
/* @todo: 1 and 2 codes are identical. */
net->error= 1;
@@ -636,11 +640,10 @@ net_real_write(NET *net,const uchar *packet, size_t len)
size_t complen;
uchar *b;
uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
- if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
- COMP_HEADER_SIZE + 1,
- MYF(MY_WME |
- (net->thread_specific_malloc ?
- MY_THREAD_SPECIFIC : 0)))))
+ if (!(b= (uchar*) my_malloc(key_memory_NET_compress_packet,
+ len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1,
+ MYF(MY_WME | (net->thread_specific_malloc
+ ? MY_THREAD_SPECIFIC : 0)))))
{
net->error= 2;
net->last_errno= ER_OUT_OF_RESOURCES;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b4e2cfdf599..5822aaa8250 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1267,9 +1267,8 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
if (!no_alloc && !parent_alloc)
{
// Allocates everything through the internal memroot
- init_sql_alloc(&alloc, "QUICK_RANGE_SELECT",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
thd->mem_root= &alloc;
}
else
@@ -1277,7 +1276,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
file= head->file;
record= head->record[0];
- my_init_dynamic_array2(&ranges, sizeof(QUICK_RANGE*),
+ my_init_dynamic_array2(PSI_INSTRUMENT_ME, &ranges, sizeof(QUICK_RANGE*),
thd->alloc(sizeof(QUICK_RANGE*) * 16), 16, 16,
MYF(MY_THREAD_SPECIFIC));
@@ -1363,9 +1362,8 @@ QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT(THD *thd_param, TABLE *table)
DBUG_ENTER("QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT");
index= MAX_KEY;
head= table;
- init_sql_alloc(&alloc, "QUICK_INDEX_SORT_SELECT",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
DBUG_VOID_RETURN;
}
@@ -1435,9 +1433,8 @@ QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
head= table;
record= head->record[0];
if (!parent_alloc)
- init_sql_alloc(&alloc, "QUICK_ROR_INTERSECT_SELECT",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
else
bzero(&alloc, sizeof(MEM_ROOT));
last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc,
@@ -1713,9 +1710,8 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
head= table;
rowid_length= table->file->ref_length;
record= head->record[0];
- init_sql_alloc(&alloc, "QUICK_ROR_UNION_SELECT",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
thd_param->mem_root= &alloc;
}
@@ -2726,9 +2722,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.possible_keys.clear_all();
thd->no_errors=1; // Don't warn about NULL
- init_sql_alloc(&alloc, "test_quick_select",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
if (!(param.key_parts=
(KEY_PART*) alloc_root(&alloc,
sizeof(KEY_PART) *
@@ -3407,9 +3402,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
SEL_TREE *tree;
double rows;
- init_sql_alloc(&alloc, "calculate_cond_selectivity_for_table",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
param.thd= thd;
param.mem_root= &alloc;
param.old_root= thd->mem_root;
@@ -3839,9 +3833,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
my_bitmap_map *old_sets[2];
prune_param.part_info= part_info;
- init_sql_alloc(&alloc, "prune_partitions",
- thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
range_par->mem_root= &alloc;
range_par->old_root= thd->mem_root;
@@ -12098,7 +12091,8 @@ int QUICK_RANGE_SELECT::reset()
if (mrr_buf_size && !mrr_buf_desc)
{
buf_size= mrr_buf_size;
- while (buf_size && !my_multi_malloc(MYF(MY_WME),
+ while (buf_size && !my_multi_malloc(key_memory_QUICK_RANGE_SELECT_mrr_buf_desc,
+ MYF(MY_WME),
&mrr_buf_desc, sizeof(*mrr_buf_desc),
&mrange_buff, buf_size,
NullS))
@@ -14450,10 +14444,10 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
DBUG_ASSERT(!parent_alloc);
if (!parent_alloc)
{
- init_sql_alloc(&alloc, "QUICK_GROUP_MIN_MAX_SELECT",
- join->thd->variables.range_alloc_block_size, 0,
- MYF(MY_THREAD_SPECIFIC));
- join->thd->mem_root= &alloc;
+ THD *thd= join->thd;
+ init_sql_alloc(key_memory_quick_range_select_root, &alloc,
+ thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC));
+ thd->mem_root= &alloc;
}
else
bzero(&alloc, sizeof(MEM_ROOT)); // ensure that it's not used
@@ -14513,7 +14507,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::init()
if (min_max_arg_part)
{
- if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16,
+ if (my_init_dynamic_array(PSI_INSTRUMENT_ME, &min_max_ranges,
+ sizeof(QUICK_RANGE*), 16, 16,
MYF(MY_THREAD_SPECIFIC)))
return 1;
diff --git a/sql/opt_split.cc b/sql/opt_split.cc
index 6f8248c315c..b27a0d757cb 100644
--- a/sql/opt_split.cc
+++ b/sql/opt_split.cc
@@ -341,7 +341,7 @@ bool JOIN::check_for_splittable_materialized()
return false;
ORDER *ord;
- Dynamic_array<SplM_field_ext_info> candidates;
+ Dynamic_array<SplM_field_ext_info> candidates(PSI_INSTRUMENT_MEM);
/*
Select from partition_list all candidates for splitting.
@@ -712,7 +712,7 @@ void JOIN::add_keyuses_for_splitting()
KEY_FIELD *added_key_field;
if (!spl_opt_info->added_key_fields.elements)
goto err;
- if (!(ext_keyuses_for_splitting= new Dynamic_array<KEYUSE_EXT>))
+ if (!(ext_keyuses_for_splitting= new Dynamic_array<KEYUSE_EXT>(PSI_INSTRUMENT_MEM)))
goto err;
while ((added_key_field= li++))
{
@@ -742,13 +742,11 @@ void JOIN::add_keyuses_for_splitting()
save_query_plan(save_qep);
if (!keyuse.buffer &&
- my_init_dynamic_array(&keyuse, sizeof(KEYUSE), 20, 64,
- MYF(MY_THREAD_SPECIFIC)))
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &keyuse, sizeof(KEYUSE),
+ 20, 64, MYF(MY_THREAD_SPECIFIC)))
goto err;
- if (allocate_dynamic(&keyuse,
- save_qep->keyuse.elements +
- added_keyuse_count))
+ if (allocate_dynamic(&keyuse, save_qep->keyuse.elements + added_keyuse_count))
goto err;
memcpy(keyuse.buffer,
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index c7d95fdadec..6c491300d17 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -4470,8 +4470,8 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
using_unique_constraint= TRUE;
/* STEP 3: Allocate memory for temptable description */
- init_sql_alloc(&own_root, "SJ_TMP_TABLE",
- TABLE_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(PSI_INSTRUMENT_ME, &own_root, TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(MY_THREAD_SPECIFIC));
if (!multi_alloc_root(&own_root,
&table, sizeof(*table),
&share, sizeof(*share),
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index 7ff11e65a30..057c6f3cc0a 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -449,7 +449,7 @@ bool Opt_trace_context::is_enabled()
return false;
}
-Opt_trace_context::Opt_trace_context()
+Opt_trace_context::Opt_trace_context() : traces(PSI_INSTRUMENT_MEM)
{
current_trace= NULL;
max_mem_size= 0;
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 252744a3a73..5e3c19850de 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -30,7 +30,6 @@
// NOT_A_PARTITION_ID
#include "partition_info.h"
#include "sql_parse.h"
-#include "sql_acl.h" // *_ACL
#include "sql_base.h" // fill_record
#include "lock.h"
#include "table.h"
@@ -733,7 +732,7 @@ char *partition_info::find_duplicate_name()
max_names= num_parts;
if (is_sub_partitioned())
max_names+= num_parts * num_subparts;
- if (my_hash_init(&partition_names, system_charset_info, max_names, 0, 0,
+ if (my_hash_init(PSI_INSTRUMENT_ME, &partition_names, system_charset_info, max_names, 0, 0,
(my_hash_get_key) get_part_name_from_elem, 0, HASH_UNIQUE))
{
DBUG_ASSERT(0);
diff --git a/sql/privilege.h b/sql/privilege.h
index 6f12546796e..c5c13186743 100644
--- a/sql/privilege.h
+++ b/sql/privilege.h
@@ -49,7 +49,7 @@ enum privilege_t: unsigned long long
LOCK_TABLES_ACL = (1UL << 17),
EXECUTE_ACL = (1UL << 18),
REPL_SLAVE_ACL = (1UL << 19),
- REPL_CLIENT_ACL = (1UL << 20),
+ BINLOG_MONITOR_ACL = (1UL << 20), // Was REPL_CLIENT_ACL prior to 10.5.2
CREATE_VIEW_ACL = (1UL << 21),
SHOW_VIEW_ACL = (1UL << 22),
CREATE_PROC_ACL = (1UL << 23),
@@ -58,20 +58,66 @@ enum privilege_t: unsigned long long
EVENT_ACL = (1UL << 26),
TRIGGER_ACL = (1UL << 27),
CREATE_TABLESPACE_ACL = (1UL << 28),
- DELETE_HISTORY_ACL = (1UL << 29),
+ DELETE_HISTORY_ACL = (1UL << 29), // Added in 10.3.4
+ SET_USER_ACL = (1UL << 30), // Added in 10.5.2
+ FEDERATED_ADMIN_ACL = (1UL << 31), // Added in 10.5.2
+ CONNECTION_ADMIN_ACL = (1ULL << 32), // Added in 10.5.2
+ READ_ONLY_ADMIN_ACL = (1ULL << 33), // Added in 10.5.2
+ REPL_SLAVE_ADMIN_ACL = (1ULL << 34), // Added in 10.5.2
+ REPL_MASTER_ADMIN_ACL = (1ULL << 35), // Added in 10.5.2
+ BINLOG_ADMIN_ACL = (1ULL << 36) // Added in 10.5.2
/*
- don't forget to update
- 1. static struct show_privileges_st sys_privileges[]
- 2. static const char *command_array[] and static uint command_lengths[]
- 3. mysql_system_tables.sql and mysql_system_tables_fix.sql
- 4. acl_init() or whatever - to define behaviour for old privilege tables
- 5. sql_yacc.yy - for GRANT/REVOKE to work
- 6. ALL_KNOWN_ACL
+ When adding new privilege bits, don't forget to update:
+ In this file:
+ - Add a new LAST_version_ACL
+ - Add a new ALL_KNOWN_ACL_version
+ - Change ALL_KNOWN_ACL to ALL_KNOWN_ACL_version
+ - Change GLOBAL_ACLS if needed
+ - Change SUPER_ADDED_SINCE_USER_TABLE_ACL if needed
+
+ In other files:
+ - static struct show_privileges_st sys_privileges[]
+ - static const char *command_array[] and static uint command_lengths[]
+ - mysql_system_tables.sql and mysql_system_tables_fix.sql
+ - acl_init() or whatever - to define behaviour for old privilege tables
+ - Update User_table_json::get_access()
+ - sql_yacc.yy - for GRANT/REVOKE to work
+
+ Important: the enum should contain only single-bit values.
+ In this case, debuggers print bit combinations in the readable form:
+ (gdb) p (privilege_t) (15)
+ $8 = (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL)
+
+ Bit-OR combinations of the above values should be declared outside!
*/
- ALL_KNOWN_ACL = (1UL << 30) - 1 // A combination of all defined bits
};
+// Version markers
+constexpr privilege_t LAST_100304_ACL= DELETE_HISTORY_ACL;
+constexpr privilege_t LAST_100502_ACL= BINLOG_ADMIN_ACL;
+
+// Current version markers
+constexpr privilege_t LAST_CURRENT_ACL= LAST_100502_ACL;
+constexpr uint PRIVILEGE_T_MAX_BIT=
+ my_bit_log2_uint64((ulonglong) LAST_CURRENT_ACL);
+
+static_assert((privilege_t)(1ULL << PRIVILEGE_T_MAX_BIT) == LAST_CURRENT_ACL,
+ "Something went fatally badly: "
+ "LAST_CURRENT_ACL and PRIVILEGE_T_MAX_BIT do not match");
+
+// A combination of all bits defined in 10.3.4 (and earlier)
+constexpr privilege_t ALL_KNOWN_ACL_100304 =
+ (privilege_t) ((LAST_100304_ACL << 1) - 1);
+
+// A combination of all bits defined in 10.5.2
+constexpr privilege_t ALL_KNOWN_ACL_100502=
+ (privilege_t) ((LAST_100502_ACL << 1) - 1);
+
+// A combination of all bits defined as of the current version
+constexpr privilege_t ALL_KNOWN_ACL= ALL_KNOWN_ACL_100502;
+
+
// Unary operators
static inline constexpr ulonglong operator~(privilege_t access)
{
@@ -168,6 +214,19 @@ static inline privilege_t& operator|=(privilege_t &a, privilege_t b)
}
+/*
+ A combination of all SUPER privileges added since the old user table format.
+ These privileges are automatically added when upgrading from the
+ old format mysql.user table if a user has the SUPER privilege.
+*/
+constexpr privilege_t GLOBAL_SUPER_ADDED_SINCE_USER_TABLE_ACLS=
+ SET_USER_ACL |
+ FEDERATED_ADMIN_ACL |
+ CONNECTION_ADMIN_ACL |
+ READ_ONLY_ADMIN_ACL |
+ REPL_SLAVE_ADMIN_ACL |
+ BINLOG_ADMIN_ACL;
+
constexpr privilege_t COL_DML_ACLS=
SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL;
@@ -206,7 +265,9 @@ constexpr privilege_t GLOBAL_ACLS=
DB_ACLS | SHOW_DB_ACL |
CREATE_USER_ACL | CREATE_TABLESPACE_ACL |
SUPER_ACL | RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL |
- REPL_SLAVE_ACL | REPL_CLIENT_ACL;
+ REPL_SLAVE_ACL | BINLOG_MONITOR_ACL |
+ GLOBAL_SUPER_ADDED_SINCE_USER_TABLE_ACLS |
+ REPL_MASTER_ADMIN_ACL;
constexpr privilege_t DEFAULT_CREATE_PROC_ACLS=
ALTER_PROC_ACL | EXECUTE_ACL;
@@ -222,6 +283,124 @@ constexpr privilege_t SHOW_CREATE_TABLE_ACLS=
constexpr privilege_t TMP_TABLE_ACLS=
COL_DML_ACLS | ALL_TABLE_DDL_ACLS;
+
+
+/*
+ Allow to set an object definer:
+ CREATE DEFINER=xxx {TRIGGER|VIEW|FUNCTION|PROCEDURE}
+ Was SUPER prior to 10.5.2
+*/
+constexpr privilege_t PRIV_DEFINER_CLAUSE= SET_USER_ACL | SUPER_ACL;
+/*
+ If a VIEW has a `definer=invoker@host` clause and
+ the specified definer does not exists, then
+ - The invoker with REVEAL_MISSING_DEFINER_ACL gets:
+ ERROR: The user specified as a definer ('definer1'@'localhost') doesn't exist
+ - The invoker without MISSING_DEFINER_ACL gets a generic access error,
+ without revealing details that the definer does not exists.
+
+ TODO: we should eventually test the same privilege when processing
+ other objects that have the DEFINER clause (e.g. routines, triggers).
+ Currently the missing definer is revealed for non-privileged invokers
+ in case of routines, triggers, etc.
+
+ Was SUPER prior to 10.5.2
+*/
+constexpr privilege_t PRIV_REVEAL_MISSING_DEFINER= SET_USER_ACL | SUPER_ACL;
+
+/* Actions that require only the SUPER privilege */
+constexpr privilege_t PRIV_DES_DECRYPT_ONE_ARG= SUPER_ACL;
+constexpr privilege_t PRIV_LOG_BIN_TRUSTED_SP_CREATOR= SUPER_ACL;
+constexpr privilege_t PRIV_DEBUG= SUPER_ACL;
+constexpr privilege_t PRIV_SET_GLOBAL_SYSTEM_VARIABLE= SUPER_ACL;
+constexpr privilege_t PRIV_SET_RESTRICTED_SESSION_SYSTEM_VARIABLE= SUPER_ACL;
+
+/* Privileges related to --read-only */
+constexpr privilege_t PRIV_IGNORE_READ_ONLY= READ_ONLY_ADMIN_ACL | SUPER_ACL;
+
+/*
+ Privileges related to connection handling.
+*/
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_IGNORE_INIT_CONNECT= CONNECTION_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_IGNORE_MAX_USER_CONNECTIONS= CONNECTION_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_IGNORE_MAX_CONNECTIONS= CONNECTION_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_IGNORE_MAX_PASSWORD_ERRORS= CONNECTION_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_KILL_OTHER_USER_PROCESS= CONNECTION_ADMIN_ACL | SUPER_ACL;
+
+
+/*
+ Binary log related privileges that are checked regardless
+ of active replication running.
+*/
+
+/*
+ This command was renamed from "SHOW MASTER STATUS"
+ to "SHOW BINLOG STATUS" in 10.5.2.
+ Was SUPER_ACL | REPL_CLIENT_ACL prior to 10.5.2
+ REPL_CLIENT_ACL was renamed to BINLOG_MONITOR_ACL.
+*/
+constexpr privilege_t PRIV_STMT_SHOW_BINLOG_STATUS= BINLOG_MONITOR_ACL | SUPER_ACL;
+
+/*
+ Was SUPER_ACL | REPL_CLIENT_ACL prior to 10.5.2
+ REPL_CLIENT_ACL was renamed to BINLOG_MONITOR_ACL.
+*/
+constexpr privilege_t PRIV_STMT_SHOW_BINARY_LOGS= BINLOG_MONITOR_ACL | SUPER_ACL;
+
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_PURGE_BINLOG= BINLOG_ADMIN_ACL | SUPER_ACL;
+
+// Was REPL_SLAVE_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_SHOW_BINLOG_EVENTS= BINLOG_MONITOR_ACL;
+
+
+/*
+ Privileges for replication related statements and commands
+ that are executed on the master.
+*/
+constexpr privilege_t PRIV_COM_REGISTER_SLAVE= REPL_SLAVE_ACL;
+constexpr privilege_t PRIV_COM_BINLOG_DUMP= REPL_SLAVE_ACL;
+// Was REPL_SLAVE_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_SHOW_SLAVE_HOSTS= REPL_MASTER_ADMIN_ACL;
+
+
+/* Privileges for statements that are executed on the slave */
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_START_SLAVE= REPL_SLAVE_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_STOP_SLAVE= REPL_SLAVE_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_CHANGE_MASTER= REPL_SLAVE_ADMIN_ACL | SUPER_ACL;
+// Was (SUPER_ACL | REPL_CLIENT_ACL) prior to 10.5.2
+constexpr privilege_t PRIV_STMT_SHOW_SLAVE_STATUS= REPL_SLAVE_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_BINLOG= REPL_SLAVE_ADMIN_ACL | SUPER_ACL;
+// Was REPL_SLAVE_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_SHOW_RELAYLOG_EVENTS= REPL_SLAVE_ADMIN_ACL;
+
+
+/* Privileges for federated database related statements */
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_CREATE_SERVER= FEDERATED_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_ALTER_SERVER= FEDERATED_ADMIN_ACL | SUPER_ACL;
+// Was SUPER_ACL prior to 10.5.2
+constexpr privilege_t PRIV_STMT_DROP_SERVER= FEDERATED_ADMIN_ACL | SUPER_ACL;
+
+
+/* Privileges related to processes */
+constexpr privilege_t PRIV_COM_PROCESS_INFO= PROCESS_ACL;
+constexpr privilege_t PRIV_STMT_SHOW_EXPLAIN= PROCESS_ACL;
+constexpr privilege_t PRIV_STMT_SHOW_ENGINE_STATUS= PROCESS_ACL;
+constexpr privilege_t PRIV_STMT_SHOW_ENGINE_MUTEX= PROCESS_ACL;
+constexpr privilege_t PRIV_STMT_SHOW_PROCESSLIST= PROCESS_ACL;
+
+
/*
Defines to change the above bits to how things are stored in tables
This is needed as the 'host' and 'db' table is missing a few privileges
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 30e4cc6c214..21efac46c52 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -799,6 +799,41 @@ bool Protocol::flush()
#ifndef EMBEDDED_LIBRARY
+
+class Send_field_packed_extended_metadata: public Binary_string
+{
+public:
+ bool append_chunk(mariadb_field_attr_t type, const LEX_CSTRING &value)
+ {
+ /*
+ If we eventually support many metadata chunk types and long metadata
+ values, we'll need to encode type and length using net_store_length()
+ and do corresponding changes to the unpacking code in libmariadb.
+ For now let's just assert that type and length fit into one byte.
+ */
+ DBUG_ASSERT(net_length_size(type) == 1);
+ DBUG_ASSERT(net_length_size(value.length) == 1);
+ size_t nbytes= 1/*type*/ + 1/*length*/ + value.length;
+ if (reserve(nbytes))
+ return true;
+ qs_append((char) (uchar) type);
+ qs_append((char) (uchar) value.length);
+ qs_append(&value);
+ return false;
+ }
+ bool pack(const Send_field_extended_metadata &src)
+ {
+ for (uint i= 0 ; i <= MARIADB_FIELD_ATTR_LAST; i++)
+ {
+ const LEX_CSTRING attr= src.attr(i);
+ if (attr.str && append_chunk((mariadb_field_attr_t) i, attr))
+ return true;
+ }
+ return false;
+ }
+};
+
+
bool Protocol_text::store_field_metadata(const THD * thd,
const Send_field &field,
CHARSET_INFO *charset_for_protocol,
@@ -816,8 +851,20 @@ bool Protocol_text::store_field_metadata(const THD * thd,
store_str(field.table_name, cs, thd_charset) ||
store_str(field.org_table_name, cs, thd_charset) ||
store_str(field.col_name, cs, thd_charset) ||
- store_str(field.org_col_name, cs, thd_charset) ||
- packet->realloc(packet->length() + 12))
+ store_str(field.org_col_name, cs, thd_charset))
+ return true;
+ if (thd->client_capabilities & MARIADB_CLIENT_EXTENDED_METADATA)
+ {
+ Send_field_packed_extended_metadata metadata;
+ metadata.pack(field);
+ /*
+ Don't apply character set conversion:
+ extended metadata is a binary encoded data.
+ */
+ if (store_str(metadata.lex_cstring(), cs, &my_charset_bin))
+ return true;
+ }
+ if (packet->realloc(packet->length() + 12))
return true;
/* Store fixed length fields */
pos= (char*) packet->end();
diff --git a/sql/proxy_protocol.cc b/sql/proxy_protocol.cc
index 550813c6457..689d1af88f0 100644
--- a/sql/proxy_protocol.cc
+++ b/sql/proxy_protocol.cc
@@ -364,7 +364,8 @@ static int parse_networks(const char *subnets_str, subnet **out_subnets, size_t
}
max_subnets= MY_MAX(3,strlen(subnets_str)/2);
- subnets= (subnet *)my_malloc(max_subnets * sizeof(subnet),MY_ZEROFILL);
+ subnets= (subnet *)my_malloc(PSI_INSTRUMENT_ME,
+ max_subnets * sizeof(subnet), MY_ZEROFILL);
/* Check for special case '*'. */
if (strcmp(subnets_str, "*") == 0)
diff --git a/sql/records.cc b/sql/records.cc
index 2b146abb005..e1766322e2f 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -39,7 +39,7 @@ static int rr_quick(READ_RECORD *info);
int rr_sequential(READ_RECORD *info);
static int rr_from_tempfile(READ_RECORD *info);
template<bool> static int rr_unpack_from_tempfile(READ_RECORD *info);
-template<bool> static int rr_unpack_from_buffer(READ_RECORD *info);
+template<bool,bool> static int rr_unpack_from_buffer(READ_RECORD *info);
int rr_from_pointers(READ_RECORD *info);
static int rr_from_cache(READ_RECORD *info);
static int init_rr_cache(THD *thd, READ_RECORD *info);
@@ -190,6 +190,7 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
DBUG_ENTER("init_read_record");
const bool using_addon_fields= filesort && filesort->using_addon_fields();
+ bool using_packed_sortkeys= filesort && filesort->using_packed_sortkeys();
bzero((char*) info,sizeof(*info));
info->thd=thd;
@@ -287,10 +288,19 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
DBUG_PRINT("info",("using rr_unpack_from_buffer"));
DBUG_ASSERT(filesort->sorted_result_in_fsbuf);
info->unpack_counter= 0;
+
if (filesort->using_packed_addons())
- info->read_record_func= rr_unpack_from_buffer<true>;
+ {
+ info->read_record_func= using_packed_sortkeys ?
+ rr_unpack_from_buffer<true, true> :
+ rr_unpack_from_buffer<true, false>;
+ }
else
- info->read_record_func= rr_unpack_from_buffer<false>;
+ {
+ info->read_record_func= using_packed_sortkeys ?
+ rr_unpack_from_buffer<false, true> :
+ rr_unpack_from_buffer<false, false>;
+ }
}
else
{
@@ -626,7 +636,7 @@ int rr_from_pointers(READ_RECORD *info)
-1 There is no record to be read anymore.
*/
-template<bool Packed_addon_fields>
+template<bool Packed_addon_fields, bool Packed_sort_keys>
static int rr_unpack_from_buffer(READ_RECORD *info)
{
if (info->unpack_counter == info->sort_info->return_rows)
@@ -634,7 +644,12 @@ static int rr_unpack_from_buffer(READ_RECORD *info)
uchar *record= info->sort_info->get_sorted_record(
static_cast<uint>(info->unpack_counter));
- uchar *plen= record + info->sort_info->get_sort_length();
+
+ uint sort_length= Packed_sort_keys ?
+ Sort_keys::read_sortkey_length(record):
+ info->sort_info->get_sort_length();
+
+ uchar *plen= record + sort_length;
info->sort_info->unpack_addon_fields<Packed_addon_fields>(plen);
info->unpack_counter++;
return 0;
@@ -772,6 +787,19 @@ static int rr_cmp(uchar *a,uchar *b)
#endif
}
+
+/**
+ Copy (unpack) values appended to sorted fields from a buffer back to
+ their regular positions specified by the Field::ptr pointers.
+
+ @param addon_field Array of descriptors for appended fields
+ @param buff Buffer which to unpack the value from
+
+ @note
+ The function is supposed to be used only as a callback function
+ when getting field values for the sorted result set.
+
+*/
template<bool Packed_addon_fields>
inline void SORT_INFO::unpack_addon_fields(uchar *buff)
{
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 7905e112e2e..1df85759a9c 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -101,7 +101,7 @@ void THD::unregister_slave()
mysql_mutex_lock(&LOCK_thd_data);
slave_info= 0;
mysql_mutex_unlock(&LOCK_thd_data);
- delete old_si;
+ my_free(old_si);
binlog_dump_thread_count--;
}
}
@@ -122,9 +122,10 @@ int THD::register_slave(uchar *packet, size_t packet_length)
uchar *p= packet, *p_end= packet + packet_length;
const char *errmsg= "Wrong parameters to function register_slave";
- if (check_access(this, REPL_SLAVE_ACL, any_db, NULL, NULL, 0, 0))
+ if (check_access(this, PRIV_COM_REGISTER_SLAVE, any_db, NULL, NULL, 0, 0))
return 1;
- if (!(si= new Slave_info))
+ if (!(si= (Slave_info*)my_malloc(key_memory_SLAVE_INFO, sizeof(Slave_info),
+ MYF(MY_WME))))
return 1;
variables.server_id= si->server_id= uint4korr(p);
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
index e96f9640098..635a0f4e2d6 100644
--- a/sql/rpl_filter.cc
+++ b/sql/rpl_filter.cc
@@ -286,7 +286,7 @@ Rpl_filter::parse_filter_rule(const char* spec, Add_filter add)
if (!spec)
return false;
- if (! (ptr= my_strdup(spec, MYF(MY_WME))))
+ if (! (ptr= my_strdup(key_memory_rpl_filter, spec, MYF(MY_WME))))
return true;
pstr= ptr;
@@ -461,8 +461,9 @@ Rpl_filter::add_table_rule(HASH* h, const char* table_spec)
if (!dot) return 1;
// len is always > 0 because we know the there exists a '.'
uint len = (uint)strlen(table_spec);
- TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
- + len, MYF(MY_WME));
+ TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(key_memory_TABLE_RULE_ENT,
+ sizeof(TABLE_RULE_ENT) + len,
+ MYF(MY_WME));
if (!e) return 1;
e->db= (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name= e->db + (dot - table_spec) + 1;
@@ -483,8 +484,9 @@ Rpl_filter::add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
const char* dot = strchr(table_spec, '.');
if (!dot) return 1;
uint len = (uint)strlen(table_spec);
- TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
- + len, MYF(MY_WME));
+ TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(key_memory_TABLE_RULE_ENT,
+ sizeof(TABLE_RULE_ENT) + len,
+ MYF(MY_WME));
if (!e) return 1;
e->db= (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name= e->db + (dot - table_spec) + 1;
@@ -500,7 +502,7 @@ Rpl_filter::add_string_list(I_List<i_string> *list, const char* spec)
char *str;
i_string *node;
- if (! (str= my_strdup(spec, MYF(MY_WME))))
+ if (! (str= my_strdup(key_memory_rpl_filter, spec, MYF(MY_WME))))
return true;
if (! (node= new i_string(str)))
@@ -571,8 +573,9 @@ void free_table_ent(void* a)
void
Rpl_filter::init_table_rule_hash(HASH* h, bool* h_inited)
{
- my_hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
- get_table_key, free_table_ent, 0);
+ my_hash_init(key_memory_TABLE_RULE_ENT, h,
+ system_charset_info,TABLE_RULE_HASH_SIZE,0,0, get_table_key,
+ free_table_ent, 0);
*h_inited = 1;
}
@@ -580,8 +583,8 @@ Rpl_filter::init_table_rule_hash(HASH* h, bool* h_inited)
void
Rpl_filter::init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
{
- my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE,
- TABLE_RULE_ARR_SIZE, MYF(0));
+ my_init_dynamic_array(key_memory_TABLE_RULE_ENT, a, sizeof(TABLE_RULE_ENT*),
+ TABLE_RULE_ARR_SIZE, TABLE_RULE_ARR_SIZE, MYF(0));
*a_inited = 1;
}
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 599129b98f4..bc87441d183 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -248,9 +248,10 @@ rpl_slave_state::rpl_slave_state()
{
mysql_mutex_init(key_LOCK_slave_state, &LOCK_slave_state,
MY_MUTEX_INIT_SLOW);
- my_hash_init(&hash, &my_charset_bin, 32, offsetof(element, domain_id),
+ my_hash_init(PSI_INSTRUMENT_ME, &hash, &my_charset_bin, 32, offsetof(element, domain_id),
sizeof(uint32), NULL, rpl_slave_state_free_element, HASH_UNIQUE);
- my_init_dynamic_array(&gtid_sort_array, sizeof(rpl_gtid), 8, 8, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &gtid_sort_array, sizeof(rpl_gtid),
+ 8, 8, MYF(0));
}
@@ -333,7 +334,8 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id,
rgi->gtid_ignore_duplicate_state= rpl_group_info::GTID_DUPLICATE_NULL;
}
- if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME))))
+ if (!(list_elem= (list_element *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(*list_elem), MYF(MY_WME))))
return 1;
list_elem->domain_id= domain_id;
list_elem->server_id= server_id;
@@ -367,7 +369,7 @@ rpl_slave_state::get_element(uint32 domain_id)
if (elem)
return elem;
- if (!(elem= (element *)my_malloc(sizeof(*elem), MYF(MY_WME))))
+ if (!(elem= (element *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*elem), MYF(MY_WME))))
return NULL;
elem->list= NULL;
elem->domain_id= domain_id;
@@ -1111,8 +1113,9 @@ rpl_slave_state::iterate(int (*cb)(rpl_gtid *, void *), void *data,
int res= 1;
bool locked= false;
- my_hash_init(&gtid_hash, &my_charset_bin, 32, offsetof(rpl_gtid, domain_id),
- sizeof(uint32), NULL, NULL, HASH_UNIQUE);
+ my_hash_init(PSI_INSTRUMENT_ME, &gtid_hash, &my_charset_bin, 32,
+ offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, NULL,
+ HASH_UNIQUE);
for (i= 0; i < num_extra; ++i)
if (extra_gtids[i].server_id == global_system_variables.server_id &&
my_hash_insert(&gtid_hash, (uchar *)(&extra_gtids[i])))
@@ -1329,7 +1332,7 @@ gtid_parse_string_to_list(const char *str, size_t str_len, uint32 *out_len)
}
if ((!list || len >= alloc_len) &&
!(list=
- (rpl_gtid *)my_realloc(list,
+ (rpl_gtid *)my_realloc(PSI_INSTRUMENT_ME, list,
(alloc_len= alloc_len*2) * sizeof(rpl_gtid),
MYF(MY_FREE_ON_ERROR|MY_ALLOW_ZERO_PTR))))
return NULL;
@@ -1466,10 +1469,8 @@ rpl_slave_state::alloc_gtid_pos_table(LEX_CSTRING *table_name, void *hton,
struct gtid_pos_table *p;
char *allocated_str;
- if (!my_multi_malloc(MYF(MY_WME),
- &p, sizeof(*p),
- &allocated_str, table_name->length+1,
- NULL))
+ if (!my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME), &p, sizeof(*p),
+ &allocated_str, table_name->length+1, NULL))
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)(sizeof(*p) + table_name->length+1));
return NULL;
@@ -1486,9 +1487,9 @@ rpl_slave_state::alloc_gtid_pos_table(LEX_CSTRING *table_name, void *hton,
void rpl_binlog_state::init()
{
- my_hash_init(&hash, &my_charset_bin, 32, offsetof(element, domain_id),
+ my_hash_init(PSI_INSTRUMENT_ME, &hash, &my_charset_bin, 32, offsetof(element, domain_id),
sizeof(uint32), NULL, my_free, HASH_UNIQUE);
- my_init_dynamic_array(&gtid_sort_array, sizeof(rpl_gtid), 8, 8, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &gtid_sort_array, sizeof(rpl_gtid), 8, 8, MYF(0));
mysql_mutex_init(key_LOCK_binlog_state, &LOCK_binlog_state,
MY_MUTEX_INIT_SLOW);
initialized= 1;
@@ -1685,7 +1686,8 @@ rpl_binlog_state::element::update_element(const rpl_gtid *gtid)
}
/* Allocate a new GTID and insert it. */
- lookup_gtid= (rpl_gtid *)my_malloc(sizeof(*lookup_gtid), MYF(MY_WME));
+ lookup_gtid= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*lookup_gtid),
+ MYF(MY_WME));
if (!lookup_gtid)
return 1;
memcpy(lookup_gtid, gtid, sizeof(*lookup_gtid));
@@ -1706,12 +1708,13 @@ rpl_binlog_state::alloc_element_nolock(const rpl_gtid *gtid)
rpl_gtid *lookup_gtid;
/* First time we see this domain_id; allocate a new element. */
- elem= (element *)my_malloc(sizeof(*elem), MYF(MY_WME));
- lookup_gtid= (rpl_gtid *)my_malloc(sizeof(*lookup_gtid), MYF(MY_WME));
+ elem= (element *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*elem), MYF(MY_WME));
+ lookup_gtid= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*lookup_gtid),
+ MYF(MY_WME));
if (elem && lookup_gtid)
{
elem->domain_id= gtid->domain_id;
- my_hash_init(&elem->hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &elem->hash, &my_charset_bin, 32,
offsetof(rpl_gtid, server_id), sizeof(uint32), NULL, my_free,
HASH_UNIQUE);
elem->last_gtid= lookup_gtid;
@@ -1784,14 +1787,15 @@ rpl_binlog_state::bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no)
}
/* We need to allocate a new, empty element to remember the next seq_no. */
- if (!(elem= (element *)my_malloc(sizeof(*elem), MYF(MY_WME))))
+ if (!(elem= (element *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*elem),
+ MYF(MY_WME))))
{
res= 1;
goto end;
}
elem->domain_id= domain_id;
- my_hash_init(&elem->hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &elem->hash, &my_charset_bin, 32,
offsetof(rpl_gtid, server_id), sizeof(uint32), NULL, my_free,
HASH_UNIQUE);
elem->last_gtid= NULL;
@@ -2006,8 +2010,8 @@ rpl_binlog_state::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size)
out_size= 0;
mysql_mutex_lock(&LOCK_binlog_state);
alloc_size= hash.records;
- if (!(*list= (rpl_gtid *)my_malloc(alloc_size * sizeof(rpl_gtid),
- MYF(MY_WME))))
+ if (!(*list= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ alloc_size * sizeof(rpl_gtid), MYF(MY_WME))))
{
res= 1;
goto end;
@@ -2122,7 +2126,7 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids,
DBUG_ENTER("rpl_binlog_state::drop_domain");
- my_init_dynamic_array2(&domain_unique,
+ my_init_dynamic_array2(PSI_INSTRUMENT_ME, &domain_unique,
sizeof(element*), domain_unique_buffer,
sizeof(domain_unique_buffer) / sizeof(element*), 4, 0);
@@ -2247,10 +2251,10 @@ end:
slave_connection_state::slave_connection_state()
{
- my_hash_init(&hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &hash, &my_charset_bin, 32,
offsetof(entry, gtid) + offsetof(rpl_gtid, domain_id),
sizeof(uint32), NULL, my_free, HASH_UNIQUE);
- my_init_dynamic_array(&gtid_sort_array, sizeof(rpl_gtid), 8, 8, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &gtid_sort_array, sizeof(rpl_gtid), 8, 8, MYF(0));
}
@@ -2294,7 +2298,7 @@ slave_connection_state::load(const char *slave_request, size_t len)
return 0;
for (;;)
{
- if (!(rec= (uchar *)my_malloc(sizeof(entry), MYF(MY_WME))))
+ if (!(rec= (uchar *)my_malloc(PSI_INSTRUMENT_ME, sizeof(entry), MYF(MY_WME))))
return 1;
gtid= &((entry *)rec)->gtid;
if (gtid_parser_helper(&p, end, gtid))
@@ -2397,7 +2401,7 @@ slave_connection_state::update(const rpl_gtid *in_gtid)
return 0;
}
- if (!(e= (entry *)my_malloc(sizeof(*e), MYF(MY_WME))))
+ if (!(e= (entry *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*e), MYF(MY_WME))))
return 1;
e->gtid= *in_gtid;
e->flags= 0;
@@ -2873,7 +2877,7 @@ free_hash_element(void *p)
void
gtid_waiting::init()
{
- my_hash_init(&hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &hash, &my_charset_bin, 32,
offsetof(hash_element, domain_id), sizeof(uint32), NULL,
free_hash_element, HASH_UNIQUE);
mysql_mutex_init(key_LOCK_gtid_waiting, &LOCK_gtid_waiting, 0);
@@ -2910,7 +2914,7 @@ gtid_waiting::get_entry(uint32 domain_id)
if ((e= (hash_element *)my_hash_search(&hash, (const uchar *)&domain_id, 0)))
return e;
- if (!(e= (hash_element *)my_malloc(sizeof(*e), MYF(MY_WME))))
+ if (!(e= (hash_element *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*e), MYF(MY_WME))))
return NULL;
if (init_queue(&e->queue, 8, offsetof(queue_element, wait_seq_no), 0,
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index 167d7461a7e..523af4856ae 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -27,6 +27,8 @@ extern const LEX_CSTRING rpl_gtid_slave_state_table_name;
class String;
+#define GTID_MAX_STR_LENGTH (10+1+10+1+20)
+
struct rpl_gtid
{
uint32 domain_id;
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index 597a357e4e2..b0b6e30bed6 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -37,7 +37,8 @@ injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
LOG_INFO log_info;
log->get_current_log(&log_info);
/* !!! binlog_pos does not follow RAII !!! */
- m_start_pos.m_file_name= my_strdup(log_info.log_file_name, MYF(0));
+ m_start_pos.m_file_name= my_strdup(key_memory_binlog_pos,
+ log_info.log_file_name, MYF(0));
m_start_pos.m_file_pos= log_info.pos;
m_thd->lex->start_transaction_opt= 0; /* for begin_trans() */
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 43a02147496..0649a8f05e8 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -58,7 +58,7 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg,
connection_name.length= cmp_connection_name.length=
connection_name_arg->length;
if ((connection_name.str= tmp= (char*)
- my_malloc(connection_name_arg->length*2+2, MYF(MY_WME))))
+ my_malloc(PSI_INSTRUMENT_ME, connection_name_arg->length*2+2, MYF(MY_WME))))
{
strmake(tmp, connection_name_arg->str, connection_name.length);
tmp+= connection_name_arg->length+1;
@@ -77,7 +77,7 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg,
parallel_mode= rpl_filter->get_parallel_mode();
- my_init_dynamic_array(&ignore_server_ids,
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &ignore_server_ids,
sizeof(global_system_variables.server_id), 16, 16,
MYF(0));
bzero((char*) &file, sizeof(file));
@@ -742,7 +742,8 @@ int flush_master_info(Master_info* mi,
char* ignore_server_ids_buf;
{
ignore_server_ids_buf=
- (char *) my_malloc((sizeof(global_system_variables.server_id) * 3 + 1) *
+ (char *) my_malloc(PSI_INSTRUMENT_ME,
+ (sizeof(global_system_variables.server_id) * 3 + 1) *
(1 + mi->ignore_server_ids.elements), MYF(MY_WME));
if (!ignore_server_ids_buf)
DBUG_RETURN(1); /* error */
@@ -1098,7 +1099,7 @@ bool Master_info_index::init_all_master_info()
}
/* Initialize Master_info Hash Table */
- if (my_hash_init(&master_info_hash, system_charset_info,
+ if (my_hash_init(PSI_INSTRUMENT_ME, &master_info_hash, system_charset_info,
MAX_REPLICATION_THREAD, 0, 0,
(my_hash_get_key) get_key_master_info,
(my_hash_free_key)free_key_master_info, HASH_UNIQUE))
@@ -1570,6 +1571,8 @@ uint any_slave_sql_running(bool already_locked)
if (!already_locked)
mysql_mutex_lock(&LOCK_active_mi);
+ else
+ mysql_mutex_assert_owner(&LOCK_active_mi);
if (unlikely(abort_loop || !master_info_index))
count= 1;
else
@@ -1739,7 +1742,8 @@ Domain_id_filter::Domain_id_filter() : m_filter(false)
{
for (int i= DO_DOMAIN_IDS; i <= IGNORE_DOMAIN_IDS; i ++)
{
- my_init_dynamic_array(&m_domain_ids[i], sizeof(ulong), 16, 16, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &m_domain_ids[i], sizeof(ulong),
+ 16, 16, MYF(0));
}
}
@@ -1902,7 +1906,7 @@ char *Domain_id_filter::as_string(enum_list_type type)
sz= (sizeof(ulong) * 3 + 1) * (1 + ids->elements);
- if (!(buf= (char *) my_malloc(sz, MYF(MY_WME))))
+ if (!(buf= (char *) my_malloc(PSI_INSTRUMENT_ME, sz, MYF(MY_WME))))
return NULL;
// Store the total number of elements followed by the individual elements.
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 4313840119e..f875ab2b4a4 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -1557,7 +1557,7 @@ rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool,
to allocate, and will not be left with a half-functional thread pool.
*/
if (new_count &&
- !my_multi_malloc(MYF(MY_WME|MY_ZEROFILL),
+ !my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME|MY_ZEROFILL),
&new_list, new_count*sizeof(*new_list),
&rpt_array, new_count*sizeof(*rpt_array),
NULL))
@@ -1789,7 +1789,7 @@ rpl_parallel_thread::get_qev_common(Log_event *ev, ulonglong event_size)
mysql_mutex_assert_owner(&LOCK_rpl_thread);
if ((qev= qev_free_list))
qev_free_list= qev->next;
- else if(!(qev= (queued_event *)my_malloc(sizeof(*qev), MYF(0))))
+ else if(!(qev= (queued_event *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*qev), MYF(0))))
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*qev));
return NULL;
@@ -1952,7 +1952,7 @@ rpl_parallel_thread::get_gco(uint64 wait_count, group_commit_orderer *prev,
mysql_mutex_assert_owner(&LOCK_rpl_thread);
if ((gco= gco_free_list))
gco_free_list= gco->next_gco;
- else if(!(gco= (group_commit_orderer *)my_malloc(sizeof(*gco), MYF(0))))
+ else if(!(gco= (group_commit_orderer *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*gco), MYF(0))))
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*gco));
return NULL;
@@ -2199,7 +2199,7 @@ free_rpl_parallel_entry(void *element)
rpl_parallel::rpl_parallel() :
current(NULL), sql_thread_stopping(false)
{
- my_hash_init(&domain_hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &domain_hash, &my_charset_bin, 32,
offsetof(rpl_parallel_entry, domain_id), sizeof(uint32),
NULL, free_rpl_parallel_entry, HASH_UNIQUE);
}
@@ -2233,7 +2233,7 @@ rpl_parallel::find(uint32 domain_id)
if (count == 0 || count > opt_slave_parallel_threads)
count= opt_slave_parallel_threads;
rpl_parallel_thread **p;
- if (!my_multi_malloc(MYF(MY_WME|MY_ZEROFILL),
+ if (!my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME|MY_ZEROFILL),
&e, sizeof(*e),
&p, count*sizeof(*p),
NULL))
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 6d55b06b497..01093d9a6da 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -73,7 +73,9 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
key_RELAYLOG_COND_relay_log_updated,
key_RELAYLOG_COND_bin_log_updated,
key_file_relaylog,
+ key_file_relaylog_cache,
key_file_relaylog_index,
+ key_file_relaylog_index_cache,
key_RELAYLOG_COND_queue_busy,
key_LOCK_relaylog_end_pos);
#endif
@@ -1435,14 +1437,15 @@ Relay_log_info::alloc_inuse_relaylog(const char *name)
uint32 gtid_count;
rpl_gtid *gtid_list;
- if (!(ir= (inuse_relaylog *)my_malloc(sizeof(*ir), MYF(MY_WME|MY_ZEROFILL))))
+ if (!(ir= (inuse_relaylog *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*ir),
+ MYF(MY_WME|MY_ZEROFILL))))
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*ir));
return 1;
}
gtid_count= relay_log_state.count();
- if (!(gtid_list= (rpl_gtid *)my_malloc(sizeof(*gtid_list)*gtid_count,
- MYF(MY_WME))))
+ if (!(gtid_list= (rpl_gtid *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(*gtid_list)*gtid_count, MYF(MY_WME))))
{
my_free(ir);
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*gtid_list)*gtid_count);
@@ -1589,8 +1592,8 @@ scan_one_gtid_slave_pos_table(THD *thd, HASH *hash, DYNAMIC_ARRAY *array,
}
else
{
- if (!(entry= (struct gtid_pos_element *)my_malloc(sizeof(*entry),
- MYF(MY_WME))))
+ if (!(entry= (struct gtid_pos_element *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(*entry), MYF(MY_WME))))
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)sizeof(*entry));
err= 1;
@@ -1831,10 +1834,11 @@ rpl_load_gtid_slave_state(THD *thd)
cb_data.table_list= NULL;
cb_data.default_entry= NULL;
- my_hash_init(&hash, &my_charset_bin, 32,
+ my_hash_init(PSI_INSTRUMENT_ME, &hash, &my_charset_bin, 32,
offsetof(gtid_pos_element, gtid) + offsetof(rpl_gtid, domain_id),
sizeof(uint32), NULL, my_free, HASH_UNIQUE);
- if ((err= my_init_dynamic_array(&array, sizeof(gtid_pos_element), 0, 0, MYF(0))))
+ if ((err= my_init_dynamic_array(PSI_INSTRUMENT_ME, &array,
+ sizeof(gtid_pos_element), 0, 0, MYF(0))))
goto end;
array_inited= true;
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
index b2da9092e3a..a230b9f6f29 100644
--- a/sql/rpl_tblmap.cc
+++ b/sql/rpl_tblmap.cc
@@ -34,6 +34,12 @@
table_mapping::table_mapping()
: m_free(0)
{
+#ifdef MYSQL_CLIENT
+ PSI_memory_key psi_key= PSI_NOT_INSTRUMENTED;
+#else
+ PSI_memory_key psi_key= key_memory_table_mapping_root;
+#endif
+
DBUG_ENTER("table_mapping::table_mapping");
/*
No "free_element" function for entries passed here, as the entries are
@@ -42,12 +48,11 @@ table_mapping::table_mapping()
Note that below we don't test if my_hash_init() succeeded. This
constructor is called at startup only.
*/
- (void) my_hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
+ (void) my_hash_init(psi_key, &m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
offsetof(entry,table_id),sizeof(ulonglong),
- 0,0,0);
+ 0,0,0);
/* We don't preallocate any block, this is consistent with m_free=0 above */
- init_alloc_root(&m_mem_root, "table_mapping",
- TABLE_ID_HASH_SIZE*sizeof(entry), 0, MYF(0));
+ init_alloc_root(psi_key, &m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0, MYF(0));
DBUG_VOID_RETURN;
}
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index 1e4b59844b8..7c347eba51f 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -171,6 +171,7 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const
return length;
}
+PSI_memory_key key_memory_table_def_memory;
table_def::table_def(unsigned char *types, ulong size,
uchar *field_metadata, int metadata_size,
@@ -179,7 +180,7 @@ table_def::table_def(unsigned char *types, ulong size,
m_field_metadata(0), m_null_bits(0), m_flags(flags),
m_memory(NULL)
{
- m_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
+ m_memory= (uchar *)my_multi_malloc(key_memory_table_def_memory, MYF(MY_WME),
&m_type, size,
&m_field_metadata,
size * sizeof(uint16),
diff --git a/sql/rpl_utility_server.cc b/sql/rpl_utility_server.cc
index e58c9cf018e..8110b142e74 100644
--- a/sql/rpl_utility_server.cc
+++ b/sql/rpl_utility_server.cc
@@ -1123,7 +1123,7 @@ err:
Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL)
{
- my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &array, sizeof(Log_event *), 32, 16, MYF(0));
}
Deferred_log_events::~Deferred_log_events()
diff --git a/sql/scheduler.h b/sql/scheduler.h
index 676262f6454..ebf8d6e9e64 100644
--- a/sql/scheduler.h
+++ b/sql/scheduler.h
@@ -82,17 +82,6 @@ extern void post_kill_notification(THD *);
struct thd_scheduler
{
public:
- /*
- Thread instrumentation for the user job.
- This member holds the instrumentation while the user job is not run
- by a thread.
-
- Note that this member is not conditionally declared
- (ifdef HAVE_PSI_INTERFACE), because doing so will change the binary
- layout of THD, which is exposed to plugin code that may be compiled
- differently.
- */
- PSI_thread *m_psi;
void *data; /* scheduler-specific data structure */
};
diff --git a/sql/select_handler.cc b/sql/select_handler.cc
index c8f92461fd0..4d2cacd1a6e 100644
--- a/sql/select_handler.cc
+++ b/sql/select_handler.cc
@@ -77,18 +77,17 @@ bool Pushdown_select::init()
bool Pushdown_select::send_result_set_metadata()
{
- THD *thd= handler->thd;
- Protocol *protocol= thd->protocol;
DBUG_ENTER("Pushdown_select::send_result_set_metadata");
#ifdef WITH_WSREP
+ THD *thd= handler->thd;
if (WSREP(thd) && thd->wsrep_retry_query)
{
WSREP_DEBUG("skipping select metadata");
DBUG_RETURN(false);
}
#endif /* WITH_WSREP */
- if (protocol->send_result_set_metadata(&result_columns,
+ if (select->join->result->send_result_set_metadata(result_columns,
Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
DBUG_RETURN(true);
@@ -99,21 +98,10 @@ bool Pushdown_select::send_result_set_metadata()
bool Pushdown_select::send_data()
{
- THD *thd= handler->thd;
- Protocol *protocol= thd->protocol;
DBUG_ENTER("Pushdown_select::send_data");
- protocol->prepare_for_resend();
- if (protocol->send_result_set_row(&result_columns))
- {
- protocol->remove_last_row();
+ if (select->join->result->send_data(result_columns))
DBUG_RETURN(true);
- }
-
- thd->inc_sent_row_count(1);
-
- if (thd->vio_ok())
- DBUG_RETURN(protocol->write());
DBUG_RETURN(false);
}
@@ -121,16 +109,10 @@ bool Pushdown_select::send_data()
bool Pushdown_select::send_eof()
{
- THD *thd= handler->thd;
DBUG_ENTER("Pushdown_select::send_eof");
- /*
- Don't send EOF if we're in error condition (which implies we've already
- sent or are sending an error)
- */
- if (thd->is_error())
+ if (select->join->result->send_eof())
DBUG_RETURN(true);
- ::my_eof(thd);
DBUG_RETURN(false);
}
diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc
index b239a9776a7..79634d142eb 100644
--- a/sql/semisync_master.cc
+++ b/sql/semisync_master.cc
@@ -724,8 +724,8 @@ int Repl_semi_sync_master::report_binlog_update(THD* thd, const char *log_file,
if (!(log_info= thd->semisync_info))
{
- if(!(log_info=
- (Trans_binlog_info*) my_malloc(sizeof(Trans_binlog_info), MYF(0))))
+ if(!(log_info= (Trans_binlog_info*)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(Trans_binlog_info), MYF(0))))
return 1;
thd->semisync_info= log_info;
}
diff --git a/sql/semisync_master.h b/sql/semisync_master.h
index 74f6c24c8ea..9f0acf57a60 100644
--- a/sql/semisync_master.h
+++ b/sql/semisync_master.h
@@ -231,7 +231,7 @@ private:
*/
int allocate_block()
{
- Block *block= (Block *)my_malloc(sizeof(Block), MYF(0));
+ Block *block= (Block *)my_malloc(PSI_INSTRUMENT_ME, sizeof(Block), MYF(0));
if (block)
{
block->next= NULL;
diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc
index e189fc5f631..6340b4bd661 100644
--- a/sql/semisync_master_ack_receiver.cc
+++ b/sql/semisync_master_ack_receiver.cc
@@ -164,7 +164,7 @@ void Ack_receiver::remove_slave(THD *thd)
inline void Ack_receiver::set_stage_info(const PSI_stage_info &stage)
{
- MYSQL_SET_STAGE(stage.m_key, __FILE__, __LINE__);
+ (void)MYSQL_SET_STAGE(stage.m_key, __FILE__, __LINE__);
}
inline void Ack_receiver::wait_for_slave_connection()
diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc
index 33ee6141658..e1c2ec37644 100644
--- a/sql/session_tracker.cc
+++ b/sql/session_tracker.cc
@@ -72,7 +72,8 @@ void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd)
bool Session_sysvars_tracker::vars_list::insert(const sys_var *svar)
{
sysvar_node_st *node;
- if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st),
+ if (!(node= (sysvar_node_st *) my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(sysvar_node_st),
MYF(MY_WME |
(mysqld_server_initialized ?
MY_THREAD_SPECIFIC : 0)))))
@@ -326,7 +327,8 @@ void Session_sysvars_tracker::init(THD *thd)
global_system_variables.session_track_system_variables);
DBUG_ASSERT(global_system_variables.session_track_system_variables);
thd->variables.session_track_system_variables=
- my_strdup(global_system_variables.session_track_system_variables,
+ my_strdup(PSI_INSTRUMENT_ME,
+ global_system_variables.session_track_system_variables,
MYF(MY_WME | MY_THREAD_SPECIFIC));
}
@@ -383,11 +385,11 @@ bool Session_sysvars_tracker::update(THD *thd, set_var *var)
size_t length= 1;
if (var->save_result.string_value.str)
- copy= my_memdup(var->save_result.string_value.str,
+ copy= my_memdup(PSI_INSTRUMENT_ME, var->save_result.string_value.str,
(length= var->save_result.string_value.length + 1),
MYF(MY_WME | MY_THREAD_SPECIFIC));
else
- copy= my_strdup("", MYF(MY_WME | MY_THREAD_SPECIFIC));
+ copy= my_strdup(PSI_INSTRUMENT_ME, "", MYF(MY_WME | MY_THREAD_SPECIFIC));
if (!copy)
return true;
diff --git a/sql/session_tracker.h b/sql/session_tracker.h
index b91e588a34e..7db1feb1b1a 100644
--- a/sql/session_tracker.h
+++ b/sql/session_tracker.h
@@ -142,10 +142,9 @@ class Session_sysvars_tracker: public State_tracker
bool track_all;
void init()
{
- my_hash_init(&m_registered_sysvars, &my_charset_bin, 0, 0, 0,
- (my_hash_get_key) sysvars_get_key, my_free,
- HASH_UNIQUE | (mysqld_server_initialized ?
- HASH_THREAD_SPECIFIC : 0));
+ my_hash_init(PSI_INSTRUMENT_ME, &m_registered_sysvars, &my_charset_bin,
+ 0, 0, 0, (my_hash_get_key) sysvars_get_key, my_free,
+ HASH_UNIQUE | (mysqld_server_initialized ? HASH_THREAD_SPECIFIC : 0));
}
void free_hash()
{
@@ -401,10 +400,9 @@ class User_variables_tracker: public State_tracker
Hash_set<const user_var_entry> m_changed_user_variables;
public:
User_variables_tracker():
- m_changed_user_variables(&my_charset_bin, 0, 0,
- sizeof(const user_var_entry*), 0, 0,
- HASH_UNIQUE | (mysqld_server_initialized ?
- HASH_THREAD_SPECIFIC : 0)) {}
+ m_changed_user_variables(PSI_INSTRUMENT_ME, &my_charset_bin, 0, 0,
+ sizeof(const user_var_entry*), 0, 0, HASH_UNIQUE |
+ mysqld_server_initialized ? HASH_THREAD_SPECIFIC : 0) {}
bool update(THD *thd, set_var *var);
bool store(THD *thd, String *buf);
void mark_as_changed(THD *thd, const user_var_entry *var)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index fac409f8ef9..551b92012d1 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -33,7 +33,6 @@
// date_time_format_make
#include "derror.h"
#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
-#include "sql_acl.h" // SUPER_ACL
#include "sql_select.h" // free_underlaid_joins
#include "sql_i_s.h"
#include "sql_view.h" // updatable_views_with_limit_typelib
@@ -43,6 +42,7 @@
static HASH system_variable_hash;
static PolyLock_mutex PLock_global_system_variables(&LOCK_global_system_variables);
+static ulonglong system_variable_hash_version= 0;
/**
Return variable name and length for hashing of variables.
@@ -64,7 +64,7 @@ int sys_var_init()
/* Must be already initialized. */
DBUG_ASSERT(system_charset_info != NULL);
- if (my_hash_init(&system_variable_hash, system_charset_info, 700, 0,
+ if (my_hash_init(PSI_INSTRUMENT_ME, &system_variable_hash, system_charset_info, 700, 0,
0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
goto error;
@@ -583,6 +583,8 @@ int mysql_add_sys_var_chain(sys_var *first)
goto error;
}
}
+ /* Update system_variable_hash version. */
+ system_variable_hash_version++;
return 0;
error:
@@ -613,6 +615,8 @@ int mysql_del_sys_var_chain(sys_var *first)
result|= my_hash_delete(&system_variable_hash, (uchar*) var);
mysql_prlock_unlock(&LOCK_system_variables_hash);
+ /* Update system_variable_hash version. */
+ system_variable_hash_version++;
return result;
}
@@ -623,6 +627,16 @@ static int show_cmp(SHOW_VAR *a, SHOW_VAR *b)
}
+/*
+ Number of records in the system_variable_hash.
+ Requires lock on LOCK_system_variables_hash.
+*/
+ulong get_system_variable_hash_records(void)
+{
+ return system_variable_hash.records;
+}
+
+
/**
Constructs an array of system variables for display to the user.
@@ -773,7 +787,8 @@ int set_var::check(THD *thd)
my_error(err, MYF(0), var->name.str);
return -1;
}
- if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
+ if (type == OPT_GLOBAL &&
+ check_global_access(thd, PRIV_SET_GLOBAL_SYSTEM_VARIABLE))
return 1;
/* value is a NULL pointer if we are using SET ... = DEFAULT */
if (!value)
@@ -810,7 +825,8 @@ int set_var::light_check(THD *thd)
my_error(err, MYF(0), var->name.str);
return -1;
}
- if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
+ if (type == OPT_GLOBAL &&
+ check_global_access(thd, PRIV_SET_GLOBAL_SYSTEM_VARIABLE))
return 1;
if (value && value->fix_fields_if_needed_for_scalar(thd, &value))
@@ -1377,7 +1393,7 @@ resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len,
if (temp_copy)
res= (plugin_ref *)thd->calloc((count+1)*sizeof(*res));
else
- res= (plugin_ref *)my_malloc((count+1)*sizeof(*res), MYF(MY_ZEROFILL|MY_WME));
+ res= (plugin_ref *)my_malloc(PSI_INSTRUMENT_ME, (count+1)*sizeof(*res), MYF(MY_ZEROFILL|MY_WME));
if (!res)
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*res)));
@@ -1428,7 +1444,7 @@ copy_engine_list(plugin_ref *list)
for (p= list, count= 0; *p; ++p, ++count)
;
- p= (plugin_ref *)my_malloc((count+1)*sizeof(*p), MYF(0));
+ p= (plugin_ref *)my_malloc(PSI_INSTRUMENT_ME, (count+1)*sizeof(*p), MYF(0));
if (!p)
{
my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*p)));
@@ -1503,3 +1519,13 @@ pretty_print_engine_list(THD *thd, plugin_ref *list)
*pos= '\0';
return buf;
}
+
+/*
+ Current version of the system_variable_hash.
+ Requires lock on LOCK_system_variables_hash.
+*/
+ulonglong get_system_variable_hash_version(void)
+{
+ return system_variable_hash_version;
+}
+
diff --git a/sql/set_var.h b/sql/set_var.h
index c4a29968818..075339c4f38 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -404,6 +404,8 @@ extern SHOW_COMP_OPTION have_openssl;
/*
Prototypes for helper functions
*/
+ulong get_system_variable_hash_records(void);
+ulonglong get_system_variable_hash_version(void);
SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type);
int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond);
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index aa740ba5248..afa9d72f2d8 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7944,6 +7944,9 @@ ER_WARN_HISTORY_ROW_START_TIME
ER_PART_STARTS_BEYOND_INTERVAL
eng "%`s: STARTS is later than query time, first history partition may exceed INTERVAL value"
ER_GALERA_REPLICATION_NOT_SUPPORTED
- eng "DDL-statement is forbidden as table storage engine does not support Galera replication"
+ eng "DDL-statement is forbidden as table storage engine does not support Galera replication"
+ER_LOAD_INFILE_CAPABILITY_DISABLED
+ eng "The used command is not allowed because the MariaDB server or client has disabled the local infile capability"
+ rum "Comanda folosită nu este permisă deoarece clientul sau serverul MariaDB a dezactivat această capabilitate"
ER_NO_SECURE_TRANSPORTS_CONFIGURED
eng "No secure transports are configured, unable to set --require_secure_transport=ON"
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 51b9d7a2c51..cbf58bb6e57 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -42,9 +42,6 @@
static volatile sig_atomic_t segfaulted= 0;
extern ulong max_used_connections;
extern volatile sig_atomic_t calling_initgroups;
-#ifdef HAVE_NPTL
-extern volatile sig_atomic_t ld_assume_kernel_is_set;
-#endif
extern const char *optimizer_switch_names[];
@@ -296,21 +293,6 @@ extern "C" sig_handler handle_fatal_signal(int sig)
}
#endif
-#ifdef HAVE_NPTL
- if (thd_lib_detected == THD_LIB_LT && !ld_assume_kernel_is_set)
- {
- my_safe_printf_stderr("%s",
- "You are running a statically-linked LinuxThreads binary on an NPTL\n"
- "system. This can result in crashes on some distributions due to "
- "LT/NPTL conflicts.\n"
- "You should either build a dynamically-linked binary, "
- "or force LinuxThreads\n"
- "to be used with the LD_ASSUME_KERNEL environment variable.\n"
- "Please consult the documentation for your distribution "
- "on how to do that.\n");
- }
-#endif
-
if (locked_in_memory)
{
my_safe_printf_stderr("%s", "\n"
diff --git a/sql/slave.cc b/sql/slave.cc
index 87c1cf6cb77..aba10b8bd6e 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -57,6 +57,9 @@
#include "wsrep_trans_observer.h"
#endif
+class Master_info_index;
+Master_info_index *master_info_index;
+
#ifdef HAVE_REPLICATION
#include "rpl_tblmap.h"
@@ -81,7 +84,6 @@ char slave_transaction_retry_error_names[SHOW_VAR_FUNC_BUFF_SIZE];
char* slave_load_tmpdir = 0;
Master_info *active_mi= 0;
-Master_info_index *master_info_index;
my_bool replicate_same_server_id;
ulonglong relay_log_space_limit = 0;
ulonglong opt_read_binlog_speed_limit = 0;
@@ -488,6 +490,7 @@ handle_slave_background(void *arg __attribute__((unused)))
#ifdef WITH_WSREP
thd->variables.wsrep_on= 0;
#endif
+ thd->set_psi(PSI_CALL_get_thread());
thd_proc_info(thd, "Loading slave GTID position from table");
if (rpl_load_gtid_slave_state(thd))
@@ -583,7 +586,7 @@ slave_background_kill_request(THD *to_kill)
if (to_kill->rgi_slave->killed_for_retry)
return; // Already deadlock killed.
slave_background_kill_t *p=
- (slave_background_kill_t *)my_malloc(sizeof(*p), MYF(MY_WME));
+ (slave_background_kill_t *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*p), MYF(MY_WME));
if (p)
{
p->to_kill= to_kill;
@@ -611,7 +614,7 @@ slave_background_gtid_pos_create_request(
if (table_entry->state != rpl_slave_state::GTID_POS_AUTO_CREATE)
return;
- p= (slave_background_gtid_pos_create_t *)my_malloc(sizeof(*p), MYF(MY_WME));
+ p= (slave_background_gtid_pos_create_t *)my_malloc(PSI_INSTRUMENT_ME, sizeof(*p), MYF(MY_WME));
if (!p)
return;
mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state);
@@ -1662,7 +1665,7 @@ bool Sql_cmd_show_slave_status::execute(THD *thd)
bool res= true;
/* Accept one of two privileges */
- if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_SLAVE_STATUS))
goto error;
if (is_show_all_slaves_stat())
{
@@ -1809,7 +1812,8 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f)
(decimal size + space) - 1 + `\n' + '\0'
*/
size_t max_size= (1 + num_items) * (sizeof(long)*3 + 1) + 1;
- buf_act= (char*) my_malloc(max_size, MYF(MY_WME));
+ buf_act= (char*) my_malloc(key_memory_Rpl_info_file_buffer, max_size,
+ MYF(MY_WME));
memcpy(buf_act, buf, read_size);
snd_size= my_b_gets(f, buf_act + read_size, max_size - read_size);
if (snd_size == 0 ||
@@ -4727,6 +4731,8 @@ pthread_handler_t handle_slave_io(void *arg)
THD_CHECK_SENTRY(thd);
mi->io_thd = thd;
+ thd->set_psi(PSI_CALL_get_thread());
+
pthread_detach_this_thread();
thd->thread_stack= (char*) &thd; // remember where our stack is
mi->clear_error();
@@ -5365,6 +5371,8 @@ pthread_handler_t handle_slave_sql(void *arg)
executing SQL queries too.
*/
serial_rgi->thd= rli->sql_driver_thd= thd;
+
+ thd->set_psi(PSI_CALL_get_thread());
/* Inform waiting threads that slave has started */
rli->slave_run_id++;
@@ -6035,7 +6043,8 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf,
*/
if ((uchar)buf[EVENT_TYPE_OFFSET] == LOAD_EVENT)
{
- if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
+ if (unlikely(!(tmp_buf=(char*)my_malloc(key_memory_binlog_ver_1_event,
+ event_len+1,MYF(MY_WME)))))
{
mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL,
ER(ER_SLAVE_FATAL_ERROR), "Memory allocation failed");
diff --git a/sql/sp.cc b/sql/sp.cc
index ae413fcf615..157ddeb63c6 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -28,12 +28,12 @@
// mysql_change_db, check_db_dir_existence,
// load_db_opt_by_name
#include "sql_table.h" // write_bin_log
-#include "sql_acl.h" // SUPER_ACL
#include "sp_head.h"
#include "sp_cache.h"
#include "lock.h" // lock_object_name
#include <my_user.h>
+#include "mysql/psi/mysql_sp.h"
sp_cache **Sp_handler_procedure::get_cache(THD *thd) const
{
@@ -718,7 +718,7 @@ Sp_handler::db_find_routine(THD *thd,
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root,
&params);
- if (type() != TYPE_ENUM_FUNCTION)
+ if (type() != SP_TYPE_FUNCTION)
returns= empty_clex_str;
else if (table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
&returns))
@@ -866,6 +866,8 @@ static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode,
thd->spcont= old_spcont;
thd->variables.sql_mode= old_sql_mode;
thd->variables.select_limit= old_select_limit;
+ if (sp != NULL)
+ sp->init_psi_share();
return sp;
}
@@ -1001,7 +1003,7 @@ Sp_handler::db_load_routine(THD *thd, const Database_qualified_name *name,
(*sphp)->set_creation_ctx(creation_ctx);
(*sphp)->optimize();
- if (type() == TYPE_ENUM_PACKAGE_BODY)
+ if (type() == SP_TYPE_PACKAGE_BODY)
{
sp_package *package= (*sphp)->get_package();
List_iterator<LEX> it(package->m_routine_implementations);
@@ -1104,6 +1106,9 @@ Sp_handler::sp_drop_routine_internal(THD *thd,
DBUG_ASSERT(spc);
if ((sp= sp_cache_lookup(spc, name)))
sp_cache_flush_obsolete(spc, &sp);
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(type(), name->m_db.str, static_cast<uint>(name->m_db.length),
+ name->m_name.str, static_cast<uint>(name->m_name.length));
DBUG_RETURN(SP_OK);
}
@@ -1231,17 +1236,17 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
if (lex->create_info.or_replace())
{
switch (type()) {
- case TYPE_ENUM_PACKAGE:
+ case SP_TYPE_PACKAGE:
// Drop together with its PACKAGE BODY mysql.proc record
ret= sp_handler_package_spec.sp_find_and_drop_routine(thd, table, sp);
break;
- case TYPE_ENUM_PACKAGE_BODY:
- case TYPE_ENUM_FUNCTION:
- case TYPE_ENUM_PROCEDURE:
+ case SP_TYPE_PACKAGE_BODY:
+ case SP_TYPE_FUNCTION:
+ case SP_TYPE_PROCEDURE:
ret= sp_drop_routine_internal(thd, sp, table);
break;
- case TYPE_ENUM_TRIGGER:
- case TYPE_ENUM_PROXY:
+ case SP_TYPE_TRIGGER:
+ case SP_TYPE_EVENT:
DBUG_ASSERT(0);
ret= SP_OK;
}
@@ -1258,7 +1263,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
ret= FALSE;
// Setting retstr as it is used for logging.
- if (type() == TYPE_ENUM_FUNCTION)
+ if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@@ -1341,7 +1346,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params, system_charset_info);
- if (type() == TYPE_ENUM_FUNCTION)
+ if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@@ -1373,7 +1378,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
store(sp->comment(), system_charset_info);
}
- if (type() == TYPE_ENUM_FUNCTION &&
+ if (type() == SP_TYPE_FUNCTION &&
!trust_function_creators && mysql_bin_log.is_open())
{
if (!sp->detistic())
@@ -1392,7 +1397,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const
goto done;
}
}
- if (!(thd->security_ctx->master_access & SUPER_ACL))
+ if (!(thd->security_ctx->master_access & PRIV_LOG_BIN_TRUSTED_SP_CREATOR))
{
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,MYF(0));
goto done;
@@ -1625,7 +1630,7 @@ Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name,
if ((ret= db_find_routine_aux(thd, name, table)) == SP_OK)
{
- if (type() == TYPE_ENUM_FUNCTION && ! trust_function_creators &&
+ if (type() == SP_TYPE_FUNCTION && ! trust_function_creators &&
mysql_bin_log.is_open() &&
(chistics->daccess == SP_CONTAINS_SQL ||
chistics->daccess == SP_MODIFIES_SQL_DATA))
@@ -1771,11 +1776,11 @@ bool lock_db_routines(THD *thd, const char *db)
longlong sp_type= table->field[MYSQL_PROC_MYSQL_TYPE]->val_int();
MDL_request *mdl_request= new (thd->mem_root) MDL_request;
- const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
+ const Sp_handler *sph= Sp_handler::handler((enum_sp_type)
sp_type);
if (!sph)
sph= &sp_handler_procedure;
- mdl_request->init(sph->get_mdl_type(), db, sp_name,
+ MDL_REQUEST_INIT(mdl_request, sph->get_mdl_type(), db, sp_name,
MDL_EXCLUSIVE, MDL_TRANSACTION);
mdl_requests.push_front(mdl_request);
} while (! (nxtres= table->file->ha_index_next_same(table->record[0], keybuf, key_len)));
@@ -1814,6 +1819,8 @@ sp_drop_db_routines(THD *thd, const char *db)
uint key_len;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
uchar keybuf[MAX_KEY_LENGTH];
+ size_t db_length= strlen(db);
+ Sql_mode_instant_remove smir(thd, MODE_PAD_CHAR_TO_FULL_LENGTH); // see below
DBUG_ENTER("sp_drop_db_routines");
DBUG_PRINT("enter", ("db: %s", db));
@@ -1821,7 +1828,7 @@ sp_drop_db_routines(THD *thd, const char *db)
if (!(table= open_proc_table_for_update(thd)))
goto err;
- table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info);
+ table->field[MYSQL_PROC_FIELD_DB]->store(db, db_length, system_charset_info);
key_len= table->key_info->key_part[0].store_length;
table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW);
@@ -1840,7 +1847,18 @@ sp_drop_db_routines(THD *thd, const char *db)
do
{
if (! table->file->ha_delete_row(table->record[0]))
+ {
deleted= TRUE; /* We deleted something */
+#ifdef HAVE_PSI_SP_INTERFACE
+ String buf;
+ // the following assumes MODE_PAD_CHAR_TO_FULL_LENGTH being *unset*
+ String *name= table->field[MYSQL_PROC_FIELD_NAME]->val_str(&buf);
+
+ enum_sp_type sp_type= (enum_sp_type) table->field[MYSQL_PROC_MYSQL_TYPE]->ptr[0];
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(sp_type, db, static_cast<uint>(db_length), name->ptr(), name->length());
+#endif
+ }
else
{
ret= SP_DELETE_ROW_FAILED;
@@ -2014,7 +2032,7 @@ Sp_handler::sp_clone_and_link_routine(THD *thd,
DBUG_RETURN(0);
}
- if (type() == TYPE_ENUM_FUNCTION)
+ if (type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
@@ -2282,7 +2300,7 @@ bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
const Sp_handler *handler,
TABLE_LIST *belong_to_view)
{
- my_hash_init_opt(&prelocking_ctx->sroutines, system_charset_info,
+ my_hash_init_opt(PSI_INSTRUMENT_ME, &prelocking_ctx->sroutines, system_charset_info,
Query_tables_list::START_SROUTINES_HASH_SIZE,
0, 0, sp_sroutine_key, 0, 0);
@@ -2292,7 +2310,7 @@ bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
(Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry));
if (unlikely(!rn)) // OOM. Error will be reported using fatal_error().
return FALSE;
- rn->mdl_request.init(key, MDL_SHARED, MDL_TRANSACTION);
+ MDL_REQUEST_INIT_BY_KEY(&rn->mdl_request, key, MDL_SHARED, MDL_TRANSACTION);
if (my_hash_insert(&prelocking_ctx->sroutines, (uchar *)rn))
return FALSE;
prelocking_ctx->sroutines_list.link_in_list(rn, &rn->next);
@@ -2362,7 +2380,7 @@ is_package_public_routine(THD *thd,
const LEX_CSTRING &db,
const LEX_CSTRING &package,
const LEX_CSTRING &routine,
- stored_procedure_type type)
+ enum_sp_type type)
{
sp_head *sp= NULL;
Database_qualified_name tmp(db, package);
@@ -2396,7 +2414,7 @@ is_package_public_routine_quick(THD *thd,
const LEX_CSTRING &db,
const LEX_CSTRING &pkgname,
const LEX_CSTRING &name,
- stored_procedure_type type)
+ enum_sp_type type)
{
Database_qualified_name tmp(db, pkgname);
sp_head *sp= sp_cache_lookup(&thd->sp_package_spec_cache, &tmp);
@@ -2415,7 +2433,7 @@ static bool
is_package_body_routine(THD *thd, sp_package *pkg,
const LEX_CSTRING &name1,
const LEX_CSTRING &name2,
- stored_procedure_type type)
+ enum_sp_type type)
{
return Sp_handler::eq_routine_name(pkg->m_name, name1) &&
(pkg->m_routine_declarations.find(name2, type) ||
@@ -2843,7 +2861,7 @@ Sp_handler::sp_cache_package_routine(THD *thd,
bool lookup_only, sp_head **sp) const
{
DBUG_ENTER("sp_cache_package_routine");
- DBUG_ASSERT(type() == TYPE_ENUM_FUNCTION || type() == TYPE_ENUM_PROCEDURE);
+ DBUG_ASSERT(type() == SP_TYPE_FUNCTION || type() == SP_TYPE_PROCEDURE);
sp_name pkgname(&name->m_db, &pkgname_cstr, false);
sp_head *ph= NULL;
int ret= sp_handler_package_body.sp_cache_routine(thd, &pkgname,
@@ -2942,7 +2960,7 @@ Sp_handler::show_create_sp(THD *thd, String *buf,
buf->append('(');
buf->append(&params);
buf->append(')');
- if (type() == TYPE_ENUM_FUNCTION)
+ if (type() == SP_TYPE_FUNCTION)
{
if (sql_mode & MODE_ORACLE)
buf->append(STRING_WITH_LEN(" RETURN "));
diff --git a/sql/sp.h b/sql/sp.h
index 69dde53b34c..72485632261 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -47,18 +47,18 @@ template <typename T> class SQL_I_List;
/*
Values for the type enum. This reflects the order of the enum declaration
in the CREATE TABLE command.
+ See also storage/perfschema/my_thread.h
*/
-enum stored_procedure_type
+enum enum_sp_type
{
- TYPE_ENUM_FUNCTION=1,
- TYPE_ENUM_PROCEDURE=2,
- TYPE_ENUM_PACKAGE=3,
- TYPE_ENUM_PACKAGE_BODY=4,
- TYPE_ENUM_TRIGGER=5,
- TYPE_ENUM_PROXY=6
+ SP_TYPE_FUNCTION=1,
+ SP_TYPE_PROCEDURE=2,
+ SP_TYPE_PACKAGE=3,
+ SP_TYPE_PACKAGE_BODY=4,
+ SP_TYPE_TRIGGER=5,
+ SP_TYPE_EVENT=6,
};
-
class Sp_handler
{
bool sp_resolve_package_routine_explicit(THD *thd,
@@ -121,13 +121,13 @@ public: // TODO: make it private or protected
public:
virtual ~Sp_handler() {}
static const Sp_handler *handler(enum enum_sql_command cmd);
- static const Sp_handler *handler(stored_procedure_type type);
+ static const Sp_handler *handler(enum_sp_type type);
static const Sp_handler *handler(MDL_key::enum_mdl_namespace ns);
/*
Return a handler only those SP objects that store
definitions in the mysql.proc system table
*/
- static const Sp_handler *handler_mysql_proc(stored_procedure_type type)
+ static const Sp_handler *handler_mysql_proc(enum_sp_type type)
{
const Sp_handler *sph= handler(type);
return sph ? sph->sp_handler_mysql_proc() : NULL;
@@ -154,7 +154,7 @@ public:
{
return this;
}
- virtual stored_procedure_type type() const= 0;
+ virtual enum_sp_type type() const= 0;
virtual LEX_CSTRING type_lex_cstring() const= 0;
virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
@@ -249,7 +249,7 @@ public:
class Sp_handler_procedure: public Sp_handler
{
public:
- stored_procedure_type type() const { return TYPE_ENUM_PROCEDURE; }
+ enum_sp_type type() const { return SP_TYPE_PROCEDURE; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")};
@@ -299,7 +299,7 @@ public:
class Sp_handler_function: public Sp_handler
{
public:
- stored_procedure_type type() const { return TYPE_ENUM_FUNCTION; }
+ enum_sp_type type() const { return SP_TYPE_FUNCTION; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")};
@@ -368,7 +368,7 @@ public: // TODO: make it private or protected
const Database_qualified_name *name)
const;
public:
- stored_procedure_type type() const { return TYPE_ENUM_PACKAGE; }
+ enum_sp_type type() const { return SP_TYPE_PACKAGE; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE")};
@@ -401,7 +401,7 @@ public:
class Sp_handler_package_body: public Sp_handler_package
{
public:
- stored_procedure_type type() const { return TYPE_ENUM_PACKAGE_BODY; }
+ enum_sp_type type() const { return SP_TYPE_PACKAGE_BODY; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= {STRING_WITH_LEN("PACKAGE BODY")};
@@ -434,7 +434,7 @@ public:
class Sp_handler_trigger: public Sp_handler
{
public:
- stored_procedure_type type() const { return TYPE_ENUM_TRIGGER; }
+ enum_sp_type type() const { return SP_TYPE_TRIGGER; }
LEX_CSTRING type_lex_cstring() const
{
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("TRIGGER")};
@@ -493,20 +493,20 @@ inline const Sp_handler *Sp_handler::handler(enum_sql_command cmd)
}
-inline const Sp_handler *Sp_handler::handler(stored_procedure_type type)
+inline const Sp_handler *Sp_handler::handler(enum_sp_type type)
{
switch (type) {
- case TYPE_ENUM_PROCEDURE:
+ case SP_TYPE_PROCEDURE:
return &sp_handler_procedure;
- case TYPE_ENUM_FUNCTION:
+ case SP_TYPE_FUNCTION:
return &sp_handler_function;
- case TYPE_ENUM_PACKAGE:
+ case SP_TYPE_PACKAGE:
return &sp_handler_package_spec;
- case TYPE_ENUM_PACKAGE_BODY:
+ case SP_TYPE_PACKAGE_BODY:
return &sp_handler_package_body;
- case TYPE_ENUM_TRIGGER:
+ case SP_TYPE_TRIGGER:
return &sp_handler_trigger;
- case TYPE_ENUM_PROXY:
+ case SP_TYPE_EVENT:
break;
}
return NULL;
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index e4ffbdcb155..a8659cc121f 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -302,7 +302,7 @@ sp_cache::~sp_cache()
void
sp_cache::init()
{
- my_hash_init(&m_hashtable, system_charset_info, 0, 0, 0,
+ my_hash_init(key_memory_sp_cache, &m_hashtable, system_charset_info, 0, 0, 0,
hash_get_key_for_sp_head, hash_free_sp_head, 0);
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c15465f105e..b63cf79dd7e 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -23,7 +23,6 @@
#include "probes_mysql.h"
#include "sql_show.h" // append_identifier
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
-#include "sql_acl.h" // *_ACL
#include "sql_array.h" // Dynamic_array
#include "log_event.h" // Query_log_event
#include "sql_derived.h" // mysql_handle_derived
@@ -56,8 +55,51 @@
#define SP_INSTR_UINT_MAXLEN 8
#define SP_STMT_PRINT_MAXLEN 40
-
#include <my_user.h>
+#include "mysql/psi/mysql_statement.h"
+#include "mysql/psi/mysql_sp.h"
+
+#ifdef HAVE_PSI_INTERFACE
+void init_sp_psi_keys()
+{
+ const char *category= "sp";
+ const int num __attribute__((unused)) = __LINE__ + 3;
+
+ PSI_server->register_statement(category, & sp_instr_stmt::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_set::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_set_trigger_field::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_jump::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_jump_if_not::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_freturn::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_preturn::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_hpush_jump::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_hpop::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_hreturn::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_cpush::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_cpop::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_copen::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_cclose::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_cfetch::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_agg_cfetch::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_cursor_copy_struct::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_error::psi_info, 1);
+ PSI_server->register_statement(category, & sp_instr_set_case_expr::psi_info, 1);
+
+ DBUG_ASSERT(SP_PSI_STATEMENT_INFO_COUNT == __LINE__ - num);
+}
+#endif
+
+#ifdef HAVE_PSI_SP_INTERFACE
+#define MYSQL_RUN_SP(SP,CODE) \
+ do { \
+ PSI_sp_locker_state psi_state; \
+ PSI_sp_locker *locker= MYSQL_START_SP(&psi_state, (SP)->m_sp_share); \
+ CODE; \
+ MYSQL_END_SP(locker); \
+ } while(0)
+#else
+#define MYSQL_RUN_SP(SP, CODE) do { CODE; } while(0)
+#endif
extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first);
@@ -188,7 +230,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_SHOW_ENGINE_MUTEX:
case SQLCOM_SHOW_EVENTS:
case SQLCOM_SHOW_KEYS:
- case SQLCOM_SHOW_MASTER_STAT:
+ case SQLCOM_SHOW_BINLOG_STAT:
case SQLCOM_SHOW_OPEN_TABLES:
case SQLCOM_SHOW_PRIVILEGES:
case SQLCOM_SHOW_PROCESSLIST:
@@ -455,8 +497,8 @@ sp_head *sp_head::create(sp_package *parent, const Sp_handler *handler,
enum_sp_aggregate_type agg_type)
{
MEM_ROOT own_root;
- init_sql_alloc(&own_root, "sp_head", MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC,
- MYF(0));
+ init_sql_alloc(key_memory_sp_head_main_root, &own_root, MEM_ROOT_BLOCK_SIZE,
+ MEM_ROOT_PREALLOC, MYF(0));
sp_head *sp;
if (!(sp= new (&own_root) sp_head(&own_root, parent, handler, agg_type)))
free_root(&own_root, MYF(0));
@@ -537,11 +579,12 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent,
m_backpatch_goto.empty();
m_cont_backpatch.empty();
m_lex.empty();
- my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, MYF(0));
- my_hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
- my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key,
- 0, 0);
- m_security_ctx.init();
+ my_init_dynamic_array(key_memory_sp_head_main_root, &m_instr,
+ sizeof(sp_instr *), 16, 8, MYF(0));
+ my_hash_init(key_memory_sp_head_main_root, &m_sptabs, system_charset_info, 0,
+ 0, 0, sp_table_key, 0, 0);
+ my_hash_init(key_memory_sp_head_main_root, &m_sroutines, system_charset_info,
+ 0, 0, 0, sp_sroutine_key, 0, 0);
DBUG_VOID_RETURN;
}
@@ -551,7 +594,7 @@ sp_package *sp_package::create(LEX *top_level_lex, const sp_name *name,
const Sp_handler *sph)
{
MEM_ROOT own_root;
- init_sql_alloc(&own_root, "sp_package", MEM_ROOT_BLOCK_SIZE,
+ init_sql_alloc(key_memory_sp_head_main_root, &own_root, MEM_ROOT_BLOCK_SIZE,
MEM_ROOT_PREALLOC, MYF(0));
sp_package *sp;
if (!(sp= new (&own_root) sp_package(&own_root, top_level_lex, name, sph)))
@@ -604,7 +647,7 @@ bool sp_head::eq_routine_spec(const sp_head *sp) const
bool sp_package::validate_after_parser(THD *thd)
{
- if (m_handler->type() != TYPE_ENUM_PACKAGE_BODY)
+ if (m_handler->type() != SP_TYPE_PACKAGE_BODY)
return false;
sp_head *sp= sp_cache_lookup(&thd->sp_package_spec_cache, this);
sp_package *spec= sp ? sp->get_package() : NULL;
@@ -683,7 +726,7 @@ bool sp_package::validate_private_routines(THD *thd)
LEX *sp_package::LexList::find(const LEX_CSTRING &name,
- stored_procedure_type type)
+ enum_sp_type type)
{
List_iterator<LEX> it(*this);
for (LEX *lex; (lex= it++); )
@@ -706,7 +749,7 @@ LEX *sp_package::LexList::find(const LEX_CSTRING &name,
LEX *sp_package::LexList::find_qualified(const LEX_CSTRING &name,
- stored_procedure_type type)
+ enum_sp_type type)
{
List_iterator<LEX> it(*this);
for (LEX *lex; (lex= it++); )
@@ -720,6 +763,17 @@ LEX *sp_package::LexList::find_qualified(const LEX_CSTRING &name,
}
+void sp_package::init_psi_share()
+{
+ List_iterator<LEX> it(m_routine_implementations);
+ for (LEX *lex; (lex= it++); )
+ {
+ DBUG_ASSERT(lex->sphead);
+ lex->sphead->init_psi_share();
+ }
+ sp_head::init_psi_share();
+}
+
void
sp_head::init(LEX *lex)
{
@@ -755,6 +809,13 @@ sp_head::init_sp_name(const sp_name *spname)
DBUG_VOID_RETURN;
}
+void
+sp_head::init_psi_share()
+{
+ m_sp_share= MYSQL_GET_SP_SHARE(m_handler->type(), m_db.str, static_cast<uint>(m_db.length),
+ m_name.str, static_cast<uint>(m_name.length));
+}
+
void
sp_head::set_body_start(THD *thd, const char *begin_ptr)
@@ -1038,7 +1099,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
{
DBUG_ENTER("subst_spvars");
- Dynamic_array<Rewritable_query_parameter*> rewritables;
+ Dynamic_array<Rewritable_query_parameter*> rewritables(PSI_INSTRUMENT_MEM);
char *pbuf;
StringBuffer<512> qbuf;
Copy_query_with_rewrite acc(thd, query_str->str, query_str->length, &qbuf);
@@ -1170,7 +1231,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
opt_trace_disable_if_no_security_context_access(thd);
/* init per-instruction memroot */
- init_sql_alloc(&execute_mem_root, "per_instruction_memroot",
+ init_sql_alloc(key_memory_sp_head_execute_root, &execute_mem_root,
MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
DBUG_ASSERT(!(m_flags & IS_INVOKED));
@@ -1357,8 +1418,24 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
WSREP_DEBUG("assigned new next trx ID for SP, trx id: %" PRIu64, thd->wsrep_next_trx_id());
}
#endif /* WITH_WSREP */
+
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
+ PSI_statement_locker_state state;
+ PSI_statement_locker *parent_locker;
+ PSI_statement_info *psi_info = i->get_psi_info();
+
+ parent_locker= thd->m_statement_psi;
+ thd->m_statement_psi= MYSQL_START_STATEMENT(& state, psi_info->m_key,
+ thd->db.str, thd->db.length, thd->charset(), m_sp_share);
+#endif
+
err_status= i->execute(thd, &ip);
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
+ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->m_statement_psi= parent_locker;
+#endif
+
#ifdef WITH_WSREP
if (WSREP(thd))
{
@@ -1815,8 +1892,8 @@ sp_head::execute_trigger(THD *thd,
TODO: we should create sp_rcontext once per command and reuse it
on subsequent executions of a trigger.
*/
- init_sql_alloc(&call_mem_root, "execute_trigger", MEM_ROOT_BLOCK_SIZE, 0,
- MYF(0));
+ init_sql_alloc(key_memory_sp_head_call_root,
+ &call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
Row_definition_list defs;
@@ -1829,7 +1906,7 @@ sp_head::execute_trigger(THD *thd,
thd->spcont= nctx;
- err_status= execute(thd, FALSE);
+ MYSQL_RUN_SP(this, err_status= execute(thd, FALSE));
err_with_cleanup:
thd->restore_active_arena(&call_arena, &backup_arena);
@@ -2079,7 +2156,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
*/
thd->set_n_backup_active_arena(call_arena, &backup_arena);
- err_status= execute(thd, TRUE);
+ MYSQL_RUN_SP(this, err_status= execute(thd, TRUE));
thd->restore_active_arena(call_arena, &backup_arena);
@@ -2360,11 +2437,9 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
#endif
opt_trace_disable_if_no_stored_proc_func_access(thd, this);
+
if (!err_status)
- {
- err_status= execute(thd, TRUE);
- DBUG_PRINT("info", ("execute returned %d", (int) err_status));
- }
+ MYSQL_RUN_SP(this, err_status= execute(thd, TRUE));
if (save_log_general)
thd->variables.option_bits &= ~OPTION_LOG_OFF;
@@ -3444,7 +3519,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
thd->mdl_context.release_statement_locks();
}
}
- //TODO: why is this here if log_slow_query is in sp_instr_stmt_execute?
+ //TODO: why is this here if log_slow_query is in sp_instr_stmt::execute?
delete_explain_query(m_lex);
if (m_lex->query_tables_own_last)
@@ -3553,6 +3628,9 @@ int sp_instr::exec_core(THD *thd, uint *nextp)
sp_instr_stmt class functions
*/
+PSI_statement_info sp_instr_stmt::psi_info=
+{ 0, "stmt", 0};
+
int
sp_instr_stmt::execute(THD *thd, uint *nextp)
{
@@ -3563,6 +3641,8 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
DBUG_ENTER("sp_instr_stmt::execute");
DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command()));
+ MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, m_query.str, static_cast<uint>(m_query.length));
+
#if defined(ENABLED_PROFILING)
/* This s-p instr is profilable and will be captured. */
thd->profiling.set_query_source(m_query.str, m_query.length);
@@ -3689,6 +3769,9 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp)
sp_instr_set class functions
*/
+PSI_statement_info sp_instr_set::psi_info=
+{ 0, "set", 0};
+
int
sp_instr_set::execute(THD *thd, uint *nextp)
{
@@ -3839,6 +3922,9 @@ sp_instr_set_row_field_by_name::print(String *str)
sp_instr_set_trigger_field class functions
*/
+PSI_statement_info sp_instr_set_trigger_field::psi_info=
+{ 0, "set_trigger_field", 0};
+
int
sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
{
@@ -3882,6 +3968,9 @@ uint sp_instr_opt_meta::get_cont_dest() const
sp_instr_jump class functions
*/
+PSI_statement_info sp_instr_jump::psi_info=
+{ 0, "jump", 0};
+
int
sp_instr_jump::execute(THD *thd, uint *nextp)
{
@@ -3947,6 +4036,9 @@ sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp)
sp_instr_jump_if_not class functions
*/
+PSI_statement_info sp_instr_jump_if_not::psi_info=
+{ 0, "jump_if_not", 0};
+
int
sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
{
@@ -4042,6 +4134,9 @@ sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr> *bp)
sp_instr_freturn class functions
*/
+PSI_statement_info sp_instr_freturn::psi_info=
+{ 0, "freturn", 0};
+
int
sp_instr_freturn::execute(THD *thd, uint *nextp)
{
@@ -4106,9 +4201,33 @@ sp_instr_freturn::print(String *str)
}
/*
+ sp_instr_preturn class functions
+*/
+
+PSI_statement_info sp_instr_preturn::psi_info=
+{ 0, "preturn", 0};
+
+int
+sp_instr_preturn::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_preturn::execute");
+ *nextp= UINT_MAX;
+ DBUG_RETURN(0);
+}
+
+void
+sp_instr_preturn::print(String *str)
+{
+ str->append(STRING_WITH_LEN("preturn"));
+}
+
+/*
sp_instr_hpush_jump class functions
*/
+PSI_statement_info sp_instr_hpush_jump::psi_info=
+{ 0, "hpush_jump", 0};
+
int
sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
{
@@ -4185,6 +4304,9 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp, List<sp_instr> *leads)
sp_instr_hpop class functions
*/
+PSI_statement_info sp_instr_hpop::psi_info=
+{ 0, "hpop", 0};
+
int
sp_instr_hpop::execute(THD *thd, uint *nextp)
{
@@ -4209,6 +4331,9 @@ sp_instr_hpop::print(String *str)
sp_instr_hreturn class functions
*/
+PSI_statement_info sp_instr_hreturn::psi_info=
+{ 0, "hreturn", 0};
+
int
sp_instr_hreturn::execute(THD *thd, uint *nextp)
{
@@ -4268,6 +4393,9 @@ sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads)
sp_instr_cpush class functions
*/
+PSI_statement_info sp_instr_cpush::psi_info=
+{ 0, "cpush", 0};
+
int
sp_instr_cpush::execute(THD *thd, uint *nextp)
{
@@ -4309,6 +4437,9 @@ sp_instr_cpush::print(String *str)
sp_instr_cpop class functions
*/
+PSI_statement_info sp_instr_cpop::psi_info=
+{ 0, "cpop", 0};
+
int
sp_instr_cpop::execute(THD *thd, uint *nextp)
{
@@ -4339,6 +4470,9 @@ sp_instr_cpop::print(String *str)
Assert that we either have an error or a cursor
*/
+PSI_statement_info sp_instr_copen::psi_info=
+{ 0, "copen", 0};
+
int
sp_instr_copen::execute(THD *thd, uint *nextp)
{
@@ -4397,6 +4531,9 @@ sp_instr_copen::print(String *str)
sp_instr_cclose class functions
*/
+PSI_statement_info sp_instr_cclose::psi_info=
+{ 0, "cclose", 0};
+
int
sp_instr_cclose::execute(THD *thd, uint *nextp)
{
@@ -4439,6 +4576,9 @@ sp_instr_cclose::print(String *str)
sp_instr_cfetch class functions
*/
+PSI_statement_info sp_instr_cfetch::psi_info=
+{ 0, "cfetch", 0};
+
int
sp_instr_cfetch::execute(THD *thd, uint *nextp)
{
@@ -4486,6 +4626,13 @@ sp_instr_cfetch::print(String *str)
}
}
+/*
+ sp_instr_agg_cfetch class functions
+*/
+
+PSI_statement_info sp_instr_agg_cfetch::psi_info=
+{ 0, "agg_cfetch", 0};
+
int
sp_instr_agg_cfetch::execute(THD *thd, uint *nextp)
{
@@ -4538,6 +4685,9 @@ sp_instr_agg_cfetch::print(String *str)
- copies the cursor structure to the associated %ROWTYPE variable.
*/
+PSI_statement_info sp_instr_cursor_copy_struct::psi_info=
+{ 0, "cursor_copy_struct", 0};
+
int
sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp)
{
@@ -4610,6 +4760,9 @@ sp_instr_cursor_copy_struct::print(String *str)
sp_instr_error class functions
*/
+PSI_statement_info sp_instr_error::psi_info=
+{ 0, "error", 0};
+
int
sp_instr_error::execute(THD *thd, uint *nextp)
{
@@ -4636,6 +4789,9 @@ sp_instr_error::print(String *str)
sp_instr_set_case_expr class implementation
**************************************************************************/
+PSI_statement_info sp_instr_set_case_expr::psi_info=
+{ 0, "set_case_expr", 0};
+
int
sp_instr_set_case_expr::execute(THD *thd, uint *nextp)
{
@@ -4976,8 +5132,8 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
table->lock_type= locktype;
table->select_lex= lex->current_select;
table->cacheable_table= 1;
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- mdl_type, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, mdl_type, MDL_TRANSACTION);
lex->add_to_query_tables(table);
return table;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 6cf4610c466..913be1aace7 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -47,6 +47,14 @@ class sp_instr;
class sp_instr_opt_meta;
class sp_instr_jump_if_not;
+/**
+ Number of PSI_statement_info instruments
+ for internal stored programs statements.
+*/
+#ifdef HAVE_PSI_INTERFACE
+void init_sp_psi_keys(void);
+#endif
+
/*************************************************************************/
/**
@@ -174,6 +182,11 @@ public:
const Sp_handler *m_handler;
uint m_flags; // Boolean attributes of a stored routine
+ /**
+ Instrumentation interface for SP.
+ */
+ PSI_sp_share *m_sp_share;
+
Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */
const char *m_tmp_query; ///< Temporary pointer to sub query string
@@ -856,6 +869,8 @@ public:
return NULL;
}
+ virtual void init_psi_share();
+
protected:
MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root
@@ -931,9 +946,9 @@ public:
public:
LexList() { elements= 0; }
// Find a package routine by a non qualified name
- LEX *find(const LEX_CSTRING &name, stored_procedure_type type);
+ LEX *find(const LEX_CSTRING &name, enum_sp_type type);
// Find a package routine by a package-qualified name, e.g. 'pkg.proc'
- LEX *find_qualified(const LEX_CSTRING &name, stored_procedure_type type);
+ LEX *find_qualified(const LEX_CSTRING &name, enum_sp_type type);
// Check if a routine with the given qualified name already exists
bool check_dup_qualified(const LEX_CSTRING &name, const Sp_handler *sph)
{
@@ -990,6 +1005,7 @@ public:
m_routine_implementations.push_back(lex, &main_mem_root);
}
sp_package *get_package() { return this; }
+ void init_psi_share();
bool is_invoked() const
{
/*
@@ -1156,6 +1172,7 @@ public:
{
m_ip= dst;
}
+ virtual PSI_statement_info* get_psi_info() = 0;
}; // class sp_instr : public Sql_alloc
@@ -1282,6 +1299,10 @@ private:
sp_lex_keeper m_lex_keeper;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
+
}; // class sp_instr_stmt : public sp_instr
@@ -1316,6 +1337,10 @@ protected:
uint m_offset; ///< Frame offset
Item *m_value;
sp_lex_keeper m_lex_keeper;
+
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_set : public sp_instr
@@ -1424,6 +1449,10 @@ private:
Item_trigger_field *trigger_field;
Item *value;
sp_lex_keeper m_lex_keeper;
+
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_trigger_field : public sp_instr
@@ -1510,6 +1539,9 @@ public:
m_dest= new_dest;
}
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_jump : public sp_instr_opt_meta
@@ -1561,6 +1593,9 @@ private:
Item *m_expr; ///< The condition
sp_lex_keeper m_lex_keeper;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_jump_if_not : public sp_instr_jump
@@ -1578,17 +1613,9 @@ public:
virtual ~sp_instr_preturn()
{}
- virtual int execute(THD *thd, uint *nextp)
- {
- DBUG_ENTER("sp_instr_preturn::execute");
- *nextp= UINT_MAX;
- DBUG_RETURN(0);
- }
+ virtual int execute(THD *thd, uint *nextp);
- virtual void print(String *str)
- {
- str->append(STRING_WITH_LEN("preturn"));
- }
+ virtual void print(String *str);
virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
{
@@ -1596,6 +1623,9 @@ public:
return UINT_MAX;
}
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_preturn : public sp_instr
@@ -1633,6 +1663,9 @@ protected:
const Type_handler *m_type_handler;
sp_lex_keeper m_lex_keeper;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_freturn : public sp_instr
@@ -1698,6 +1731,9 @@ private:
// debug version only). It's used in print().
uint m_frame;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_hpush_jump : public sp_instr_jump
@@ -1728,6 +1764,9 @@ private:
uint m_count;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_hpop : public sp_instr
@@ -1762,12 +1801,14 @@ private:
uint m_frame;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_hreturn : public sp_instr_jump
/** This is DECLARE CURSOR */
-class sp_instr_cpush : public sp_instr,
- public sp_cursor
+class sp_instr_cpush : public sp_instr, public sp_cursor
{
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
void operator=(sp_instr_cpush &);
@@ -1796,6 +1837,9 @@ private:
sp_lex_keeper m_lex_keeper;
uint m_cursor; /**< Frame offset (for debugging) */
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_cpush : public sp_instr
@@ -1826,6 +1870,9 @@ private:
uint m_count;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_cpop : public sp_instr
@@ -1853,6 +1900,9 @@ private:
uint m_cursor; ///< Stack index
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_copen : public sp_instr_stmt
@@ -1880,6 +1930,10 @@ public:
virtual int execute(THD *thd, uint *nextp);
virtual int exec_core(THD *thd, uint *nextp);
virtual void print(String *str);
+
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
};
@@ -1905,6 +1959,9 @@ private:
uint m_cursor;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_cclose : public sp_instr
@@ -1939,6 +1996,9 @@ private:
List<sp_variable> m_varlist;
bool m_error_on_no_data;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_cfetch : public sp_instr
/*
@@ -1963,6 +2023,10 @@ public:
virtual int execute(THD *thd, uint *nextp);
virtual void print(String *str);
+
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_agg_cfetch : public sp_instr
@@ -1996,6 +2060,9 @@ private:
int m_errcode;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_error : public sp_instr
@@ -2035,6 +2102,9 @@ private:
Item *m_case_expr;
sp_lex_keeper m_lex_keeper;
+public:
+ virtual PSI_statement_info* get_psi_info() { return & psi_info; }
+ static PSI_statement_info psi_info;
}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access);
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 01841bb57b7..848d1f0c655 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -96,6 +96,9 @@ sp_pcontext::sp_pcontext()
: Sql_alloc(),
m_max_var_index(0), m_max_cursor_index(0),
m_parent(NULL), m_pboundary(0),
+ m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
+ m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
+ m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
m_scope(REGULAR_SCOPE)
{
init(0, 0, 0);
@@ -106,6 +109,9 @@ sp_pcontext::sp_pcontext(sp_pcontext *prev, sp_pcontext::enum_scope scope)
: Sql_alloc(),
m_max_var_index(0), m_max_cursor_index(0),
m_parent(prev), m_pboundary(0),
+ m_vars(PSI_INSTRUMENT_MEM), m_case_expr_ids(PSI_INSTRUMENT_MEM),
+ m_conditions(PSI_INSTRUMENT_MEM), m_cursors(PSI_INSTRUMENT_MEM),
+ m_handlers(PSI_INSTRUMENT_MEM), m_children(PSI_INSTRUMENT_MEM),
m_scope(scope)
{
init(prev->m_var_offset + prev->m_max_var_index,
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 17b4c83b7bc..c4c19dd39f6 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -74,6 +74,7 @@ sp_rcontext::sp_rcontext(const sp_head *owner,
m_return_value_fld(return_value_fld),
m_return_value_set(false),
m_in_sub_stmt(in_sub_stmt),
+ m_handlers(PSI_INSTRUMENT_MEM), m_handler_call_stack(PSI_INSTRUMENT_MEM),
m_ccount(0)
{
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 45bb6ae89ad..4c9a523159d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -68,6 +68,15 @@ const uint max_hostname_length= 60;
const uint max_dbname_length= 64;
#endif
+const char *safe_vio_type_name(Vio *vio)
+{
+ size_t unused;
+#ifdef EMBEDDED_LIBRARY
+ if (!vio) return "Internal";
+#endif
+ return vio_type_name(vio_type(vio), &unused);
+}
+
#include "sql_acl_getsort.ic"
static LEX_CSTRING native_password_plugin_name= {
@@ -645,7 +654,7 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, const char *username,
#define ROLE_OPENED (1L << 3)
static DYNAMIC_ARRAY acl_hosts, acl_users, acl_proxy_users;
-static Dynamic_array<ACL_DB> acl_dbs(0U,50U);
+static Dynamic_array<ACL_DB> acl_dbs(PSI_INSTRUMENT_MEM, 0U, 50U);
typedef Dynamic_array<ACL_DB>::CMP_FUNC acl_dbs_cmp;
static HASH acl_roles;
/*
@@ -992,7 +1001,7 @@ class User_table_tabular: public User_table
{
access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
if (access & FILE_ACL)
- access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
+ access|= BINLOG_MONITOR_ACL | REPL_SLAVE_ACL | BINLOG_ADMIN_ACL ;
if (access & PROCESS_ACL)
access|= SUPER_ACL | EXECUTE_ACL;
}
@@ -1020,6 +1029,12 @@ class User_table_tabular: public User_table
if (num_fields() <= 46 && (access & DELETE_ACL))
access|= DELETE_HISTORY_ACL;
+ if (access & SUPER_ACL)
+ access|= GLOBAL_SUPER_ADDED_SINCE_USER_TABLE_ACLS;
+
+ if (access & REPL_SLAVE_ACL)
+ access|= REPL_MASTER_ADMIN_ACL;
+
return access & GLOBAL_ACLS;
}
@@ -1470,15 +1485,79 @@ class User_table_json: public User_table
set_str_value("authentication_string",
u.auth[i].auth_string.str, u.auth[i].auth_string.length);
}
+
+ void print_warning_bad_version_id(ulonglong version_id) const
+ {
+ sql_print_warning("'user' entry '%s@%s' has a wrong 'version_id' value %lld",
+ safe_str(get_user(current_thd->mem_root)),
+ safe_str(get_host(current_thd->mem_root)),
+ version_id);
+ }
+
+ void print_warning_bad_access(ulonglong version_id,
+ privilege_t mask,
+ ulonglong access) const
+ {
+ sql_print_warning("'user' entry '%s@%s' "
+ "has a wrong 'access' value 0x%llx "
+ "(allowed mask is 0x%llx, version_id=%lld)",
+ safe_str(get_user(current_thd->mem_root)),
+ safe_str(get_host(current_thd->mem_root)),
+ access, mask, version_id);
+ }
+
+ privilege_t adjust_access(ulonglong version_id, ulonglong access) const
+ {
+ privilege_t mask= ALL_KNOWN_ACL_100304;
+ ulonglong orig_access= access;
+ if (version_id >= 100502)
+ {
+ mask= ALL_KNOWN_ACL_100502;
+ }
+ else // 100501 or earlier
+ {
+ if (access & SUPER_ACL)
+ access|= GLOBAL_SUPER_ADDED_SINCE_USER_TABLE_ACLS;
+
+ if (access & REPL_SLAVE_ACL)
+ access|= REPL_MASTER_ADMIN_ACL;
+ }
+
+ if (orig_access & ~mask)
+ {
+ print_warning_bad_access(version_id, mask, orig_access);
+ return NO_ACL;
+ }
+ return access & ALL_KNOWN_ACL;
+ }
+
privilege_t get_access() const
{
+ ulonglong version_id= (ulonglong) get_int_value("version_id");
+ ulonglong access= (ulonglong) get_int_value("access");
+
/*
- when new privileges will be added, we'll start storing GLOBAL_ACLS
- (or, for example, my_count_bits(GLOBAL_ACLS))
- in the json too, and it'll allow us to do privilege upgrades
+ Special case:
+ mysql_system_tables_data.sql populates "ALL PRIVILEGES"
+ for the super user this way:
+ {"access":18446744073709551615}
*/
- return get_access_value("access") & GLOBAL_ACLS;
+ if (access == (ulonglong) ~0)
+ return GLOBAL_ACLS;
+
+ /*
+ Reject obviously bad (negative and too large) version_id values.
+ Also reject versions before 10.4.0 (when JSON table was added).
+ */
+ if ((longlong) version_id < 0 || version_id > 999999 ||
+ (version_id > 0 && version_id < 100400))
+ {
+ print_warning_bad_version_id(version_id);
+ return NO_ACL;
+ }
+ return adjust_access(version_id, access) & GLOBAL_ACLS;
}
+
void set_access(const privilege_t rights, bool revoke) const
{
privilege_t access= get_access();
@@ -1487,6 +1566,7 @@ class User_table_json: public User_table
else
access|= rights;
set_int_value("access", (longlong) (access & GLOBAL_ACLS));
+ set_int_value("version_id", (longlong) MYSQL_VERSION_ID);
}
const char *unsafe_str(const char *s) const
{ return s[0] ? s : NULL; }
@@ -1607,10 +1687,6 @@ class User_table_json: public User_table
const char *value_end= value_start + value_len;
return my_strtoll10(value_start, (char**)&value_end, &err);
}
- privilege_t get_access_value(const char *key) const
- {
- return privilege_t(ALL_KNOWN_ACL & (ulonglong) get_int_value(key));
- }
double get_double_value(const char *key) const
{
int err;
@@ -2251,9 +2327,9 @@ bool acl_init(bool dont_read_acl_tables)
bool return_val;
DBUG_ENTER("acl_init");
- acl_cache= new Hash_filo<acl_entry>(ACL_CACHE_SIZE, 0, 0,
+ acl_cache= new Hash_filo<acl_entry>(key_memory_acl_cache, ACL_CACHE_SIZE, 0, 0,
(my_hash_get_key) acl_entry_get_key,
- (my_hash_free_key) free,
+ (my_hash_free_key) my_free,
&my_charset_utf8mb3_bin);
/*
@@ -2328,7 +2404,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
grant_version++; /* Privileges updated */
const Host_table& host_table= tables.host_table();
- init_sql_alloc(&acl_memroot, "ACL", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_acl_mem, &acl_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
if (host_table.table_exists()) // "host" table may not exist (e.g. in MySQL 5.6.7+)
{
if (host_table.init_read_record(&read_record_info))
@@ -2405,7 +2481,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
user.sort= get_magic_sort("hu", user.host.hostname, user.user.str);
user.hostname_length= safe_strlen(user.host.hostname);
- my_init_dynamic_array(&user.role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0));
+ my_init_dynamic_array(key_memory_acl_mem, &user.role_grants,
+ sizeof(ACL_ROLE *), 0, 8, MYF(0));
user.account_locked= user_table.get_account_locked();
@@ -2423,7 +2500,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
ACL_ROLE *entry= new (&acl_memroot) ACL_ROLE(&user, &acl_memroot);
entry->role_grants = user.role_grants;
- my_init_dynamic_array(&entry->parent_grantee,
+ my_init_dynamic_array(key_memory_acl_mem, &entry->parent_grantee,
sizeof(ACL_USER_BASE *), 0, 8, MYF(0));
my_hash_insert(&acl_roles, (uchar *)entry);
@@ -2568,7 +2645,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
DBUG_RETURN(TRUE);
MEM_ROOT temp_root;
- init_alloc_root(&temp_root, "ACL_tmp", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_alloc_root(key_memory_acl_mem, &temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
while (!(read_record_info.read_record()))
{
char *hostname= safe_str(get_field(&temp_root, roles_mapping_table.host()));
@@ -2687,15 +2764,16 @@ bool acl_reload(THD *thd)
old_acl_roles_mappings= acl_roles_mappings;
old_acl_proxy_users= acl_proxy_users;
old_acl_dbs= acl_dbs;
- my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50, MYF(0));
- my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100, MYF(0));
- acl_dbs.init(50, 100);
- my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100, MYF(0));
- my_hash_init2(&acl_roles,50, &my_charset_utf8mb3_bin,
+ my_init_dynamic_array(key_memory_acl_mem, &acl_hosts, sizeof(ACL_HOST), 20, 50, MYF(0));
+ my_init_dynamic_array(key_memory_acl_mem, &acl_users, sizeof(ACL_USER), 50, 100, MYF(0));
+ acl_dbs.init(key_memory_acl_mem, 50, 100);
+ my_init_dynamic_array(key_memory_acl_mem, &acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100, MYF(0));
+ my_hash_init2(key_memory_acl_mem, &acl_roles,50, &my_charset_utf8mb3_bin,
0, 0, 0, (my_hash_get_key) acl_role_get_key, 0,
(void (*)(void *))free_acl_role, 0);
- my_hash_init2(&acl_roles_mappings, 50, &my_charset_utf8mb3_bin, 0, 0, 0,
- (my_hash_get_key) acl_role_map_get_key, 0, 0, 0);
+ my_hash_init2(key_memory_acl_mem, &acl_roles_mappings, 50,
+ &my_charset_utf8mb3_bin, 0, 0, 0, (my_hash_get_key)
+ acl_role_map_get_key, 0, 0, 0);
old_mem= acl_memroot;
delete_dynamic(&acl_wild_hosts);
my_hash_free(&acl_check_hosts);
@@ -3133,7 +3211,7 @@ ACL_USER::ACL_USER(THD *thd, const LEX_USER &combo,
sort= get_magic_sort("hu", host.hostname, user.str);
password_last_changed= thd->query_start();
password_lifetime= -1;
- my_init_dynamic_array(&role_grants, sizeof(ACL_USER *), 0, 8, MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &role_grants, sizeof(ACL_USER *), 0, 8, MYF(0));
}
@@ -3218,9 +3296,10 @@ static void acl_insert_role(const char *rolename, privilege_t privileges)
mysql_mutex_assert_owner(&acl_cache->lock);
entry= new (&acl_memroot) ACL_ROLE(rolename, privileges, &acl_memroot);
- my_init_dynamic_array(&entry->parent_grantee,
+ my_init_dynamic_array(key_memory_acl_mem, &entry->parent_grantee,
sizeof(ACL_USER_BASE *), 0, 8, MYF(0));
- my_init_dynamic_array(&entry->role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0));
+ my_init_dynamic_array(key_memory_acl_mem, &entry->role_grants,
+ sizeof(ACL_ROLE *), 0, 8, MYF(0));
my_hash_insert(&acl_roles, (uchar *)entry);
}
@@ -3367,7 +3446,8 @@ privilege_t acl_get(const char *host, const char *ip,
exit:
/* Save entry in cache for quick retrieval */
if (!db_is_pattern &&
- (entry= (acl_entry*) malloc(sizeof(acl_entry)+key_length)))
+ (entry= (acl_entry*) my_malloc(key_memory_acl_cache,
+ sizeof(acl_entry)+key_length, MYF(MY_WME))))
{
entry->access=(db_access & host_access);
DBUG_ASSERT(key_length < 0xffff);
@@ -3391,9 +3471,10 @@ exit:
static void init_check_host(void)
{
DBUG_ENTER("init_check_host");
- (void) my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip),
+ (void) my_init_dynamic_array(key_memory_acl_mem, &acl_wild_hosts,
+ sizeof(struct acl_host_and_ip),
acl_users.elements, 1, MYF(0));
- (void) my_hash_init(&acl_check_hosts,system_charset_info,
+ (void) my_hash_init(key_memory_acl_mem, &acl_check_hosts,system_charset_info,
acl_users.elements, 0, 0,
(my_hash_get_key) check_get_key, 0, 0);
if (!allow_all_hosts)
@@ -5040,8 +5121,8 @@ public:
bool ok() { return privs != NO_ACL || cols != NO_ACL; }
void init_hash()
{
- my_hash_init2(&hash_columns, 4, system_charset_info, 0, 0, 0,
- (my_hash_get_key) get_key_column, 0, 0, 0);
+ my_hash_init2(key_memory_acl_memex, &hash_columns, 4, system_charset_info,
+ 0, 0, 0, (my_hash_get_key) get_key_column, 0, 0, 0);
}
};
@@ -5307,8 +5388,7 @@ column_hash_search(GRANT_TABLE *t, const char *cname, size_t length)
{
if (!my_hash_inited(&t->hash_columns))
return (GRANT_COLUMN*) 0;
- return (GRANT_COLUMN*) my_hash_search(&t->hash_columns,
- (uchar*) cname, length);
+ return (GRANT_COLUMN*)my_hash_search(&t->hash_columns, (uchar*)cname, length);
}
@@ -5824,19 +5904,19 @@ struct PRIVS_TO_MERGE
};
-static enum PRIVS_TO_MERGE::what sp_privs_to_merge(stored_procedure_type type)
+static enum PRIVS_TO_MERGE::what sp_privs_to_merge(enum_sp_type type)
{
switch (type) {
- case TYPE_ENUM_FUNCTION:
+ case SP_TYPE_FUNCTION:
return PRIVS_TO_MERGE::FUNC;
- case TYPE_ENUM_PROCEDURE:
+ case SP_TYPE_PROCEDURE:
return PRIVS_TO_MERGE::PROC;
- case TYPE_ENUM_PACKAGE:
+ case SP_TYPE_PACKAGE:
return PRIVS_TO_MERGE::PACKAGE_SPEC;
- case TYPE_ENUM_PACKAGE_BODY:
+ case SP_TYPE_PACKAGE_BODY:
return PRIVS_TO_MERGE::PACKAGE_BODY;
- case TYPE_ENUM_TRIGGER:
- case TYPE_ENUM_PROXY:
+ case SP_TYPE_EVENT:
+ case SP_TYPE_TRIGGER:
break;
}
DBUG_ASSERT(0);
@@ -6229,7 +6309,7 @@ static int update_role_db(int merged, int first, privilege_t access,
static bool merge_role_db_privileges(ACL_ROLE *grantee, const char *dbname,
role_hash_t *rhash)
{
- Dynamic_array<int> dbs;
+ Dynamic_array<int> dbs(PSI_INSTRUMENT_MEM);
/*
Supposedly acl_dbs can be huge, but only a handful of db grants
@@ -6448,7 +6528,7 @@ static int update_role_table_columns(GRANT_TABLE *merged,
static bool merge_role_table_and_column_privileges(ACL_ROLE *grantee,
const char *db, const char *tname, role_hash_t *rhash)
{
- Dynamic_array<GRANT_TABLE *> grants;
+ Dynamic_array<GRANT_TABLE *> grants(PSI_INSTRUMENT_MEM);
DBUG_ASSERT(MY_TEST(db) == MY_TEST(tname)); // both must be set, or neither
/*
@@ -6577,7 +6657,7 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee,
DBUG_ASSERT(MY_TEST(db) == MY_TEST(tname)); // both must be set, or neither
- Dynamic_array<GRANT_NAME *> grants;
+ Dynamic_array<GRANT_NAME *> grants(PSI_INSTRUMENT_MEM);
/* first, collect routine privileges granted to roles in question */
for (uint i=0 ; i < hash->records ; i++)
@@ -6638,7 +6718,7 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
grantee->counter= 1; // Mark the grantee as merged.
/* if we'll do db/table/routine privileges, create a hash of role names */
- role_hash_t role_hash(role_key);
+ role_hash_t role_hash(PSI_INSTRUMENT_MEM, role_key);
if (data->what != PRIVS_TO_MERGE::GLOBAL)
{
role_hash.insert(grantee);
@@ -7590,18 +7670,22 @@ static bool grant_load(THD *thd,
Sql_mode_instant_remove sms(thd, MODE_PAD_CHAR_TO_FULL_LENGTH);
- (void) my_hash_init(&column_priv_hash, &my_charset_utf8mb3_bin,
- 0,0,0, (my_hash_get_key) get_grant_table,
- (my_hash_free_key) free_grant_table,0);
- (void) my_hash_init(&proc_priv_hash, &my_charset_utf8mb3_bin,
- 0,0,0, (my_hash_get_key) get_grant_table, 0,0);
- (void) my_hash_init(&func_priv_hash, &my_charset_utf8mb3_bin,
- 0,0,0, (my_hash_get_key) get_grant_table, 0,0);
- (void) my_hash_init(&package_spec_priv_hash, &my_charset_utf8mb3_bin,
- 0,0,0, (my_hash_get_key) get_grant_table, 0,0);
- (void) my_hash_init(&package_body_priv_hash, &my_charset_utf8mb3_bin,
- 0,0,0, (my_hash_get_key) get_grant_table, 0,0);
- init_sql_alloc(&grant_memroot, "GRANT", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ (void) my_hash_init(key_memory_acl_memex, &column_priv_hash,
+ &my_charset_utf8mb3_bin, 0,0,0, (my_hash_get_key)
+ get_grant_table, (my_hash_free_key) free_grant_table, 0);
+ (void) my_hash_init(key_memory_acl_memex, &proc_priv_hash,
+ &my_charset_utf8mb3_bin, 0,0,0, (my_hash_get_key)
+ get_grant_table, 0,0);
+ (void) my_hash_init(key_memory_acl_memex, &func_priv_hash,
+ &my_charset_utf8mb3_bin, 0,0,0, (my_hash_get_key)
+ get_grant_table, 0,0);
+ (void) my_hash_init(key_memory_acl_memex, &package_spec_priv_hash,
+ &my_charset_utf8mb3_bin, 0,0,0, (my_hash_get_key)
+ get_grant_table, 0,0);
+ (void) my_hash_init(key_memory_acl_memex, &package_body_priv_hash,
+ &my_charset_utf8mb3_bin, 0,0,0, (my_hash_get_key)
+ get_grant_table, 0,0);
+ init_sql_alloc(key_memory_acl_mem, &grant_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
t_table= tables_priv.table();
c_table= columns_priv.table();
@@ -7682,7 +7766,7 @@ static bool grant_load(THD *thd,
continue;
}
}
- stored_procedure_type type= (stored_procedure_type)procs_priv.routine_type()->val_int();
+ enum_sp_type type= (enum_sp_type)procs_priv.routine_type()->val_int();
const Sp_handler *sph= Sp_handler::handler(type);
if (!sph || !(hash= sph->get_priv_hash()))
{
@@ -7930,15 +8014,7 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables,
switch(access->check(orig_want_access, &t_ref->grant.privilege))
{
case ACL_INTERNAL_ACCESS_GRANTED:
- /*
- Currently,
- - the information_schema does not subclass ACL_internal_table_access,
- there are no per table privilege checks for I_S,
- - the performance schema does use per tables checks, but at most
- returns 'CHECK_GRANT', and never 'ACCESS_GRANTED'.
- so this branch is not used.
- */
- DBUG_ASSERT(0);
+ continue;
case ACL_INTERNAL_ACCESS_DENIED:
goto err;
case ACL_INTERNAL_ACCESS_CHECK_GRANT:
@@ -8801,19 +8877,32 @@ static const char *command_array[]=
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
"SHUTDOWN", "PROCESS","FILE", "GRANT", "REFERENCES", "INDEX",
"ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
- "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
+ "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "BINLOG MONITOR",
"CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE",
- "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE",
- "DELETE HISTORY"
+ "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE", "DELETE HISTORY",
+ "SET USER", "FEDERATED ADMIN", "CONNECTION ADMIN", "READ_ONLY ADMIN",
+ "REPLICATION SLAVE ADMIN", "REPLICATION MASTER ADMIN", "BINLOG ADMIN"
};
static uint command_lengths[]=
{
- 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9,
- 14, 13, 11, 5, 7, 17, 14,
+ 6, 6, 6, 6, 6, 4, 6,
+ 8, 7, 4, 5, 10, 5,
+ 5, 14, 5, 23,
+ 11, 7, 17, 14,
+ 11, 9, 14, 13,
+ 11, 5, 7, 17, 14,
+ 8, 15, 16, 15,
+ 23, 24, 12
};
+static_assert(array_elements(command_array) == PRIVILEGE_T_MAX_BIT + 1,
+ "The definition of command_array does not match privilege_t");
+static_assert(array_elements(command_lengths) == PRIVILEGE_T_MAX_BIT + 1,
+ "The definition of command_lengths does not match privilege_t");
+
+
static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
{
char buff[1024];
@@ -12937,7 +13026,7 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio,
static bool ignore_max_password_errors(const ACL_USER *acl_user)
{
const char *host= acl_user->host.hostname;
- return (acl_user->access & SUPER_ACL)
+ return (acl_user->access & PRIV_IGNORE_MAX_PASSWORD_ERRORS)
&& (!strcasecmp(host, "localhost") ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "::1"));
@@ -13125,7 +13214,8 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
system_charset_info, user, user_len,
thd->charset(), &dummy_errors);
- if (!(sctx->user= my_strndup(user_buff, user_len, MYF(MY_WME))))
+ if (!(sctx->user= my_strndup(key_memory_MPVIO_EXT_auth_info, user_buff,
+ user_len, MYF(MY_WME))))
DBUG_RETURN(1);
/* Clear variables that are allocated */
@@ -13384,8 +13474,8 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
Security_context *sctx= thd->security_ctx;
- my_free((char*) sctx->user);
- if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
+ my_free(const_cast<char*>(sctx->user));
+ if (!(sctx->user= my_strndup(key_memory_MPVIO_EXT_auth_info, user, user_len, MYF(MY_WME))))
return packet_error; /* The error is set by my_strdup(). */
@@ -13929,6 +14019,8 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
res= do_auth_once(thd, default_auth_plugin_name, &mpvio);
}
+ PSI_CALL_set_connection_type(vio_type(thd->net.vio));
+
Security_context * const sctx= thd->security_ctx;
const ACL_USER * acl_user= mpvio.acl_user;
if (!acl_user)
@@ -13966,17 +14058,9 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
*/
if (sctx->user)
{
- if (strcmp(sctx->priv_user, sctx->user))
- {
- general_log_print(thd, command, "%s@%s as %s on %s",
- sctx->user, sctx->host_or_ip,
- sctx->priv_user[0] ? sctx->priv_user : "anonymous",
- safe_str(mpvio.db.str));
- }
- else
- general_log_print(thd, command, (char*) "%s@%s on %s",
- sctx->user, sctx->host_or_ip,
- safe_str(mpvio.db.str));
+ general_log_print(thd, command, (char*) "%s@%s on %s using %s",
+ sctx->user, sctx->host_or_ip,
+ safe_str(mpvio.db.str), safe_vio_type_name(thd->net.vio));
}
if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS)
@@ -14158,7 +14242,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
(longlong) sctx->master_access, mpvio.db.str));
if (command == COM_CONNECT &&
- !(thd->main_security_ctx.master_access & SUPER_ACL))
+ !(thd->main_security_ctx.master_access & PRIV_IGNORE_MAX_CONNECTIONS))
{
if (*thd->scheduler->connection_count > *thd->scheduler->max_connections)
{ // too many connections
@@ -14220,16 +14304,17 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
if (mpvio.auth_info.external_user[0])
- sctx->external_user= my_strdup(mpvio.auth_info.external_user, MYF(0));
+ sctx->external_user= my_strdup(key_memory_MPVIO_EXT_auth_info,
+ mpvio.auth_info.external_user, MYF(0));
if (res == CR_OK_HANDSHAKE_COMPLETE)
thd->get_stmt_da()->disable_status();
else
my_ok(thd);
- PSI_CALL_set_thread_user_host
- (thd->main_security_ctx.user, (uint)strlen(thd->main_security_ctx.user),
- thd->main_security_ctx.host_or_ip, (uint)strlen(thd->main_security_ctx.host_or_ip));
+ PSI_CALL_set_thread_account
+ (thd->main_security_ctx.user, static_cast<uint>(strlen(thd->main_security_ctx.user)),
+ thd->main_security_ctx.host_or_ip, static_cast<uint>(strlen(thd->main_security_ctx.host_or_ip)));
/* Ready to handle queries */
DBUG_RETURN(0);
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 000228945f4..2cf1637c8db 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -167,8 +167,6 @@ enum ACL_internal_access_result
/**
Access granted for all the requested privileges,
do not use the grant tables.
- This flag is used only for the INFORMATION_SCHEMA privileges,
- for compatibility reasons.
*/
ACL_INTERNAL_ACCESS_GRANTED,
/** Access denied, do not use the grant tables. */
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index e5347f2fda4..cfc48c82b4d 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -26,7 +26,6 @@
#include "sql_view.h" // view_checksum
#include "sql_table.h" // mysql_recreate_table
#include "debug_sync.h" // DEBUG_SYNC
-#include "sql_acl.h" // *_ACL
#include "sp.h" // Sroutine_hash_entry
#include "sql_parse.h" // check_table_access
#include "strfunc.h"
@@ -122,9 +121,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
Let us try to open at least a .FRM for this table.
*/
- table_list->mdl_request.init(MDL_key::TABLE,
- table_list->db.str, table_list->table_name.str,
- MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE,
+ table_list->db.str, table_list->table_name.str,
+ MDL_EXCLUSIVE, MDL_TRANSACTION);
if (lock_table_names(thd, table_list, table_list->next_global,
thd->variables.lock_wait_timeout, 0))
@@ -547,8 +546,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
table->table= NULL;
thd->mdl_context.release_transactional_locks();
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, MDL_SHARED_NO_READ_WRITE,
+ MDL_TRANSACTION);
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -822,8 +822,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
table->table= NULL;
thd->mdl_context.release_transactional_locks();
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, MDL_SHARED_NO_READ_WRITE,
+ MDL_TRANSACTION);
table->mdl_request.set_type(MDL_SHARED_READ);
table->lock_type= TL_READ;
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 0828e1b7ba8..23e2e3e097f 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -25,6 +25,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
+ alter_rename_key_list(rhs.alter_rename_key_list, mem_root),
create_list(rhs.create_list, mem_root),
check_constraint_list(rhs.check_constraint_list, mem_root),
flags(rhs.flags), partition_flags(rhs.partition_flags),
@@ -46,6 +47,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
list_copy_and_replace_each_value(drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
+ list_copy_and_replace_each_value(alter_rename_key_list, mem_root);
list_copy_and_replace_each_value(create_list, mem_root);
/* partition_names are not deeply copied currently */
}
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 41408a91836..a553c31346a 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -19,6 +19,7 @@
class Alter_drop;
class Alter_column;
+class Alter_rename_key;
class Key;
/**
@@ -87,6 +88,8 @@ public:
List<Alter_column> alter_list;
// List of keys, used by both CREATE and ALTER TABLE.
List<Key> key_list;
+ // List of keys to be renamed.
+ List<Alter_rename_key> alter_rename_key_list;
// List of columns, used by both CREATE and ALTER TABLE.
List<Create_field> create_list;
@@ -123,6 +126,7 @@ public:
drop_list.empty();
alter_list.empty();
key_list.empty();
+ alter_rename_key_list.empty();
create_list.empty();
check_constraint_list.empty();
flags= 0;
diff --git a/sql/sql_analyze_stmt.cc b/sql/sql_analyze_stmt.cc
index fdabcf1e494..2f87b9b0d40 100644
--- a/sql/sql_analyze_stmt.cc
+++ b/sql/sql_analyze_stmt.cc
@@ -26,6 +26,7 @@
void Filesort_tracker::print_json_members(Json_writer *writer)
{
const char *varied_str= "(varied across executions)";
+ String str;
if (!get_r_loops())
writer->add_member("r_loops").add_null();
@@ -78,6 +79,28 @@ void Filesort_tracker::print_json_members(Json_writer *writer)
else
writer->add_size(sort_buffer_size);
}
+
+ get_data_format(&str);
+ writer->add_member("r_sort_mode").add_str(str.c_ptr(), str.length());
+}
+
+void Filesort_tracker::get_data_format(String *str)
+{
+ if (r_sort_keys_packed)
+ str->append("packed_sort_key");
+ else
+ str->append("sort_key");
+ str->append(",");
+
+ if (r_using_addons)
+ {
+ if (r_packed_addon_fields)
+ str->append("packed_addon_fields");
+ else
+ str->append("addon_fields");
+ }
+ else
+ str->append("rowid");
}
void attach_gap_time_tracker(THD *thd, Gap_time_tracker *gap_tracker,
diff --git a/sql/sql_analyze_stmt.h b/sql/sql_analyze_stmt.h
index 9d5151c3be2..bc7c60a318b 100644
--- a/sql/sql_analyze_stmt.h
+++ b/sql/sql_analyze_stmt.h
@@ -221,7 +221,10 @@ public:
time_tracker(do_timing), r_limit(0), r_used_pq(0),
r_examined_rows(0), r_sorted_rows(0), r_output_rows(0),
sort_passes(0),
- sort_buffer_size(0)
+ sort_buffer_size(0),
+ r_using_addons(false),
+ r_packed_addon_fields(false),
+ r_sort_keys_packed(false)
{}
/* Functions that filesort uses to report various things about its execution */
@@ -263,6 +266,18 @@ public:
else
sort_buffer_size= bufsize;
}
+
+ inline void report_addon_fields_format(bool addons_packed)
+ {
+ r_using_addons= true;
+ r_packed_addon_fields= addons_packed;
+ }
+ inline void report_sort_keys_format(bool sort_keys_packed)
+ {
+ r_sort_keys_packed= sort_keys_packed;
+ }
+
+ void get_data_format(String *str);
/* Functions to get the statistics */
void print_json_members(Json_writer *writer);
@@ -322,6 +337,9 @@ private:
other - value
*/
ulonglong sort_buffer_size;
+ bool r_using_addons;
+ bool r_packed_addon_fields;
+ bool r_sort_keys_packed;
};
diff --git a/sql/sql_array.h b/sql/sql_array.h
index 44dde114d62..b6de1b18d78 100644
--- a/sql/sql_array.h
+++ b/sql/sql_array.h
@@ -114,21 +114,21 @@ template <class Elem> class Dynamic_array
{
DYNAMIC_ARRAY array;
public:
- Dynamic_array(uint prealloc=16, uint increment=16)
+ Dynamic_array(PSI_memory_key psi_key, uint prealloc=16, uint increment=16)
{
- init(prealloc, increment);
+ init(psi_key, prealloc, increment);
}
Dynamic_array(MEM_ROOT *root, uint prealloc=16, uint increment=16)
{
void *init_buffer= alloc_root(root, sizeof(Elem) * prealloc);
- my_init_dynamic_array2(&array, sizeof(Elem), init_buffer,
+ init_dynamic_array2(root->m_psi_key, &array, sizeof(Elem), init_buffer,
prealloc, increment, MYF(0));
}
- void init(uint prealloc=16, uint increment=16)
+ void init(PSI_memory_key psi_key, uint prealloc=16, uint increment=16)
{
- init_dynamic_array2(&array, sizeof(Elem), 0, prealloc, increment, MYF(0));
+ init_dynamic_array2(psi_key, &array, sizeof(Elem), 0, prealloc, increment, MYF(0));
}
/**
@@ -170,6 +170,11 @@ public:
return ((const Elem*)array.buffer) + array.elements - 1;
}
+ const Elem *end() const
+ {
+ return back() + 1;
+ }
+
/// @returns pointer to n-th element
Elem *get_pos(size_t idx)
{
@@ -182,7 +187,6 @@ public:
return ((const Elem*)array.buffer) + idx;
}
-
/**
@retval false ok
@retval true OOM, @c my_error() has been called.
@@ -240,10 +244,16 @@ public:
freeze_size(&array);
}
+ bool reserve(size_t new_size)
+ {
+ return allocate_dynamic(&array, (uint)new_size);
+ }
+
+
bool resize(size_t new_size, Elem default_val)
{
size_t old_size= elements();
- if (unlikely(allocate_dynamic(&array, (uint)new_size)))
+ if (reserve(new_size))
return true;
if (new_size > old_size)
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index ed175ae4865..3e9379ebe33 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -88,7 +88,7 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
if (unlikely(!thd->audit_class_plugins.buffer))
{
/* specify some reasonable initialization defaults */
- my_init_dynamic_array(&thd->audit_class_plugins,
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &thd->audit_class_plugins,
sizeof(plugin_ref), 16, 16, MYF(0));
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c88aef09c96..c41e08e4b8c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -30,9 +30,6 @@
#include "sql_view.h" // mysql_make_view, VIEW_ANY_ACL
#include "sql_parse.h" // check_table_access
#include "sql_insert.h" // kill_delayed_threads
-#include "sql_acl.h" // *_ACL, check_grant_all_columns,
- // check_column_grant_in_table_ref,
- // get_column_grant
#include "sql_partition.h" // ALTER_PARTITION_PARAM_TYPE
#include "sql_derived.h" // mysql_derived_prepare,
// mysql_handle_derived,
@@ -437,7 +434,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
MDL_request *mdl_request= new (thd->mem_root) MDL_request;
if (mdl_request == NULL)
DBUG_RETURN(true);
- mdl_request->init(&table->mdl_request.key, MDL_EXCLUSIVE, MDL_STATEMENT);
+ MDL_REQUEST_INIT_BY_KEY(mdl_request, &table->mdl_request.key,
+ MDL_EXCLUSIVE, MDL_STATEMENT);
mdl_requests.push_front(mdl_request);
}
@@ -566,12 +564,12 @@ bool flush_tables(THD *thd, flush_tables_type flag)
write after last time all tables was closed.
*/
- if (!(tmp_table= (TABLE*) my_malloc(sizeof(*tmp_table),
+ if (!(tmp_table= (TABLE*) my_malloc(PSI_INSTRUMENT_ME, sizeof(*tmp_table),
MYF(MY_WME | MY_THREAD_SPECIFIC))))
DBUG_RETURN(1);
- my_init_dynamic_array(&collect_arg.shares, sizeof(TABLE_SHARE*), 100, 100,
- MYF(0));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares,
+ sizeof(TABLE_SHARE*), 100, 100, MYF(0));
collect_arg.flush_type= flag;
if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares,
&collect_arg, true))
@@ -1577,10 +1575,9 @@ open_table_get_mdl_lock(THD *thd, Open_table_context *ot_ctx,
DBUG_ASSERT(!(flags & MYSQL_OPEN_FORCE_SHARED_MDL) ||
!(flags & MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL));
- mdl_request_shared.init(&mdl_request->key,
- (flags & MYSQL_OPEN_FORCE_SHARED_MDL) ?
- MDL_SHARED : MDL_SHARED_HIGH_PRIO,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT_BY_KEY(&mdl_request_shared, &mdl_request->key,
+ flags & MYSQL_OPEN_FORCE_SHARED_MDL ? MDL_SHARED : MDL_SHARED_HIGH_PRIO,
+ MDL_TRANSACTION);
mdl_request= &mdl_request_shared;
}
@@ -2064,7 +2061,8 @@ retry_share:
{
enum open_frm_error error;
/* make a new table */
- if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
+ if (!(table=(TABLE*) my_malloc(key_memory_TABLE, sizeof(*table),
+ MYF(MY_WME))))
goto err_lock;
error= open_table_from_share(thd, share, &table_list->alias,
@@ -2150,8 +2148,8 @@ retry_share:
DBUG_RETURN(TRUE);
}
- protection_request.init(MDL_key::BACKUP, "", "", mdl_type,
- MDL_STATEMENT);
+ MDL_REQUEST_INIT(&protection_request, MDL_key::BACKUP, "", "", mdl_type,
+ MDL_STATEMENT);
/*
Install error handler which if possible will convert deadlock error
@@ -3004,7 +3002,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
thd->clear_error();
- if (!(entry= (TABLE*)my_malloc(sizeof(TABLE), MYF(MY_WME))))
+ if (!(entry= (TABLE*)my_malloc(key_memory_TABLE, sizeof(TABLE), MYF(MY_WME))))
return result;
if (!(share= tdc_acquire_share(thd, table_list, GTS_TABLE)))
@@ -4043,9 +4041,8 @@ lock_table_names(THD *thd, const DDL_options_st &options,
MDL_request *schema_request= new (thd->mem_root) MDL_request;
if (schema_request == NULL)
DBUG_RETURN(TRUE);
- schema_request->init(MDL_key::SCHEMA, table->db.str, "",
- MDL_INTENTION_EXCLUSIVE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(schema_request, MDL_key::SCHEMA, table->db.str, "",
+ MDL_INTENTION_EXCLUSIVE, MDL_TRANSACTION);
mdl_requests.push_front(schema_request);
}
@@ -4067,7 +4064,8 @@ lock_table_names(THD *thd, const DDL_options_st &options,
if (thd->has_read_only_protection())
DBUG_RETURN(true);
- global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT);
+ MDL_REQUEST_INIT(&global_request, MDL_key::BACKUP, "", "", MDL_BACKUP_DDL,
+ MDL_STATEMENT);
mdl_savepoint= thd->mdl_context.mdl_savepoint();
while (!thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout) &&
@@ -5767,7 +5765,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
replace. If the item was aliased by the user, set the alias to
the replacing item.
*/
- if (*ref && !(*ref)->is_autogenerated_name)
+ if (*ref && !(*ref)->is_autogenerated_name())
item->set_name(thd, (*ref)->name);
if (register_tree_change)
thd->change_item_tree(ref, item);
@@ -5858,7 +5856,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, si
replace. If the item was aliased by the user, set the alias to
the replacing item.
*/
- if (*ref && !(*ref)->is_autogenerated_name)
+ if (*ref && !(*ref)->is_autogenerated_name())
item->set_name(thd, (*ref)->name);
if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup);
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index 44a885bf0eb..ea91f68f360 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -144,7 +144,7 @@ int binlog_defragment(THD *thd)
}
thd->lex->comment.str= // to be freed by the caller
- (char *) my_malloc(thd->lex->comment.length, MYF(MY_WME));
+ (char *) my_malloc(PSI_INSTRUMENT_ME, thd->lex->comment.length, MYF(MY_WME));
if (!thd->lex->comment.str)
{
my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1);
@@ -189,7 +189,7 @@ void mysql_client_binlog_statement(THD* thd)
thd->lex->comment.length : 2048),
thd->lex->comment.str));
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_BINLOG))
DBUG_VOID_RETURN;
/*
@@ -242,7 +242,8 @@ void mysql_client_binlog_statement(THD* thd)
}
decoded_len= my_base64_needed_decoded_length((int)coded_len);
- if (!(buf= (char *) my_malloc(decoded_len, MYF(MY_WME))))
+ if (!(buf= (char *) my_malloc(key_memory_binlog_statement_buffer,
+ decoded_len, MYF(MY_WME))))
{
my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1);
goto end;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 5b649b739c6..00681ba8e2a 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2727,8 +2727,8 @@ size_t Query_cache::init_cache()
DUMP(this);
- (void) my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
- query_cache_query_get_key, 0, 0);
+ (void) my_hash_init(key_memory_Query_cache, &queries, &my_charset_bin,
+ def_query_hash_size, 0,0, query_cache_query_get_key,0,0);
#ifndef FN_NO_CASE_SENSE
/*
If lower_case_table_names!=0 then db and table names are already
@@ -2738,8 +2738,8 @@ size_t Query_cache::init_cache()
lower_case_table_names == 0 then we should distinguish my_table
and MY_TABLE cases and so again can use binary collation.
*/
- (void) my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
- query_cache_table_get_key, 0, 0);
+ (void) my_hash_init(key_memory_Query_cache, &tables, &my_charset_bin,
+ def_table_hash_size, 0,0, query_cache_table_get_key, 0,0);
#else
/*
On windows, OS/2, MacOS X with HFS+ or any other case insensitive
@@ -2749,11 +2749,9 @@ size_t Query_cache::init_cache()
file system) and so should use case insensitive collation for
comparison.
*/
- (void) my_hash_init(&tables,
- lower_case_table_names ? &my_charset_bin :
- files_charset_info,
- def_table_hash_size, 0, 0,query_cache_table_get_key,
- 0, 0);
+ (void) my_hash_init(PSI_INSTRUMENT_ME, &tables, lower_case_table_names ?
+ &my_charset_bin : files_charset_info,
+ def_table_hash_size, 0,0, query_cache_table_get_key, 0,0);
#endif
queries_in_cache = 0;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 2ffb61a98f2..2143a9d4008 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -632,8 +632,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
/* statement id */ 0),
rli_fake(0), rgi_fake(0), rgi_slave(NULL),
- protocol_text(this), protocol_binary(this),
- m_current_stage_key(0),
+ protocol_text(this), protocol_binary(this), initial_status_var(0),
+ m_current_stage_key(0), m_psi(0),
in_sub_stmt(0), log_all_errors(0),
binlog_unsafe_warning_flags(0),
binlog_table_maps(0),
@@ -643,6 +643,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
accessed_rows_and_keys(0),
m_digest(NULL),
m_statement_psi(NULL),
+ m_transaction_psi(NULL),
m_idle_psi(NULL),
col_access(NO_ACL),
thread_id(id),
@@ -743,8 +744,9 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
the destructor works OK in case of an error. The main_mem_root
will be re-initialized in init_for_queries().
*/
- init_sql_alloc(&main_mem_root, "THD::main_mem_root",
- ALLOC_ROOT_MIN_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_thd_main_mem_root,
+ &main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0,
+ MYF(MY_THREAD_SPECIFIC));
/*
Allocation of user variables for binary logging is always done with main
@@ -756,7 +758,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
thread_stack= 0;
scheduler= thread_scheduler; // Will be fixed later
event_scheduler.data= 0;
- event_scheduler.m_psi= 0;
skip_wait_timeout= false;
catalog= (char*)"std"; // the only catalog we have for now
main_security_ctx.init();
@@ -843,12 +844,13 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
profiling.set_thd(this);
#endif
user_connect=(USER_CONN *)0;
- my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
- (my_hash_get_key) get_var_key,
+ my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info,
+ USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key,
(my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC);
- my_hash_init(&sequences, system_charset_info, SEQUENCES_HASH_SIZE, 0, 0,
- (my_hash_get_key) get_sequence_last_key,
- (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
+ my_hash_init(PSI_INSTRUMENT_ME, &sequences, system_charset_info,
+ SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key)
+ get_sequence_last_key, (my_hash_free_key) free_sequence_last,
+ HASH_THREAD_SPECIFIC);
sp_proc_cache= NULL;
sp_func_cache= NULL;
@@ -857,7 +859,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
/* For user vars replication*/
if (opt_bin_log)
- my_init_dynamic_array(&user_var_events,
+ my_init_dynamic_array(key_memory_user_var_entry, &user_var_events,
sizeof(BINLOG_USER_VAR_EVENT *), 16, 16, MYF(0));
else
bzero((char*) &user_var_events, sizeof(user_var_events));
@@ -885,7 +887,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
m_token_array= NULL;
if (max_digest_length > 0)
{
- m_token_array= (unsigned char*) my_malloc(max_digest_length,
+ m_token_array= (unsigned char*) my_malloc(PSI_INSTRUMENT_ME,
+ max_digest_length,
MYF(MY_WME|MY_THREAD_SPECIFIC));
}
@@ -1185,19 +1188,9 @@ void *thd_memdup(MYSQL_THD thd, const void* str, size_t size)
extern "C"
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
{
-#ifdef WITH_WSREP
- if (!thd->wsrep_xid.is_null())
- {
- *xid = *(MYSQL_XID *) &thd->wsrep_xid;
- return;
- }
-#endif /* WITH_WSREP */
- *xid= thd->transaction.xid_state.is_explicit_XA() ?
- *(MYSQL_XID *) thd->transaction.xid_state.get_xid() :
- *(MYSQL_XID *) &thd->transaction.implicit_xid;
+ *xid = *(MYSQL_XID *) thd->get_xid();
}
-
extern "C"
my_time_t thd_TIME_to_gmt_sec(MYSQL_THD thd, const MYSQL_TIME *ltime,
unsigned int *errcode)
@@ -1448,12 +1441,13 @@ void THD::change_user(void)
init();
stmt_map.reset();
- my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
- (my_hash_get_key) get_var_key,
- (my_hash_free_key) free_user_var, 0);
- my_hash_init(&sequences, system_charset_info, SEQUENCES_HASH_SIZE, 0, 0,
- (my_hash_get_key) get_sequence_last_key,
- (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
+ my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info,
+ USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key,
+ (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC);
+ my_hash_init(key_memory_user_var_entry, &sequences, system_charset_info,
+ SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key)
+ get_sequence_last_key, (my_hash_free_key) free_sequence_last,
+ HASH_THREAD_SPECIFIC);
sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache);
sp_cache_clear(&sp_package_spec_cache);
@@ -1490,7 +1484,8 @@ bool THD::set_db(const LEX_CSTRING *new_db)
const char *tmp= NULL;
if (new_db->str)
{
- if (!(tmp= my_strndup(new_db->str, new_db->length, MYF(MY_WME | ME_FATAL))))
+ if (!(tmp= my_strndup(key_memory_THD_db, new_db->str, new_db->length,
+ MYF(MY_WME | ME_FATAL))))
result= 1;
}
@@ -1682,6 +1677,8 @@ THD::~THD()
DBUG_ENTER("~THD()");
/* Make sure threads are not available via server_threads. */
assert_not_linked();
+ if (m_psi)
+ PSI_CALL_set_thread_THD(m_psi, 0);
/*
In error cases, thd may not be current thd. We have to fix this so
@@ -3929,12 +3926,12 @@ Statement_map::Statement_map() :
START_STMT_HASH_SIZE = 16,
START_NAME_HASH_SIZE = 16
};
- my_hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
- get_statement_id_as_hash_key,
+ my_hash_init(key_memory_prepared_statement_map, &st_hash, &my_charset_bin,
+ START_STMT_HASH_SIZE, 0, 0, get_statement_id_as_hash_key,
delete_statement_as_hash_key, MYF(0));
- my_hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
+ my_hash_init(key_memory_prepared_statement_map, &names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
(my_hash_get_key) get_stmt_name_hash_key,
- NULL,MYF(0));
+ NULL, MYF(0));
}
@@ -4338,8 +4335,8 @@ void Security_context::skip_grants()
bool Security_context::set_user(char *user_arg)
{
- my_free((char*) user);
- user= my_strdup(user_arg, MYF(0));
+ my_free(const_cast<char*>(user));
+ user= my_strdup(key_memory_MPVIO_EXT_auth_info, user_arg, MYF(0));
return user == 0;
}
@@ -4827,6 +4824,7 @@ MYSQL_THD create_background_thd()
auto thd_mysysvar= pthread_getspecific(THR_KEY_mysys);
auto thd= new THD(0);
pthread_setspecific(THR_KEY_mysys, save_mysysvar);
+ thd->set_psi(PSI_CALL_get_thread());
/*
Workaround the adverse effect of incrementing thread_count
@@ -6601,7 +6599,8 @@ CPP_UNNAMED_NS_START
}
else
{
- m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME));
+ m_memory= (uchar *) my_malloc(key_memory_Row_data_memory_memory,
+ total_length, MYF(MY_WME));
m_release_memory_on_destruction= TRUE;
}
}
@@ -7785,3 +7784,8 @@ bool THD::timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts,
}
return 0;
}
+
+THD_list_iterator *THD_list_iterator::iterator()
+{
+ return &server_threads;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 13b2659789d..acd304e24ea 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -106,7 +106,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};
@@ -333,17 +334,40 @@ 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)
+ :name(par_name), new_name(_new_name), default_value(NULL), alter_if_exists(false) {}
/**
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;
+
+ Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg)
+ : old_name(old_name_arg), new_name(new_name_arg) {}
+
+ Alter_rename_key *clone(MEM_ROOT *mem_root) const
+ { return new (mem_root) Alter_rename_key(*this); }
+
};
@@ -936,6 +960,10 @@ 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. */
+const int COUNT_GLOBAL_STATUS_VARS= (offsetof(STATUS_VAR, last_system_status_var) /
+ sizeof(ulong)) + 1;
+
/*
Global status variables
*/
@@ -993,6 +1021,39 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs)
return MY_TEST(cs->mbminlen == 1);
}
+/** 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();
+};
+
#ifdef MYSQL_SERVER
void free_tmp_table(THD *thd, TABLE *entry);
@@ -1905,9 +1966,8 @@ public:
m_reopen_array(NULL),
m_locked_tables_count(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);
@@ -2348,9 +2408,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,
@@ -2367,7 +2440,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
}
@@ -2666,9 +2739,8 @@ 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;
Global_read_lock global_read_lock;
@@ -2966,6 +3038,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. */
@@ -2979,6 +3053,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
@@ -4745,6 +4827,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. */
@@ -6253,8 +6346,52 @@ 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 LEX_CSTRING &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; }
};
@@ -6795,8 +6932,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;
}
@@ -6806,7 +6943,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;
@@ -6817,13 +6954,12 @@ 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;
}
-
extern pthread_attr_t *get_connection_attrib(void);
/**
@@ -7191,11 +7327,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.
@@ -7243,28 +7376,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;
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index 1f8f2dcabc9..ce34852117f 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -38,7 +38,7 @@ enum enum_sql_command {
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX,
- SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+ SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_BINLOG_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_SHOW_TRIGGERS,
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index e2a3c482ae4..d5a90089da4 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -35,7 +35,6 @@
#include "sql_db.h" // mysql_change_db
#include "hostname.h" // inc_host_errors, ip_to_hostname,
// reset_host_errors
-#include "privilege.h" // acl_getroot, SUPER_ACL
#include "sql_callback.h"
#ifdef WITH_WSREP
@@ -81,8 +80,8 @@ int get_or_create_user_conn(THD *thd, const char *user,
{
/* First connection for user; Create a user connection object */
if (!(uc= ((struct user_conn*)
- my_malloc(sizeof(struct user_conn) + temp_len+1,
- MYF(MY_WME)))))
+ my_malloc(key_memory_user_conn,
+ sizeof(struct user_conn) + temp_len+1, MYF(MY_WME)))))
{
/* MY_WME ensures an error is set in THD. */
return_val= 1;
@@ -140,7 +139,7 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
if (global_system_variables.max_user_connections &&
!uc->user_resources.user_conn &&
global_system_variables.max_user_connections < uc->connections &&
- !(thd->security_ctx->master_access & SUPER_ACL))
+ !(thd->security_ctx->master_access & PRIV_IGNORE_MAX_USER_CONNECTIONS))
{
my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
error=1;
@@ -322,9 +321,9 @@ extern "C" void free_user(struct user_conn *uc)
void init_max_user_conn(void)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- my_hash_init(&hash_user_connections, system_charset_info, max_connections,
- 0, 0, (my_hash_get_key) get_key_conn,
- (my_hash_free_key) free_user, 0);
+ my_hash_init(key_memory_user_conn, &hash_user_connections,
+ system_charset_info, max_connections, 0, 0, (my_hash_get_key)
+ get_key_conn, (my_hash_free_key) free_user, 0);
#endif
}
@@ -483,14 +482,14 @@ void init_user_stats(USER_STATS *user_stats,
void init_global_user_stats(void)
{
- my_hash_init(&global_user_stats, system_charset_info, max_connections,
+ my_hash_init(PSI_INSTRUMENT_ME, &global_user_stats, system_charset_info, max_connections,
0, 0, (my_hash_get_key) get_key_user_stats,
(my_hash_free_key) free_user_stats, 0);
}
void init_global_client_stats(void)
{
- my_hash_init(&global_client_stats, system_charset_info, max_connections,
+ my_hash_init(PSI_INSTRUMENT_ME, &global_client_stats, system_charset_info, max_connections,
0, 0, (my_hash_get_key) get_key_user_stats,
(my_hash_free_key) free_user_stats, 0);
}
@@ -509,8 +508,8 @@ extern "C" void free_table_stats(TABLE_STATS* table_stats)
void init_global_table_stats(void)
{
- my_hash_init(&global_table_stats, system_charset_info, max_connections,
- 0, 0, (my_hash_get_key) get_key_table_stats,
+ my_hash_init(PSI_INSTRUMENT_ME, &global_table_stats, system_charset_info,
+ max_connections, 0, 0, (my_hash_get_key) get_key_table_stats,
(my_hash_free_key) free_table_stats, 0);
}
@@ -528,8 +527,8 @@ extern "C" void free_index_stats(INDEX_STATS* index_stats)
void init_global_index_stats(void)
{
- my_hash_init(&global_index_stats, system_charset_info, max_connections,
- 0, 0, (my_hash_get_key) get_key_index_stats,
+ my_hash_init(PSI_INSTRUMENT_ME, &global_index_stats, system_charset_info,
+ max_connections, 0, 0, (my_hash_get_key) get_key_index_stats,
(my_hash_free_key) free_index_stats, 0);
}
@@ -571,7 +570,7 @@ static bool increment_count_by_name(const char *name, size_t name_length,
{
/* First connection for this user or client */
if (!(user_stats= ((USER_STATS*)
- my_malloc(sizeof(USER_STATS),
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(USER_STATS),
MYF(MY_WME | MY_ZEROFILL)))))
return TRUE; // Out of memory
@@ -880,7 +879,7 @@ int thd_set_peer_addr(THD *thd,
}
my_free((void *)thd->main_security_ctx.ip);
- if (!(thd->main_security_ctx.ip = my_strdup(ip, MYF(MY_WME))))
+ if (!(thd->main_security_ctx.ip = my_strdup(PSI_INSTRUMENT_ME, ip, MYF(MY_WME))))
{
/*
No error accounting per IP in host_cache,
@@ -1246,7 +1245,8 @@ void prepare_new_connection_state(THD* thd)
thd->set_command(COM_SLEEP);
thd->init_for_queries();
- if (opt_init_connect.length && !(sctx->master_access & SUPER_ACL))
+ if (opt_init_connect.length &&
+ !(sctx->master_access & PRIV_IGNORE_INIT_CONNECT))
{
execute_init_command(thd, &opt_init_connect, &LOCK_sys_init_connect);
if (unlikely(thd->is_error()))
@@ -1435,6 +1435,10 @@ end_thread:
!(connect= cache_thread(thd)))
break;
+ /* Create new instrumentation for the new THD job */
+ PSI_CALL_set_thread(PSI_CALL_new_thread(key_thread_one_connection, thd,
+ thd->thread_id));
+
if (!(connect->create_thd(thd)))
{
/* Out of resources. Free thread to get more resources */
@@ -1449,13 +1453,6 @@ end_thread:
*/
thd->store_globals();
- /*
- Create new instrumentation for the new THD job,
- and attach it to this running pthread.
- */
- PSI_CALL_set_thread(PSI_CALL_new_thread(key_thread_one_connection,
- thd, thd->thread_id));
-
/* reset abort flag for the thread */
thd->mysys_var->abort= 0;
thd->thr_create_utime= microsecond_interval_timer();
@@ -1576,5 +1573,14 @@ THD *CONNECT::create_thd(THD *thd)
thd->scheduler= scheduler;
thd->real_id= pthread_self(); /* Duplicates THD::store_globals() setting. */
+
+ /* Attach PSI instrumentation to the new THD */
+
+ PSI_thread *psi= PSI_CALL_get_thread();
+ PSI_CALL_set_thread_os_id(psi);
+ PSI_CALL_set_thread_THD(psi, thd);
+ PSI_CALL_set_thread_id(psi, thd->thread_id);
+ thd->set_psi(psi);
+
DBUG_RETURN(thd);
}
diff --git a/sql/sql_const.h b/sql/sql_const.h
index f7c820c727b..a3f0e35ac47 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -309,4 +309,6 @@
#define QUERY_PRIOR 6
#endif /* __WIN92__ */
+#define SP_PSI_STATEMENT_INFO_COUNT 19
+
#endif /* SQL_CONST_INCLUDED */
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index c7a0f9186e2..93344956468 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -21,6 +21,7 @@
#include "sql_view.h" // for make_valid_column_names
#include "sql_parse.h"
#include "sql_select.h"
+#include "sql_show.h" // append_definer, append_identifier
/**
@@ -944,9 +945,9 @@ err:
false otherwise
*/
-bool
-With_element::rename_columns_of_derived_unit(THD *thd,
- st_select_lex_unit *unit)
+bool
+With_element::process_columns_of_derived_unit(THD *thd,
+ st_select_lex_unit *unit)
{
if (unit->columns_are_renamed)
return false;
@@ -973,7 +974,7 @@ With_element::rename_columns_of_derived_unit(THD *thd,
while ((item= it++, name= nm++))
{
item->set_name(thd, *name);
- item->is_autogenerated_name= false;
+ item->common_flags&= ~IS_AUTO_GENERATED_NAME;
}
if (arena)
@@ -982,6 +983,43 @@ With_element::rename_columns_of_derived_unit(THD *thd,
else
make_valid_column_names(thd, select->item_list);
+ if (cycle_list)
+ {
+ List_iterator_fast<Item> it(select->item_list);
+ List_iterator_fast<Lex_ident_sys> nm(*cycle_list);
+ List_iterator_fast<Lex_ident_sys> nm_check(*cycle_list);
+ DBUG_ASSERT(cycle_list->elements != 0);
+ while (LEX_CSTRING *name= nm++)
+ {
+ Item *item;
+ /*
+ Check for uniqueness of each element in the cycle list:
+ It's sufficient to check that there is no duplicate of 'name'
+ among the elements that precede it.
+ */
+ LEX_CSTRING *check;
+ nm_check.rewind();
+ while ((check= nm_check++) && check != name)
+ {
+ if (check->length == name->length &&
+ strncmp(check->str, name->str, name->length) == 0)
+ {
+ my_error(ER_DUP_FIELDNAME, MYF(0), check->str);
+ return true;
+ }
+ }
+ /* Check that 'name' is the name of a column of the processed CTE */
+ while ((item= it++) &&
+ (item->name.length != name->length ||
+ strncmp(item->name.str, name->str, name->length) != 0));
+ if (item == NULL)
+ {
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), name->str, "CYCLE clause");
+ return true;
+ }
+ item->common_flags|= IS_IN_WITH_CYCLE;
+ }
+ }
unit->columns_are_renamed= true;
return false;
@@ -1018,7 +1056,7 @@ bool With_element::prepare_unreferenced(THD *thd)
thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
if (!spec->prepared &&
(spec->prepare(spec->derived, 0, 0) ||
- rename_columns_of_derived_unit(thd, spec) ||
+ process_columns_of_derived_unit(thd, spec) ||
check_duplicate_names(thd, first_sl->item_list, 1)))
rc= true;
@@ -1394,16 +1432,17 @@ bool st_select_lex::check_subqueries_with_recursive_references()
/**
@brief
Print this with clause
-
+
+ @param thd Thread handle
@param str Where to print to
- @param query_type The mode of printing
-
+ @param query_type The mode of printing
+
@details
- The method prints a string representation of this clause in the
+ The method prints a string representation of this clause in the
string str. The parameter query_type specifies the mode of printing.
-*/
+*/
-void With_clause::print(String *str, enum_query_type query_type)
+void With_clause::print(THD *thd, String *str, enum_query_type query_type)
{
/*
Any with clause contains just definitions of CTE tables.
@@ -1420,7 +1459,22 @@ void With_clause::print(String *str, enum_query_type query_type)
{
if (with_elem != with_list.first)
str->append(", ");
- with_elem->print(str, query_type);
+ with_elem->print(thd, str, query_type);
+ }
+}
+
+
+static void list_strlex_print(THD *thd, String *str, List<Lex_ident_sys> *list)
+{
+ List_iterator_fast<Lex_ident_sys> li(*list);
+ bool first= TRUE;
+ while(Lex_ident_sys *col_name= li++)
+ {
+ if (first)
+ first= FALSE;
+ else
+ str->append(',');
+ append_identifier(thd, str, col_name);
}
}
@@ -1428,38 +1482,37 @@ void With_clause::print(String *str, enum_query_type query_type)
/**
@brief
Print this with element
-
+
+ @param thd Thread handle
@param str Where to print to
- @param query_type The mode of printing
-
+ @param query_type The mode of printing
+
@details
- The method prints a string representation of this with element in the
+ The method prints a string representation of this with element in the
string str. The parameter query_type specifies the mode of printing.
*/
-void With_element::print(String *str, enum_query_type query_type)
+void With_element::print(THD *thd, String *str, enum_query_type query_type)
{
str->append(query_name);
if (column_list.elements)
{
List_iterator_fast<Lex_ident_sys> li(column_list);
str->append('(');
- for (LEX_CSTRING *col_name= li++; ; )
- {
- str->append(col_name);
- col_name= li++;
- if (!col_name)
- {
- str->append(')');
- break;
- }
- str->append(',');
- }
+ list_strlex_print(thd, str, &column_list);
+ str->append(')');
}
- str->append(STRING_WITH_LEN(" as "));
- str->append('(');
+ str->append(STRING_WITH_LEN(" as ("));
spec->print(str, query_type);
str->append(')');
+
+ if (cycle_list)
+ {
+ DBUG_ASSERT(cycle_list->elements != 0);
+ str->append(STRING_WITH_LEN(" CYCLE "));
+ list_strlex_print(thd, str, cycle_list);
+ str->append(STRING_WITH_LEN(" RESTRICT "));
+ }
}
@@ -1483,3 +1536,26 @@ bool With_element::instantiate_tmp_tables()
return false;
}
+void With_element::set_cycle_list(List<Lex_ident_sys> *cycle_list_arg)
+{
+ cycle_list= cycle_list_arg;
+
+ /*
+ If a CTE table with columns c1,...,cn is defined with a cycle
+ clause CYCLE(ci1,...,cik) then no two rows r1 and r2 from the
+ table shall have r1.ci1=r2.ci1 && ... && r1.cik=r2.cik.
+
+ If a cycle clause is used in the specification of a CTE then
+ each UNION ALL at the top level of the specification is interpreted
+ as a UNION DISTINCT over the cycle columns.
+ */
+ for (st_select_lex *sl= spec->first_select(); sl; sl= sl->next_select())
+ {
+ spec->union_distinct= sl;
+ if (sl != spec->first_select())
+ {
+ sl->distinct= TRUE;
+ sl->with_all_modifier= FALSE;
+ }
+ }
+}
diff --git a/sql/sql_cte.h b/sql/sql_cte.h
index 92aca5090f3..4c42dd23614 100644
--- a/sql/sql_cte.h
+++ b/sql/sql_cte.h
@@ -112,6 +112,7 @@ public:
always empty.
*/
List <Lex_ident_sys> column_list;
+ List <Lex_ident_sys> *cycle_list;
/* The query that specifies the table introduced by this with element */
st_select_lex_unit *spec;
/*
@@ -169,7 +170,7 @@ public:
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
top_level_dep_map(0), sq_rec_ref(NULL),
next_mutually_recursive(NULL), references(0),
- query_name(name), column_list(list), spec(unit),
+ query_name(name), column_list(list), cycle_list(0), spec(unit),
is_recursive(false), rec_outer_references(0), with_anchor(false),
level(0), rec_result(NULL)
{ unit->with_element= this; }
@@ -206,7 +207,7 @@ public:
void inc_references() { references++; }
- bool rename_columns_of_derived_unit(THD *thd, st_select_lex_unit *unit);
+ bool process_columns_of_derived_unit(THD *thd, st_select_lex_unit *unit);
bool prepare_unreferenced(THD *thd);
@@ -214,7 +215,7 @@ public:
table_map &unrestricted,
table_map &encountered);
- void print(String *str, enum_query_type query_type);
+ void print(THD *thd, String *str, enum_query_type query_type);
With_clause *get_owner() { return owner; }
@@ -259,6 +260,8 @@ public:
void prepare_for_next_iteration();
+ void set_cycle_list(List<Lex_ident_sys> *cycle_list_arg);
+
friend class With_clause;
};
@@ -353,7 +356,7 @@ public:
void add_unrestricted(table_map map) { unrestricted|= map; }
- void print(String *str, enum_query_type query_type);
+ void print(THD *thd, String *str, enum_query_type query_type);
friend class With_element;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index ae7f26370fa..3ad7bea5661 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -186,9 +186,9 @@ bool my_dboptions_cache_init(void)
if (!dboptions_init)
{
dboptions_init= 1;
- error= my_hash_init(&dboptions, table_alias_charset,
- 32, 0, 0, (my_hash_get_key) dboptions_get_key,
- free_dbopt,0);
+ error= my_hash_init(key_memory_dboptions_hash, &dboptions,
+ table_alias_charset, 32, 0, 0, (my_hash_get_key)
+ dboptions_get_key, free_dbopt, 0);
}
return error;
}
@@ -218,9 +218,8 @@ void my_dbopt_cleanup(void)
{
mysql_rwlock_wrlock(&LOCK_dboptions);
my_hash_free(&dboptions);
- my_hash_init(&dboptions, table_alias_charset,
- 32, 0, 0, (my_hash_get_key) dboptions_get_key,
- free_dbopt,0);
+ my_hash_init(key_memory_dboptions_hash, &dboptions, table_alias_charset, 32,
+ 0, 0, (my_hash_get_key) dboptions_get_key, free_dbopt, 0);
mysql_rwlock_unlock(&LOCK_dboptions);
}
@@ -290,7 +289,7 @@ static my_bool put_dbopt(const char *dbname, Schema_specification_st *create)
/* Options are not in the hash, insert them */
char *tmp_name;
char *tmp_comment= NULL;
- if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
+ if (!my_multi_malloc(key_memory_dboptions_hash, MYF(MY_WME | MY_ZEROFILL),
&opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
&tmp_comment, (uint) DATABASE_COMMENT_MAXLEN+1,
NullS))
@@ -1148,9 +1147,9 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
(char*) table_list->table_name.str);
table_list->alias= table_list->table_name; // If lower_case_table_names=2
- table_list->mdl_request.init(MDL_key::TABLE, table_list->db.str,
- table_list->table_name.str, MDL_EXCLUSIVE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE,
+ table_list->db.str, table_list->table_name.str,
+ MDL_EXCLUSIVE, MDL_TRANSACTION);
/* Link into list */
(*tot_list_next_local)= table_list;
(*tot_list_next_global)= table_list;
@@ -1547,8 +1546,8 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
TODO: fix check_db_name().
*/
- new_db_file_name.str= my_strndup(new_db_name->str, new_db_name->length,
- MYF(MY_WME));
+ new_db_file_name.str= my_strndup(key_memory_THD_db, new_db_name->str,
+ new_db_name->length, MYF(MY_WME));
new_db_file_name.length= new_db_name->length;
if (new_db_file_name.str == NULL)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 6a4ce266af2..bef77e1a2e9 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -30,7 +30,6 @@
#include "lock.h" // unlock_table_name
#include "sql_view.h" // check_key_in_view, mysql_frm_type
#include "sql_parse.h" // mysql_init_select
-#include "sql_acl.h" // *_ACL
#include "filesort.h" // filesort
#include "sql_handler.h" // mysql_ha_rm_tables
#include "sql_select.h"
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index c713f1322dc..7d09c85a7c7 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -816,8 +816,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
if ((res= unit->prepare(derived, derived->derived_result, 0)))
goto exit;
if (derived->with &&
- (res= derived->with->rename_columns_of_derived_unit(thd, unit)))
- goto exit;
+ (res= derived->with->process_columns_of_derived_unit(thd, unit)))
+ goto exit;
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
if ((res= check_duplicate_names(thd, unit->types, 0)))
goto exit;
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 7e6ffb67b94..4045f30a6bd 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -506,7 +506,7 @@ void Warning_info::init()
{
/* Initialize sub structures */
DBUG_ASSERT(initialized == 0);
- init_sql_alloc(&m_warn_root, "Warning_info", WARN_ALLOC_BLOCK_SIZE,
+ init_sql_alloc(PSI_INSTRUMENT_ME, &m_warn_root, WARN_ALLOC_BLOCK_SIZE,
WARN_ALLOC_PREALLOC_SIZE, MYF(MY_THREAD_SPECIFIC));
initialized= 1;
}
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index bd8c8a4d499..041f77b6f42 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -342,7 +342,7 @@ class Explain_union : public Explain_node
{
public:
Explain_union(MEM_ROOT *root, bool is_analyze) :
- Explain_node(root),
+ Explain_node(root), union_members(PSI_INSTRUMENT_MEM),
is_recursive_cte(false),
fake_select_lex_explain(root, is_analyze)
{}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 12119997430..d7adc35c5c9 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -289,10 +289,11 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
/*
HASH entries are of type SQL_HANDLER
*/
- if (my_hash_init(&thd->handler_tables_hash, &my_charset_latin1,
- HANDLER_TABLES_HASH_SIZE, 0, 0,
- (my_hash_get_key) mysql_ha_hash_get_key,
- (my_hash_free_key) mysql_ha_hash_free, 0))
+ if (my_hash_init(key_memory_THD_handler_tables_hash,
+ &thd->handler_tables_hash, &my_charset_latin1,
+ HANDLER_TABLES_HASH_SIZE, 0, 0, (my_hash_get_key)
+ mysql_ha_hash_get_key, (my_hash_free_key)
+ mysql_ha_hash_free, 0))
{
DBUG_PRINT("exit",("ERROR"));
DBUG_RETURN(TRUE);
@@ -332,8 +333,8 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
right from the start as open_tables() can't handle properly
back-off for such locks.
*/
- tables->mdl_request.init(MDL_key::TABLE, tables->db.str, tables->table_name.str,
- MDL_SHARED_READ, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&tables->mdl_request, MDL_key::TABLE, tables->db.str,
+ tables->table_name.str, MDL_SHARED_READ, MDL_TRANSACTION);
mdl_savepoint= thd->mdl_context.mdl_savepoint();
/* for now HANDLER can be used only for real TABLES */
@@ -384,14 +385,14 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
/* copy data to sql_handler */
if (!(sql_handler= new SQL_HANDLER(thd)))
goto err;
- init_alloc_root(&sql_handler->mem_root, "sql_handler", 1024, 0,
+ init_alloc_root(PSI_INSTRUMENT_ME, &sql_handler->mem_root, 1024, 0,
MYF(MY_THREAD_SPECIFIC));
sql_handler->db.length= tables->db.length;
sql_handler->table_name.length= tables->table_name.length;
sql_handler->handler_name.length= tables->alias.length;
- if (!(my_multi_malloc(MY_WME,
+ if (!(my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&sql_handler->base_data,
(uint) sql_handler->db.length + 1,
&sql_handler->table_name.str,
diff --git a/sql/sql_hset.h b/sql/sql_hset.h
index aaecef9f0d4..b3d8165f6f6 100644
--- a/sql/sql_hset.h
+++ b/sql/sql_hset.h
@@ -31,18 +31,19 @@ public:
Constructs an empty hash. Does not allocate memory, it is done upon
the first insert. Thus does not cause or return errors.
*/
- Hash_set(uchar *(*K)(const T *, size_t *, my_bool),
+ Hash_set(PSI_memory_key psi_key, uchar *(*K)(const T *, size_t *, my_bool),
CHARSET_INFO *cs= &my_charset_bin)
{
my_hash_clear(&m_hash);
m_hash.get_key= (my_hash_get_key)K;
m_hash.charset= cs;
+ m_hash.array.m_psi_key= psi_key;
}
- Hash_set(CHARSET_INFO *charset, ulong default_array_elements,
+ Hash_set(PSI_memory_key psi_key, CHARSET_INFO *charset, ulong default_array_elements,
size_t key_offset, size_t key_length, my_hash_get_key get_key,
void (*free_element)(void*), uint flags)
{
- my_hash_init(&m_hash, charset, default_array_elements, key_offset,
+ my_hash_init(psi_key, &m_hash, charset, default_array_elements, key_offset,
key_length, get_key, free_element, flags);
}
/**
@@ -64,8 +65,8 @@ public:
*/
bool insert(T *value)
{
- my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0,
- m_hash.get_key, 0, HASH_UNIQUE);
+ my_hash_init_opt(m_hash.array.m_psi_key, &m_hash, m_hash.charset,
+ START_SIZE, 0, 0, m_hash.get_key, 0, HASH_UNIQUE);
return my_hash_insert(&m_hash, reinterpret_cast<const uchar*>(value));
}
bool remove(T *value)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 60b60ec1e54..708423c6214 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -67,7 +67,6 @@
#include "sp_head.h"
#include "sql_view.h" // check_key_in_view, insert_view_fields
#include "sql_table.h" // mysql_create_table_no_lock
-#include "sql_acl.h" // *_ACL, check_grant_all_columns
#include "sql_trigger.h"
#include "sql_select.h"
#include "sql_show.h"
@@ -554,8 +553,8 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
if (thd->has_read_only_protection())
DBUG_RETURN(TRUE);
- protection_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DML,
- MDL_STATEMENT);
+ MDL_REQUEST_INIT(&protection_request, MDL_key::BACKUP, "", "",
+ MDL_BACKUP_DML, MDL_STATEMENT);
if (thd->mdl_context.acquire_lock(&protection_request,
thd->variables.lock_wait_timeout))
@@ -2402,7 +2401,8 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
di->thd.variables.binlog_annotate_row_events= 0;
di->thd.set_db(&table_list->db);
- di->thd.set_query(my_strndup(table_list->table_name.str,
+ di->thd.set_query(my_strndup(PSI_INSTRUMENT_ME,
+ table_list->table_name.str,
table_list->table_name.length,
MYF(MY_WME | ME_FATAL)),
table_list->table_name.length, system_charset_info);
@@ -2421,8 +2421,8 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
We need the tickets so that they can be cloned in
handle_delayed_insert
*/
- di->grl_protection.init(MDL_key::BACKUP, "", "",
- MDL_BACKUP_DML, MDL_STATEMENT);
+ MDL_REQUEST_INIT(&di->grl_protection, MDL_key::BACKUP, "", "",
+ MDL_BACKUP_DML, MDL_STATEMENT);
di->grl_protection.ticket= grl_protection_request->ticket;
init_mdl_requests(&di->table_list);
di->table_list.mdl_request.ticket= table_list->mdl_request.ticket;
@@ -2731,7 +2731,8 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
if (query.str)
{
char *str;
- if (!(str= my_strndup(query.str, query.length, MYF(MY_WME))))
+ if (!(str= my_strndup(PSI_INSTRUMENT_ME, query.str, query.length,
+ MYF(MY_WME))))
goto err;
query.str= str;
}
@@ -2754,7 +2755,8 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
ip_len= strlen(thd->security_ctx->ip) + 1;
}
/* This can't be THREAD_SPECIFIC as it's freed in delayed thread */
- if (!(row->record= (char*) my_malloc(table->s->reclength +
+ if (!(row->record= (char*) my_malloc(PSI_INSTRUMENT_ME,
+ table->s->reclength +
user_len + host_len + ip_len,
MYF(MY_WME))))
goto err;
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 3a509b3d750..b3d0d985582 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -937,7 +937,8 @@ int JOIN_CACHE::alloc_buffer()
{
size_t next_buff_size;
- if ((buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC))))
+ if ((buff= (uchar*) my_malloc(key_memory_JOIN_CACHE, buff_size,
+ MYF(MY_THREAD_SPECIFIC))))
break;
next_buff_size= buff_size > buff_size_decr ? buff_size-buff_size_decr : 0;
@@ -1013,11 +1014,11 @@ bool JOIN_CACHE::shrink_join_buffer_in_ratio(ulonglong n, ulonglong d)
int JOIN_CACHE::realloc_buffer()
{
- int rc;
free();
- rc= MY_TEST(!(buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC))));
+ buff= (uchar*) my_malloc(key_memory_JOIN_CACHE, buff_size,
+ MYF(MY_THREAD_SPECIFIC));
reset(TRUE);
- return rc;
+ return buff == NULL;
}
@@ -2084,8 +2085,13 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last)
if (!join_tab->first_unmatched)
{
+ bool pfs_batch_update= join_tab->pfs_batch_update(join);
+ if (pfs_batch_update)
+ join_tab->table->file->start_psi_batch_mode();
/* Find all records from join_tab that match records from join buffer */
rc= join_matching_records(skip_last);
+ if (pfs_batch_update)
+ join_tab->table->file->end_psi_batch_mode();
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
goto finish;
if (outer_join_first_inner)
@@ -2809,12 +2815,12 @@ int JOIN_CACHE_HASHED::init_hash_table()
int JOIN_CACHE_HASHED::realloc_buffer()
{
- int rc;
free();
- rc= MY_TEST(!(buff= (uchar*) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC))));
+ buff= (uchar*) my_malloc(key_memory_JOIN_CACHE, buff_size,
+ MYF(MY_THREAD_SPECIFIC));
init_hash_table();
reset(TRUE);
- return rc;
+ return buff == NULL;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ea60d0cebd0..da255c2701d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -511,7 +511,7 @@ void LEX::add_key_to_list(LEX_CSTRING *field_name,
}
-bool LEX::add_alter_list(const char *name, Virtual_column_info *expr,
+bool LEX::add_alter_list(LEX_CSTRING name, Virtual_column_info *expr,
bool exists)
{
MEM_ROOT *mem_root= thd->mem_root;
@@ -524,6 +524,17 @@ bool LEX::add_alter_list(const char *name, Virtual_column_info *expr,
}
+bool LEX::add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name)
+{
+ Alter_column *ac= new (thd->mem_root) Alter_column(name, new_name);
+ if (unlikely(ac == NULL))
+ return true;
+ alter_info.alter_list.push_back(ac, thd->mem_root);
+ alter_info.flags|= ALTER_RENAME_COLUMN;
+ return false;
+}
+
+
void LEX::init_last_field(Column_definition *field,
const LEX_CSTRING *field_name,
const CHARSET_INFO *cs)
@@ -3503,10 +3514,74 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
}
+/*
+ @brief
+ Print the whole statement
+
+ @param str Print into this string
+ @param query_type Flags describing how to print
+
+ @detail
+ The intent is to allow to eventually print back any query.
+
+ This is useful e.g. for storage engines that take over diferrent kinds of
+ queries
+*/
+
+void LEX::print(String *str, enum_query_type query_type)
+{
+ if (sql_command == SQLCOM_UPDATE)
+ {
+ SELECT_LEX *sel= first_select_lex();
+ str->append(STRING_WITH_LEN("UPDATE "));
+ if (ignore)
+ str->append(STRING_WITH_LEN("IGNORE "));
+ // table name
+ str->append(query_tables->alias);
+ str->append(STRING_WITH_LEN(" SET "));
+ // print item assignments
+ List_iterator<Item> it(sel->item_list);
+ List_iterator<Item> it2(value_list);
+ Item *col_ref, *value;
+ bool first= true;
+ while ((col_ref= it++) && (value= it2++))
+ {
+ if (first)
+ first= false;
+ else
+ str->append(STRING_WITH_LEN(", "));
+ col_ref->print(str, query_type);
+ str->append(STRING_WITH_LEN("="));
+ value->print(str, query_type);
+ }
+
+ str->append(STRING_WITH_LEN(" WHERE "));
+ sel->where->print(str, query_type);
+
+ if (sel->order_list.elements)
+ {
+ str->append(STRING_WITH_LEN(" ORDER BY "));
+ for (ORDER *ord= sel->order_list.first; ord; ord= ord->next)
+ {
+ if (ord != sel->order_list.first)
+ str->append(STRING_WITH_LEN(", "));
+ (*ord->item)->print(str, query_type);
+ }
+ }
+ if (sel->select_limit)
+ {
+ str->append(STRING_WITH_LEN(" LIMIT "));
+ sel->select_limit->print(str, query_type);
+ }
+ }
+ else
+ DBUG_ASSERT(0); // Not implemented yet
+}
+
void st_select_lex_unit::print(String *str, enum_query_type query_type)
{
if (with_clause)
- with_clause->print(str, query_type);
+ with_clause->print(thd, str, query_type);
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl != first_select())
@@ -3751,12 +3826,12 @@ LEX::LEX()
default_used(0), is_lex_started(0), limit_rows_examined_cnt(ULONGLONG_MAX)
{
- init_dynamic_array2(&plugins, sizeof(plugin_ref), plugins_static_buffer,
- INITIAL_LEX_PLUGIN_LIST_SIZE,
+ init_dynamic_array2(PSI_INSTRUMENT_ME, &plugins, sizeof(plugin_ref),
+ plugins_static_buffer, INITIAL_LEX_PLUGIN_LIST_SIZE,
INITIAL_LEX_PLUGIN_LIST_SIZE, 0);
reset_query_tables_list(TRUE);
mi.init();
- init_dynamic_array2(&delete_gtid_domain, sizeof(uint32),
+ init_dynamic_array2(PSI_INSTRUMENT_ME, &delete_gtid_domain, sizeof(uint32),
gtid_domain_static_buffer,
initial_gtid_domain_buffer_size,
initial_gtid_domain_buffer_size, 0);
@@ -5584,8 +5659,8 @@ bool LEX::set_arena_for_set_stmt(Query_arena *backup)
mem_root_for_set_stmt= new MEM_ROOT();
if (unlikely(!(mem_root_for_set_stmt)))
DBUG_RETURN(1);
- init_sql_alloc(mem_root_for_set_stmt, "set_stmt",
- ALLOC_ROOT_SET, ALLOC_ROOT_SET, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(PSI_INSTRUMENT_ME, mem_root_for_set_stmt, ALLOC_ROOT_SET,
+ ALLOC_ROOT_SET, MYF(MY_THREAD_SPECIFIC));
}
if (unlikely(!(arena_for_set_stmt= new(mem_root_for_set_stmt)
Query_arena_memroot(mem_root_for_set_stmt,
@@ -6181,7 +6256,7 @@ static bool is_old(const char *str)
bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) const
{
// "name" is not necessarily NULL-terminated!
- return sphead && sphead->m_handler->type() == TYPE_ENUM_TRIGGER &&
+ return sphead && sphead->m_handler->type() == SP_TYPE_TRIGGER &&
name->length == 3 && (is_new(name->str) || is_old(name->str));
}
@@ -8934,7 +9009,7 @@ sp_package *LEX::create_package_start(THD *thd,
}
if (unlikely(set_command_with_check(command, options)))
return NULL;
- if (sph->type() == TYPE_ENUM_PACKAGE_BODY)
+ if (sph->type() == SP_TYPE_PACKAGE_BODY)
{
/*
If we start parsing a "CREATE PACKAGE BODY", we need to load
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 2d08aa6c79b..b2f0272a7d2 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -30,7 +30,7 @@
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
#include "sql_trigger.h"
-#include "sp.h" // enum stored_procedure_type
+#include "sp.h" // enum enum_sp_type
#include "sql_tvc.h"
#include "item.h"
#include "sql_limit.h" // Select_limit_counters
@@ -510,11 +510,11 @@ struct LEX_MASTER_INFO
void init()
{
bzero(this, sizeof(*this));
- my_init_dynamic_array(&repl_ignore_server_ids,
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_ignore_server_ids,
sizeof(::server_id), 0, 16, MYF(0));
- my_init_dynamic_array(&repl_do_domain_ids,
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_do_domain_ids,
sizeof(ulong), 0, 16, MYF(0));
- my_init_dynamic_array(&repl_ignore_domain_ids,
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &repl_ignore_domain_ids,
sizeof(ulong), 0, 16, MYF(0));
sql_delay= -1;
}
@@ -3264,6 +3264,7 @@ public:
void reset_arena_for_set_stmt(Query_arena *backup);
void free_arena_for_set_stmt();
+ void print(String *str, enum_query_type qtype);
List<Item_func_set_user_var> set_var_list; // in-query assignment list
List<Item_param> param_list;
List<LEX_CSTRING> view_list; // view list (list of field names in view)
@@ -4320,8 +4321,9 @@ public:
alter_info.check_constraint_list.push_back(constr);
return false;
}
- bool add_alter_list(const char *par_name, Virtual_column_info *expr,
+ bool add_alter_list(LEX_CSTRING par_name, Virtual_column_info *expr,
bool par_exists);
+ bool add_alter_list(LEX_CSTRING name, LEX_CSTRING new_name);
void set_command(enum_sql_command command,
DDL_options_st options)
{
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 9d1c01a484d..91134bcbeb2 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -677,7 +677,8 @@ struct ilink
struct ilink **prev,*next;
static void *operator new(size_t size) throw ()
{
- return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATAL));
+ return (void*)my_malloc(PSI_INSTRUMENT_ME,
+ (uint)size, MYF(MY_WME | MY_FAE | ME_FATAL));
}
static void operator delete(void* ptr_arg, size_t)
{
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index 2ad8d8a914a..a3d1a7242e4 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -51,7 +51,8 @@ bool mysql_manager_submit(void (*action)())
cb= &(*cb)->next;
if (!*cb)
{
- *cb= (struct handler_cb *)my_malloc(sizeof(struct handler_cb), MYF(MY_WME));
+ *cb= (struct handler_cb *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(struct handler_cb), MYF(MY_WME));
if (!*cb)
result= TRUE;
else
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index dac5b025821..cb0d210b12c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -56,13 +56,6 @@
#include "sql_rename.h" // mysql_rename_tables
#include "sql_tablespace.h" // mysql_alter_tablespace
#include "hostname.h" // hostname_cache_refresh
-#include "sql_acl.h" // *_ACL, check_grant, is_acl_user,
- // has_any_table_level_privileges,
- // mysql_drop_user, mysql_rename_user,
- // check_grant_routine,
- // mysql_routine_grant,
- // mysql_show_grants,
- // sp_grant_privileges, ...
#include "sql_test.h" // mysql_print_status
#include "sql_select.h" // handle_select, mysql_select,
// mysql_explain_union
@@ -101,6 +94,7 @@
#include "sql_bootstrap.h"
#include "sql_sequence.h"
#include "opt_trace.h"
+#include "mysql/psi/mysql_sp.h"
#include "my_json_writer.h"
@@ -679,7 +673,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_CREATE_USER]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_BINLOG_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
@@ -1010,7 +1004,8 @@ int bootstrap(MYSQL_FILE *file)
thd->thread_stack= (char*) &thd;
thd->store_globals();
- thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
+ thd->security_ctx->user= (char*) my_strdup(key_memory_MPVIO_EXT_auth_info,
+ "boot", MYF(MY_WME));
thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=
thd->security_ctx->priv_role[0]= 0;
/*
@@ -1404,7 +1399,7 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
LEX *lex= thd->lex;
/* Super user is allowed to do changes */
- if ((thd->security_ctx->master_access & SUPER_ACL) == SUPER_ACL)
+ if ((thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) != NO_ACL)
DBUG_RETURN(FALSE);
/* Check if command doesn't update anything */
@@ -1444,10 +1439,10 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables)
{
int opt_readonly_saved = opt_readonly;
- privilege_t flag_saved= thd->security_ctx->master_access & SUPER_ACL;
+ privilege_t flag_saved= thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY;
opt_readonly = 0;
- thd->security_ctx->master_access &= ~SUPER_ACL;
+ thd->security_ctx->master_access &= ~PRIV_IGNORE_READ_ONLY;
my_bool ret = !deny_updates_if_read_only_option(thd, all_tables);
@@ -1464,7 +1459,7 @@ static void wsrep_copy_query(THD *thd)
if (thd->wsrep_retry_query) {
my_free(thd->wsrep_retry_query);
}
- thd->wsrep_retry_query = (char *)my_malloc(
+ thd->wsrep_retry_query = (char *)my_malloc(PSI_INSTRUMENT_ME,
thd->wsrep_retry_query_len + 1, MYF(0));
strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len);
thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0';
@@ -1908,8 +1903,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
com_statement_info[command].m_key,
thd->db.str, thd->db.length,
- thd->charset());
- THD_STAGE_INFO(thd, stage_init);
+ thd->charset(), NULL);
+ THD_STAGE_INFO(thd, stage_starting);
MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt,
length);
@@ -2091,7 +2086,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
status_var_increment(thd->status_var.com_other);
thd->query_plan_flags|= QPLAN_ADMIN;
- if (check_global_access(thd, REPL_SLAVE_ACL))
+ if (check_global_access(thd, PRIV_COM_BINLOG_DUMP))
break;
/* TODO: The following has to be changed to an 8 byte integer */
@@ -2247,12 +2242,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_PROCESS_INFO:
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]);
if (!thd->security_ctx->priv_user[0] &&
- check_global_access(thd, PROCESS_ACL))
+ check_global_access(thd, PRIV_COM_PROCESS_INFO))
break;
general_log_print(thd, command, NullS);
mysqld_list_processes(thd,
- thd->security_ctx->master_access & PROCESS_ACL ?
- NullS : thd->security_ctx->priv_user, 0);
+ thd->security_ctx->master_access & PRIV_COM_PROCESS_INFO ?
+ NullS : thd->security_ctx->priv_user, 0);
break;
case COM_PROCESS_KILL:
{
@@ -2284,7 +2279,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_DEBUG:
status_var_increment(thd->status_var.com_other);
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_DEBUG))
break; /* purecov: inspected */
mysql_print_status();
general_log_print(thd, command, NullS);
@@ -2838,7 +2833,7 @@ bool sp_process_definer(THD *thd)
!my_strcasecmp(system_charset_info, d->host.str,
thd->security_ctx->priv_host);
if (!curuserhost && !currole &&
- check_global_access(thd, SUPER_ACL, false))
+ check_global_access(thd, PRIV_DEFINER_CLAUSE, false))
DBUG_RETURN(TRUE);
}
@@ -3062,7 +3057,7 @@ mysql_create_routine(THD *thd, LEX *lex)
const LEX_CSTRING *name= lex->sphead->name();
#ifdef HAVE_DLOPEN
- if (lex->sphead->m_handler->type() == TYPE_ENUM_FUNCTION)
+ if (lex->sphead->m_handler->type() == SP_TYPE_FUNCTION)
{
udf_func *udf = find_udf(name->str, name->length);
@@ -3826,7 +3821,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_EXPLAIN:
{
if (!thd->security_ctx->priv_user[0] &&
- check_global_access(thd,PROCESS_ACL))
+ check_global_access(thd, PRIV_STMT_SHOW_EXPLAIN))
break;
/*
@@ -3944,7 +3939,7 @@ mysql_execute_command(THD *thd)
#ifndef EMBEDDED_LIBRARY
case SQLCOM_PURGE:
{
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_PURGE_BINLOG))
goto error;
/* PURGE MASTER LOGS TO 'file' */
res = purge_master_logs(thd, lex->to_log);
@@ -3954,7 +3949,7 @@ mysql_execute_command(THD *thd)
{
Item *it;
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_PURGE_BINLOG))
goto error;
/* PURGE MASTER LOGS BEFORE 'data' */
it= (Item *)lex->value_list.head();
@@ -4001,16 +3996,23 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
case SQLCOM_SHOW_SLAVE_HOSTS:
{
- if (check_global_access(thd, REPL_SLAVE_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_SLAVE_HOSTS))
goto error;
res = show_slave_hosts(thd);
break;
}
- case SQLCOM_SHOW_RELAYLOG_EVENTS: /* fall through */
+ case SQLCOM_SHOW_RELAYLOG_EVENTS:
+ {
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
+ if (check_global_access(thd, PRIV_STMT_SHOW_RELAYLOG_EVENTS))
+ goto error;
+ res = mysql_show_binlog_events(thd);
+ break;
+ }
case SQLCOM_SHOW_BINLOG_EVENTS:
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
- if (check_global_access(thd, REPL_SLAVE_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_BINLOG_EVENTS))
goto error;
res = mysql_show_binlog_events(thd);
break;
@@ -4047,7 +4049,7 @@ mysql_execute_command(THD *thd)
bool new_master= 0;
bool master_info_added;
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_CHANGE_MASTER))
goto error;
/*
In this code it's ok to use LOCK_active_mi as we are adding new things
@@ -4102,10 +4104,10 @@ mysql_execute_command(THD *thd)
break;
}
- case SQLCOM_SHOW_MASTER_STAT:
+ case SQLCOM_SHOW_BINLOG_STAT:
{
/* Accept one of two privileges */
- if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_BINLOG_STATUS))
goto error;
res = show_binlog_info(thd);
break;
@@ -4114,14 +4116,14 @@ mysql_execute_command(THD *thd)
#endif /* HAVE_REPLICATION */
case SQLCOM_SHOW_ENGINE_STATUS:
{
- if (check_global_access(thd, PROCESS_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_ENGINE_STATUS))
goto error;
res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS);
break;
}
case SQLCOM_SHOW_ENGINE_MUTEX:
{
- if (check_global_access(thd, PROCESS_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_ENGINE_MUTEX))
goto error;
res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX);
break;
@@ -4282,7 +4284,7 @@ mysql_execute_command(THD *thd)
goto error;
#else
{
- if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
+ if (check_global_access(thd, PRIV_STMT_SHOW_BINARY_LOGS))
goto error;
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
res = show_binlogs(thd);
@@ -4414,7 +4416,7 @@ mysql_execute_command(THD *thd)
if (res)
break;
if (opt_readonly &&
- !(thd->security_ctx->master_access & SUPER_ACL) &&
+ !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
some_non_temp_table_to_be_updated(thd, all_tables))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
@@ -4890,13 +4892,13 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
- check_global_access(thd,PROCESS_ACL))
+ check_global_access(thd, PRIV_STMT_SHOW_PROCESSLIST))
break;
mysqld_list_processes(thd,
- (thd->security_ctx->master_access & PROCESS_ACL ?
- NullS :
- thd->security_ctx->priv_user),
- lex->verbose);
+ (thd->security_ctx->master_access & PRIV_STMT_SHOW_PROCESSLIST ?
+ NullS :
+ thd->security_ctx->priv_user),
+ lex->verbose);
break;
case SQLCOM_SHOW_AUTHORS:
res= mysqld_show_authors(thd);
@@ -4940,8 +4942,9 @@ mysql_execute_command(THD *thd)
if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
!opt_local_infile)
{
- my_message(ER_NOT_ALLOWED_COMMAND, ER_THD(thd, ER_NOT_ALLOWED_COMMAND), MYF(0));
- goto error;
+ my_message(ER_LOAD_INFILE_CAPABILITY_DISABLED,
+ ER_THD(thd, ER_LOAD_INFILE_CAPABILITY_DISABLED), MYF(0));
+ goto error;
}
}
@@ -5615,12 +5618,18 @@ mysql_execute_command(THD *thd)
break; /* break super switch */
} /* end case group bracket */
case SQLCOM_COMPOUND:
+ {
+ sp_head *sp= lex->sphead;
DBUG_ASSERT(all_tables == 0);
DBUG_ASSERT(thd->in_sub_stmt == 0);
- lex->sphead->m_sql_mode= thd->variables.sql_mode;
+ sp->m_sql_mode= thd->variables.sql_mode;
+ sp->m_sp_share= MYSQL_GET_SP_SHARE(sp->m_handler->type(),
+ sp->m_db.str, static_cast<uint>(sp->m_db.length),
+ sp->m_name.str, static_cast<uint>(sp->m_name.length));
if (do_execute_sp(thd, lex->sphead))
goto error;
break;
+ }
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_FUNCTION:
@@ -5801,7 +5810,7 @@ mysql_execute_command(THD *thd)
{
DBUG_PRINT("info", ("case SQLCOM_CREATE_SERVER"));
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_CREATE_SERVER))
break;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
@@ -5814,7 +5823,7 @@ mysql_execute_command(THD *thd)
int error;
DBUG_PRINT("info", ("case SQLCOM_ALTER_SERVER"));
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_ALTER_SERVER))
break;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
@@ -5834,7 +5843,7 @@ mysql_execute_command(THD *thd)
int err_code;
DBUG_PRINT("info", ("case SQLCOM_DROP_SERVER"));
- if (check_global_access(thd, SUPER_ACL))
+ if (check_global_access(thd, PRIV_STMT_DROP_SERVER))
break;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
@@ -6179,6 +6188,7 @@ execute_show_status(THD *thd, TABLE_LIST *all_tables)
UINT_MAX, FALSE)))
res= execute_sqlcom_select(thd, all_tables);
+ thd->initial_status_var= NULL;
/* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
@@ -7136,10 +7146,8 @@ bool check_some_access(THD *thd, privilege_t want_access, TABLE_LIST *table)
@param want_access Use should have any of these global rights
@warning
- One gets access right if one has ANY of the rights in want_access.
- This is useful as one in most cases only need one global right,
- but in some case we want to check if the user has SUPER or
- REPL_CLIENT_ACL rights.
+ Starting from 10.5.2 only one bit is allowed in want_access.
+ Access denied error is returned if want_access has multiple bits set.
@retval
0 ok
@@ -7151,7 +7159,7 @@ bool check_global_access(THD *thd, privilege_t want_access, bool no_errors)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
char command[128];
- if ((thd->security_ctx->master_access & want_access))
+ if (thd->security_ctx->master_access & want_access)
return 0;
if (unlikely(!no_errors))
{
@@ -7365,11 +7373,11 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, size_t *yystacksize)
old_info= *yystacksize;
*yystacksize= set_zone((int)(*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
if (!(state->yacc_yyvs= (uchar*)
- my_realloc(state->yacc_yyvs,
+ my_realloc(key_memory_bison_stack, state->yacc_yyvs,
*yystacksize*sizeof(**yyvs),
MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
!(state->yacc_yyss= (uchar*)
- my_realloc(state->yacc_yyss,
+ my_realloc(key_memory_bison_stack, state->yacc_yyss,
*yystacksize*sizeof(**yyss),
MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
return 1;
@@ -8219,9 +8227,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
// Pure table aliases do not need to be locked:
if (ptr->db.str && !(table_options & TL_OPTION_ALIAS))
{
- ptr->mdl_request.init(MDL_key::TABLE, ptr->db.str, ptr->table_name.str,
- mdl_type,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&ptr->mdl_request, MDL_key::TABLE, ptr->db.str,
+ ptr->table_name.str, mdl_type, MDL_TRANSACTION);
}
DBUG_RETURN(ptr);
}
@@ -9090,11 +9097,11 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
*/
#ifdef WITH_WSREP
- if (((thd->security_ctx->master_access & SUPER_ACL) ||
+ if (((thd->security_ctx->master_access & PRIV_KILL_OTHER_USER_PROCESS) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_BF(tmp, false) && !tmp->wsrep_applier)
#else
- if ((thd->security_ctx->master_access & SUPER_ACL) ||
+ if ((thd->security_ctx->master_access & PRIV_KILL_OTHER_USER_PROCESS) ||
thd->security_ctx->user_matches(tmp->security_ctx))
#endif /* WITH_WSREP */
{
@@ -9147,7 +9154,8 @@ static my_bool kill_threads_callback(THD *thd, kill_threads_callback_arg *arg)
!strcmp(thd->security_ctx->host_or_ip, arg->user->host.str)) &&
!strcmp(thd->security_ctx->user, arg->user->user.str))
{
- if (!(arg->thd->security_ctx->master_access & SUPER_ACL) &&
+ if (!(arg->thd->security_ctx->master_access &
+ PRIV_KILL_OTHER_USER_PROCESS) &&
!arg->thd->security_ctx->user_matches(thd->security_ctx))
return 1;
if (!arg->threads_to_kill.push_back(thd, arg->thd->mem_root))
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 5885e3715bf..f722dc54fb4 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4805,7 +4805,6 @@ static void check_datadir_altered_for_innodb(THD *thd,
uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
HA_CREATE_INFO *create_info,
- Alter_table_ctx *alter_ctx,
bool *partition_changed,
bool *fast_alter_table)
{
@@ -4900,8 +4899,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
object to allow fast_alter_partition_table to perform the changes.
*/
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
- alter_ctx->db.str,
- alter_ctx->table_name.str,
+ table->s->db.str,
+ table->s->table_name.str,
MDL_INTENTION_EXCLUSIVE));
tab_part_info= table->part_info;
@@ -7501,7 +7500,7 @@ void append_row_to_str(String &str, const uchar *row, TABLE *table)
rec= row;
/* Create a new array of all read fields. */
- fields= (Field**) my_malloc(sizeof(void*) * (num_fields + 1),
+ fields= (Field**) my_malloc(PSI_INSTRUMENT_ME, sizeof(void*) * (num_fields + 1),
MYF(0));
if (!fields)
return;
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 8732aacbbd7..58ba82dcd9f 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -262,7 +262,6 @@ bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
enum partition_state part_state);
uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
HA_CREATE_INFO *create_info,
- Alter_table_ctx *alter_ctx,
bool *partition_changed,
bool *fast_alter_table);
char *generate_partition_syntax(THD *thd, partition_info *part_info,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index bbfbdc3a22e..1d18b0ef392 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -28,7 +28,6 @@
#include "sql_table.h"
#include "sql_show.h" // remove_status_vars, add_status_vars
#include "strfunc.h" // find_set
-#include "sql_acl.h" // *_ACL
#include "records.h" // init_read_record, end_read_record
#include <my_pthread.h>
#include <my_getopt.h>
@@ -42,6 +41,12 @@
#include <mysql/plugin_function.h>
#include "sql_plugin_compat.h"
+static PSI_memory_key key_memory_plugin_mem_root;
+static PSI_memory_key key_memory_plugin_int_mem_root;
+static PSI_memory_key key_memory_mysql_plugin;
+static PSI_memory_key key_memory_mysql_plugin_dl;
+static PSI_memory_key key_memory_plugin_bookmark;
+
#ifdef HAVE_LINK_H
#include <link.h>
#endif
@@ -573,7 +578,7 @@ static my_bool read_mysql_plugin_info(struct st_plugin_dl *plugin_dl,
/* no op */;
cur= (struct st_maria_plugin*)
- my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ my_malloc(key_memory_mysql_plugin, (i + 1) * sizeof(struct st_maria_plugin),
MYF(MY_ZEROFILL|MY_WME));
if (!cur)
{
@@ -693,7 +698,7 @@ static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
/* no op */;
cur= (struct st_maria_plugin*)
- my_malloc((i + 1) * sizeof(struct st_maria_plugin),
+ my_malloc(key_memory_mysql_plugin, (i + 1) * sizeof(struct st_maria_plugin),
MYF(MY_ZEROFILL|MY_WME));
if (!cur)
{
@@ -818,7 +823,8 @@ static st_plugin_dl *plugin_dl_add(const LEX_CSTRING *dl, myf MyFlags)
if (plugin_dl.nbackups)
{
size_t bytes= plugin_dl.nbackups * sizeof(plugin_dl.ptr_backup[0]);
- plugin_dl.ptr_backup= (st_ptr_backup *)my_malloc(bytes, MYF(0));
+ plugin_dl.ptr_backup= (st_ptr_backup *)my_malloc(key_memory_mysql_plugin_dl,
+ bytes, MYF(0));
if (!plugin_dl.ptr_backup)
{
restore_ptr_backup(plugin_dl.nbackups, tmp_backup);
@@ -830,7 +836,8 @@ static st_plugin_dl *plugin_dl_add(const LEX_CSTRING *dl, myf MyFlags)
/* Duplicate and convert dll name */
plugin_dl.dl.length= dl->length * files_charset_info->mbmaxlen + 1;
- if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
+ if (! (plugin_dl.dl.str= (char*) my_malloc(key_memory_mysql_plugin_dl,
+ plugin_dl.dl.length, MYF(0))))
{
my_error(ER_OUTOFMEMORY, MyFlags,
static_cast<int>(plugin_dl.dl.length));
@@ -977,7 +984,8 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc,
memory manager and/or valgrind to track locked references and
double unlocks to aid resolving reference counting problems.
*/
- if (!(plugin= (plugin_ref) my_malloc(sizeof(pi), MYF(MY_WME))))
+ if (!(plugin= (plugin_ref) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(pi),
+ MYF(MY_WME))))
DBUG_RETURN(NULL);
*plugin= pi;
@@ -1186,7 +1194,8 @@ static enum install_status plugin_add(MEM_ROOT *tmp_root, bool if_not_exists,
goto err;
if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
- init_alloc_root(&tmp_plugin_ptr->mem_root, "plugin", 4096, 4096, MYF(0));
+ init_alloc_root(key_memory_plugin_int_mem_root, &tmp_plugin_ptr->mem_root,
+ 4096, 4096, MYF(0));
if (name->str)
DBUG_RETURN(INSTALL_GOOD); // all done
@@ -1541,6 +1550,15 @@ static PSI_mutex_info all_plugin_mutexes[]=
{ &key_LOCK_plugin, "LOCK_plugin", PSI_FLAG_GLOBAL}
};
+static PSI_memory_info all_plugin_memory[]=
+{
+ { &key_memory_plugin_mem_root, "plugin_mem_root", PSI_FLAG_GLOBAL},
+ { &key_memory_plugin_int_mem_root, "plugin_int_mem_root", 0},
+ { &key_memory_mysql_plugin_dl, "mysql_plugin_dl", 0},
+ { &key_memory_mysql_plugin, "mysql_plugin", 0},
+ { &key_memory_plugin_bookmark, "plugin_bookmark", PSI_FLAG_GLOBAL}
+};
+
static void init_plugin_psi_keys(void)
{
const char* category= "sql";
@@ -1551,7 +1569,12 @@ static void init_plugin_psi_keys(void)
count= array_elements(all_plugin_mutexes);
PSI_server->register_mutex(category, all_plugin_mutexes, count);
+
+ count= array_elements(all_plugin_memory);
+ mysql_memory_register(category, all_plugin_memory, count);
}
+#else
+static void init_plugin_psi_keys(void) {}
#endif /* HAVE_PSI_INTERFACE */
/*
@@ -1578,11 +1601,13 @@ int plugin_init(int *argc, char **argv, int flags)
dlopen_count =0;
- init_alloc_root(&plugin_mem_root, "plugin", 4096, 4096, MYF(0));
- init_alloc_root(&plugin_vars_mem_root, "plugin_vars", 4096, 4096, MYF(0));
- init_alloc_root(&tmp_root, "plugin_tmp", 4096, 4096, MYF(0));
+ init_plugin_psi_keys();
+
+ init_alloc_root(key_memory_plugin_mem_root, &plugin_mem_root, 4096, 4096, MYF(0));
+ init_alloc_root(key_memory_plugin_mem_root, &plugin_vars_mem_root, 4096, 4096, MYF(0));
+ init_alloc_root(PSI_NOT_INSTRUMENTED, &tmp_root, 4096, 4096, MYF(0));
- if (my_hash_init(&bookmark_hash, &my_charset_bin, 32, 0, 0,
+ if (my_hash_init(key_memory_plugin_bookmark, &bookmark_hash, &my_charset_bin, 32, 0, 0,
get_bookmark_hash_key, NULL, HASH_UNIQUE))
goto err;
@@ -1590,15 +1615,15 @@ int plugin_init(int *argc, char **argv, int flags)
The 80 is from 2016-04-27 when we had 71 default plugins
Big enough to avoid many mallocs even in future
*/
- if (my_init_dynamic_array(&plugin_dl_array,
+ if (my_init_dynamic_array(key_memory_mysql_plugin_dl, &plugin_dl_array,
sizeof(struct st_plugin_dl *), 16, 16, MYF(0)) ||
- my_init_dynamic_array(&plugin_array,
+ my_init_dynamic_array(key_memory_mysql_plugin, &plugin_array,
sizeof(struct st_plugin_int *), 80, 32, MYF(0)))
goto err;
for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
{
- if (my_hash_init(&plugin_hash[i], system_charset_info, 32, 0, 0,
+ if (my_hash_init(key_memory_plugin_mem_root, &plugin_hash[i], system_charset_info, 32, 0, 0,
get_plugin_hash_key, NULL, HASH_UNIQUE))
goto err;
}
@@ -2214,6 +2239,7 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
mysql_audit_acquire_plugins(thd, event_class_mask);
mysql_mutex_lock(&LOCK_plugin);
+ DEBUG_SYNC(thd, "acquired_LOCK_plugin");
error= plugin_add(thd->mem_root, thd->lex->create_info.if_not_exists(),
name, &dl, MYF(0));
if (unlikely(error != INSTALL_GOOD))
@@ -2832,7 +2858,8 @@ static void update_func_str(THD *thd, struct st_mysql_sys_var *var,
{
char *old= *(char**) tgt;
if (value)
- *(char**) tgt= my_strdup(value, MYF(0));
+ *(char**) tgt= my_strdup(key_memory_global_system_variables,
+ value, MYF(0));
else
*(char**) tgt= 0;
my_free(old);
@@ -2976,10 +3003,12 @@ static st_bookmark *register_var(const char *plugin, const char *name,
if (new_size > global_variables_dynamic_size)
{
global_system_variables.dynamic_variables_ptr= (char*)
- my_realloc(global_system_variables.dynamic_variables_ptr, new_size,
+ my_realloc(key_memory_global_system_variables,
+ global_system_variables.dynamic_variables_ptr, new_size,
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
max_system_variables.dynamic_variables_ptr= (char*)
- my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
+ my_realloc(key_memory_global_system_variables,
+ max_system_variables.dynamic_variables_ptr, new_size,
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
/*
Clear the new variable value space. This is required for string
@@ -3021,7 +3050,8 @@ void sync_dynamic_session_variables(THD* thd, bool global_lock)
uint idx;
thd->variables.dynamic_variables_ptr= (char*)
- my_realloc(thd->variables.dynamic_variables_ptr,
+ my_realloc(key_memory_THD_variables,
+ thd->variables.dynamic_variables_ptr,
global_variables_dynamic_size,
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
@@ -3055,7 +3085,7 @@ void sync_dynamic_session_variables(THD* thd, bool global_lock)
{
char **pp= (char**) (thd->variables.dynamic_variables_ptr + v->offset);
if (*pp)
- *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE));
+ *pp= my_strdup(key_memory_THD_variables, *pp, MYF(MY_WME|MY_FAE));
}
}
@@ -3912,7 +3942,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
(opt->flags & PLUGIN_VAR_MEMALLOC))
{
char *def_val= *(char**)var_def_ptr(opt);
- *(char**)val= def_val ? my_strdup(def_val, MYF(0)) : NULL;
+ *(char**)val= def_val ? my_strdup(PSI_INSTRUMENT_ME, def_val, MYF(0)) : NULL;
}
else
memcpy(val, var_def_ptr(opt), var_storage_size(opt->flags));
@@ -4349,9 +4379,7 @@ int thd_setspecific(MYSQL_THD thd, MYSQL_THD_KEY_T key, void *value)
void plugin_mutex_init()
{
-#ifdef HAVE_PSI_INTERFACE
init_plugin_psi_keys();
-#endif
mysql_mutex_init(key_LOCK_plugin, &LOCK_plugin, MY_MUTEX_INIT_FAST);
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index dcf445f3cfb..98ffc842196 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -99,7 +99,6 @@ When one supplies long data for a placeholder:
#include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert
#include "sql_update.h" // mysql_prepare_update
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
-#include "sql_acl.h" // *_ACL
#include "sql_derived.h" // mysql_derived_prepare,
// mysql_handle_derived
#include "sql_cte.h"
@@ -122,6 +121,7 @@ When one supplies long data for a placeholder:
#include "lock.h" // MYSQL_OPEN_FORCE_SHARED_MDL
#include "sql_handler.h"
#include "transaction.h" // trans_rollback_implicit
+#include "mysql/psi/mysql_ps.h" // MYSQL_EXECUTE_PS
#include "wsrep_mysqld.h"
/**
@@ -160,6 +160,7 @@ public:
};
THD *thd;
+ PSI_prepared_stmt* m_prepared_stmt;
Select_fetch_protocol_binary result;
Item_param **param_array;
Server_side_cursor *cursor;
@@ -1947,7 +1948,7 @@ static int mysql_test_show_slave_status(Prepared_statement *stmt,
/**
- Validate and prepare for execution SHOW MASTER STATUS statement.
+ Validate and prepare for execution SHOW BINLOG STATUS statement.
@param stmt prepared statement
@@ -1957,9 +1958,9 @@ static int mysql_test_show_slave_status(Prepared_statement *stmt,
TRUE error, error message is set in THD
*/
-static int mysql_test_show_master_status(Prepared_statement *stmt)
+static int mysql_test_show_binlog_status(Prepared_statement *stmt)
{
- DBUG_ENTER("mysql_test_show_master_status");
+ DBUG_ENTER("mysql_test_show_binlog_status");
THD *thd= stmt->thd;
List<Item> fields;
@@ -2408,8 +2409,8 @@ static bool check_prepared_statement(Prepared_statement *stmt)
}
break;
}
- case SQLCOM_SHOW_MASTER_STAT:
- if ((res= mysql_test_show_master_status(stmt)) == 2)
+ case SQLCOM_SHOW_BINLOG_STAT:
+ if ((res= mysql_test_show_binlog_status(stmt)) == 2)
{
/* Statement and field info has already been sent */
DBUG_RETURN(FALSE);
@@ -2664,6 +2665,11 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
thd->protocol= &thd->protocol_binary;
+ /* Create PS table entry, set query text after rewrite. */
+ stmt->m_prepared_stmt= MYSQL_CREATE_PS(stmt, stmt->id,
+ thd->m_statement_psi,
+ stmt->name.str, stmt->name.length);
+
if (stmt->prepare(packet, packet_length))
{
/* Statement map deletes statement on erase */
@@ -2865,6 +2871,11 @@ void mysql_sql_stmt_prepare(THD *thd)
*/
Item_change_list_savepoint change_list_savepoint(thd);
+ /* Create PS table entry, set query text after rewrite. */
+ stmt->m_prepared_stmt= MYSQL_CREATE_PS(stmt, stmt->id,
+ thd->m_statement_psi,
+ stmt->name.str, stmt->name.length);
+
if (stmt->prepare(query.str, (uint) query.length))
{
/* Statement map deletes the statement on erase */
@@ -3260,6 +3271,8 @@ static void mysql_stmt_execute_common(THD *thd,
open_cursor= MY_TEST(cursor_flags & (ulong) CURSOR_TYPE_READ_ONLY);
thd->protocol= &thd->protocol_binary;
+ MYSQL_EXECUTE_PS(thd->m_statement_psi, stmt->m_prepared_stmt);
+
if (!bulk_op)
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
else
@@ -3369,6 +3382,8 @@ void mysql_sql_stmt_execute(THD *thd)
CALL p1('x');
*/
Item_change_list_savepoint change_list_savepoint(thd);
+ MYSQL_EXECUTE_PS(thd->m_statement_psi, stmt->m_prepared_stmt);
+
(void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL);
change_list_savepoint.rollback(thd);
thd->free_items(); // Free items created by execute_loop()
@@ -3787,6 +3802,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
STMT_INITIALIZED,
((++thd_arg->statement_id_counter) & STMT_ID_MASK)),
thd(thd_arg),
+ m_prepared_stmt(NULL),
result(thd_arg),
param_array(0),
cursor(0),
@@ -3800,10 +3816,9 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
read_types(0),
m_sql_mode(thd->variables.sql_mode)
{
- init_sql_alloc(&main_mem_root, "Prepared_statement",
- thd_arg->variables.query_alloc_block_size,
- thd_arg->variables.query_prealloc_size,
- MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_prepared_statement_main_mem_root,
+ &main_mem_root, thd_arg->variables.query_alloc_block_size,
+ thd_arg->variables.query_prealloc_size, MYF(MY_THREAD_SPECIFIC));
*last_error= '\0';
}
@@ -3869,6 +3884,9 @@ Prepared_statement::~Prepared_statement()
DBUG_ENTER("Prepared_statement::~Prepared_statement");
DBUG_PRINT("enter",("stmt: %p cursor: %p",
this, cursor));
+
+ MYSQL_DESTROY_PS(m_prepared_stmt);
+
delete cursor;
/*
We have to call free on the items even if cleanup is called as some items,
@@ -4102,6 +4120,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
state= Query_arena::STMT_PREPARED;
flags&= ~ (uint) IS_IN_USE;
+ MYSQL_SET_PS_TEXT(m_prepared_stmt, query(), query_length());
+
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
prepared statements this causes two records to be output:
@@ -4519,6 +4539,7 @@ Prepared_statement::reprepare()
if (likely(!error))
{
+ MYSQL_REPREPARE_PS(m_prepared_stmt);
swap_prepared_statement(&copy);
swap_parameter_array(param_array, copy.param_array, param_count);
#ifdef DBUG_ASSERT_EXISTS
@@ -4756,17 +4777,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
if (query_cache_send_result_to_client(thd, thd->query(),
thd->query_length()) <= 0)
{
- PSI_statement_locker *parent_locker;
MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
thd->get_db(),
&thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip,
1);
- parent_locker= thd->m_statement_psi;
- thd->m_statement_psi= NULL;
error= mysql_execute_command(thd);
- thd->m_statement_psi= parent_locker;
MYSQL_QUERY_EXEC_DONE(error);
}
else
@@ -4879,7 +4896,11 @@ bool Prepared_statement::execute_immediate(const char *query, uint query_len)
set_sql_prepare();
name= execute_immediate_stmt_name; // for DBUG_PRINT etc
- if (unlikely(prepare(query, query_len)))
+
+ m_prepared_stmt= MYSQL_CREATE_PS(this, id, thd->m_statement_psi,
+ name.str, name.length);
+
+ if (prepare(query, query_len))
DBUG_RETURN(true);
if (param_count != thd->lex->prepared_stmt.param_count())
@@ -4889,6 +4910,7 @@ bool Prepared_statement::execute_immediate(const char *query, uint query_len)
DBUG_RETURN(true);
}
+ MYSQL_EXECUTE_PS(thd->m_statement_psi, m_prepared_stmt);
(void) execute_loop(&expanded_query, FALSE, NULL, NULL);
deallocate_immediate();
DBUG_RETURN(false);
@@ -5388,8 +5410,8 @@ bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint)
{
DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root));
- init_sql_alloc(&m_rset_root, "send_result_set_metadata",
- MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(PSI_INSTRUMENT_ME, &m_rset_root, MEM_ROOT_BLOCK_SIZE, 0,
+ MYF(MY_THREAD_SPECIFIC));
if (! (m_rset= new (&m_rset_root) List<Ed_row>))
return TRUE;
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index cee55761a98..2a47aa846eb 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -200,7 +200,8 @@ void PROF_MEASUREMENT::set_label(const char *status_arg,
sizes[1]= (function_arg == NULL) ? 0 : strlen(function_arg) + 1;
sizes[2]= (file_arg == NULL) ? 0 : strlen(file_arg) + 1;
- allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0));
+ allocated_status_memory= (char *) my_malloc(key_memory_PROFILE, sizes[0] +
+ sizes[1] + sizes[2], MYF(0));
DBUG_ASSERT(allocated_status_memory != NULL);
cursor= allocated_status_memory;
@@ -289,7 +290,7 @@ void QUERY_PROFILE::set_query_source(char *query_source_arg, size_t query_length
DBUG_ASSERT(query_source == NULL); /* we don't leak memory */
if (query_source_arg != NULL)
- query_source= my_strndup(query_source_arg, length, MYF(0));
+ query_source= my_strndup(key_memory_PROFILE, query_source_arg, length, MYF(0));
}
void QUERY_PROFILE::new_status(const char *status_arg,
diff --git a/sql/sql_profile.h b/sql/sql_profile.h
index b0b1642ee02..85018a2598b 100644
--- a/sql/sql_profile.h
+++ b/sql/sql_profile.h
@@ -54,6 +54,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table);
#include <sys/resource.h>
#endif
+extern PSI_memory_key key_memory_queue_item;
class PROF_MEASUREMENT;
class QUERY_PROFILE;
@@ -100,7 +101,8 @@ public:
{
struct queue_item *new_item;
- new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0));
+ new_item= (struct queue_item *) my_malloc(key_memory_queue_item,
+ sizeof(struct queue_item), MYF(0));
new_item->payload= payload;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 5bfa29b72c4..f11b3a35a80 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -24,7 +24,6 @@
#include "rpl_mi.h"
#include "rpl_rli.h"
#include "sql_repl.h"
-#include "sql_acl.h" // SUPER_ACL
#include "log_event.h"
#include "rpl_filter.h"
#include <my_dir.h>
@@ -1221,7 +1220,8 @@ check_slave_start_position(binlog_send_info *info, const char **errormsg,
if (!delete_list)
{
if (!(delete_list= (slave_connection_state::entry **)
- my_malloc(sizeof(*delete_list) * st->hash.records, MYF(MY_WME))))
+ my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(*delete_list) * st->hash.records, MYF(MY_WME))))
{
*errormsg= "Out of memory while checking slave start position";
err= ER_OUT_OF_RESOURCES;
@@ -1283,8 +1283,9 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name,
const char *errormsg= NULL;
char buf[FN_REFLEN];
- init_alloc_root(&memroot, "gtid_find_binlog_file",
- 8192, 0, MYF(MY_THREAD_SPECIFIC));
+ init_alloc_root(PSI_INSTRUMENT_ME, &memroot,
+ 10*(FN_REFLEN+sizeof(binlog_file_entry)), 0,
+ MYF(MY_THREAD_SPECIFIC));
if (!(list= get_binlog_list(&memroot)))
{
errormsg= "Out of memory while looking for GTID position in binlog";
@@ -3079,7 +3080,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
char relay_log_info_file_tmp[FN_REFLEN];
DBUG_ENTER("start_slave");
- if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0))
+ if (check_global_access(thd, PRIV_STMT_START_SLAVE))
DBUG_RETURN(-1);
create_logfile_name_with_suffix(master_info_file_tmp,
@@ -3282,7 +3283,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report )
DBUG_ENTER("stop_slave");
DBUG_PRINT("enter",("Connection: %s", mi->connection_name.str));
- if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0))
+ if (check_global_access(thd, PRIV_STMT_STOP_SLAVE))
DBUG_RETURN(-1);
THD_STAGE_INFO(thd, stage_killing_slave);
int thread_mask;
@@ -4215,7 +4216,7 @@ void show_binlog_info_get_fields(THD *thd, List<Item> *field_list)
/**
- Execute a SHOW MASTER STATUS statement.
+ Execute a SHOW BINLOG STATUS statement.
@param thd Pointer to THD object for the client thread executing the
statement.
@@ -4307,8 +4308,7 @@ bool show_binlogs(THD* thd)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- init_alloc_root(&mem_root, "binlog_file_list", 8192, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_alloc_root(PSI_INSTRUMENT_ME, &mem_root, 8192, 0, MYF(MY_THREAD_SPECIFIC));
retry:
/*
The current mutex handling here is to ensure we get the current log position
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 09a15aaf7df..e8fd275c55b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -43,7 +43,6 @@
#include "sql_base.h" // setup_wild, setup_fields, fill_record
#include "sql_parse.h" // check_stack_overrun
#include "sql_partition.h" // make_used_partitions_str
-#include "sql_acl.h" // *_ACL
#include "sql_test.h" // print_where, print_keyuse_array,
// print_sjm, print_plan, TEST_join
#include "records.h" // init_read_record, end_read_record
@@ -6769,7 +6768,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
/* set a barrier for the array of SARGABLE_PARAM */
(*sargables)[0].field= 0;
- if (my_init_dynamic_array2(keyuse, sizeof(KEYUSE),
+ if (my_init_dynamic_array2(thd->mem_root->m_psi_key, keyuse, sizeof(KEYUSE),
thd->alloc(sizeof(KEYUSE) * 20), 20, 64,
MYF(MY_THREAD_SPECIFIC)))
DBUG_RETURN(TRUE);
@@ -13495,8 +13494,7 @@ bool JOIN_TAB::preread_init()
if ((!derived->get_unit()->executed ||
derived->is_recursive_with_table() ||
derived->get_unit()->uncacheable) &&
- mysql_handle_single_derived(join->thd->lex,
- derived, DT_CREATE | DT_FILL))
+ mysql_handle_single_derived(join->thd->lex, derived, DT_CREATE | DT_FILL))
return TRUE;
if (!(derived->get_unit()->uncacheable & UNCACHEABLE_DEPENDENT) ||
@@ -13521,6 +13519,21 @@ bool JOIN_TAB::preread_init()
}
+bool JOIN_TAB::pfs_batch_update(JOIN *join)
+{
+ /*
+ Use PFS batch mode if
+ 1. tab is an inner-most table, or
+ 2. will read more than one row (not eq_ref or const access type)
+ 3. no subqueries
+ */
+
+ return join->join_tab + join->table_count - 1 == this && // 1
+ type != JT_EQ_REF && type != JT_CONST && type != JT_SYSTEM && // 2
+ (!select_cond || !select_cond->with_subquery()); // 3
+}
+
+
/**
Build a TABLE_REF structure for index lookup in the temporary table
@@ -18023,14 +18036,27 @@ class Create_tmp_table: public Data_type_statistics
ORDER *m_group;
bool m_distinct;
bool m_save_sum_fields;
+ bool m_with_cycle;
ulonglong m_select_options;
ha_rows m_rows_limit;
- uint m_hidden_field_count; // Remove this eventually
uint m_group_null_items;
- uint m_null_count;
- uint m_hidden_uneven_bit_length;
- uint m_hidden_null_count;
+
+ // counter for distinct/other fields
+ uint m_field_count[2];
+ // counter for distinct/other fields which can be NULL
+ uint m_null_count[2];
+ // counter for distinct/other blob fields
+ uint m_blobs_count[2];
+ // counter for "tails" of bit fields which do not fit in a byte
+ uint m_uneven_bit[2];
+
public:
+ enum counter {distinct, other};
+ /*
+ shows which field we are processing: distinct/other (set in processing
+ cycles)
+ */
+ counter current_counter;
Create_tmp_table(const TMP_TABLE_PARAM *param,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit)
@@ -18040,14 +18066,21 @@ public:
m_group(group),
m_distinct(distinct),
m_save_sum_fields(save_sum_fields),
+ m_with_cycle(false),
m_select_options(select_options),
m_rows_limit(rows_limit),
- m_hidden_field_count(param->hidden_field_count),
m_group_null_items(0),
- m_null_count(0),
- m_hidden_uneven_bit_length(0),
- m_hidden_null_count(0)
- { }
+ current_counter(other)
+ {
+ m_field_count[Create_tmp_table::distinct]= 0;
+ m_field_count[Create_tmp_table::other]= 0;
+ m_null_count[Create_tmp_table::distinct]= 0;
+ m_null_count[Create_tmp_table::other]= 0;
+ m_blobs_count[Create_tmp_table::distinct]= 0;
+ m_blobs_count[Create_tmp_table::other]= 0;
+ m_uneven_bit[Create_tmp_table::distinct]= 0;
+ m_uneven_bit[Create_tmp_table::other]= 0;
+ }
void add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols);
@@ -18080,13 +18113,16 @@ void Create_tmp_table::add_field(TABLE *table, Field *field, uint fieldnr, bool
}
if (!(field->flags & NOT_NULL_FLAG))
- m_null_count++;
+ m_null_count[current_counter]++;
table->s->reclength+= field->pack_length();
// Assign it here, before update_data_type_statistics() changes m_blob_count
if (field->flags & BLOB_FLAG)
+ {
table->s->blob_field[m_blob_count]= fieldnr;
+ m_blobs_count[current_counter]++;
+ }
table->field[fieldnr]= field;
field->field_index= fieldnr;
@@ -18215,7 +18251,7 @@ TABLE *Create_tmp_table::start(THD *thd,
if (param->precomputed_group_by)
copy_func_count+= param->sum_func_count;
- init_sql_alloc(&own_root, "tmp_table", TABLE_ALLOC_BLOCK_SIZE, 0,
+ init_sql_alloc(key_memory_TABLE, &own_root, TABLE_ALLOC_BLOCK_SIZE, 0,
MYF(MY_THREAD_SPECIFIC));
if (!multi_alloc_root(&own_root,
@@ -18298,6 +18334,7 @@ bool Create_tmp_table::add_fields(THD *thd,
DBUG_ASSERT(table->s->blob_fields == 0);
const bool not_all_columns= !(m_select_options & TMP_TABLE_ALL_COLUMNS);
+ bool distinct_record_structure= m_distinct;
uint fieldnr= 0;
TABLE_SHARE *share= table->s;
Item **copy_func= param->items_to_copy;
@@ -18308,8 +18345,29 @@ bool Create_tmp_table::add_fields(THD *thd,
List_iterator_fast<Item> li(fields);
Item *item;
Field **tmp_from_field= m_from_field;
+ uint uneven_delta;
+ while (!m_with_cycle && (item= li++))
+ if (item->common_flags & IS_IN_WITH_CYCLE)
+ {
+ m_with_cycle= true;
+ /*
+ Following distinct_record_structure is (m_distinct || m_with_cycle)
+
+ Note: distinct_record_structure can be true even if m_distinct is
+ false, for example for incr_table in recursive CTE
+ (see select_union_recursive::create_result_table)
+ */
+ distinct_record_structure= true;
+ }
+ li.rewind();
while ((item=li++))
{
+ current_counter= (((param->hidden_field_count < (fieldnr + 1)) &&
+ distinct_record_structure &&
+ (!m_with_cycle ||
+ (item->common_flags & IS_IN_WITH_CYCLE)))?
+ distinct :
+ other);
Item::Type type= item->type();
if (type == Item::COPY_STR_ITEM)
{
@@ -18334,7 +18392,8 @@ bool Create_tmp_table::add_fields(THD *thd,
continue;
}
}
- if (item->const_item() && (int) m_hidden_field_count <= 0)
+ if (item->const_item() &&
+ param->hidden_field_count < (fieldnr + 1))
continue; // We don't have to store this
}
if (type == Item::SUM_FUNC_ITEM && !m_group && !m_save_sum_fields)
@@ -18351,7 +18410,7 @@ bool Create_tmp_table::add_fields(THD *thd,
create_tmp_field(table, arg, &copy_func,
tmp_from_field, &m_default_field[fieldnr],
m_group != 0, not_all_columns,
- m_distinct, false);
+ distinct_record_structure , false);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
@@ -18363,7 +18422,10 @@ bool Create_tmp_table::add_fields(THD *thd,
arg= sum_item->set_arg(i, thd, tmp_item);
thd->mem_root= &table->mem_root;
+ uneven_delta= m_uneven_bit_length;
add_field(table, new_field, fieldnr++, param->force_not_null_cols);
+ uneven_delta= m_uneven_bit_length - uneven_delta;
+ m_field_count[current_counter]++;
if (!(new_field->flags & NOT_NULL_FLAG))
{
@@ -18373,6 +18435,8 @@ bool Create_tmp_table::add_fields(THD *thd,
*/
arg->maybe_null=1;
}
+ if (current_counter == distinct)
+ new_field->flags|= FIELD_PART_OF_TMP_UNIQUE;
}
}
}
@@ -18440,36 +18504,23 @@ bool Create_tmp_table::add_fields(THD *thd,
}
tmp_from_field++;
+ uneven_delta= m_uneven_bit_length;
add_field(table, new_field, fieldnr++, param->force_not_null_cols);
+ uneven_delta= m_uneven_bit_length - uneven_delta;
+ m_field_count[current_counter]++;
if (item->marker == 4 && item->maybe_null)
{
m_group_null_items++;
new_field->flags|= GROUP_FLAG;
}
+ if (current_counter == distinct)
+ new_field->flags|= FIELD_PART_OF_TMP_UNIQUE;
}
- if (!--m_hidden_field_count)
- {
- /*
- This was the last hidden field; Remember how many hidden fields could
- have null
- */
- m_hidden_null_count= m_null_count;
- /*
- We need to update hidden_field_count as we may have stored group
- functions with constant arguments
- */
- param->hidden_field_count= fieldnr;
- m_null_count= 0;
- /*
- On last hidden field we store uneven bit length in
- m_hidden_uneven_bit_length and proceed calculation of
- uneven bits for visible fields into m_uneven_bit_length.
- */
- m_hidden_uneven_bit_length= m_uneven_bit_length;
- m_uneven_bit_length= 0;
- }
+ m_uneven_bit[current_counter]+= uneven_delta;
}
+ DBUG_ASSERT(fieldnr == m_field_count[other] + m_field_count[distinct]);
+ DBUG_ASSERT(m_blob_count == m_blobs_count[other] + m_blobs_count[distinct]);
share->fields= fieldnr;
share->blob_fields= m_blob_count;
table->field[fieldnr]= 0; // End marker
@@ -18495,8 +18546,12 @@ bool Create_tmp_table::finalize(THD *thd,
DBUG_ENTER("Create_tmp_table::finalize");
DBUG_ASSERT(table);
- uint hidden_null_pack_length;
- uint null_pack_length;
+ uint null_pack_length[2];
+ uint null_pack_base[2];
+ uint null_counter[2]= {0, 0};
+
+ uint whole_null_pack_length;
+
bool use_packed_rows= false;
uchar *pos;
uchar *null_flags;
@@ -18547,16 +18602,21 @@ bool Create_tmp_table::finalize(THD *thd,
if (share->blob_fields == 0)
{
/* We need to ensure that first byte is not 0 for the delete link */
- if (param->hidden_field_count)
- m_hidden_null_count++;
+ if (m_field_count[other])
+ m_null_count[other]++;
else
- m_null_count++;
- }
- hidden_null_pack_length= (m_hidden_null_count + 7 +
- m_hidden_uneven_bit_length) / 8;
- null_pack_length= (hidden_null_pack_length +
- (m_null_count + m_uneven_bit_length + 7) / 8);
- share->reclength+= null_pack_length;
+ m_null_count[distinct]++;
+ }
+
+ null_pack_length[other]= (m_null_count[other] + 7 +
+ m_uneven_bit[other]) / 8;
+ null_pack_base[other]= 0;
+ null_pack_length[distinct]= (m_null_count[distinct] + 7 +
+ m_uneven_bit[distinct]) / 8;
+ null_pack_base[distinct]= null_pack_length[other];
+ whole_null_pack_length= null_pack_length[other] +
+ null_pack_length[distinct];
+ share->reclength+= whole_null_pack_length;
if (!share->reclength)
share->reclength= 1; // Dummy select
/* Use packed rows if there is blobs or a lot of space to gain */
@@ -18580,43 +18640,53 @@ bool Create_tmp_table::finalize(THD *thd,
recinfo=param->start_recinfo;
null_flags=(uchar*) table->record[0];
- pos=table->record[0]+ null_pack_length;
- if (null_pack_length)
+ pos=table->record[0]+ whole_null_pack_length;
+ if (whole_null_pack_length)
{
bzero((uchar*) recinfo,sizeof(*recinfo));
recinfo->type=FIELD_NORMAL;
- recinfo->length=null_pack_length;
+ recinfo->length= whole_null_pack_length;
recinfo++;
- bfill(null_flags,null_pack_length,255); // Set null fields
+ bfill(null_flags, whole_null_pack_length, 255); // Set null fields
table->null_flags= (uchar*) table->record[0];
- share->null_fields= m_null_count + m_hidden_null_count;
- share->null_bytes= share->null_bytes_for_compare= null_pack_length;
+ share->null_fields= m_null_count[other] + m_null_count[distinct];
+ share->null_bytes= share->null_bytes_for_compare= whole_null_pack_length;
+ }
+
+ if (share->blob_fields == 0)
+ {
+ null_counter[(m_field_count[other] ? other : distinct)]++;
}
- m_null_count= (share->blob_fields == 0) ? 1 : 0;
- m_hidden_field_count= param->hidden_field_count;
for (uint i= 0; i < share->fields; i++, recinfo++)
{
Field *field= table->field[i];
uint length;
bzero((uchar*) recinfo,sizeof(*recinfo));
+ current_counter= ((field->flags & FIELD_PART_OF_TMP_UNIQUE) ?
+ distinct :
+ other);
+
if (!(field->flags & NOT_NULL_FLAG))
{
- recinfo->null_bit= (uint8)1 << (m_null_count & 7);
- recinfo->null_pos= m_null_count/8;
- field->move_field(pos, null_flags + m_null_count/8,
- (uint8)1 << (m_null_count & 7));
- m_null_count++;
+
+ recinfo->null_bit= (uint8)1 << (null_counter[current_counter] & 7);
+ recinfo->null_pos= (null_pack_base[current_counter] +
+ null_counter[current_counter]/8);
+ field->move_field(pos, null_flags + recinfo->null_pos, recinfo->null_bit);
+ null_counter[current_counter]++;
}
else
field->move_field(pos,(uchar*) 0,0);
if (field->type() == MYSQL_TYPE_BIT)
{
/* We have to reserve place for extra bits among null bits */
- ((Field_bit*) field)->set_bit_ptr(null_flags + m_null_count / 8,
- m_null_count & 7);
- m_null_count+= (field->field_length & 7);
+ ((Field_bit*) field)->set_bit_ptr(null_flags +
+ null_pack_base[current_counter] +
+ null_counter[current_counter]/8,
+ null_counter[current_counter] & 7);
+ null_counter[current_counter]+= (field->field_length & 7);
}
field->reset();
@@ -18655,8 +18725,6 @@ bool Create_tmp_table::finalize(THD *thd,
/* Make entry for create table */
recinfo->length=length;
recinfo->type= field->tmp_engine_column_type(use_packed_rows);
- if (!--m_hidden_field_count)
- m_null_count= (m_null_count + 7) & ~7; // move to next byte
// fix table name in field entry
field->set_table_name(&table->alias);
@@ -18777,7 +18845,8 @@ bool Create_tmp_table::finalize(THD *thd,
m_group_buff <= param->group_buff + param->group_length);
}
- if (m_distinct && share->fields != param->hidden_field_count)
+ if (m_distinct && (share->fields != param->hidden_field_count ||
+ m_with_cycle))
{
uint i;
Field **reg_field;
@@ -18789,7 +18858,7 @@ bool Create_tmp_table::finalize(THD *thd,
*/
DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));
- if (share->blob_fields)
+ if (m_blobs_count[distinct])
{
/*
Special mode for index creation in MyISAM used to support unique
@@ -18798,10 +18867,8 @@ bool Create_tmp_table::finalize(THD *thd,
*/
share->uniques= 1;
}
- null_pack_length-=hidden_null_pack_length;
- keyinfo->user_defined_key_parts=
- ((share->fields - param->hidden_field_count)+
- (share->uniques ? MY_TEST(null_pack_length) : 0));
+ keyinfo->user_defined_key_parts= m_field_count[distinct] +
+ (share->uniques ? MY_TEST(null_pack_length[distinct]) : 0);
keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
keyinfo->usable_key_parts= keyinfo->user_defined_key_parts;
table->distinct= 1;
@@ -18844,11 +18911,11 @@ bool Create_tmp_table::finalize(THD *thd,
blobs can distinguish NULL from 0. This extra field is not needed
when we do not use UNIQUE indexes for blobs.
*/
- if (null_pack_length && share->uniques)
+ if (null_pack_length[distinct] && share->uniques)
{
m_key_part_info->null_bit=0;
- m_key_part_info->offset=hidden_null_pack_length;
- m_key_part_info->length=null_pack_length;
+ m_key_part_info->offset= null_pack_base[distinct];
+ m_key_part_info->length= null_pack_length[distinct];
m_key_part_info->field= new Field_string(table->record[0],
(uint32) m_key_part_info->length,
(uchar*) 0,
@@ -18866,8 +18933,10 @@ bool Create_tmp_table::finalize(THD *thd,
/* Create a distinct key over the columns we are going to return */
for (i= param->hidden_field_count, reg_field= table->field + i ;
i < share->fields;
- i++, reg_field++, m_key_part_info++)
+ i++, reg_field++)
{
+ if (!((*reg_field)->flags & FIELD_PART_OF_TMP_UNIQUE))
+ continue;
m_key_part_info->field= *reg_field;
(*reg_field)->flags |= PART_KEY_FLAG;
if (m_key_part_info == keyinfo->key_part)
@@ -18904,6 +18973,8 @@ bool Create_tmp_table::finalize(THD *thd,
(ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
(ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
0 : FIELDFLAG_BINARY;
+
+ m_key_part_info++;
}
}
@@ -20446,6 +20517,10 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if (join_tab->loosescan_match_tab)
join_tab->loosescan_match_tab->found_match= FALSE;
+ const bool pfs_batch_update= join_tab->pfs_batch_update(join);
+ if (pfs_batch_update)
+ join_tab->table->file->start_psi_batch_mode();
+
if (rc != NESTED_LOOP_NO_MORE_ROWS)
{
error= (*join_tab->read_first_record)(join_tab);
@@ -20497,6 +20572,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
join_tab->last_inner && !join_tab->found)
rc= evaluate_null_complemented_join_record(join, join_tab);
+ if (pfs_batch_update)
+ join_tab->table->file->end_psi_batch_mode();
+
if (rc == NESTED_LOOP_NO_MORE_ROWS)
rc= NESTED_LOOP_OK;
DBUG_RETURN(rc);
@@ -23952,21 +24030,21 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
Field **ptr;
DBUG_ENTER("remove_dup_with_hash_index");
- if (unlikely(!my_multi_malloc(MYF(MY_WME),
- &key_buffer,
- (uint) ((key_length + extra_length) *
- (long) file->stats.records),
- &field_lengths,
- (uint) (field_count*sizeof(*field_lengths)),
- NullS)))
+ if (!my_multi_malloc(key_memory_hash_index_key_buffer, MYF(MY_WME),
+ &key_buffer,
+ (uint) ((key_length + extra_length) *
+ (long) file->stats.records),
+ &field_lengths,
+ (uint) (field_count*sizeof(*field_lengths)),
+ NullS))
DBUG_RETURN(1);
for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
(*field_length++)= (*ptr)->sort_length();
- if (unlikely(my_hash_init(&hash, &my_charset_bin,
- (uint) file->stats.records, 0,
- key_length, (my_hash_get_key) 0, 0, 0)))
+ if (my_hash_init(key_memory_hash_index_key_buffer, &hash, &my_charset_bin,
+ (uint) file->stats.records, 0, key_length,
+ (my_hash_get_key) 0, 0, 0))
{
my_free(key_buffer);
DBUG_RETURN(1);
@@ -24002,7 +24080,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
field_length=field_lengths;
for (ptr= first_field ; *ptr ; ptr++)
{
- (*ptr)->make_sort_key(key_pos, *field_length);
+ (*ptr)->make_sort_key_part(key_pos, *field_length);
key_pos+= (*ptr)->maybe_null() + *field_length++;
}
/* Check if it exists before */
@@ -27481,7 +27559,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
else
str->append(',');
- if (is_subquery_function() && item->is_autogenerated_name)
+ if (is_subquery_function() && item->is_autogenerated_name())
{
/*
Do not print auto-generated aliases in subqueries. It has no purpose
@@ -27777,8 +27855,8 @@ JOIN::reoptimize(Item *added_where, table_map join_tables,
reset_query_plan();
if (!keyuse.buffer &&
- my_init_dynamic_array(&keyuse, sizeof(KEYUSE), 20, 64,
- MYF(MY_THREAD_SPECIFIC)))
+ my_init_dynamic_array(thd->mem_root->m_psi_key, &keyuse, sizeof(KEYUSE),
+ 20, 64, MYF(MY_THREAD_SPECIFIC)))
{
delete_dynamic(&added_keyuse);
return REOPT_ERROR;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index e3501fb98c6..8b2df74702b 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -247,13 +247,13 @@ class SplM_opt_info;
typedef struct st_join_table {
TABLE *table;
TABLE_LIST *tab_list;
- KEYUSE *keyuse; /**< pointer to first used key */
+ KEYUSE *keyuse; /**< pointer to first used key */
KEY *hj_key; /**< descriptor of the used best hash join key
- not supported by any index */
+ not supported by any index */
SQL_SELECT *select;
COND *select_cond;
COND *on_precond; /**< part of on condition to check before
- accessing the first inner table */
+ accessing the first inner table */
QUICK_SELECT_I *quick;
/*
The value of select_cond before we've attempted to do Index Condition
@@ -635,6 +635,8 @@ typedef struct st_join_table {
ha_rows get_examined_rows();
bool preread_init();
+ bool pfs_batch_update(JOIN *join);
+
bool is_sjm_nest() { return MY_TEST(bush_children); }
/*
@@ -1095,7 +1097,7 @@ protected:
keyuse.buffer= NULL;
keyuse.malloc_flags= 0;
best_positions= 0; /* To detect errors */
- error= my_multi_malloc(MYF(MY_WME),
+ error= my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME),
&best_positions,
sizeof(*best_positions) * (tables + 1),
&join_tab_keyuse,
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 8b2f49a5910..a5676b8989a 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -452,10 +452,9 @@ int SEQUENCE::read_initial_values(TABLE *table)
where we don't have a mdl lock on the table
*/
- mdl_request.init(MDL_key::TABLE,
- table->s->db.str,
- table->s->table_name.str,
- MDL_SHARED_READ, MDL_EXPLICIT);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, table->s->db.str,
+ table->s->table_name.str, MDL_SHARED_READ,
+ MDL_EXPLICIT);
mdl_requests.push_front(&mdl_request);
if (thd->mdl_context.acquire_locks(&mdl_requests,
thd->variables.lock_wait_timeout))
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 7913a7d2b9f..1d12e95bbbb 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -93,6 +93,8 @@ static uchar *servers_cache_get_key(FOREIGN_SERVER *server, size_t *length,
DBUG_RETURN((uchar*) server->server_name);
}
+static PSI_memory_key key_memory_servers;
+
#ifdef HAVE_PSI_INTERFACE
static PSI_rwlock_key key_rwlock_THR_LOCK_servers;
@@ -101,6 +103,11 @@ static PSI_rwlock_info all_servers_cache_rwlocks[]=
{ &key_rwlock_THR_LOCK_servers, "THR_LOCK_servers", PSI_FLAG_GLOBAL}
};
+static PSI_memory_info all_servers_cache_memory[]=
+{
+ { &key_memory_servers, "servers_cache", PSI_FLAG_GLOBAL}
+};
+
static void init_servers_cache_psi_keys(void)
{
const char* category= "sql";
@@ -111,6 +118,9 @@ static void init_servers_cache_psi_keys(void)
count= array_elements(all_servers_cache_rwlocks);
PSI_server->register_rwlock(category, all_servers_cache_rwlocks, count);
+
+ count= array_elements(all_servers_cache_memory);
+ mysql_memory_register(category, all_servers_cache_memory, count);
}
#endif /* HAVE_PSI_INTERFACE */
@@ -148,7 +158,7 @@ bool servers_init(bool dont_read_servers_table)
DBUG_RETURN(TRUE);
/* initialise our servers cache */
- if (my_hash_init(&servers_cache, system_charset_info, 32, 0, 0,
+ if (my_hash_init(key_memory_servers, &servers_cache, system_charset_info, 32, 0, 0,
(my_hash_get_key) servers_cache_get_key, 0, 0))
{
return_val= TRUE; /* we failed, out of memory? */
@@ -156,7 +166,7 @@ bool servers_init(bool dont_read_servers_table)
}
/* Initialize the mem root for data */
- init_sql_alloc(&mem, "servers", ACL_ALLOC_BLOCK_SIZE, 0,
+ init_sql_alloc(key_memory_servers, &mem, ACL_ALLOC_BLOCK_SIZE, 0,
MYF(MY_THREAD_SPECIFIC));
if (dont_read_servers_table)
@@ -206,7 +216,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
my_hash_reset(&servers_cache);
free_root(&mem, MYF(0));
- init_sql_alloc(&mem, "servers_load", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_servers, &mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
if (init_read_record(&read_record_info,thd,table=tables[0].table, NULL, NULL,
1,0, FALSE))
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 94a28e74eff..02f6278140c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -480,7 +480,10 @@ static struct show_privileges_st sys_privileges[]=
{"Proxy", "Server Admin", "To make proxy user possible"},
{"References", "Databases,Tables", "To have references on tables"},
{"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
- {"Replication client","Server Admin","To ask where the slave or master servers are"},
+ {"Binlog admin", "Server", "To purge binary logs"},
+ {"Binlog monitor", "Server", "To use SHOW BINLOG STATUS and SHOW BINARY LOG"},
+ {"Replication master admin", "Server", "To monitor connected slaves"},
+ {"Replication slave admin", "Server", "To start/monitor/stop slave and apply binlog events"},
{"Replication slave","Server Admin","To read binary log events from the master"},
{"Select", "Tables", "To retrieve rows from table"},
{"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
@@ -490,6 +493,10 @@ static struct show_privileges_st sys_privileges[]=
{"Trigger","Tables", "To use triggers"},
{"Create tablespace", "Server Admin", "To create/alter/drop tablespaces"},
{"Update", "Tables", "To update existing rows"},
+ {"Set user","Server", "To create views and stored routines with a different definer"},
+ {"Federated admin", "Server", "To execute the CREATE SERVER, ALTER SERVER, DROP SERVER statements"},
+ {"Connection admin", "Server", "To bypass connection limits and kill other users' connections"},
+ {"Read_only admin", "Server", "To perform write operations even if @@read_only=ON"},
{"Usage","Server Admin","No privileges - allow connect only"},
{NullS, NullS, NullS}
};
@@ -571,8 +578,8 @@ static bool skip_ignored_dir_check= TRUE;
bool
ignore_db_dirs_init()
{
- return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_CSTRING *),
- 0, 0, MYF(0));
+ return my_init_dynamic_array(key_memory_ignored_db, &ignore_db_dirs_array,
+ sizeof(LEX_STRING *), 0, 0, MYF(0));
}
@@ -620,8 +627,8 @@ push_ignored_db_dir(char *path)
return true;
// No need to normalize, it's only a directory name, not a path.
- if (!my_multi_malloc(0,
- &new_elt, sizeof(LEX_CSTRING),
+ if (!my_multi_malloc(key_memory_ignored_db, MYF(0),
+ &new_elt, sizeof(LEX_STRING),
&new_elt_buffer, path_len + 1,
NullS))
return true;
@@ -701,7 +708,7 @@ void ignore_db_dirs_append(const char *dirname_arg)
LEX_STRING *new_entry;
size_t len= strlen(dirname_arg);
- if (!my_multi_malloc(0,
+ if (!my_multi_malloc(PSI_INSTRUMENT_ME, MYF(0),
&new_entry, sizeof(LEX_STRING),
&new_entry_buf, len + 1,
NullS))
@@ -723,7 +730,7 @@ void ignore_db_dirs_append(const char *dirname_arg)
// Add one for comma and one for \0.
size_t newlen= curlen + len + 1 + 1;
char *new_db_dirs;
- if (!(new_db_dirs= (char*)my_malloc(newlen ,MYF(0))))
+ if (!(new_db_dirs= (char*)my_malloc(PSI_INSTRUMENT_ME, newlen, MYF(0))))
{
// This is not a critical condition
return;
@@ -749,12 +756,10 @@ ignore_db_dirs_process_additions()
skip_ignored_dir_check= TRUE;
- if (my_hash_init(&ignore_db_dirs_hash,
- lower_case_table_names ?
- character_set_filesystem : &my_charset_bin,
- 0, 0, 0, db_dirs_hash_get_key,
- dispose_db_dir,
- HASH_UNIQUE))
+ if (my_hash_init(key_memory_ignored_db, &ignore_db_dirs_hash,
+ lower_case_table_names ? character_set_filesystem :
+ &my_charset_bin, 0, 0, 0, db_dirs_hash_get_key,
+ dispose_db_dir, HASH_UNIQUE))
return true;
/* len starts from 1 because of the terminating zero. */
@@ -776,7 +781,8 @@ ignore_db_dirs_process_additions()
len--;
/* +1 the terminating zero */
- ptr= opt_ignore_db_dirs= (char *) my_malloc(len + 1, MYF(0));
+ ptr= opt_ignore_db_dirs= (char *) my_malloc(key_memory_ignored_db, len + 1,
+ MYF(0));
if (!ptr)
return true;
@@ -1976,6 +1982,14 @@ static void append_period(THD *thd, String *packet, const LEX_CSTRING &start,
packet->append(STRING_WITH_LEN(")"));
}
+int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
+ Table_specification_st *create_info_arg,
+ enum_with_db_name with_db_name)
+{
+ return show_create_table_ex(thd, table_list, NULL, NULL, packet,
+ create_info_arg, with_db_name);
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1984,6 +1998,11 @@ static void append_period(THD *thd, String *packet, const LEX_CSTRING &start,
thd The thread
table_list A list containing one table to write statement
for.
+ force_db If not NULL, database name to use in the CREATE
+ TABLE statement.
+ force_name If not NULL, table name to use in the CREATE TABLE
+ statement. if NULL, the name from table_list will be
+ used.
packet Pointer to a string where statement will be
written.
create_info_arg Pointer to create information that can be used
@@ -2000,9 +2019,11 @@ static void append_period(THD *thd, String *packet, const LEX_CSTRING &start,
0 OK
*/
-int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
- Table_specification_st *create_info_arg,
- enum_with_db_name with_db_name)
+int show_create_table_ex(THD *thd, TABLE_LIST *table_list,
+ const char *force_db, const char *force_name,
+ String *packet,
+ Table_specification_st *create_info_arg,
+ enum_with_db_name with_db_name)
{
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
@@ -2052,41 +2073,55 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN("TABLE "));
if (create_info_arg && create_info_arg->if_not_exists())
packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
- if (table_list->schema_table)
+
+ if (force_name)
{
- alias.str= table_list->schema_table->table_name;
- alias.length= strlen(alias.str);
+ if (force_db)
+ {
+ append_identifier(thd, packet, force_db, strlen(force_db));
+ packet->append(STRING_WITH_LEN("."));
+ }
+ append_identifier(thd, packet, force_name, strlen(force_name));
}
else
{
- if (lower_case_table_names == 2)
+ if (table_list->schema_table)
{
- alias.str= table->alias.c_ptr();
- alias.length= table->alias.length();
+ alias.str= table_list->schema_table->table_name;
+ alias.length= strlen(alias.str);
}
else
- alias= share->table_name;
- }
+ {
+ if (lower_case_table_names == 2)
+ {
+ alias.str= table->alias.c_ptr();
+ alias.length= table->alias.length();
+ }
+ else
+ alias= share->table_name;
+ }
- /*
- Print the database before the table name if told to do that. The
- database name is only printed in the event that it is different
- from the current database. The main reason for doing this is to
- avoid having to update gazillions of tests and result files, but
- it also saves a few bytes of the binary log.
- */
- if (with_db_name == WITH_DB_NAME)
- {
- const LEX_CSTRING *const db=
- table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
- if (!thd->db.str || cmp(db, &thd->db))
- {
- append_identifier(thd, packet, db);
- packet->append(STRING_WITH_LEN("."));
+ /*
+ Print the database before the table name if told to do that. The
+ database name is only printed in the event that it is different
+ from the current database. The main reason for doing this is to
+ avoid having to update gazillions of tests and result files, but
+ it also saves a few bytes of the binary log.
+ */
+ if (with_db_name == WITH_DB_NAME)
+ {
+ const LEX_CSTRING *const db=
+ table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
+ if (!thd->db.str || cmp(db, &thd->db))
+ {
+ append_identifier(thd, packet, db);
+ packet->append(STRING_WITH_LEN("."));
+ }
}
+
+ append_identifier(thd, packet, &alias);
}
- append_identifier(thd, packet, &alias);
packet->append(STRING_WITH_LEN(" (\n"));
/*
We need this to get default values from the table
@@ -3025,8 +3060,8 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
DBUG_ASSERT(cond==NULL);
thread_id= thd->lex->value_list.head()->val_int();
- calling_user= (thd->security_ctx->master_access & PROCESS_ACL) ? NullS :
- thd->security_ctx->priv_user;
+ calling_user= (thd->security_ctx->master_access & PRIV_STMT_SHOW_EXPLAIN) ?
+ NullS : thd->security_ctx->priv_user;
if ((tmp= find_thread_by_id(thread_id)))
{
@@ -3143,8 +3178,9 @@ static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg)
const char *val;
ulonglong max_counter;
bool got_thd_data;
- char *user= arg->thd->security_ctx->master_access & PROCESS_ACL ?
- NullS : arg->thd->security_ctx->priv_user;
+ char *user=
+ arg->thd->security_ctx->master_access & PRIV_STMT_SHOW_PROCESSLIST ?
+ NullS : arg->thd->security_ctx->priv_user;
if ((!tmp->vio_ok() && !tmp->system_thread) ||
(user && (tmp->system_thread || !tmp_sctx->user ||
@@ -3277,8 +3313,9 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
Status functions
*****************************************************************************/
-static DYNAMIC_ARRAY all_status_vars;
+DYNAMIC_ARRAY all_status_vars;
static bool status_vars_inited= 0;
+ulonglong status_var_array_version= 0;
C_MODE_START
static int show_var_cmp(const void *var1, const void *var2)
@@ -3306,6 +3343,7 @@ static void shrink_var_array(DYNAMIC_ARRAY *array)
}
else // array is completely empty - delete it
delete_dynamic(array);
+ status_var_array_version++;
}
/*
@@ -3333,7 +3371,8 @@ int add_status_vars(SHOW_VAR *list)
if (status_vars_inited)
mysql_rwlock_wrlock(&LOCK_all_status_vars);
if (!all_status_vars.buffer && // array is not allocated yet - do it now
- my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 250, 50, MYF(0)))
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &all_status_vars,
+ sizeof(SHOW_VAR), 250, 50, MYF(0)))
{
res= 1;
goto err;
@@ -3344,6 +3383,7 @@ int add_status_vars(SHOW_VAR *list)
all_status_vars.elements--; // but next insert_dynamic should overwite it
if (status_vars_inited)
sort_dynamic(&all_status_vars, show_var_cmp);
+ status_var_array_version++;
err:
if (status_vars_inited)
mysql_rwlock_unlock(&LOCK_all_status_vars);
@@ -3362,6 +3402,7 @@ void init_status_vars()
{
status_vars_inited=1;
sort_dynamic(&all_status_vars, show_var_cmp);
+ status_var_array_version++;
}
void reset_status_vars()
@@ -3388,6 +3429,7 @@ void reset_status_vars()
void free_status_vars()
{
delete_dynamic(&all_status_vars);
+ status_var_array_version++;
}
/*
@@ -3449,6 +3491,11 @@ void remove_status_vars(SHOW_VAR *list)
}
}
+/* Current version of the all_status_vars. */
+ulonglong get_status_vars_version(void)
+{
+ return status_var_array_version;
+}
/**
@brief Returns the value of a system or a status variable.
@@ -4738,8 +4785,9 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table,
bool can_deadlock)
{
bool error;
- table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str,
- MDL_SHARED_HIGH_PRIO, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str,
+ table->table_name.str, MDL_SHARED_HIGH_PRIO,
+ MDL_TRANSACTION);
if (can_deadlock)
{
@@ -4861,8 +4909,8 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
if (schema_table->i_s_requested_object & OPEN_TRIGGER_ONLY)
{
- init_sql_alloc(&tbl.mem_root, "fill_schema_table_from_frm",
- TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_table_triggers_list,
+ &tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
if (!Table_triggers_list::check_n_load(thd, db_name,
table_name, &tbl, 1))
{
@@ -5016,7 +5064,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
IS_table_read_plan *plan= tables->is_table_read_plan;
enum enum_schema_tables schema_table_idx;
- Dynamic_array<LEX_CSTRING*> db_names;
+ Dynamic_array<LEX_CSTRING*> db_names(PSI_INSTRUMENT_MEM);
Item *partial_cond= plan->partial_cond;
int error= 1;
Open_tables_backup open_tables_state_backup;
@@ -5085,7 +5133,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
goto err;
/* Use tmp_mem_root to allocate data for opened tables */
- init_alloc_root(&tmp_mem_root, "get_all_tables", SHOW_ALLOC_BLOCK_SIZE,
+ init_alloc_root(PSI_INSTRUMENT_ME, &tmp_mem_root, SHOW_ALLOC_BLOCK_SIZE,
SHOW_ALLOC_BLOCK_SIZE, MY_THREAD_SPECIFIC);
for (size_t i=0; i < db_names.elements(); i++)
@@ -5100,7 +5148,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0))
#endif
{
- Dynamic_array<LEX_CSTRING*> table_names;
+ Dynamic_array<LEX_CSTRING*> table_names(PSI_INSTRUMENT_MEM);
int res= make_table_name_list(thd, &table_names, lex,
&plan->lookup_field_vals, db_name);
if (unlikely(res == 2)) /* Not fatal error, continue */
@@ -5216,7 +5264,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
*/
LOOKUP_FIELD_VALUES lookup_field_vals;
- Dynamic_array<LEX_CSTRING*> db_names;
+ Dynamic_array<LEX_CSTRING*> db_names(PSI_INSTRUMENT_MEM);
Schema_specification_st create;
TABLE *table= tables->table;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -6200,11 +6248,11 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
- sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
+ sph= Sp_handler::handler_mysql_proc((enum_sp_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
- if (!sph || sph->type() == TYPE_ENUM_PACKAGE ||
- sph->type() == TYPE_ENUM_PACKAGE_BODY)
+ if (!sph || sph->type() == SP_TYPE_PACKAGE ||
+ sph->type() == SP_TYPE_PACKAGE_BODY)
DBUG_RETURN(0);
if (!full_access)
@@ -6215,7 +6263,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root,
&params);
- if (sph->type() == TYPE_ENUM_FUNCTION)
+ if (sph->type() == SP_TYPE_FUNCTION)
proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
&returns);
sp= sph->sp_load_for_information_schema(thd, proc_table, db, name,
@@ -6228,7 +6276,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
Sql_mode_save sql_mode_backup(thd);
thd->variables.sql_mode= sql_mode;
- if (sph->type() == TYPE_ENUM_FUNCTION)
+ if (sph->type() == SP_TYPE_FUNCTION)
{
restore_record(table, s->default_values);
table->field[0]->store(STRING_WITH_LEN("def"), cs);
@@ -6312,7 +6360,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db);
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
- sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
+ sph= Sp_handler::handler_mysql_proc((enum_sp_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
if (!sph)
@@ -6341,7 +6389,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
copy_field_as_string(table->field[4],
proc_table->field[MYSQL_PROC_MYSQL_TYPE]);
- if (sph->type() == TYPE_ENUM_FUNCTION)
+ if (sph->type() == SP_TYPE_FUNCTION)
{
sp_head *sp;
bool free_sp_head;
@@ -9504,7 +9552,8 @@ int initialize_schema_table(st_plugin_int *plugin)
ST_SCHEMA_TABLE *schema_table;
DBUG_ENTER("initialize_schema_table");
- if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
+ if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(key_memory_ST_SCHEMA_TABLE,
+ sizeof(ST_SCHEMA_TABLE),
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(1);
/* Historical Requirement */
diff --git a/sql/sql_show.h b/sql/sql_show.h
index a98ba451088..80588cda8b5 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -83,6 +83,12 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
Table_specification_st *create_info_arg,
enum_with_db_name with_db_name);
+int show_create_table_ex(THD *thd, TABLE_LIST *table_list,
+ const char * forced_db, const char *forced_name,
+ String *packet,
+ Table_specification_st *create_info_arg,
+ enum_with_db_name with_db_name);
+
int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
bool append_identifier(THD *thd, String *packet, const char *name, size_t length);
@@ -113,6 +119,7 @@ bool append_definer(THD *thd, String *buffer, const LEX_CSTRING *definer_user,
const LEX_CSTRING *definer_host);
int add_status_vars(SHOW_VAR *list);
void remove_status_vars(SHOW_VAR *list);
+ulonglong get_status_vars_version(void);
void init_status_vars();
void free_status_vars();
void reset_status_vars();
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
index 2c01b01b607..5b3f5a67d17 100644
--- a/sql/sql_sort.h
+++ b/sql/sql_sort.h
@@ -20,8 +20,8 @@
#include "my_base.h" /* ha_rows */
#include <my_sys.h> /* qsort2_cmp */
#include "queues.h"
+#include "sql_class.h"
-struct SORT_FIELD;
class Field;
struct TABLE;
@@ -156,6 +156,7 @@ public:
};
typedef Bounds_checked_array<SORT_ADDON_FIELD> Addon_fields_array;
+typedef Bounds_checked_array<SORT_FIELD> Sort_keys_array;
/**
This class wraps information about usage of addon fields.
@@ -182,7 +183,7 @@ public:
/// rr_unpack_from_tempfile needs an extra buffer when unpacking.
uchar *allocate_addon_buf(uint sz)
{
- m_addon_buf= (uchar *)my_malloc(sz, MYF(MY_WME | MY_THREAD_SPECIFIC));
+ m_addon_buf= (uchar *)my_malloc(PSI_INSTRUMENT_ME, sz, MYF(MY_WME | MY_THREAD_SPECIFIC));
if (m_addon_buf)
m_addon_buf_length= sz;
return m_addon_buf;
@@ -241,22 +242,263 @@ private:
bool m_using_packed_addons; ///< Are we packing the addon fields?
};
+/**
+ This class wraps information about usage of sort keys.
+ A Sort_keys object is used both during packing of data in the filesort
+ buffer, and later during unpacking in 'Filesort_info::unpack_addon_fields'.
+
+ @see SORT_FIELD struct.
+*/
+
+class Sort_keys :public Sql_alloc,
+ public Sort_keys_array
+{
+public:
+ Sort_keys(SORT_FIELD* arr, size_t count):
+ Sort_keys_array(arr, count),
+ m_using_packed_sortkeys(false),
+ size_of_packable_fields(0),
+ sort_length(0)
+ {
+ DBUG_ASSERT(!is_null());
+ }
+
+ bool using_packed_sortkeys() const
+ { return m_using_packed_sortkeys; }
+
+ void set_using_packed_sortkeys(bool val)
+ {
+ m_using_packed_sortkeys= val;
+ }
+ void set_size_of_packable_fields(uint len)
+ {
+ size_of_packable_fields= len;
+ }
+
+ uint get_size_of_packable_fields()
+ {
+ return size_of_packable_fields;
+ }
+
+ void set_sort_length(uint len)
+ {
+ sort_length= len;
+ }
+
+ uint get_sort_length()
+ {
+ return sort_length;
+ }
+
+ static void store_sortkey_length(uchar *p, uint sz)
+ {
+ int4store(p, sz - size_of_length_field);
+ }
+
+ static uint read_sortkey_length(uchar *p)
+ {
+ return size_of_length_field + uint4korr(p);
+ }
+
+ void increment_size_of_packable_fields(uint len)
+ {
+ size_of_packable_fields+= len;
+ }
+
+ void increment_original_sort_length(uint len)
+ {
+ sort_length+= len;
+ }
+
+ static const uint size_of_length_field= 4;
+
+private:
+ bool m_using_packed_sortkeys; // Are we packing sort keys
+ uint size_of_packable_fields; // Total length bytes for packable columns
+
+ /*
+ The length that would be needed if we stored non-packed mem-comparable
+ images of fields?
+ */
+ uint sort_length;
+};
+
+
+/**
+PACKED SORT KEYS
+
+Description
+
+In this optimization where we would like the pack the values of the sort key
+inside the sort buffer for each record.
+
+Contents:
+1. Background
+1.1 Implementation details
+2. Solution : Packed Sort Keys
+2.1 Packed key format
+2.2 Which format to use
+3. Special cases
+3.1 Handling very long strings
+3.2 Handling for long binary strings
+3.3 Handling very long strings with Packed sort keys
+4. Sort key columns in addon_fields
+
+1. Background
+Before this optimization of using packed sort keys, filesort() sorted the
+data using mem-comparable keys.
+
+That is, if we wanted to sort by
+
+ ORDER BY col1, col2, ... colN
+then the filesort code would for each row generate one "Sort Key"
+and then sort the rows by their Sort Keys.
+
+The Sort Keys are mem-comparable (that is, are compared by memcmp()) and
+they are of FIXED SIZE. The sort key has the same length regardless of
+what value it represents. This causes INEFFICIENT MEMORY USAGE.
+
+1.1 Implementation details
+
+make_sortkey() is the function that produces a sort key
+from a record.
+
+The function treats Field and Item objects differently.
+
+class Field has:
+
+a) void make_sort_key(uchar *buff, uint length);
+ make_sort_key is a non-virtual function which handles encoding of
+ SQL null values.
+
+b) virtual void sort_string(uchar *buff,uint length)=0;
+ sort_string produces mem-comparable image of the field value
+ for each datatype.
+
+For Items, Type_handler has a virtual function:
+
+ virtual void make_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const= 0;
+ which various datatypes overload.
+
+
+2. SOLUTION: PACKED SORT KEYS
+
+Note that one can have mem-comparable keys are that are not fixed-size.
+MyRocks uses such encoding for example.
+
+However for this optimization it was decided to store the original
+(non-mem-comparable) values instead and use a datatype-aware
+key comparison function.
+
+2.1 Packed key format
+The keys are stored in a new variable-size data format called "packed".
+
+The format is as follows:
+
+ <sort_key_length><packed_value_1><packed_value2> ....... <packed_valueN>
+
+ format for a n-part sort key
+
+<sort_key_length> is the length of the whole key.
+Each packed value is encoded as follows:
+
+ <null_byte=0> // This is a an SQL NULL
+ [<null_byte=1>] <packed_value> // this a non-NULL value
+null_byte is present if the field/item is NULLable.
+SQL NULL is encoded as just one NULL-indicator byte. The value itself is omitted.
+
+The format of the packed_value depends on the datatype.
+For "non-packable" datatypes it is just their mem-comparable form, as before.
+
+The "packable" datatypes are currently variable-length strings and the
+packed format for them is (for binary blobs, see a note below):
+
+<length> <string>
+2.2 Which format to use
+
+The advantage of Packed Key Format is potential space savings for
+variable-length fields.
+
+The disadvantages are:
+
+a) It may actually take more space, because of sort_key_length and
+ length fields.
+b) The comparison function is more expensive.
+
+Currently the logic is: use Packed Key Format if we would save 128 or more
+bytes when constructing a sort key from values that have empty string
+for each packable component.
+
+3. SPECIAL CASES
+3.1 HANDLING VERY LONG STRINGS
+the size of sort key part was limited by @@max_sort_length variable.
+It is defined as:
+
+The number of bytes to use when sorting data values. The server uses only the
+first max_sort_length bytes of each value and ignores the rest.
+
+3.2 HANDLING VERY LONG BINARY STRINGS
+Long binary strings receive special treatment. A sort key for the long
+binary string is truncated at max_sort_length bytes like described above,
+but then a "suffix" is appended which contains the total length of the
+value before the truncation.
+
+3.3 HANDLING VERY LONG STRINGS WITH PACKED SORT KEY
+Truncating multi-byte string at N bytes is not safe because one can cut in the
+middle of a character. One is tempted to solve this by discarding the partial
+character but that's also not a good idea as in some collations multiple
+characters may produce one weight (this is called "contraction").
+
+This combination of circumstances:
+
+The string value is very long, so truncation is necessary
+The collation is "complex", so truncation is dangerous
+is deemed to be relatively rare so it was decided to just use
+the non-packed sort keys in this case.
+
+4. SORT KEY COLUMNS IN ADDON FIELDS
+Currently, each sort key column is actually stored twice
+1. as part of the sort key
+2. in the addon_fields
+This made total sense when sort key stored the mem-comparable image
+(from which one cannot restore the original value in general case).
+But since we now store the original value, we could also remove it from the
+addon_fields and further save space. This is still a limitation and needs
+to be fixed later
+
+@see Sort_keys
+
+**/
/**
- There are two record formats for sorting:
- |<key a><key b>...|<rowid>|
- / sort_length / ref_l /
+ The sort record format may use one of two formats for the non-sorted part of
+ the record:
+
+ 1. Use the rowid
+
+ |<sort_key>| <rowid> |
+ / / ref_length /
- or with "addon fields"
- |<key a><key b>...|<null bits>|<field a><field b>...|
- / sort_length / addon_length /
+ 2. Use "addon fields"
+
+ |<sort_key>|<null bits>|<field a><field b>...|
+ / / addon_length /
The packed format for "addon fields"
- |<key a><key b>...|<length>|<null bits>|<field a><field b>...|
- / sort_length / addon_length /
+
+ |<sort_key>|<length>|<null bits>|<field a><field b>...|
+ / / addon_length /
+
+ <sort_key> The key may use one of the two formats:
+ A. fixed-size mem-comparable form. The record is always
+ sort_length bytes long.
+ B. "PackedKeyFormat" - the records are variable-size.
<key> Fields are fixed-size, specially encoded with
Field::make_sort_key() so we can do byte-by-byte compare.
+
<length> Contains the *actual* packed length (after packing) of
everything after the sort keys.
The size of the length field is 2 bytes,
@@ -289,6 +531,7 @@ public:
*/
Bounds_checked_array<SORT_FIELD> local_sortorder;
Addon_fields *addon_fields; // Descriptors for companion fields.
+ Sort_keys *sort_keys;
bool using_pq;
uchar *unique_buff;
@@ -316,12 +559,59 @@ public:
return m_using_packed_addons;
}
+ bool using_packed_sortkeys() const
+ {
+ DBUG_ASSERT(m_using_packed_sortkeys ==
+ (sort_keys != NULL && sort_keys->using_packed_sortkeys()));
+ return m_using_packed_sortkeys;
+ }
+
/// Are we using "addon fields"?
bool using_addon_fields() const
{
return addon_fields != NULL;
}
+ uint32 get_result_length(uchar *plen)
+ {
+ if (!m_using_packed_addons)
+ return res_length;
+ return Addon_fields::read_addon_length(plen);
+ }
+
+ uint32 get_addon_length(uchar *plen)
+ {
+ if (using_packed_addons())
+ return Addon_fields::read_addon_length(plen);
+ else
+ return addon_length;
+ }
+
+ uint32 get_sort_length(uchar *plen)
+ {
+ if (using_packed_sortkeys())
+ return Sort_keys::read_sortkey_length(plen) +
+ /*
+ when addon fields are not present, then the sort_length also
+ includes the res_length. For packed keys here we add
+ the res_length
+ */
+ (using_addon_fields() ? 0: res_length);
+ else
+ return sort_length;
+ }
+
+ uint get_record_length(uchar *plen)
+ {
+ if (m_packed_format)
+ {
+ uint sort_len= get_sort_length(plen);
+ return sort_len + get_addon_length(plen + sort_len);
+ }
+ else
+ return rec_length;
+ }
+
/**
Getter for record length and result length.
@param record_start Pointer to record.
@@ -330,22 +620,46 @@ public:
*/
void get_rec_and_res_len(uchar *record_start, uint *recl, uint *resl)
{
- if (!using_packed_addons())
+ if (m_packed_format)
+ {
+ uint sort_len= get_sort_length(record_start);
+ uint addon_len= get_addon_length(record_start + sort_len);
+ *recl= sort_len + addon_len;
+ *resl= using_addon_fields() ? addon_len : res_length;
+ }
+ else
{
*recl= rec_length;
*resl= res_length;
- return;
}
- uchar *plen= record_start + sort_length;
- *resl= Addon_fields::read_addon_length(plen);
- DBUG_ASSERT(*resl <= res_length);
- const uchar *record_end= plen + *resl;
- *recl= static_cast<uint>(record_end - record_start);
+ }
+
+ void try_to_pack_sortkeys();
+
+ qsort2_cmp get_compare_function() const
+ {
+ return using_packed_sortkeys() ?
+ get_packed_keys_compare_ptr() :
+ get_ptr_compare(sort_length);
+ }
+ void* get_compare_argument(size_t *sort_len) const
+ {
+ return using_packed_sortkeys() ?
+ (void*) this :
+ (void*) sort_len;
+ }
+
+ bool is_packed_format() const
+ {
+ return m_packed_format;
}
private:
uint m_packable_length;
bool m_using_packed_addons; ///< caches the value of using_packed_addons()
+ /* caches the value of using_packed_sortkeys() */
+ bool m_using_packed_sortkeys;
+ bool m_packed_format;
};
typedef Bounds_checked_array<uchar> Sort_buffer;
@@ -353,7 +667,7 @@ typedef Bounds_checked_array<uchar> Sort_buffer;
int merge_many_buff(Sort_param *param, Sort_buffer sort_buffer,
Merge_chunk *buffpek, uint *maxbuffer, IO_CACHE *t_file);
ulong read_to_buffer(IO_CACHE *fromfile, Merge_chunk *buffpek,
- Sort_param *param);
+ Sort_param *param, bool packing_format);
bool merge_buffers(Sort_param *param,IO_CACHE *from_file,
IO_CACHE *to_file, Sort_buffer sort_buffer,
Merge_chunk *lastbuff, Merge_chunk *Fb,
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index a94fb1196b4..55e8e52c052 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1432,7 +1432,7 @@ public:
*/
bool init(uint n_keyparts)
{
- if (!(rowid_buf= (uchar*)my_malloc(rowid_size, MYF(0))))
+ if (!(rowid_buf= (uchar*)my_malloc(PSI_INSTRUMENT_ME, rowid_size, MYF(0))))
return true;
if (open_cached_file(&io_cache, mysql_tmpdir, TEMP_PREFIX,
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 4ddc467794f..2fc6ae0ad7d 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -41,8 +41,8 @@ bool Binary_string::real_alloc(size_t length)
if (Alloced_length < arg_length)
{
free();
- if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME |
- (thread_specific ?
+ if (!(Ptr=(char*) my_malloc(PSI_INSTRUMENT_ME,
+ arg_length,MYF(MY_WME | (thread_specific ?
MY_THREAD_SPECIFIC : 0)))))
return TRUE;
DBUG_ASSERT(length < UINT_MAX32);
@@ -92,13 +92,13 @@ bool Binary_string::realloc_raw(size_t alloc_length)
return TRUE; /* Overflow */
if (alloced)
{
- if (!(new_ptr= (char*) my_realloc(Ptr,len,
+ if (!(new_ptr= (char*) my_realloc(PSI_INSTRUMENT_ME, Ptr,len,
MYF(MY_WME |
(thread_specific ?
MY_THREAD_SPECIFIC : 0)))))
return TRUE; // Signal error
}
- else if ((new_ptr= (char*) my_malloc(len,
+ else if ((new_ptr= (char*) my_malloc(PSI_INSTRUMENT_ME, len,
MYF(MY_WME |
(thread_specific ?
MY_THREAD_SPECIFIC : 0)))))
@@ -1236,3 +1236,25 @@ bool String::append_semi_hex(const char *s, uint len, CHARSET_INFO *cs)
str_length+= nbytes;
return false;
}
+
+// Shrink the buffer, but only if it is allocated on the heap.
+void Binary_string::shrink(size_t arg_length)
+{
+ if (!is_alloced())
+ return;
+ if (ALIGN_SIZE(arg_length + 1) < Alloced_length)
+ {
+ char* new_ptr;
+ if (!(new_ptr = (char*)my_realloc(STRING_PSI_MEMORY_KEY, Ptr, arg_length,
+ MYF(thread_specific ? MY_THREAD_SPECIFIC : 0))))
+ {
+ Alloced_length = 0;
+ real_alloc(arg_length);
+ }
+ else
+ {
+ Ptr = new_ptr;
+ Alloced_length = (uint32)arg_length;
+ }
+ }
+}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index eb69d21eaeb..4eeac0a8a82 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -30,6 +30,13 @@
#include "sql_list.h"
class String;
+#ifdef MYSQL_SERVER
+extern PSI_memory_key key_memory_String_value;
+#define STRING_PSI_MEMORY_KEY key_memory_String_value
+#else
+#define STRING_PSI_MEMORY_KEY PSI_NOT_INSTRUMENTED
+#endif
+
typedef struct st_io_cache IO_CACHE;
typedef struct st_mem_root MEM_ROOT;
@@ -659,28 +666,8 @@ public:
return realloc_with_extra(arg_length);
}
// Shrink the buffer, but only if it is allocated on the heap.
- inline void shrink(size_t arg_length)
- {
- if (!is_alloced())
- return;
- if (ALIGN_SIZE(arg_length+1) < Alloced_length)
- {
- char *new_ptr;
- if (unlikely(!(new_ptr=(char*)
- my_realloc(Ptr,
- arg_length,MYF((thread_specific ?
- MY_THREAD_SPECIFIC : 0))))))
- {
- Alloced_length= 0;
- real_alloc(arg_length);
- }
- else
- {
- Ptr= new_ptr;
- Alloced_length= (uint32) arg_length;
- }
- }
- }
+ void shrink(size_t arg_length);
+
void move(Binary_string &s)
{
set_alloced(s.Ptr, s.str_length, s.Alloced_length);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 240f001f7de..a499f91397a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1127,8 +1127,8 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
ddl_log_entry->tmp_name));
handler_name.str= (char*)ddl_log_entry->handler_name;
handler_name.length= strlen(ddl_log_entry->handler_name);
- init_sql_alloc(&mem_root, "execute_ddl_log_action", TABLE_ALLOC_BLOCK_SIZE,
- 0, MYF(MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_gdl, &mem_root, TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(MY_THREAD_SPECIFIC));
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
frm_action= TRUE;
else
@@ -1162,7 +1162,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
- (void) mysql_file_delete(key_file_partition, to_path, MYF(MY_WME));
+ (void) mysql_file_delete(key_file_partition_ddl_log, to_path, MYF(MY_WME));
#endif
}
else
@@ -1200,7 +1200,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
#ifdef WITH_PARTITION_STORAGE_ENGINE
strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS);
- (void) mysql_file_rename(key_file_partition, from_path, to_path, MYF(MY_WME));
+ (void) mysql_file_rename(key_file_partition_ddl_log, from_path, to_path, MYF(MY_WME));
#endif
}
else
@@ -1297,7 +1297,7 @@ static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
if (global_ddl_log.first_free == NULL)
{
- if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
+ if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(key_memory_DDL_LOG_MEMORY_ENTRY,
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
{
sql_print_error("Failed to allocate memory for ddl log free list");
@@ -6167,7 +6167,7 @@ drop_create_field:
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
- acol->name, (*f_ptr)->field_name.str) == 0)
+ acol->name.str, (*f_ptr)->field_name.str) == 0)
break;
}
if (unlikely(*f_ptr == NULL))
@@ -6175,7 +6175,7 @@ drop_create_field:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR,
ER_THD(thd, ER_BAD_FIELD_ERROR),
- acol->name, table->s->table_name.str);
+ acol->name.str, table->s->table_name.str);
it.remove();
if (alter_info->alter_list.is_empty())
{
@@ -6601,7 +6601,7 @@ static int compare_uint(const uint *s, const uint *t)
enum class Compare_keys : uint32_t
{
- Equal,
+ Equal= 0,
EqualButKeyPartLength,
EqualButComment,
NotEqual
@@ -7998,6 +7998,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
List<Create_field> new_create_list;
/* New key definitions are added here */
List<Key> new_key_list;
+ List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -8138,24 +8139,6 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
- /*
- If we are doing a rename of a column, update all references in virtual
- column expressions, constraints and defaults to use the new column name
- */
- if (alter_info->flags & ALTER_RENAME_COLUMN)
- {
- if (field->vcol_info)
- field->vcol_info->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- if (field->check_constraint)
- field->check_constraint->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- if (field->default_value)
- field->default_value->expr->walk(&Item::rename_fields_processor, 1,
- &column_rename_param);
- table->m_needs_reopen= 1; // because new column name is on thd->mem_root
- }
-
/* Check if field is changed */
def_it.rewind();
while ((def=def_it++))
@@ -8229,19 +8212,61 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
while ((alter=alter_it++))
{
if (!my_strcasecmp(system_charset_info,field->field_name.str,
- alter->name))
+ alter->name.str))
break;
}
if (alter)
{
- if ((def->default_value= alter->default_value))
- def->flags&= ~NO_DEFAULT_VALUE_FLAG;
+ if (alter->is_rename())
+ {
+ def->change= alter->name;
+ def->field_name= alter->new_name;
+ column_rename_param.fields.push_back(def);
+ }
else
- def->flags|= NO_DEFAULT_VALUE_FLAG;
+ {
+ if ((def->default_value= alter->default_value))
+ def->flags&= ~NO_DEFAULT_VALUE_FLAG;
+ else
+ def->flags|= NO_DEFAULT_VALUE_FLAG;
+ }
alter_it.remove();
}
}
}
+
+ /*
+ If we are doing a rename of a column, update all references in virtual
+ column expressions, constraints and defaults to use the new column name
+ */
+ if (alter_info->flags & ALTER_RENAME_COLUMN)
+ {
+ alter_it.rewind();
+ Alter_column *alter;
+ while ((alter=alter_it++))
+ {
+ if (alter->is_rename())
+ {
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), alter->name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+ }
+ for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
+ {
+ if (field->vcol_info)
+ field->vcol_info->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ if (field->check_constraint)
+ field->check_constraint->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ if (field->default_value)
+ field->default_value->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ }
+ table->m_needs_reopen= 1; // because new column name is on thd->mem_root
+ }
+
dropped_sys_vers_fields &= VERS_SYSTEM_FIELD;
if ((dropped_sys_vers_fields ||
alter_info->flags & ALTER_DROP_PERIOD) &&
@@ -8357,7 +8382,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
while ((alter=alter_it++))
{
if (!my_strcasecmp(system_charset_info,def->field_name.str,
- alter->name))
+ alter->name.str))
break;
}
if (alter)
@@ -8372,7 +8397,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (unlikely(alter_info->alter_list.elements))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
- alter_info->alter_list.head()->name, table->s->table_name.str);
+ alter_info->alter_list.head()->name.str, table->s->table_name.str);
goto err;
}
if (unlikely(!new_create_list.elements))
@@ -8422,6 +8447,39 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
+ /* If this index is to stay in the table check if it has to be renamed. */
+ List_iterator<Alter_rename_key> rename_key_it(rename_key_list);
+ Alter_rename_key *rename_key;
+
+ while ((rename_key= rename_key_it++))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, rename_key->old_name.str))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name.str);
+ goto err;
+ }
+ else if (!my_strcasecmp(system_charset_info, rename_key->new_name.str,
+ primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name.str);
+ goto err;
+ }
+
+ key_name= rename_key->new_name.str;
+ rename_key_it.remove();
+ /*
+ If the user has explicitly renamed the key, we should no longer
+ treat it as generated. Otherwise this key might be automatically
+ dropped by mysql_prepare_create_table() and this will confuse
+ code in fill_alter_inplace_info().
+ */
+ key_info->flags&= ~HA_GENERATED_KEY;
+ break;
+ }
+ }
+
if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
{
setup_keyinfo_hash(key_info);
@@ -8748,6 +8806,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
+ if (rename_key_list.elements)
+ {
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list.head()->old_name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+
if (!create_info->comment.str)
{
create_info->comment.str= table->s->comment.str;
@@ -9140,8 +9205,8 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
ref_table= tbuf;
}
- mdl_request.init(MDL_key::TABLE, ref_db, ref_table, MDL_SHARED_NO_WRITE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, ref_db, ref_table,
+ MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
if (thd->mdl_context.acquire_lock(&mdl_request,
thd->variables.lock_wait_timeout))
DBUG_RETURN(true);
@@ -9566,9 +9631,9 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
MDL_request_list mdl_requests;
MDL_request target_db_mdl_request;
- target_mdl_request.init(MDL_key::TABLE,
- alter_ctx.new_db.str, alter_ctx.new_name.str,
- MDL_EXCLUSIVE, MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&target_mdl_request, MDL_key::TABLE,
+ alter_ctx.new_db.str, alter_ctx.new_name.str,
+ MDL_EXCLUSIVE, MDL_TRANSACTION);
mdl_requests.push_front(&target_mdl_request);
/*
@@ -9578,9 +9643,9 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
*/
if (alter_ctx.is_database_changed())
{
- target_db_mdl_request.init(MDL_key::SCHEMA, alter_ctx.new_db.str, "",
- MDL_INTENTION_EXCLUSIVE,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&target_db_mdl_request, MDL_key::SCHEMA,
+ alter_ctx.new_db.str, "", MDL_INTENTION_EXCLUSIVE,
+ MDL_TRANSACTION);
mdl_requests.push_front(&target_db_mdl_request);
}
@@ -9827,8 +9892,7 @@ do_continue:;
bool fast_alter_partition= false;
{
if (prep_alter_part_table(thd, table, alter_info, create_info,
- &alter_ctx, &partition_changed,
- &fast_alter_partition))
+ &partition_changed, &fast_alter_partition))
{
DBUG_RETURN(true);
}
@@ -10680,6 +10744,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
+ mysql_stage_set_work_estimated(thd->m_stage_progress_psi, from->file->stats.records);
+
List_iterator<Create_field> it(create);
Create_field *def;
copy_end=copy;
@@ -10780,7 +10846,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
from->file->column_bitmaps_signal();
- THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
/* Add virtual columns to vcol_set to ensure they are updated */
@@ -10926,7 +10991,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
}
else
+ {
+ DEBUG_SYNC(thd, "copy_data_between_tables_before");
found_count++;
+ mysql_stage_set_work_completed(thd->m_stage_progress_psi, found_count);
+ }
thd->get_stmt_da()->inc_current_row_for_warning();
}
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 07e2d5e084e..ffd42599527 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -466,7 +466,8 @@ static void display_table_locks(void)
void *saved_base;
DYNAMIC_ARRAY saved_table_locks;
- (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),
+ (void) my_init_dynamic_array(key_memory_locked_thread_list,
+ &saved_table_locks, sizeof(TABLE_LOCK_INFO),
tc_records() + 20, 50, MYF(0));
mysql_mutex_lock(&THR_LOCK_lock);
for (list= thr_lock_thread_list; list; list= list_rest(list))
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 8a9311ae577..c08e54bed87 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -830,7 +830,8 @@ DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format)
if (thd)
new_format= (DATE_TIME_FORMAT *) thd->alloc(length);
else
- new_format= (DATE_TIME_FORMAT *) my_malloc(length, MYF(MY_WME));
+ new_format= (DATE_TIME_FORMAT *) my_malloc(key_memory_DATE_TIME_FORMAT,
+ length, MYF(MY_WME));
if (new_format)
{
/* Put format string after current pos */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 0ae3d58b11f..5b8ae46d33f 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -30,11 +30,11 @@
#include "sql_table.h" // build_table_filename,
// check_n_cut_mysql50_prefix
#include "sql_db.h" // get_default_db_collation
-#include "sql_acl.h" // *_ACL
#include "sql_handler.h" // mysql_ha_rm_tables
#include "sp_cache.h" // sp_invalidate_cache
#include <mysys_err.h>
#include "debug_sync.h"
+#include "mysql/psi/mysql_sp.h"
/*************************************************************************/
@@ -440,7 +440,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
*/
if (!trust_function_creators &&
(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
- !(thd->security_ctx->master_access & SUPER_ACL))
+ !(thd->security_ctx->master_access & PRIV_LOG_BIN_TRUSTED_SP_CREATOR))
{
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
@@ -463,7 +463,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
*/
thd->lex->sql_command= backup.sql_command;
- if (opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) &&
+ if (opt_readonly &&
+ !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
!thd->slave_thread)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
@@ -624,7 +625,13 @@ end:
thd->lex->restore_backup_query_tables_list(&backup);
if (!result)
+ {
my_ok(thd);
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(SP_TYPE_TRIGGER,
+ thd->lex->spname->m_db.str, static_cast<uint>(thd->lex->spname->m_db.length),
+ thd->lex->spname->m_name.str, static_cast<uint>(thd->lex->spname->m_name.length));
+ }
DBUG_RETURN(result);
#ifdef WITH_WSREP
@@ -1554,6 +1561,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
trigger->definer= *trg_definer;
}
+ sp->m_sp_share= MYSQL_GET_SP_SHARE(SP_TYPE_TRIGGER,
+ sp->m_db.str, static_cast<uint>(sp->m_db.length),
+ sp->m_name.str, static_cast<uint>(sp->m_name.length));
+
#ifndef DBUG_OFF
/*
Let us check that we correctly update trigger definitions when we
@@ -1813,8 +1824,8 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db,
DBUG_ENTER("Triggers::drop_all_triggers");
table.reset();
- init_sql_alloc(&table.mem_root, "Triggers::drop_all_triggers", 8192, 0,
- MYF(0));
+ init_sql_alloc(key_memory_Table_trigger_dispatcher,
+ &table.mem_root, 8192, 0, MYF(0));
if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
{
@@ -1846,6 +1857,9 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db,
*/
result= 1;
}
+ /* Drop statistics for this stored program from performance schema. */
+ MYSQL_DROP_SP(SP_TYPE_TRIGGER, db->str, static_cast<uint>(db->length),
+ trigger->name.str, static_cast<uint>(trigger->name.length));
}
}
}
@@ -2065,8 +2079,8 @@ bool Table_triggers_list::change_table_name(THD *thd, const LEX_CSTRING *db,
DBUG_ENTER("Triggers::change_table_name");
table.reset();
- init_sql_alloc(&table.mem_root, "Triggers::change_table_name", 8192, 0,
- MYF(0));
+ init_sql_alloc(key_memory_Table_trigger_dispatcher,
+ &table.mem_root, 8192, 0, MYF(0));
/*
This method interfaces the mysql server code protected by
diff --git a/sql/sql_type.h b/sql/sql_type.h
index ce87c8e9d93..f87e398bd71 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -23,6 +23,7 @@
#include "mysqld.h"
+#include "lex_string.h"
#include "sql_array.h"
#include "sql_const.h"
#include "sql_time.h"
@@ -86,6 +87,7 @@ class handler;
struct Schema_specification_st;
struct TABLE;
struct SORT_FIELD_ATTR;
+struct SORT_FIELD;
class Vers_history_point;
class Virtual_column_info;
class Conv_source;
@@ -137,6 +139,41 @@ enum column_definition_type_t
};
+class Send_field_extended_metadata
+{
+ LEX_CSTRING m_attr[MARIADB_FIELD_ATTR_LAST+1];
+public:
+ Send_field_extended_metadata()
+ {
+ bzero(this, sizeof(*this));
+ }
+ bool set_data_type_name(const LEX_CSTRING &str)
+ {
+ m_attr[MARIADB_FIELD_ATTR_DATA_TYPE_NAME]= str;
+ return false;
+ }
+ bool set_format_name(const LEX_CSTRING &str)
+ {
+ m_attr[MARIADB_FIELD_ATTR_FORMAT_NAME]= str;
+ return false;
+ }
+ bool has_extended_metadata() const
+ {
+ for (uint i= 0; i <= MARIADB_FIELD_ATTR_LAST; i++)
+ {
+ if (m_attr[i].str)
+ return true;
+ }
+ return false;
+ }
+ const LEX_CSTRING &attr(uint i) const
+ {
+ DBUG_ASSERT(i <= MARIADB_FIELD_ATTR_LAST);
+ return m_attr[i];
+ }
+};
+
+
class Data_type_statistics
{
public:
@@ -3332,6 +3369,14 @@ protected:
bool maybe_null, bool null_value,
bool unsigned_flag,
longlong value) const;
+ void store_sort_key_longlong(uchar *to, bool unsigned_flag,
+ longlong value) const;
+
+ uint make_packed_sort_key_longlong(uchar *to, bool maybe_null,
+ bool null_value, bool unsigned_flag,
+ longlong value,
+ const SORT_FIELD_ATTR *sort_field) const;
+
bool Item_func_or_sum_illegal_param(const char *name) const;
bool Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
bool check_null(const Item *item, st_value *value) const;
@@ -3426,6 +3471,11 @@ public:
return field_type();
}
virtual protocol_send_type_t protocol_send_type() const= 0;
+ virtual bool Item_append_extended_type_info(Send_field_extended_metadata *to,
+ const Item *item) const
+ {
+ return false;
+ }
virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0;
virtual enum_dynamic_column_type
@@ -3752,12 +3802,25 @@ public:
const uchar *buffer,
LEX_CUSTRING *gis_options) const;
- virtual void make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const= 0;
- virtual void sortlength(THD *thd,
+ /*
+ Create a fixed size key part for a sort key
+ */
+ virtual void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const= 0;
+
+ /*
+ create a compact size key part for a sort key
+ */
+ virtual uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const=0;
+
+ virtual void sort_length(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const= 0;
+ virtual bool is_packable() const { return false; }
+
virtual uint32 max_display_length(const Item *item) const= 0;
virtual uint32 Item_decimal_notation_int_digits(const Item *item) const { return 0; }
@@ -4149,14 +4212,21 @@ public:
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const override;
- void make_sort_key(uchar *to, Item *item,
- const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override
{
DBUG_ASSERT(0);
}
- void sortlength(THD *thd, const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ void sort_length(THD *thd, const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override
{
DBUG_ASSERT(0);
}
@@ -4481,11 +4551,15 @@ public:
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer)
const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const override;
bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
@@ -4588,8 +4662,12 @@ public:
bool show_field) const override;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *)
const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const override;
@@ -4599,9 +4677,9 @@ public:
const uchar *buffer,
LEX_CUSTRING *gis_options)
const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
uint32 max_display_length(const Item *item) const override;
uint32 Item_decimal_notation_int_digits(const Item *item) const override;
Item *create_typecast_item(THD *thd, Item *item,
@@ -4838,14 +4916,18 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE_SHARE *share) const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const override;
bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
@@ -4945,11 +5027,15 @@ public:
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const override;
bool Item_param_set_from_value(THD *thd,
@@ -5034,11 +5120,16 @@ public:
const Type_handler *
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
+ bool is_packable()const override { return true; }
bool union_element_finalize(const Item * item) const override;
uint calc_key_length(const Column_definition &def) const override;
bool Column_definition_prepare_stage1(THD *thd,
@@ -6230,11 +6321,15 @@ public:
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const override;
in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs)
const override;
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const override;
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const override;
+ void make_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ uint make_packed_sort_key_part(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const override;
+ void sort_length(THD *thd,
+ const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const override;
bool Column_definition_fix_attributes(Column_definition *c) const override;
uint Item_decimal_scale(const Item *item) const override
{
@@ -7192,7 +7287,7 @@ private:
const Type_handler *handler2) const;
public:
Type_aggregator(bool is_commutative= false)
- :m_is_commutative(is_commutative)
+ :m_is_commutative(is_commutative), m_array(PSI_INSTRUMENT_MEM)
{ }
bool add(const Type_handler *handler1,
const Type_handler *handler2,
diff --git a/sql/sql_type_geom.cc b/sql/sql_type_geom.cc
index 3ca0eaabc3f..0dcde0009b0 100644
--- a/sql/sql_type_geom.cc
+++ b/sql/sql_type_geom.cc
@@ -34,6 +34,14 @@ Named_type_handler<Type_handler_geometrycollection> type_handler_geometrycollect
Type_collection_geometry type_collection_geometry;
+
+LEX_CSTRING Type_handler_geometry::extended_metadata_data_type_name() const
+{
+ return geometry_type() == GEOM_GEOMETRY ? null_clex_str :
+ name().lex_cstring();
+}
+
+
const Type_handler_geometry *
Type_handler_geometry::type_handler_geom_by_type(uint type)
{
diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h
index a2baa5ae299..b1aa8063902 100644
--- a/sql/sql_type_geom.h
+++ b/sql/sql_type_geom.h
@@ -39,9 +39,16 @@ public:
Item * const *args,
uint start, uint end);
static const Type_handler_geometry *type_handler_geom_by_type(uint type);
+ LEX_CSTRING extended_metadata_data_type_name() const;
public:
virtual ~Type_handler_geometry() {}
enum_field_types field_type() const override { return MYSQL_TYPE_GEOMETRY; }
+ bool Item_append_extended_type_info(Send_field_extended_metadata *to,
+ const Item *item) const override
+ {
+ LEX_CSTRING tmp= extended_metadata_data_type_name();
+ return tmp.length ? to->set_data_type_name(tmp) : false;
+ }
bool is_param_long_data_type() const override { return true; }
uint32 max_display_length_for_field(const Conv_source &src) const override;
uint32 calc_pack_length(uint32 length) const override;
@@ -361,6 +368,9 @@ public:
void make_send_field(Send_field *to) override
{
Field_longstr::make_send_field(to);
+ LEX_CSTRING tmp= m_type_handler->extended_metadata_data_type_name();
+ if (tmp.length)
+ to->set_data_type_name(tmp);
}
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 35c799d4a86..4da85de7852 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -110,6 +110,8 @@ extern "C" uchar* get_hash_key(const uchar *buff, size_t *length,
return (uchar*) udf->name.str;
}
+static PSI_memory_key key_memory_udf_mem;
+
#ifdef HAVE_PSI_INTERFACE
static PSI_rwlock_key key_rwlock_THR_LOCK_udf;
@@ -118,6 +120,11 @@ static PSI_rwlock_info all_udf_rwlocks[]=
{ &key_rwlock_THR_LOCK_udf, "THR_LOCK_udf", PSI_FLAG_GLOBAL}
};
+static PSI_memory_info all_udf_memory[]=
+{
+ { &key_memory_udf_mem, "udf_mem", PSI_FLAG_GLOBAL}
+};
+
static void init_udf_psi_keys(void)
{
const char* category= "sql";
@@ -128,6 +135,9 @@ static void init_udf_psi_keys(void)
count= array_elements(all_udf_rwlocks);
PSI_server->register_rwlock(category, all_udf_rwlocks, count);
+
+ count= array_elements(all_udf_memory);
+ mysql_memory_register(category, all_udf_memory, count);
}
#endif
@@ -154,10 +164,11 @@ void udf_init()
mysql_rwlock_init(key_rwlock_THR_LOCK_udf, &THR_LOCK_udf);
- init_sql_alloc(&mem, "udf", UDF_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_udf_mem, &mem, UDF_ALLOC_BLOCK_SIZE, 0, MYF(0));
THD *new_thd = new THD(0);
if (!new_thd ||
- my_hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0))
+ my_hash_init(key_memory_udf_mem,
+ &udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0))
{
sql_print_error("Can't allocate memory for udf structures");
my_hash_free(&udf_hash);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index d5d43e56875..f8025cdf701 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -257,6 +257,8 @@ int select_union_recursive::send_data(List<Item> &values)
write_err != HA_ERR_FOUND_DUPP_UNIQUE)
{
int err;
+ DBUG_ASSERT(incr_table->s->reclength == table->s->reclength ||
+ incr_table->s->reclength == table->s->reclength - MARIA_UNIQUE_HASH_LENGTH);
if ((err= incr_table->file->ha_write_tmp_row(table->record[0])))
{
bool is_duplicate;
@@ -1561,7 +1563,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
{
if (with_element)
{
- if (with_element->rename_columns_of_derived_unit(thd, this))
+ if (with_element->process_columns_of_derived_unit(thd, this))
goto err;
if (check_duplicate_names(thd, sl->item_list, 0))
goto err;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6d6958ba50b..d0a920fd473 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -35,7 +35,6 @@
#include "probes_mysql.h"
#include "debug_sync.h"
#include "key.h" // is_key_used
-#include "sql_acl.h" // *_ACL, check_grant
#include "records.h" // init_read_record,
// end_read_record
#include "filesort.h" // filesort
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index f47e910c0fe..b2e977151fd 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -27,7 +27,6 @@
#include "sql_show.h" // append_identifier
#include "sql_table.h" // build_table_filename
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
-#include "sql_acl.h" // *_ACL, check_grant
#include "sql_select.h"
#include "parse_file.h"
#include "sp_head.h"
@@ -138,7 +137,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view
Item *check;
/* treat underlying fields like set by user names */
if (item->real_item()->type() == Item::FIELD_ITEM)
- item->is_autogenerated_name= FALSE;
+ item->common_flags&= ~IS_AUTO_GENERATED_NAME;
itc.rewind();
while ((check= itc++) && check != item)
{
@@ -146,9 +145,9 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view
{
if (!gen_unique_view_name)
goto err;
- if (item->is_autogenerated_name)
+ if (item->is_autogenerated_name())
make_unique_view_field_name(thd, item, item_list, item);
- else if (check->is_autogenerated_name)
+ else if (check->is_autogenerated_name())
make_unique_view_field_name(thd, check, item_list, item);
else
goto err;
@@ -180,7 +179,7 @@ void make_valid_column_names(THD *thd, List<Item> &item_list)
for (uint column_no= 1; (item= it++); column_no++)
{
- if (!item->is_autogenerated_name || !check_column_name(item->name.str))
+ if (!item->is_autogenerated_name() || !check_column_name(item->name.str))
continue;
name_len= my_snprintf(buff, NAME_LEN, "Name_exp_%u", column_no);
item->orig_name= item->name.str;
@@ -566,7 +565,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
while ((item= it++, name= nm++))
{
item->set_name(thd, *name);
- item->is_autogenerated_name= FALSE;
+ item->common_flags&= ~IS_AUTO_GENERATED_NAME;
}
}
diff --git a/sql/sql_window.cc b/sql/sql_window.cc
index 7e319c96000..a9a1dccf9f6 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -778,10 +778,10 @@ public:
{
//DBUG_ASSERT(info->read_record == rr_from_tempfile);
rownum= 0;
- io_cache= (IO_CACHE*)my_malloc(sizeof(IO_CACHE), MYF(0));
+ io_cache= (IO_CACHE*)my_malloc(PSI_INSTRUMENT_ME, sizeof(IO_CACHE), MYF(0));
init_slave_io_cache(info->io_cache, io_cache);
- ref_buffer= (uchar*)my_malloc(ref_length, MYF(0));
+ ref_buffer= (uchar*)my_malloc(PSI_INSTRUMENT_ME, ref_length, MYF(0));
ref_buffer_valid= false;
}
}
@@ -2816,7 +2816,7 @@ bool compute_window_func(THD *thd,
List_iterator_fast<Group_bound_tracker> iter_part_trackers(partition_trackers);
ha_rows rownum= 0;
- uchar *rowid_buf= (uchar*) my_malloc(tbl->file->ref_length, MYF(0));
+ uchar *rowid_buf= (uchar*) my_malloc(PSI_INSTRUMENT_ME, tbl->file->ref_length, MYF(0));
while (true)
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f24da3ed412..3f0f7251d5c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -38,7 +38,6 @@
#include "sql_parse.h" /* comp_*_creator */
#include "sql_table.h" /* primary_key_name */
#include "sql_partition.h" /* partition_info, HASH_PARTITION */
-#include "sql_acl.h" /* *_ACL */
#include "sql_class.h" /* Key_part_spec, enum_filetype, Diag_condition_item_name */
#include "slave.h"
#include "lex_symbol.h"
@@ -835,6 +834,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
%token <kwd> EXTENT_SIZE_SYM
%token <kwd> FAST_SYM
%token <kwd> FAULTS_SYM
+%token <kwd> FEDERATED_SYM /* MariaDB privilege */
%token <kwd> FILE_SYM
%token <kwd> FIRST_SYM /* SQL-2003-N */
%token <kwd> FIXED_SYM
@@ -931,6 +931,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
%token <kwd> MIN_ROWS
%token <kwd> MODE_SYM
%token <kwd> MODIFY_SYM
+%token <kwd> MONITOR_SYM /* MariaDB privilege */
%token <kwd> MONTH_SYM /* SQL-2003-R */
%token <kwd> MUTEX_SYM
%token <kwd> MYSQL_SYM
@@ -1749,6 +1750,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
comma_separated_ident_list
opt_with_column_list
with_column_list
+ opt_cycle
%type <vers_range_unit> opt_history_unit
%type <vers_history_point> history_point
@@ -7705,13 +7707,12 @@ alter_list_item:
}
| ALTER opt_column opt_if_exists_table_element field_ident SET DEFAULT column_default_expr
{
- if (unlikely(Lex->add_alter_list($4.str, $7, $3)))
+ if (unlikely(Lex->add_alter_list($4, $7, $3)))
MYSQL_YYABORT;
}
| ALTER opt_column opt_if_exists_table_element field_ident DROP DEFAULT
{
- if (unlikely(Lex->add_alter_list($4.str, (Virtual_column_info*) 0,
- $3)))
+ if (unlikely(Lex->add_alter_list($4, (Virtual_column_info*) 0, $3)))
MYSQL_YYABORT;
}
| RENAME opt_to table_ident
@@ -7728,6 +7729,21 @@ alter_list_item:
lex->name= $3->table;
lex->alter_info.flags|= ALTER_RENAME;
}
+ | RENAME COLUMN_SYM ident TO_SYM ident
+ {
+ if (unlikely(Lex->add_alter_list($3, $5)))
+ MYSQL_YYABORT;
+ }
+ | RENAME key_or_index field_ident TO_SYM field_ident
+ {
+ LEX *lex=Lex;
+ Alter_rename_key *ak= new (thd->mem_root)
+ Alter_rename_key($3, $5);
+ if (ak == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.alter_rename_key_list.push_back(ak);
+ lex->alter_info.flags|= ALTER_RENAME_INDEX;
+ }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{
if (!$4)
@@ -9062,7 +9078,7 @@ select_item:
if (unlikely(Lex->sql_command == SQLCOM_CREATE_VIEW &&
check_column_name($4.str)))
my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
- $2->is_autogenerated_name= FALSE;
+ $2->common_flags&= ~IS_AUTO_GENERATED_NAME;
$2->set_name(thd, $4);
}
else if (!$2->name.str || $2->name.str == item_empty_name)
@@ -10624,7 +10640,7 @@ udf_expr:
*/
if ($4.str)
{
- $2->is_autogenerated_name= FALSE;
+ $2->common_flags&= ~IS_AUTO_GENERATED_NAME;
$2->set_name(thd, $4);
}
/*
@@ -12330,7 +12346,7 @@ int_num:
ulong_num:
opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
- | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
+ | HEX_NUM { $$= strtoul($1.str, (char**) 0, 16); }
| opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
| opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
| opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
@@ -13605,9 +13621,13 @@ show_param:
MYSQL_YYABORT;
lex->table_type= TABLE_TYPE_SEQUENCE;
}
+ | BINLOG_SYM STATUS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_BINLOG_STAT;
+ }
| MASTER_SYM STATUS_SYM
{
- Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
+ Lex->sql_command = SQLCOM_SHOW_BINLOG_STAT;
}
| ALL SLAVES STATUS_SYM
{
@@ -14735,7 +14755,7 @@ with_list:
with_list_element:
query_name
opt_with_column_list
- AS '(' query_expression ')'
+ AS '(' query_expression ')' opt_cycle
{
LEX *lex= thd->lex;
const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
@@ -14747,9 +14767,30 @@ with_list_element:
if (elem->set_unparsed_spec(thd, spec_start, $6.pos(),
spec_start - query_start))
MYSQL_YYABORT;
+ if ($7)
+ {
+ elem->set_cycle_list($7);
+ }
}
;
+opt_cycle:
+ /* empty */
+ { $$= NULL; }
+ |
+ CYCLE_SYM
+ {
+ if (!Lex->curr_with_clause->with_recursive)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, $1.pos());
+ }
+ }
+ comma_separated_ident_list RESTRICT
+ {
+ $$= $3;
+ }
+ ;
+
opt_with_column_list:
/* empty */
@@ -15476,6 +15517,7 @@ keyword_sp_var_and_label:
| FAST_SYM
| FOUND_SYM
| ENABLE_SYM
+ | FEDERATED_SYM
| FULL
| FILE_SYM
| FIRST_SYM
@@ -15554,6 +15596,7 @@ keyword_sp_var_and_label:
| MIN_ROWS
| MODIFY_SYM
| MODE_SYM
+ | MONITOR_SYM
| MONTH_SYM
| MUTEX_SYM
| MYSQL_SYM
@@ -16862,7 +16905,7 @@ object_privilege:
| CREATE TEMPORARY TABLES { $$= CREATE_TMP_ACL;}
| LOCK_SYM TABLES { $$= LOCK_TABLES_ACL; }
| REPLICATION SLAVE { $$= REPL_SLAVE_ACL; }
- | REPLICATION CLIENT_SYM { $$= REPL_CLIENT_ACL; }
+ | REPLICATION CLIENT_SYM { $$= BINLOG_MONITOR_ACL; /*Compatibility*/ }
| CREATE VIEW_SYM { $$= CREATE_VIEW_ACL; }
| SHOW VIEW_SYM { $$= SHOW_VIEW_ACL; }
| CREATE ROUTINE_SYM { $$= CREATE_PROC_ACL; }
@@ -16872,6 +16915,15 @@ object_privilege:
| TRIGGER_SYM { $$= TRIGGER_ACL; }
| CREATE TABLESPACE { $$= CREATE_TABLESPACE_ACL; }
| DELETE_SYM HISTORY_SYM { $$= DELETE_HISTORY_ACL; }
+ | SET USER_SYM { $$= SET_USER_ACL; }
+ | FEDERATED_SYM ADMIN_SYM { $$= FEDERATED_ADMIN_ACL; }
+ | CONNECTION_SYM ADMIN_SYM { $$= CONNECTION_ADMIN_ACL; }
+ | READ_SYM ONLY_SYM ADMIN_SYM { $$= READ_ONLY_ADMIN_ACL; }
+ | READ_ONLY_SYM ADMIN_SYM { $$= READ_ONLY_ADMIN_ACL; }
+ | BINLOG_SYM MONITOR_SYM { $$= BINLOG_MONITOR_ACL; }
+ | BINLOG_SYM ADMIN_SYM { $$= BINLOG_ADMIN_ACL; }
+ | REPLICATION MASTER_SYM ADMIN_SYM { $$= REPL_MASTER_ADMIN_ACL; }
+ | REPLICATION SLAVE ADMIN_SYM { $$= REPL_SLAVE_ADMIN_ACL; }
;
opt_and:
@@ -17539,7 +17591,10 @@ xid:
}
| text_string ',' text_string ',' ulong_num
{
- MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE &&
+ $3->length() <= MAXBQUALSIZE &&
+ $5 <= static_cast<ulong>(
+ std::numeric_limits<int32_t>::max()));
if (unlikely(!(Lex->xid=(XID *)thd->alloc(sizeof(XID)))))
MYSQL_YYABORT;
Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 4ba866749ee..15b749dcb61 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -45,8 +45,7 @@
#include "mysqld.h"
#include "lock.h"
#include "sql_time.h" // known_date_time_formats
-#include "sql_acl.h" // SUPER_ACL,
- // mysql_user_table_is_in_short_password_format
+#include "sql_acl.h" // mysql_user_table_is_in_short_password_format
#include "derror.h" // read_texts
#include "sql_base.h" // close_cached_tables
#include "hostname.h" // host_cache_size
@@ -81,8 +80,7 @@
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
static Sys_var_mybool Sys_pfs_enabled(
- "performance_schema",
- "Enable the performance schema.",
+ "performance_schema", "Enable the performance schema.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_enabled),
CMD_LINE(OPT_ARG), DEFAULT(FALSE));
@@ -90,10 +88,9 @@ static Sys_var_long Sys_pfs_events_waits_history_long_size(
"performance_schema_events_waits_history_long_size",
"Number of rows in EVENTS_WAITS_HISTORY_LONG."
" Use 0 to disable, -1 for automated sizing.",
- PARSED_EARLY READ_ONLY
- GLOBAL_VAR(pfs_param.m_events_waits_history_long_sizing),
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_long_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_events_waits_history_size(
"performance_schema_events_waits_history_size",
@@ -101,7 +98,7 @@ static Sys_var_long Sys_pfs_events_waits_history_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_cond_classes(
"performance_schema_max_cond_classes",
@@ -116,7 +113,23 @@ static Sys_var_long Sys_pfs_max_cond_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_cond_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_program_instances(
+ "performance_schema_max_program_instances",
+ "Maximum number of instrumented programs."
+ " Use 0 to disable, -1 for automated scaling.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_program_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_prepared_stmt_instances(
+ "performance_schema_max_prepared_statements_instances",
+ "Maximum number of instrumented prepared statements."
+ " Use 0 to disable, -1 for automated scaling.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_prepared_stmt_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_file_classes(
"performance_schema_max_file_classes",
@@ -138,7 +151,7 @@ static Sys_var_long Sys_pfs_max_file_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_file_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_max_sockets(
"performance_schema_max_socket_instances",
@@ -146,16 +159,14 @@ static Sys_var_long Sys_pfs_max_sockets(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_socket_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_socket_classes(
"performance_schema_max_socket_classes",
"Maximum number of socket instruments.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_socket_class_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
- DEFAULT(PFS_MAX_SOCKET_CLASS),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_MAX_SOCKET_CLASS), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_mutex_classes(
"performance_schema_max_mutex_classes",
@@ -170,7 +181,7 @@ static Sys_var_long Sys_pfs_max_mutex_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_mutex_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 100*1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_rwlock_classes(
"performance_schema_max_rwlock_classes",
@@ -185,7 +196,7 @@ static Sys_var_long Sys_pfs_max_rwlock_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_rwlock_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 100*1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_max_table_handles(
"performance_schema_max_table_handles",
@@ -193,7 +204,7 @@ static Sys_var_long Sys_pfs_max_table_handles(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_table_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_max_table_instances(
"performance_schema_max_table_instances",
@@ -201,7 +212,23 @@ static Sys_var_long Sys_pfs_max_table_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_table_share_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_table_lock_stat(
+ "performance_schema_max_table_lock_stat",
+ "Maximum number of lock statistics for instrumented tables."
+ " Use 0 to disable, -1 for automated scaling.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_table_lock_stat_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_index_stat(
+ "performance_schema_max_index_stat",
+ "Maximum number of index statistics for instrumented tables."
+ " Use 0 to disable, -1 for automated scaling.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_index_stat_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_thread_classes(
"performance_schema_max_thread_classes",
@@ -216,23 +243,21 @@ static Sys_var_long Sys_pfs_max_thread_instances(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_thread_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1), BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
-static Sys_var_ulong Sys_pfs_setup_actors_size(
+static Sys_var_long Sys_pfs_setup_actors_size(
"performance_schema_setup_actors_size",
"Maximum number of rows in SETUP_ACTORS.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_setup_actor_sizing),
- CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024),
- DEFAULT(PFS_MAX_SETUP_ACTOR),
- BLOCK_SIZE(1));
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
-static Sys_var_ulong Sys_pfs_setup_objects_size(
+static Sys_var_long Sys_pfs_setup_objects_size(
"performance_schema_setup_objects_size",
"Maximum number of rows in SETUP_OBJECTS.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_setup_object_sizing),
- CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024),
- DEFAULT(PFS_MAX_SETUP_OBJECT),
- BLOCK_SIZE(1));
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_accounts_size(
"performance_schema_accounts_size",
@@ -240,8 +265,7 @@ static Sys_var_long Sys_pfs_accounts_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_account_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_hosts_size(
"performance_schema_hosts_size",
@@ -249,8 +273,7 @@ static Sys_var_long Sys_pfs_hosts_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_host_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_users_size(
"performance_schema_users_size",
@@ -258,16 +281,14 @@ static Sys_var_long Sys_pfs_users_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_user_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_ulong Sys_pfs_max_stage_classes(
"performance_schema_max_stage_classes",
"Maximum number of stage instruments.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_stage_class_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
- DEFAULT(PFS_MAX_STAGE_CLASS),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_MAX_STAGE_CLASS), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_events_stages_history_long_size(
"performance_schema_events_stages_history_long_size",
@@ -275,8 +296,7 @@ static Sys_var_long Sys_pfs_events_stages_history_long_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_stages_history_long_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_events_stages_history_size(
"performance_schema_events_stages_history_size",
@@ -284,26 +304,27 @@ static Sys_var_long Sys_pfs_events_stages_history_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_stages_history_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
/**
Variable performance_schema_max_statement_classes.
The default number of statement classes is the sum of:
+ - SQLCOM_END for all regular "statement/sql/...",
+ - SP_PSI_STATEMENT_INFO_COUNT for "statement/sp/...".
- (COM_END - mariadb gap) for all regular "statement/com/...",
- 1 for "statement/com/new_packet", for unknown enum_server_command
- 1 for "statement/com/Error", for invalid enum_server_command
- - SQLCOM_END for all regular "statement/sql/...",
- 1 for "statement/sql/error", for invalid enum_sql_command
- 1 for "statement/rpl/relay_log", for replicated statements.
+ - 1 for "statement/scheduler/event", for scheduled events.
*/
static Sys_var_ulong Sys_pfs_max_statement_classes(
"performance_schema_max_statement_classes",
"Maximum number of statement instruments.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
- DEFAULT((ulong) SQLCOM_END +
- (ulong) (COM_END -(COM_MDB_GAP_END - COM_MDB_GAP_BEG + 1)) + 4),
+ DEFAULT((ulong) SQLCOM_END + SP_PSI_STATEMENT_INFO_COUNT +
+ (ulong) (COM_END -(COM_MDB_GAP_END - COM_MDB_GAP_BEG + 1)) + 5),
BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_events_statements_history_long_size(
@@ -312,8 +333,7 @@ static Sys_var_long Sys_pfs_events_statements_history_long_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_statements_history_long_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_events_statements_history_size(
"performance_schema_events_statements_history_size",
@@ -321,8 +341,21 @@ static Sys_var_long Sys_pfs_events_statements_history_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_statements_history_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_ulong Sys_pfs_statement_stack_size(
+ "performance_schema_max_statement_stack",
+ "Number of rows per thread in EVENTS_STATEMENTS_CURRENT.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_statement_stack_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, 256),
+ DEFAULT(PFS_STATEMENTS_STACK_SIZE), BLOCK_SIZE(1));
+
+static Sys_var_ulong Sys_pfs_max_memory_classes(
+ "performance_schema_max_memory_classes",
+ "Maximum number of memory pool instruments.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_memory_class_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024),
+ DEFAULT(PFS_MAX_MEMORY_CLASS), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_digest_size(
"performance_schema_digests_size",
@@ -330,16 +363,30 @@ static Sys_var_long Sys_pfs_digest_size(
" Use 0 to disable, -1 for automated sizing.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_digest_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 200),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_events_transactions_history_long_size(
+ "performance_schema_events_transactions_history_long_size",
+ "Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG."
+ " Use 0 to disable, -1 for automated sizing.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_transactions_history_long_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024*1024),
+ DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_events_transactions_history_size(
+ "performance_schema_events_transactions_history_size",
+ "Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY."
+ " Use 0 to disable, -1 for automated sizing.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_events_transactions_history_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024),
+ DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_max_digest_length(
"performance_schema_max_digest_length",
"Maximum length considered for digest text, when stored in performance_schema tables.",
PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_max_digest_length),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024),
- DEFAULT(1024),
- BLOCK_SIZE(1));
+ DEFAULT(1024), BLOCK_SIZE(1));
static Sys_var_long Sys_pfs_connect_attrs_size(
"performance_schema_session_connect_attrs_size",
@@ -348,8 +395,22 @@ static Sys_var_long Sys_pfs_connect_attrs_size(
PARSED_EARLY READ_ONLY
GLOBAL_VAR(pfs_param.m_session_connect_attrs_sizing),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
- DEFAULT(-1),
- BLOCK_SIZE(1));
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_metadata_locks(
+ "performance_schema_max_metadata_locks",
+ "Maximum number of metadata locks."
+ " Use 0 to disable, -1 for automated scaling.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_metadata_lock_sizing),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 100*1024*1024),
+ DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1));
+
+static Sys_var_long Sys_pfs_max_sql_text_length(
+ "performance_schema_max_sql_text_length",
+ "Maximum length of displayed sql text.",
+ PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_max_sql_text_length),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024),
+ DEFAULT(1024), BLOCK_SIZE(1));
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
@@ -523,7 +584,8 @@ bool check_has_super(sys_var *self, THD *thd, set_var *var)
{
DBUG_ASSERT(self->scope() != sys_var::GLOBAL);// don't abuse check_has_super()
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (!(thd->security_ctx->master_access & SUPER_ACL))
+ if (!(thd->security_ctx->master_access &
+ PRIV_SET_RESTRICTED_SESSION_SYSTEM_VARIABLE))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
return true;
@@ -1517,24 +1579,21 @@ static Sys_var_ulong Sys_slave_max_allowed_packet(
"The maximum packet length to sent successfully from the master to slave.",
GLOBAL_VAR(slave_max_allowed_packet), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1024, MAX_MAX_ALLOWED_PACKET),
- DEFAULT(MAX_MAX_ALLOWED_PACKET),
- BLOCK_SIZE(1024));
+ DEFAULT(MAX_MAX_ALLOWED_PACKET), BLOCK_SIZE(1024));
static Sys_var_ulonglong Sys_max_binlog_cache_size(
"max_binlog_cache_size",
"Sets the total size of the transactional cache",
GLOBAL_VAR(max_binlog_cache_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(IO_SIZE, SIZE_T_MAX),
- DEFAULT((SIZE_T_MAX/IO_SIZE)*IO_SIZE),
- BLOCK_SIZE(IO_SIZE));
+ DEFAULT((SIZE_T_MAX/IO_SIZE)*IO_SIZE), BLOCK_SIZE(IO_SIZE));
static Sys_var_ulonglong Sys_max_binlog_stmt_cache_size(
"max_binlog_stmt_cache_size",
"Sets the total size of the statement cache",
GLOBAL_VAR(max_binlog_stmt_cache_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(IO_SIZE, SIZE_T_MAX),
- DEFAULT((SIZE_T_MAX/IO_SIZE)*IO_SIZE),
- BLOCK_SIZE(IO_SIZE));
+ DEFAULT((SIZE_T_MAX/IO_SIZE)*IO_SIZE), BLOCK_SIZE(IO_SIZE));
static bool fix_max_binlog_size(sys_var *self, THD *thd, enum_var_type type)
{
@@ -1935,7 +1994,8 @@ Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var)
my_error(ER_INCORRECT_GTID_STATE, MYF(0));
return true;
}
- if (!(data= (gtid_binlog_state_data *)my_malloc(sizeof(*data), MYF(0))))
+ if (!(data= (gtid_binlog_state_data *)my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(*data), MYF(0))))
{
my_free(list);
my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -3136,16 +3196,17 @@ static Sys_var_enum Slave_ddl_exec_mode(
slave_exec_mode_names, DEFAULT(SLAVE_EXEC_MODE_IDEMPOTENT));
static const char *slave_run_triggers_for_rbr_names[]=
- {"NO", "YES", "LOGGING", 0};
+ {"NO", "YES", "LOGGING", "ENFORCE", 0};
static Sys_var_enum Slave_run_triggers_for_rbr(
"slave_run_triggers_for_rbr",
"Modes for how triggers in row-base replication on slave side will be "
- "executed. Legal values are NO (default), YES and LOGGING. NO means "
+ "executed. Legal values are NO (default), YES, LOGGING and ENFORCE. NO means "
"that trigger for RBR will not be running on slave. YES and LOGGING "
"means that triggers will be running on slave, if there was not "
"triggers running on the master for the statement. LOGGING also means "
"results of that the executed triggers work will be written to "
- "the binlog.",
+ "the binlog. ENFORCE means that triggers will always be run on the slave, "
+ "even if there are triggers on the master. ENFORCE implies LOGGING.",
GLOBAL_VAR(slave_run_triggers_for_rbr), CMD_LINE(REQUIRED_ARG),
slave_run_triggers_for_rbr_names,
DEFAULT(SLAVE_RUN_TRIGGERS_FOR_RBR_NO));
@@ -3901,8 +3962,7 @@ static Sys_var_ulonglong Sys_tmp_disk_table_size(
"Max size for data for an internal temporary on-disk MyISAM or Aria table.",
SESSION_VAR(tmp_disk_table_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1024, (ulonglong)~(intptr)0),
- DEFAULT((ulonglong)~(intptr)0),
- BLOCK_SIZE(1));
+ DEFAULT((ulonglong)~(intptr)0), BLOCK_SIZE(1));
static Sys_var_charptr Sys_version(
"version", "Server version number. It may also include a suffix "
@@ -4009,7 +4069,8 @@ static Sys_var_plugin Sys_enforce_storage_engine(
"enforce_storage_engine", "Force the use of a storage engine for new tables",
SESSION_VAR(enforced_table_plugin),
NO_CMD_LINE, MYSQL_STORAGE_ENGINE_PLUGIN,
- DEFAULT(&enforced_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super));
+ DEFAULT(&enforced_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(check_has_super));
#ifdef HAVE_REPLICATION
@@ -4189,7 +4250,8 @@ static Sys_var_bit Sys_log_off(
"query log is done for the client. Only clients with the SUPER privilege "
"can update this variable.",
NO_SET_STMT SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_LOG_OFF,
- DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super));
+ DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(check_has_super));
/**
This function sets the session variable thd->variables.sql_log_bin
@@ -5846,8 +5908,7 @@ static Sys_var_ulong Sys_host_cache_size(
"How many host names should be cached to avoid resolving.",
AUTO_SET GLOBAL_VAR(host_cache_size),
CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 65536),
- DEFAULT(HOST_CACHE_SIZE),
- BLOCK_SIZE(1),
+ DEFAULT(HOST_CACHE_SIZE), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_host_cache_size));
@@ -6334,8 +6395,7 @@ static Sys_var_ulong Sys_log_tc_size(
READ_ONLY GLOBAL_VAR(opt_tc_log_size),
CMD_LINE(REQUIRED_ARG),
VALID_RANGE(my_getpagesize() * 3, ULONG_MAX),
- DEFAULT(my_getpagesize() * 6),
- BLOCK_SIZE(my_getpagesize()));
+ DEFAULT(my_getpagesize() * 6), BLOCK_SIZE(my_getpagesize()));
#endif
static Sys_var_ulonglong Sys_max_thread_mem(
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index f33f469b160..698062d9bed 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -529,7 +529,8 @@ public:
size_t len=var->save_result.string_value.length;
if (ptr)
{
- new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
+ new_val= (char*)my_memdup(key_memory_Sys_var_charptr_value,
+ ptr, len+1, MYF(MY_WME));
if (!new_val) return 0;
new_val[len]=0;
}
diff --git a/sql/table.cc b/sql/table.cc
index 718efa5767c..10c44013538 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -27,7 +27,6 @@
#include "strfunc.h" // unhex_type2
#include "sql_partition.h" // mysql_unpack_partition,
// fix_partition_func, partition_info
-#include "sql_acl.h" // *_ACL, acl_getroot_no_password
#include "sql_base.h"
#include "create_options.h"
#include "sql_trigger.h"
@@ -273,7 +272,7 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
if (is_infoschema_db(db))
return TABLE_CATEGORY_INFORMATION;
- if (lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, db))
+ if (is_perfschema_db(db))
return TABLE_CATEGORY_PERFORMANCE;
if (lex_string_eq(&MYSQL_SCHEMA_NAME, db))
@@ -323,7 +322,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
path_length= build_table_filename(path, sizeof(path) - 1,
db, table_name, "", 0);
- init_sql_alloc(&mem_root, "table_share", TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_table_share, &mem_root, TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(0));
if (multi_alloc_root(&mem_root,
&share, sizeof(*share),
&key_buff, key_length,
@@ -349,7 +349,7 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
table_alias_charset->strnncoll(key, 6, "mysql", 6) == 0)
share->not_usable_by_query_cache= 1;
- init_sql_alloc(&share->stats_cb.mem_root, "share_stats",
+ init_sql_alloc(PSI_INSTRUMENT_ME, &share->stats_cb.mem_root,
TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root));
@@ -411,8 +411,9 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
This can't be MY_THREAD_SPECIFIC for slaves as they are freed
during cleanup() from Relay_log_info::close_temporary_tables()
*/
- init_sql_alloc(&share->mem_root, "tmp_table_share", TABLE_ALLOC_BLOCK_SIZE,
- 0, MYF(thd->slave_thread ? 0 : MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_table_share, &share->mem_root,
+ TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(thd->slave_thread ? 0 : MY_THREAD_SPECIFIC));
share->table_category= TABLE_CATEGORY_TEMPORARY;
share->tmp_table= INTERNAL_TMP_TABLE;
share->db.str= (char*) key;
@@ -676,7 +677,8 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
frmlen= uint4korr(head+10);
set_if_smaller(frmlen, FRM_MAX_SIZE); // safety
- if (!(buf= (uchar*)my_malloc(frmlen, MYF(MY_THREAD_SPECIFIC|MY_WME))))
+ if (!(buf= (uchar*)my_malloc(PSI_INSTRUMENT_ME, frmlen,
+ MYF(MY_THREAD_SPECIFIC|MY_WME))))
goto err;
memcpy(buf, head, sizeof(head));
@@ -2195,10 +2197,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
if (use_hash)
- use_hash= !my_hash_init(&share->name_hash,
- system_charset_info,
- share->fields,0,0,
- (my_hash_get_key) get_field_name,0,0);
+ use_hash= !my_hash_init(PSI_INSTRUMENT_ME, &share->name_hash,
+ system_charset_info, share->fields, 0, 0,
+ (my_hash_get_key) get_field_name, 0, 0);
if (share->mysql_version >= 50700 && share->mysql_version < 100000 &&
vcol_screen_length)
@@ -3756,8 +3757,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
error= OPEN_FRM_NEEDS_REBUILD;
goto err;
}
- init_sql_alloc(&outparam->mem_root, "table", TABLE_ALLOC_BLOCK_SIZE, 0,
- MYF(0));
+ init_sql_alloc(key_memory_TABLE, &outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE,
+ 0, MYF(0));
/*
We have to store the original alias in mem_root as constraints and virtual
@@ -6207,7 +6208,7 @@ bool TABLE_LIST::prepare_view_security_context(THD *thd)
}
else
{
- if (thd->security_ctx->master_access & SUPER_ACL)
+ if (thd->security_ctx->master_access & PRIV_REVEAL_MISSING_DEFINER)
{
my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str);
@@ -8219,11 +8220,10 @@ size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data)
void init_mdl_requests(TABLE_LIST *table_list)
{
for ( ; table_list ; table_list= table_list->next_global)
- table_list->mdl_request.init(MDL_key::TABLE,
- table_list->db.str, table_list->table_name.str,
- table_list->lock_type >= TL_WRITE_ALLOW_WRITE ?
- MDL_SHARED_WRITE : MDL_SHARED_READ,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE,
+ table_list->db.str, table_list->table_name.str,
+ table_list->lock_type >= TL_WRITE_ALLOW_WRITE
+ ? MDL_SHARED_WRITE : MDL_SHARED_READ, MDL_TRANSACTION);
}
diff --git a/sql/table.h b/sql/table.h
index 6ce92ee048e..ad3336b9bd9 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1075,8 +1075,8 @@ private:
public:
Blob_mem_storage() :truncated_value(false)
{
- init_alloc_root(&storage, "Blob_mem_storage", MAX_FIELD_VARCHARLENGTH, 0,
- MYF(0));
+ init_alloc_root(key_memory_blob_mem_storage,
+ &storage, MAX_FIELD_VARCHARLENGTH, 0, MYF(0));
}
~ Blob_mem_storage()
{
@@ -2012,8 +2012,8 @@ struct TABLE_LIST
alias= (alias_arg ? *alias_arg : *table_name_arg);
lock_type= lock_type_arg;
updating= lock_type >= TL_WRITE_ALLOW_WRITE;
- mdl_request.init(MDL_key::TABLE, db.str, table_name.str, mdl_type,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, db.str, table_name.str,
+ mdl_type, MDL_TRANSACTION);
}
TABLE_LIST(TABLE *table_arg, thr_lock_type lock_type)
@@ -3060,9 +3060,12 @@ extern LEX_CSTRING MYSQL_PROC_NAME;
inline bool is_infoschema_db(const LEX_CSTRING *name)
{
- return (INFORMATION_SCHEMA_NAME.length == name->length &&
- !my_strcasecmp(system_charset_info,
- INFORMATION_SCHEMA_NAME.str, name->str));
+ return lex_string_eq(&INFORMATION_SCHEMA_NAME, name);
+}
+
+inline bool is_perfschema_db(const LEX_CSTRING *name)
+{
+ return lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, name);
}
inline void mark_as_null_row(TABLE *table)
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index 8e5c3a8471d..d8786f72244 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -1257,10 +1257,10 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument,
if (no_dups)
{
- init_alloc_root(&no_dups_argument.root, "no_dups", 4096, 4096,
- MYF(alloc_flags));
- my_hash_init(&no_dups_argument.hash, &my_charset_bin, tdc_records(), 0, 0,
- eliminate_duplicates_get_key, 0, hash_flags);
+ init_alloc_root(PSI_INSTRUMENT_ME, &no_dups_argument.root, 4096, 4096, MYF(alloc_flags));
+ my_hash_init(PSI_INSTRUMENT_ME, &no_dups_argument.hash, &my_charset_bin,
+ tdc_records(), 0, 0, eliminate_duplicates_get_key, 0,
+ hash_flags);
no_dups_argument.action= action;
no_dups_argument.argument= argument;
action= (my_hash_walk_action) eliminate_duplicates;
diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc
index 2e0f0a4918e..c675b11741a 100644
--- a/sql/temporary_tables.cc
+++ b/sql/temporary_tables.cc
@@ -955,7 +955,8 @@ TMP_TABLE_SHARE *THD::create_temporary_table(LEX_CUSTRING *frm,
/* Create the table definition key for the temporary table. */
key_length= create_tmp_table_def_key(key_cache, db, table_name);
- if (!(share= (TMP_TABLE_SHARE *) my_malloc(sizeof(TMP_TABLE_SHARE) +
+ if (!(share= (TMP_TABLE_SHARE *) my_malloc(key_memory_table_share,
+ sizeof(TMP_TABLE_SHARE) +
strlen(path) + 1 + key_length,
MYF(MY_WME))))
{
@@ -1002,7 +1003,8 @@ TMP_TABLE_SHARE *THD::create_temporary_table(LEX_CUSTRING *frm,
if (!temporary_tables)
{
if ((temporary_tables=
- (All_tmp_tables_list *) my_malloc(sizeof(All_tmp_tables_list),
+ (All_tmp_tables_list *) my_malloc(key_memory_table_share,
+ sizeof(All_tmp_tables_list),
MYF(MY_WME))))
{
temporary_tables->empty();
@@ -1107,7 +1109,8 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
DBUG_ENTER("THD::open_temporary_table");
- if (!(table= (TABLE *) my_malloc(sizeof(TABLE), MYF(MY_WME))))
+ if (!(table= (TABLE *) my_malloc(key_memory_TABLE, sizeof(TABLE),
+ MYF(MY_WME))))
{
DBUG_RETURN(NULL); /* Out of memory */
}
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index d43e7c4c9b5..89ad359befa 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -58,11 +58,10 @@ extern "C" {
}
}
-void init_sql_alloc(MEM_ROOT *mem_root,
- const char *area_name __attribute__((unused)),
- uint block_size, uint pre_alloc, myf my_flags)
+void init_sql_alloc(PSI_memory_key key, MEM_ROOT *mem_root, uint block_size,
+ uint pre_alloc, myf my_flags)
{
- init_alloc_root(mem_root, area_name, block_size, pre_alloc, my_flags);
+ init_alloc_root(key, mem_root, block_size, pre_alloc, my_flags);
mem_root->error_handler=sql_alloc_error_handler;
}
diff --git a/sql/thr_malloc.h b/sql/thr_malloc.h
index a6ab5477d41..cc56666bcc9 100644
--- a/sql/thr_malloc.h
+++ b/sql/thr_malloc.h
@@ -18,8 +18,8 @@
typedef struct st_mem_root MEM_ROOT;
-void init_sql_alloc(MEM_ROOT *root, const char *area_name, uint block_size,
- uint pre_alloc_size, myf my_flags);
+void init_sql_alloc(PSI_memory_key key, MEM_ROOT *root, uint block_size, uint
+ pre_alloc_size, myf my_flags);
char *sql_strmake_with_convert(THD *thd, const char *str, size_t arg_length,
CHARSET_INFO *from_cs,
size_t max_res_length,
diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc
index 0588562ae61..40b230e5392 100644
--- a/sql/threadpool_common.cc
+++ b/sql/threadpool_common.cc
@@ -151,7 +151,7 @@ static void thread_attach(THD* thd)
pthread_setspecific(THR_KEY_mysys,thd->mysys_var);
thd->thread_stack=(char*)&thd;
thd->store_globals();
- PSI_CALL_set_thread(thd->event_scheduler.m_psi);
+ PSI_CALL_set_thread(thd->get_psi());
mysql_socket_set_thread_owner(thd->net.vio->mysql_socket);
}
@@ -235,21 +235,13 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data)
pthread_setspecific(THR_KEY_mysys, 0);
my_thread_init();
st_my_thread_var* mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
+ PSI_CALL_set_thread(PSI_CALL_new_thread(key_thread_one_connection, connect, 0));
if (!mysys_var ||!(thd= connect->create_thd(NULL)))
{
/* Out of memory? */
connect->close_and_delete();
if (mysys_var)
- {
-#ifdef HAVE_PSI_INTERFACE
- /*
- current PSI is still from worker thread.
- Set to 0, to avoid premature cleanup by my_thread_end
- */
- if (PSI_server) PSI_server->set_thread(0);
-#endif
my_thread_end();
- }
return NULL;
}
delete connect;
@@ -257,11 +249,6 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data)
thd->set_mysys_var(mysys_var);
thd->event_scheduler.data= scheduler_data;
- /* Create new PSI thread for use with the THD. */
- thd->event_scheduler.m_psi=
- PSI_CALL_new_thread(key_thread_one_connection, thd, thd->thread_id);
-
-
/* Login. */
thread_attach(thd);
re_init_net_server_extension(thd);
@@ -301,6 +288,7 @@ static void threadpool_remove_connection(THD *thd)
end_connection(thd);
close_connection(thd, 0);
unlink_thd(thd);
+ PSI_CALL_delete_current_thread(); // before THD is destroyed
delete thd;
/*
diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc
index e11a0613425..e8e3497eae4 100644
--- a/sql/threadpool_generic.cc
+++ b/sql/threadpool_generic.cc
@@ -1532,7 +1532,8 @@ int TP_pool_generic::init()
DBUG_ENTER("TP_pool_generic::TP_pool_generic");
threadpool_max_size= MY_MAX(threadpool_size, 128);
all_groups= (thread_group_t *)
- my_malloc(sizeof(thread_group_t) * threadpool_max_size, MYF(MY_WME|MY_ZEROFILL));
+ my_malloc(PSI_INSTRUMENT_ME,
+ sizeof(thread_group_t) * threadpool_max_size, MYF(MY_WME|MY_ZEROFILL));
if (!all_groups)
{
threadpool_max_size= 0;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index f0426b1fcc4..82e04d35479 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -25,6 +25,8 @@
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_acl.h"
#include "semisync_master.h"
+#include <pfs_transaction_provider.h>
+#include <mysql/psi/mysql_transaction.h>
#ifdef WITH_WSREP
#include "wsrep_trans_observer.h"
#endif /* WITH_WSREP */
@@ -161,7 +163,7 @@ bool trans_begin(THD *thd, uint flags)
compatibility.
*/
const bool user_is_super=
- MY_TEST(thd->security_ctx->master_access & SUPER_ACL);
+ MY_TEST(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY);
if (opt_readonly && !user_is_super)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
@@ -209,6 +211,23 @@ bool trans_begin(THD *thd, uint flags)
#endif //EMBEDDED_LIBRARY
res= ha_start_consistent_snapshot(thd);
}
+ /*
+ Register transaction start in performance schema if not done already.
+ We handle explicitly started transactions here, implicitly started
+ transactions (and single-statement transactions in autocommit=1 mode)
+ are handled in trans_register_ha().
+ We can't handle explicit transactions in the same way as implicit
+ because we want to correctly attribute statements which follow
+ BEGIN but do not touch any transactional tables.
+ */
+ if (thd->m_transaction_psi == NULL)
+ {
+ thd->m_transaction_psi= MYSQL_START_TRANSACTION(&thd->m_transaction_state,
+ NULL, 0, thd->tx_isolation,
+ thd->tx_read_only, false);
+ DEBUG_SYNC(thd, "after_set_transaction_psi_before_set_transaction_gtid");
+ //gtid_set_performance_schema_values(thd);
+ }
DBUG_RETURN(MY_TEST(res));
}
@@ -245,22 +264,18 @@ bool trans_commit(THD *thd)
if res is non-zero, then ha_commit_trans has rolled back the
transaction, so the hooks for rollback will be called.
*/
- if (res)
- {
#ifdef HAVE_REPLICATION
+ if (res)
repl_semisync_master.wait_after_rollback(thd, FALSE);
-#endif
- }
else
- {
-#ifdef HAVE_REPLICATION
repl_semisync_master.wait_after_commit(thd, FALSE);
#endif
- }
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;
+ /* The transaction should be marked as complete in P_S. */
+ DBUG_ASSERT(thd->m_transaction_psi == NULL);
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
@@ -305,6 +320,9 @@ bool trans_commit_implicit(THD *thd)
thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
thd->transaction.all.reset();
+ /* The transaction should be marked as complete in P_S. */
+ DBUG_ASSERT(thd->m_transaction_psi == NULL);
+
/*
Upon implicit commit, reset the current transaction
isolation level and access mode. We do not care about
@@ -349,6 +367,9 @@ bool trans_rollback(THD *thd)
thd->transaction.all.reset();
thd->lex->start_transaction_opt= 0;
+ /* The transaction should be marked as complete in P_S. */
+ DBUG_ASSERT(thd->m_transaction_psi == NULL);
+
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
@@ -395,7 +416,9 @@ bool trans_rollback_implicit(THD *thd)
thd->transaction.all.reset();
/* Rollback should clear transaction_rollback_request flag. */
- DBUG_ASSERT(! thd->transaction_rollback_request);
+ DBUG_ASSERT(!thd->transaction_rollback_request);
+ /* The transaction should be marked as complete in P_S. */
+ DBUG_ASSERT(thd->m_transaction_psi == NULL);
trans_track_end_trx(thd);
@@ -463,6 +486,10 @@ bool trans_commit_stmt(THD *thd)
#endif
}
+ /* In autocommit=1 mode the transaction should be marked as complete in P_S */
+ DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
+ thd->m_transaction_psi == NULL);
+
thd->transaction.stmt.reset();
DBUG_RETURN(MY_TEST(res));
@@ -502,6 +529,10 @@ bool trans_rollback_stmt(THD *thd)
repl_semisync_master.wait_after_rollback(thd, FALSE);
#endif
+ /* In autocommit=1 mode the transaction should be marked as complete in P_S */
+ DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
+ thd->m_transaction_psi == NULL);
+
thd->transaction.stmt.reset();
DBUG_RETURN(FALSE);
diff --git a/sql/tztime.cc b/sql/tztime.cc
index fbac2923a84..72db37fde9c 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1543,6 +1543,8 @@ tz_init_table_list(TABLE_LIST *tz_tabs)
}
}
+static PSI_memory_key key_memory_tz_storage;
+
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_tz_LOCK;
@@ -1551,6 +1553,11 @@ static PSI_mutex_info all_tz_mutexes[]=
{ & key_tz_LOCK, "tz_LOCK", PSI_FLAG_GLOBAL}
};
+static PSI_memory_info all_tz_memory[]=
+{
+ { &key_memory_tz_storage, "tz_storage", PSI_FLAG_GLOBAL}
+};
+
static void init_tz_psi_keys(void)
{
const char* category= "sql";
@@ -1561,6 +1568,9 @@ static void init_tz_psi_keys(void)
count= array_elements(all_tz_mutexes);
PSI_server->register_mutex(category, all_tz_mutexes, count);
+
+ count= array_elements(all_tz_memory);
+ mysql_memory_register(category, all_tz_memory, count);
}
#endif /* HAVE_PSI_INTERFACE */
@@ -1615,20 +1625,20 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
thd->store_globals();
/* Init all memory structures that require explicit destruction */
- if (my_hash_init(&tz_names, &my_charset_latin1, 20,
- 0, 0, (my_hash_get_key) my_tz_names_get_key, 0, 0))
+ if (my_hash_init(key_memory_tz_storage, &tz_names, &my_charset_latin1, 20, 0,
+ 0, (my_hash_get_key) my_tz_names_get_key, 0, 0))
{
sql_print_error("Fatal error: OOM while initializing time zones");
goto end;
}
- if (my_hash_init(&offset_tzs, &my_charset_latin1, 26, 0, 0,
- (my_hash_get_key)my_offset_tzs_get_key, 0, 0))
+ if (my_hash_init(key_memory_tz_storage, &offset_tzs, &my_charset_latin1, 26,
+ 0, 0, (my_hash_get_key)my_offset_tzs_get_key, 0, 0))
{
sql_print_error("Fatal error: OOM while initializing time zones");
my_hash_free(&tz_names);
goto end;
}
- init_sql_alloc(&tz_storage, "timezone_storage", 32 * 1024, 0, MYF(0));
+ init_sql_alloc(key_memory_tz_storage, &tz_storage, 32 * 1024, 0, MYF(0));
mysql_mutex_init(key_tz_LOCK, &tz_LOCK, MY_MUTEX_INIT_FAST);
tz_inited= 1;
@@ -2568,8 +2578,8 @@ scan_tz_dir(char * name_end, uint symlink_recursion_level, uint verbose)
}
else if (MY_S_ISREG(cur_dir->dir_entry[i].mystat->st_mode))
{
- init_alloc_root(&tz_storage, "timezone_storage", 32768, 0,
- MYF(MY_THREAD_SPECIFIC));
+ init_alloc_root(PSI_INSTRUMENT_ME, &tz_storage,
+ 32768, 0, MYF(MY_THREAD_SPECIFIC));
if (!tz_load(fullname, &tz_info, &tz_storage))
print_tz_as_sql(root_name_end + 1, &tz_info);
else
@@ -2758,7 +2768,7 @@ main(int argc, char **argv)
First argument is timezonefile.
The second is timezonename if opt_leap is not given
*/
- init_alloc_root(&tz_storage, "timezone_storage", 32768, 0, MYF(0));
+ init_alloc_root(PSI_INSTRUMENT_ME, &tz_storage, 32768, 0, MYF(0));
if (tz_load(argv[0], &tz_info, &tz_storage))
{
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 931aa868199..4e327a4cc09 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -93,8 +93,8 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
init_tree(&tree, (max_in_memory_size / 16), 0, size, comp_func,
NULL, comp_func_fixed_arg, MYF(MY_THREAD_SPECIFIC));
/* If the following fail's the next add will also fail */
- my_init_dynamic_array(&file_ptrs, sizeof(Merge_chunk), 16, 16,
- MYF(MY_THREAD_SPECIFIC));
+ my_init_dynamic_array(PSI_INSTRUMENT_ME, &file_ptrs, sizeof(Merge_chunk), 16,
+ 16, MYF(MY_THREAD_SPECIFIC));
/*
If you change the following, change it in get_max_elements function, too.
*/
@@ -531,7 +531,7 @@ static bool merge_walk(uchar *merge_buffer, size_t merge_buffer_size,
top->set_buffer(merge_buffer + (top - begin) * piece_size,
merge_buffer + (top - begin) * piece_size + piece_size);
top->set_max_keys(max_key_count_per_piece);
- bytes_read= read_to_buffer(file, top, &sort_param);
+ bytes_read= read_to_buffer(file, top, &sort_param, false);
if (unlikely(bytes_read == (ulong) -1))
goto end;
DBUG_ASSERT(bytes_read);
@@ -561,7 +561,7 @@ static bool merge_walk(uchar *merge_buffer, size_t merge_buffer_size,
/* save old_key not to overwrite it in read_to_buffer */
memcpy(save_key_buff, old_key, key_length);
old_key= save_key_buff;
- bytes_read= read_to_buffer(file, top, &sort_param);
+ bytes_read= read_to_buffer(file, top, &sort_param, false);
if (unlikely(bytes_read == (ulong) -1))
goto end;
else if (bytes_read) /* top->key, top->mem_count are reset */
@@ -609,7 +609,7 @@ static bool merge_walk(uchar *merge_buffer, size_t merge_buffer_size,
top->advance_current_key(key_length);
}
while (top->decrement_mem_count());
- bytes_read= read_to_buffer(file, top, &sort_param);
+ bytes_read= read_to_buffer(file, top, &sort_param, false);
if (unlikely(bytes_read == (ulong) -1))
goto end;
}
@@ -662,7 +662,8 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
is needed when a piece of merge buffer is re-read, see merge_walk()
*/
size_t buff_sz= MY_MAX(MERGEBUFF2+1, max_in_memory_size/full_size+1) * full_size;
- if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_WME))))
+ if (!(merge_buffer = (uchar *)my_malloc(key_memory_Unique_merge_buffer,
+ buff_sz, MYF(MY_THREAD_SPECIFIC|MY_WME))))
return 1;
if (buff_sz < full_size * (file_ptrs.elements + 1UL))
res= merge(table, merge_buffer, buff_sz,
@@ -782,7 +783,8 @@ bool Unique::get(TABLE *table)
{
/* Whole tree is in memory; Don't use disk if you don't need to */
if ((sort.record_pointers= (uchar*)
- my_malloc(size * tree.elements_in_tree, MYF(MY_THREAD_SPECIFIC))))
+ my_malloc(key_memory_Filesort_info_record_pointers,
+ size * tree.elements_in_tree, MYF(MY_THREAD_SPECIFIC))))
{
uchar *save_record_pointers= sort.record_pointers;
tree_walk_action action= min_dupl_count ?
@@ -801,7 +803,7 @@ bool Unique::get(TABLE *table)
if (flush())
DBUG_RETURN(1);
size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size;
- if (!(sort_buffer= (uchar*) my_malloc(buff_sz,
+ if (!(sort_buffer= (uchar*) my_malloc(key_memory_Unique_sort_buffer, buff_sz,
MYF(MY_THREAD_SPECIFIC|MY_WME))))
DBUG_RETURN(1);
diff --git a/sql/unireg.cc b/sql/unireg.cc
index e4a43d3ace5..2aa46131efb 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -425,8 +425,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
DBUG_RETURN(frm);
}
- frm_ptr= (uchar*) my_malloc(frm.length, MYF(MY_WME | MY_ZEROFILL |
- MY_THREAD_SPECIFIC));
+ frm_ptr= (uchar*) my_malloc(PSI_INSTRUMENT_ME, frm.length,
+ MYF(MY_WME | MY_ZEROFILL | MY_THREAD_SPECIFIC));
if (!frm_ptr)
DBUG_RETURN(frm);
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index a81503a50da..f555480d2e0 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -64,7 +64,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len)
wsrep_max_ws_size, total_length);
goto error;
}
- uchar* tmp= (uchar *)my_realloc(*buf, total_length,
+ uchar* tmp= (uchar *)my_realloc(PSI_INSTRUMENT_ME, *buf, total_length,
MYF(MY_ALLOW_ZERO_PTR));
if (!tmp)
{
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index ff01473e816..99e8f0a52ec 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1270,7 +1270,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
wsrep_key_arr_t* ka)
{
wsrep_key_t* tmp;
- tmp= (wsrep_key_t*)my_realloc(ka->keys,
+ tmp= (wsrep_key_t*)my_realloc(PSI_INSTRUMENT_ME, ka->keys,
(ka->keys_len + 1) * sizeof(wsrep_key_t),
MYF(MY_ALLOW_ZERO_PTR));
if (!tmp)
@@ -1280,7 +1280,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
}
ka->keys= tmp;
if (!(ka->keys[ka->keys_len].key_parts= (wsrep_buf_t*)
- my_malloc(sizeof(wsrep_buf_t)*2, MYF(0))))
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(wsrep_buf_t)*2, MYF(0))))
{
WSREP_ERROR("Can't allocate memory for key_parts");
return false;
@@ -1916,7 +1916,7 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
log_query.set_charset(system_charset_info);
- if (sp->m_handler->type() == TYPE_ENUM_FUNCTION)
+ if (sp->m_handler->type() == SP_TYPE_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
returns= retstr.lex_cstring();
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index d478ea486cd..0bb8a9eb675 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -245,7 +245,7 @@ static bool sst_auth_real_set (const char* value)
if (value)
{
- v= my_strdup(value, MYF(0));
+ v= my_strdup(PSI_INSTRUMENT_ME, value, MYF(0));
}
else // its NULL
{
@@ -263,7 +263,7 @@ static bool sst_auth_real_set (const char* value)
if (strlen(sst_auth_real))
{
if (wsrep_sst_auth) { my_free((void*) wsrep_sst_auth); }
- wsrep_sst_auth= my_strdup(WSREP_SST_AUTH_MASK, MYF(0));
+ wsrep_sst_auth= my_strdup(PSI_INSTRUMENT_ME, WSREP_SST_AUTH_MASK, MYF(0));
}
return 0;
}
@@ -414,7 +414,7 @@ static char* generate_name_value(const char* name, const char* value)
size_t name_len= strlen(name);
size_t value_len= strlen(value);
char* buf=
- (char*) my_malloc((name_len + value_len + 5) * sizeof(char), MYF(0));
+ (char*) my_malloc(PSI_INSTRUMENT_ME, (name_len + value_len + 5), MYF(0));
if (buf)
{
char* ref= buf;
@@ -449,11 +449,11 @@ static int generate_binlog_opt_val(char** ret)
*ret= strcmp(opt_bin_logname, "0") ?
generate_name_value(WSREP_SST_OPT_BINLOG,
opt_bin_logname) :
- my_strdup("", MYF(0));
+ my_strdup(PSI_INSTRUMENT_ME, "", MYF(0));
}
else
{
- *ret= my_strdup("", MYF(0));
+ *ret= my_strdup(PSI_INSTRUMENT_ME, "", MYF(0));
}
if (!*ret) return -ENOMEM;
return 0;
@@ -468,11 +468,11 @@ static int generate_binlog_index_opt_val(char** ret)
*ret= strcmp(opt_binlog_index_name, "0") ?
generate_name_value(WSREP_SST_OPT_BINLOG_INDEX,
opt_binlog_index_name) :
- my_strdup("", MYF(0));
+ my_strdup(PSI_INSTRUMENT_ME, "", MYF(0));
}
else
{
- *ret= my_strdup("", MYF(0));
+ *ret= my_strdup(PSI_INSTRUMENT_ME, "", MYF(0));
}
if (!*ret) return -ENOMEM;
return 0;
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 950e4aae34d..28dbe4096f7 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -30,17 +30,17 @@ ulong wsrep_reject_queries;
int wsrep_init_vars()
{
- wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME));
- wsrep_provider_options= my_strdup("", MYF(MY_WME));
- wsrep_cluster_address = my_strdup("", MYF(MY_WME));
- wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME));
- wsrep_node_name = my_strdup("", MYF(MY_WME));
- wsrep_node_address = my_strdup("", MYF(MY_WME));
- wsrep_node_incoming_address= my_strdup(WSREP_NODE_INCOMING_AUTO, MYF(MY_WME));
+ wsrep_provider = my_strdup(PSI_INSTRUMENT_ME, WSREP_NONE, MYF(MY_WME));
+ wsrep_provider_options= my_strdup(PSI_INSTRUMENT_ME, "", MYF(MY_WME));
+ wsrep_cluster_address = my_strdup(PSI_INSTRUMENT_ME, "", MYF(MY_WME));
+ wsrep_cluster_name = my_strdup(PSI_INSTRUMENT_ME, WSREP_CLUSTER_NAME, MYF(MY_WME));
+ wsrep_node_name = my_strdup(PSI_INSTRUMENT_ME, "", MYF(MY_WME));
+ wsrep_node_address = my_strdup(PSI_INSTRUMENT_ME, "", MYF(MY_WME));
+ wsrep_node_incoming_address= my_strdup(PSI_INSTRUMENT_ME, WSREP_NODE_INCOMING_AUTO, MYF(MY_WME));
if (wsrep_gtid_mode)
- wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO_GTID, MYF(MY_WME));
+ wsrep_start_position = my_strdup(PSI_INSTRUMENT_ME, WSREP_START_POSITION_ZERO_GTID, MYF(MY_WME));
else
- wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME));
+ wsrep_start_position = my_strdup(PSI_INSTRUMENT_ME, WSREP_START_POSITION_ZERO, MYF(MY_WME));
return 0;
}
@@ -50,7 +50,7 @@ static int get_provider_option_value(const char* opts,
{
int ret= 1;
ulong opt_value_tmp;
- char *opt_value_str, *s, *opts_copy= my_strdup(opts, MYF(MY_WME));
+ char *opt_value_str, *s, *opts_copy= my_strdup(PSI_INSTRUMENT_ME, opts, MYF(MY_WME));
if ((opt_value_str= strstr(opts_copy, opt_name)) == NULL)
goto end;
@@ -436,7 +436,7 @@ void wsrep_provider_init (const char* value)
}
if (wsrep_provider) my_free((void *)wsrep_provider);
- wsrep_provider= my_strdup(value, MYF(0));
+ wsrep_provider= my_strdup(PSI_INSTRUMENT_MEM, value, MYF(0));
}
bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var)
@@ -466,7 +466,7 @@ void wsrep_provider_options_init(const char* value)
{
if (wsrep_provider_options && wsrep_provider_options != value)
my_free((void *)wsrep_provider_options);
- wsrep_provider_options= (value) ? my_strdup(value, MYF(0)) : NULL;
+ wsrep_provider_options= value ? my_strdup(PSI_INSTRUMENT_MEM, value, MYF(0)) : NULL;
}
bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type)
@@ -578,8 +578,8 @@ void wsrep_cluster_address_init (const char* value)
(wsrep_cluster_address) ? wsrep_cluster_address : "null",
(value) ? value : "null");
- my_free((void*) wsrep_cluster_address);
- wsrep_cluster_address= my_strdup(value ? value : "", MYF(0));
+ my_free(const_cast<char*>(wsrep_cluster_address));
+ wsrep_cluster_address= my_strdup(PSI_INSTRUMENT_MEM, safe_str(value), MYF(0));
}
/* wsrep_cluster_name cannot be NULL or an empty string. */
@@ -652,7 +652,7 @@ void wsrep_node_address_init (const char* value)
if (wsrep_node_address && strcmp(wsrep_node_address, value))
my_free ((void*)wsrep_node_address);
- wsrep_node_address= (value) ? my_strdup(value, MYF(0)) : NULL;
+ wsrep_node_address= value ? my_strdup(PSI_INSTRUMENT_MEM, value, MYF(0)) : NULL;
}
static void wsrep_slave_count_change_update ()
diff --git a/sql/xa.cc b/sql/xa.cc
index 3ead73fe1e1..4d9846d2f4d 100644
--- a/sql/xa.cc
+++ b/sql/xa.cc
@@ -19,10 +19,11 @@
#include "mariadb.h"
#include "sql_class.h"
#include "transaction.h"
-
+#include <pfs_transaction_provider.h>
+#include <mysql/psi/mysql_transaction.h>
/***************************************************************************
- Handling of XA id cacheing
+ Handling of XA id caching
***************************************************************************/
enum xa_states { XA_ACTIVE= 0, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY };
@@ -425,19 +426,25 @@ bool trans_xa_start(THD *thd)
if (not_equal)
my_error(ER_XAER_NOTA, MYF(0));
else
+ {
thd->transaction.xid_state.xid_cache_element->xa_state= XA_ACTIVE;
+ MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_ACTIVE);
+ }
DBUG_RETURN(not_equal);
}
/* TODO: JOIN is not supported yet. */
if (thd->lex->xa_opt != XA_NONE)
my_error(ER_XAER_INVAL, MYF(0));
+ else if (!thd->lex->xid->gtrid_length)
+ my_error(ER_XAER_INVAL, MYF(0));
else if (thd->transaction.xid_state.is_explicit_XA())
thd->transaction.xid_state.er_xaer_rmfail();
else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction())
my_error(ER_XAER_OUTSIDE, MYF(0));
else if (!trans_begin(thd))
{
+ MYSQL_SET_TRANSACTION_XID(thd->m_transaction_psi, thd->lex->xid, XA_ACTIVE);
if (xid_cache_insert(thd, &thd->transaction.xid_state, thd->lex->xid))
{
trans_rollback(thd);
@@ -472,7 +479,10 @@ bool trans_xa_end(THD *thd)
else if (!thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid))
my_error(ER_XAER_NOTA, MYF(0));
else if (!xa_trans_rolled_back(thd->transaction.xid_state.xid_cache_element))
+ {
thd->transaction.xid_state.xid_cache_element->xa_state= XA_IDLE;
+ MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_IDLE);
+ }
DBUG_RETURN(thd->is_error() ||
thd->transaction.xid_state.xid_cache_element->xa_state != XA_IDLE);
@@ -503,7 +513,10 @@ bool trans_xa_prepare(THD *thd)
my_error(ER_XA_RBROLLBACK, MYF(0));
}
else
+ {
thd->transaction.xid_state.xid_cache_element->xa_state= XA_PREPARED;
+ MYSQL_SET_TRANSACTION_XA_STATE(thd->m_transaction_psi, XA_PREPARED);
+ }
DBUG_RETURN(thd->is_error() ||
thd->transaction.xid_state.xid_cache_element->xa_state != XA_PREPARED);
@@ -527,6 +540,24 @@ bool trans_xa_commit(THD *thd)
if (!thd->transaction.xid_state.is_explicit_XA() ||
!thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid))
{
+ if (thd->in_multi_stmt_transaction_mode())
+ {
+ /*
+ Not allow to commit from inside an not-"native" to xid
+ ongoing transaction: the commit effect can't be reversed.
+ */
+ my_error(ER_XAER_OUTSIDE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (thd->lex->xa_opt != XA_NONE)
+ {
+ /*
+ Not allow to commit with one phase a prepared xa out of compatibility
+ with the native commit branch's error out.
+ */
+ my_error(ER_XAER_INVAL, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
if (thd->fix_xid_hash_pins())
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -556,10 +587,14 @@ bool trans_xa_commit(THD *thd)
if ((res= MY_TEST(r)))
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
}
- else if (thd->transaction.xid_state.xid_cache_element->xa_state == XA_PREPARED &&
- thd->lex->xa_opt == XA_NONE)
+ else if (thd->transaction.xid_state.xid_cache_element->xa_state == XA_PREPARED)
{
MDL_request mdl_request;
+ if (thd->lex->xa_opt != XA_NONE)
+ {
+ my_error(ER_XAER_INVAL, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
/*
Acquire metadata lock which will ensure that COMMIT is blocked
@@ -568,7 +603,7 @@ bool trans_xa_commit(THD *thd)
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
*/
- mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_TRANSACTION);
if (thd->mdl_context.acquire_lock(&mdl_request,
@@ -584,6 +619,16 @@ bool trans_xa_commit(THD *thd)
res= MY_TEST(ha_commit_one_phase(thd, 1));
if (res)
my_error(ER_XAER_RMERR, MYF(0));
+ else
+ {
+ /*
+ Since we don't call ha_commit_trans() for prepared transactions,
+ we need to explicitly mark the transaction as committed.
+ */
+ MYSQL_COMMIT_TRANSACTION(thd->m_transaction_psi);
+ }
+
+ thd->m_transaction_psi= NULL;
}
}
else
@@ -600,7 +645,8 @@ bool trans_xa_commit(THD *thd)
xid_cache_delete(thd, &thd->transaction.xid_state);
trans_track_end_trx(thd);
-
+ /* The transaction should be marked as complete in P_S. */
+ DBUG_ASSERT(thd->m_transaction_psi == NULL || res);
DBUG_RETURN(res);
}
@@ -621,6 +667,11 @@ bool trans_xa_rollback(THD *thd)
if (!thd->transaction.xid_state.is_explicit_XA() ||
!thd->transaction.xid_state.xid_cache_element->xid.eq(thd->lex->xid))
{
+ if (thd->in_multi_stmt_transaction_mode())
+ {
+ my_error(ER_XAER_OUTSIDE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
if (thd->fix_xid_hash_pins())
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));