summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/client.c189
-rw-r--r--sql-common/client_plugin.c41
-rw-r--r--sql-common/errmsg.c19
-rw-r--r--sql-common/my_time.c186
4 files changed, 329 insertions, 106 deletions
diff --git a/sql-common/client.c b/sql-common/client.c
index a1bdbebf639..811bd4e8e58 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -69,9 +69,9 @@ my_bool net_flush(NET *net);
#include "errmsg.h"
#include <violite.h>
-#if !defined(__WIN__)
+#if !defined(_WIN32)
#include <my_pthread.h> /* because of signal() */
-#endif /* !defined(__WIN__) */
+#endif /* !defined(_WIN32) */
#include <sys/stat.h>
#include <signal.h>
@@ -81,29 +81,20 @@ my_bool net_flush(NET *net);
#include <pwd.h>
#endif
-#if !defined(__WIN__)
+#if !defined(_WIN32)
#ifdef HAVE_SELECT_H
# include <select.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#endif /* !defined(__WIN__) */
+#endif /* !defined(_WIN32) */
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
-#ifndef _WIN32
-#include <errno.h>
-#define SOCKET_ERROR -1
-#define INVALID_SOCKET -1
-#endif
-#ifdef __WIN__
-#define CONNECT_TIMEOUT 20
-#else
#define CONNECT_TIMEOUT 0
-#endif
#include "client_settings.h"
#include <ssl_compat.h>
@@ -121,6 +112,52 @@ typedef enum {
#define native_password_plugin_name "mysql_native_password"
#define old_password_plugin_name "mysql_old_password"
+PSI_memory_key key_memory_mysql_options;
+PSI_memory_key key_memory_MYSQL_DATA;
+PSI_memory_key key_memory_MYSQL;
+PSI_memory_key key_memory_MYSQL_RES;
+PSI_memory_key key_memory_MYSQL_ROW;
+PSI_memory_key key_memory_MYSQL_state_change_info;
+PSI_memory_key key_memory_MYSQL_HANDSHAKE;
+
+#if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
+PSI_memory_key key_memory_create_shared_memory;
+#endif /* _WIN32 && ! EMBEDDED_LIBRARY */
+
+#ifdef HAVE_PSI_INTERFACE
+/*
+ This code is common to the client and server,
+ and also used in the server when server A connects to server B,
+ for example with replication.
+ Therefore, the code is also instrumented.
+*/
+
+static PSI_memory_info all_client_memory[]=
+{
+#if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
+ { &key_memory_create_shared_memory, "create_shared_memory", 0},
+#endif /* _WIN32 && ! EMBEDDED_LIBRARY */
+
+ { &key_memory_mysql_options, "mysql_options", 0},
+ { &key_memory_MYSQL_DATA, "MYSQL_DATA", 0},
+ { &key_memory_MYSQL, "MYSQL", 0},
+ { &key_memory_MYSQL_RES, "MYSQL_RES", 0},
+ { &key_memory_MYSQL_ROW, "MYSQL_ROW", 0},
+ { &key_memory_MYSQL_state_change_info, "MYSQL_STATE_CHANGE_INFO", 0},
+ { &key_memory_MYSQL_HANDSHAKE, "MYSQL_HANDSHAKE", 0}
+};
+
+void init_client_psi_keys(void)
+{
+ const char *category= "client";
+ int count;
+
+ count= array_elements(all_client_memory);
+ mysql_memory_register(category, all_client_memory, count);
+}
+
+#endif /* HAVE_PSI_INTERFACE */
+
uint mariadb_deinitialize_ssl= 1;
uint mysql_port=0;
char *mysql_unix_port= 0;
@@ -252,7 +289,7 @@ void set_mysql_extended_error(MYSQL *mysql, int errcode,
Create a named pipe connection
*/
-#ifdef __WIN__
+#ifdef _WIN32
HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host,
char **arg_unix_socket)
@@ -502,7 +539,7 @@ void free_old_query(MYSQL *mysql)
if (mysql->fields)
free_root(&mysql->field_alloc,MYF(0));
/* Assume rowlength < 8192 */
- init_alloc_root(&mysql->field_alloc, "fields", 8192, 0,
+ init_alloc_root(PSI_INSTRUMENT_ME, &mysql->field_alloc, 8192, 0,
MYF(mysql->options.use_thread_specific_memory ?
MY_THREAD_SPECIFIC : 0));
mysql->fields= 0;
@@ -764,6 +801,11 @@ enum option_id {
OPT_keep_this_one_last
};
+static char *opt_strdup(const char *from, myf my_flags)
+{
+ return my_strdup(key_memory_mysql_options, from, my_flags);
+}
+
static TYPELIB option_types={array_elements(default_options)-1,
"options",default_options, NULL};
@@ -773,12 +815,14 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
if (!options->init_commands)
{
- options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
+ options->init_commands= (DYNAMIC_ARRAY*)my_malloc(key_memory_mysql_options,
+ sizeof(DYNAMIC_ARRAY),
MYF(MY_WME));
- my_init_dynamic_array(options->init_commands,sizeof(char*),5, 5, MYF(0));
+ my_init_dynamic_array(key_memory_mysql_options, options->init_commands,
+ sizeof(char*),5, 5, MYF(0));
}
- if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
+ if (!(tmp= opt_strdup(cmd,MYF(MY_WME))) ||
insert_dynamic(options->init_commands, &tmp))
{
my_free(tmp);
@@ -791,7 +835,8 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
#define ALLOCATE_EXTENSIONS(OPTS) \
(OPTS)->extension= (struct st_mysql_options_extention *) \
- my_malloc(sizeof(struct st_mysql_options_extention), \
+ my_malloc(key_memory_mysql_options, \
+ sizeof(struct st_mysql_options_extention), \
MYF(MY_WME | MY_ZEROFILL)) \
@@ -813,7 +858,7 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
} while (0)
#define EXTENSION_SET_STRING(OPTS, X, STR) \
- EXTENSION_SET_STRING_X(OPTS, X, STR, my_strdup)
+ EXTENSION_SET_STRING_X(OPTS, X, STR, opt_strdup)
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
@@ -827,7 +872,7 @@ static char *set_ssl_option_unpack_path(const char *arg, myf flags)
{
char buff[FN_REFLEN + 1];
unpack_filename(buff, (char *)arg);
- return my_strdup(buff, flags);
+ return opt_strdup(buff, flags);
}
#else
@@ -835,8 +880,8 @@ static char *set_ssl_option_unpack_path(const char *arg, myf flags)
#define EXTENSION_SET_SSL_STRING_X(OPTS, X, STR, dup) do { } while(0)
#endif /* defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) */
-#define SET_SSL_OPTION(OPTS, opt_var,arg) SET_SSL_OPTION_X(OPTS, opt_var, arg, my_strdup)
-#define EXTENSION_SET_SSL_STRING(OPTS, X, STR) EXTENSION_SET_SSL_STRING_X(OPTS, X, STR, my_strdup)
+#define SET_SSL_OPTION(OPTS, opt_var,arg) SET_SSL_OPTION_X(OPTS, opt_var, arg, opt_strdup)
+#define EXTENSION_SET_SSL_STRING(OPTS, X, STR) EXTENSION_SET_SSL_STRING_X(OPTS, X, STR, opt_strdup)
#define SET_SSL_PATH_OPTION(OPTS, opt_var,arg) SET_SSL_OPTION_X(OPTS, opt_var, arg, set_ssl_option_unpack_path)
#define EXTENSION_SET_SSL_PATH_STRING(OPTS, X, STR) EXTENSION_SET_SSL_STRING_X(OPTS, X, STR, set_ssl_option_unpack_path)
@@ -865,8 +910,6 @@ void mysql_read_default_options(struct st_mysql_options *options,
char **option=argv;
while (*++option)
{
- if (my_getopt_is_args_separator(option[0])) /* skip arguments separator */
- continue;
/* DBUG_PRINT("info",("option: %s",option[0])); */
if (option[0][0] == '-' && option[0][1] == '-')
{
@@ -889,7 +932,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
if (opt_arg)
{
my_free(options->unix_socket);
- options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
+ options->unix_socket=opt_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_compress:
@@ -900,7 +943,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
if (opt_arg)
{
my_free(options->password);
- options->password=my_strdup(opt_arg,MYF(MY_WME));
+ options->password=opt_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_pipe:
@@ -915,7 +958,7 @@ void mysql_read_default_options(struct st_mysql_options *options,
if (opt_arg)
{
my_free(options->user);
- options->user=my_strdup(opt_arg,MYF(MY_WME));
+ options->user=opt_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_init_command:
@@ -925,14 +968,14 @@ void mysql_read_default_options(struct st_mysql_options *options,
if (opt_arg)
{
my_free(options->host);
- options->host=my_strdup(opt_arg,MYF(MY_WME));
+ options->host=opt_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_database:
if (opt_arg)
{
my_free(options->db);
- options->db=my_strdup(opt_arg,MYF(MY_WME));
+ options->db=opt_strdup(opt_arg,MYF(MY_WME));
}
break;
case OPT_debug:
@@ -966,11 +1009,11 @@ void mysql_read_default_options(struct st_mysql_options *options,
break;
case OPT_character_sets_dir:
my_free(options->charset_dir);
- options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
+ options->charset_dir = opt_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_default_character_set:
my_free(options->charset_name);
- options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
+ options->charset_name = opt_strdup(opt_arg, MYF(MY_WME));
break;
case OPT_interactive_timeout:
options->client_flag|= CLIENT_INTERACTIVE;
@@ -1228,14 +1271,14 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
if ((pkt_len= cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(0);
if (pkt_len == 0) DBUG_RETURN(0);
- if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
+ if (!(result=(MYSQL_DATA*) my_malloc(key_memory_MYSQL_DATA, sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL))))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0);
}
/* Assume rowlength < 8192 */
- init_alloc_root(&result->alloc, "result", 8192, 0,
+ init_alloc_root(key_memory_MYSQL_DATA, &result->alloc, 8192, 0,
MYF(mysql->options.use_thread_specific_memory ?
MY_THREAD_SPECIFIC : 0));
result->alloc.min_malloc=sizeof(MYSQL_ROWS);
@@ -1379,7 +1422,8 @@ mysql_init(MYSQL *mysql)
return 0;
if (!mysql)
{
- if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
+ if (!(mysql=(MYSQL*) my_malloc(key_memory_MYSQL,
+ sizeof(*mysql), MYF(MY_WME | MY_ZEROFILL))))
{
set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
return 0;
@@ -1691,7 +1735,7 @@ mysql_autodetect_character_set(MYSQL *mysql)
{
if (mysql->options.charset_name)
my_free(mysql->options.charset_name);
- if (!(mysql->options.charset_name= my_strdup(my_default_csname(),MYF(MY_WME))))
+ if (!(mysql->options.charset_name= opt_strdup(my_default_csname(),MYF(MY_WME))))
return 1;
return 0;
}
@@ -2218,7 +2262,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
end= strmake(end, mpvio->db, NAME_LEN) + 1;
- mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
+ mysql->db= my_strdup(key_memory_MYSQL, mpvio->db, MYF(MY_WME));
}
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
@@ -2614,14 +2658,10 @@ set_connect_attributes(MYSQL *mysql, char *buff, size_t buf_len)
"_platform", MACHINE_TYPE);
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
"_server_host", mysql->host);
-#ifdef __WIN__
- snprintf(buff, buf_len, "%lu", (ulong) GetCurrentProcessId());
-#else
snprintf(buff, buf_len, "%lu", (ulong) getpid());
-#endif
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_pid", buff);
-#ifdef __WIN__
+#ifdef _WIN32
snprintf(buff, buf_len, "%lu", (ulong) GetCurrentThreadId());
rc+= mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_thread", buff);
#endif
@@ -2642,7 +2682,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
const char *scramble_plugin;
ulong pkt_length;
NET *net= &mysql->net;
-#ifdef __WIN__
+#ifdef _WIN32
HANDLE hPipe=INVALID_HANDLE_VALUE;
#endif
#ifdef HAVE_SYS_UN_H
@@ -2734,7 +2774,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
VIO_LOCALHOST | VIO_BUFFERED_READ);
if (!net->vio)
{
- DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+ DBUG_PRINT("error",("Unknown protocol %d ", mysql->options.protocol));
set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
closesocket(sock);
goto error;
@@ -2764,21 +2804,19 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
}
mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
}
-#elif defined(__WIN__)
+#elif defined(_WIN32)
if (!net->vio &&
(mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
- (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
- (! have_tcpip && (unix_socket || !host ))))
+ (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE))))
{
if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout,
(char**) &host, (char**) &unix_socket)) ==
INVALID_HANDLE_VALUE)
{
DBUG_PRINT("error",
- ("host: '%s' socket: '%s' have_tcpip: %d",
+ ("host: '%s' socket: '%s'",
host ? host : "<null>",
- unix_socket ? unix_socket : "<null>",
- (int) have_tcpip));
+ unix_socket ? unix_socket : "<null>"));
if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
(host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
(unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
@@ -2911,7 +2949,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
DBUG_PRINT("info", ("net->vio: %p", net->vio));
if (!net->vio)
{
- DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
+ DBUG_PRINT("error",("Unknown protocol %d ",mysql->options.protocol));
set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
goto error;
}
@@ -3020,7 +3058,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
/* Save connection information */
- if (!my_multi_malloc(MYF(0),
+ if (!my_multi_malloc(key_memory_MYSQL, MYF(0),
&mysql->host_info, (uint) strlen(host_info)+1,
&mysql->host, (uint) strlen(host)+1,
&mysql->unix_socket,unix_socket ?
@@ -3028,8 +3066,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
&mysql->server_version,
(uint) (server_version_end - (char*) net->read_pos + 1),
NullS) ||
- !(mysql->user=my_strdup(user,MYF(0))) ||
- !(mysql->passwd=my_strdup(passwd,MYF(0))))
+ !(mysql->user=my_strdup(key_memory_MYSQL, user,MYF(0))) ||
+ !(mysql->passwd=my_strdup(key_memory_MYSQL, passwd,MYF(0))))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
goto error;
@@ -3290,7 +3328,7 @@ mysql_select_db(MYSQL *mysql, const char *db)
(ulong) strlen(db),0)))
DBUG_RETURN(error);
my_free(mysql->db);
- mysql->db=my_strdup(db,MYF(MY_WME));
+ mysql->db=my_strdup(key_memory_MYSQL, db,MYF(MY_WME));
DBUG_RETURN(0);
}
@@ -3617,7 +3655,8 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
DBUG_RETURN(0);
}
mysql->status=MYSQL_STATUS_READY; /* server is ready */
- if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
+ if (!(result=(MYSQL_RES*) my_malloc(key_memory_MYSQL_RES,
+ (uint) (sizeof(MYSQL_RES)+
sizeof(ulong) *
mysql->field_count),
MYF(MY_WME | MY_ZEROFILL))))
@@ -3670,15 +3709,17 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
- if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
+ if (!(result=(MYSQL_RES*) my_malloc(key_memory_MYSQL_RES,
+ sizeof(*result)+
sizeof(ulong)*mysql->field_count,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(0);
result->lengths=(ulong*) (result+1);
result->methods= mysql->methods;
if (!(result->row=(MYSQL_ROW)
- my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
- { /* Ptrs: to one row */
+ my_malloc(key_memory_MYSQL_ROW,
+ sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
+ { /* Ptrs: to one row */
my_free(result);
DBUG_RETURN(0);
}
@@ -3696,6 +3737,12 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql)
}
+my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
+{
+ return mysql->affected_rows;
+}
+
+
/**************************************************************************
Return next row of the query results
**************************************************************************/
@@ -3808,19 +3855,19 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
break;
case MYSQL_READ_DEFAULT_FILE:
my_free(mysql->options.my_cnf_file);
- mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
+ mysql->options.my_cnf_file= opt_strdup(arg,MYF(MY_WME));
break;
case MYSQL_READ_DEFAULT_GROUP:
my_free(mysql->options.my_cnf_group);
- mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
+ mysql->options.my_cnf_group= opt_strdup(arg,MYF(MY_WME));
break;
case MYSQL_SET_CHARSET_DIR:
my_free(mysql->options.charset_dir);
- mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
+ mysql->options.charset_dir= opt_strdup(arg,MYF(MY_WME));
break;
case MYSQL_SET_CHARSET_NAME:
my_free(mysql->options.charset_name);
- mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
+ mysql->options.charset_name= opt_strdup(arg,MYF(MY_WME));
break;
case MYSQL_OPT_PROTOCOL:
mysql->options.protocol= *(uint*) arg;
@@ -3832,7 +3879,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
break;
case MYSQL_SET_CLIENT_IP:
my_free(mysql->options.client_ip);
- mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
+ mysql->options.client_ip= opt_strdup(arg, MYF(MY_WME));
break;
case MYSQL_SECURE_AUTH:
mysql->options.secure_auth= *(my_bool *) arg;
@@ -3863,7 +3910,8 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
case MYSQL_PROGRESS_CALLBACK:
if (!mysql->options.extension)
mysql->options.extension= (struct st_mysql_options_extention *)
- my_malloc(sizeof(struct st_mysql_options_extention),
+ my_malloc(key_memory_mysql_options,
+ sizeof(struct st_mysql_options_extention),
MYF(MY_WME | MY_ZEROFILL));
if (mysql->options.extension)
mysql->options.extension->report_progress=
@@ -3883,7 +3931,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
my_free(ctxt);
}
if (!(ctxt= (struct mysql_async_context *)
- my_malloc(sizeof(*ctxt), MYF(MY_ZEROFILL))))
+ my_malloc(PSI_INSTRUMENT_ME, sizeof(*ctxt), MYF(MY_ZEROFILL))))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
@@ -4023,15 +4071,16 @@ mysql_options4(MYSQL *mysql,enum mysql_option option,
if (!my_hash_inited(&mysql->options.extension->connection_attributes))
{
- if (my_hash_init(&mysql->options.extension->connection_attributes,
- &my_charset_bin, 0, 0, 0, (my_hash_get_key) get_attr_key,
- my_free, HASH_UNIQUE))
+ if (my_hash_init(key_memory_mysql_options,
+ &mysql->options.extension->connection_attributes,
+ &my_charset_bin, 0, 0, 0, (my_hash_get_key)
+ get_attr_key, my_free, HASH_UNIQUE))
{
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
}
}
- if (!my_multi_malloc(MY_WME,
+ if (!my_multi_malloc(key_memory_mysql_options, MYF(MY_WME),
&elt, 2 * sizeof(LEX_STRING),
&key, key_len + 1,
&value, value_len + 1,
diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c
index af86b19f309..0a2e39f7daa 100644
--- a/sql-common/client_plugin.c
+++ b/sql-common/client_plugin.c
@@ -38,6 +38,36 @@
#include "errmsg.h"
#include <mysql/client_plugin.h>
+PSI_memory_key key_memory_root;
+PSI_memory_key key_memory_load_env_plugins;
+
+#ifdef HAVE_PSI_INTERFACE
+PSI_mutex_key key_mutex_LOCK_load_client_plugin;
+
+static PSI_mutex_info all_client_plugin_mutexes[]=
+{
+ {&key_mutex_LOCK_load_client_plugin, "LOCK_load_client_plugin", PSI_FLAG_GLOBAL}
+};
+
+static PSI_memory_info all_client_plugin_memory[]=
+{
+ {&key_memory_root, "root", PSI_FLAG_GLOBAL},
+ {&key_memory_load_env_plugins, "load_env_plugins", PSI_FLAG_GLOBAL}
+};
+
+static void init_client_plugin_psi_keys()
+{
+ const char* category= "sql";
+ int count;
+
+ count= array_elements(all_client_plugin_mutexes);
+ mysql_mutex_register(category, all_client_plugin_mutexes, count);
+
+ count= array_elements(all_client_plugin_memory);
+ mysql_memory_register(category, all_client_plugin_memory, count);
+}
+#endif /* HAVE_PSI_INTERFACE */
+
struct st_client_plugin_int {
struct st_client_plugin_int *next;
void *dlhandle;
@@ -209,7 +239,7 @@ static void load_env_plugins(MYSQL *mysql)
if (!s)
DBUG_VOID_RETURN;
- free_env= plugs= my_strdup(s, MYF(MY_WME));
+ free_env= plugs= my_strdup(key_memory_load_env_plugins, s, MYF(MY_WME));
do {
if ((s= strchr(plugs, ';')))
@@ -242,11 +272,16 @@ int mysql_client_plugin_init()
if (initialized)
DBUG_RETURN(0);
+#ifdef HAVE_PSI_INTERFACE
+ init_client_plugin_psi_keys();
+#endif /* HAVE_PSI_INTERFACE */
+
bzero(&mysql, sizeof(mysql)); /* dummy mysql for set_mysql_extended_error */
bzero(&unused, sizeof unused);
- mysql_mutex_init(0, &LOCK_load_client_plugin, MY_MUTEX_INIT_SLOW);
- init_alloc_root(&mem_root, "client_plugin", 128, 128, MYF(0));
+ mysql_mutex_init(key_mutex_LOCK_load_client_plugin,
+ &LOCK_load_client_plugin, MY_MUTEX_INIT_SLOW);
+ init_alloc_root(key_memory_root, &mem_root, 128, 128, MYF(0));
bzero(&plugin_list, sizeof(plugin_list));
diff --git a/sql-common/errmsg.c b/sql-common/errmsg.c
index 049fb51ec87..47d72170525 100644
--- a/sql-common/errmsg.c
+++ b/sql-common/errmsg.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ Copyright (C) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,20 +26,20 @@
const char *client_errors[]=
{
- "Unknown MySQL error",
+ "Unknown error",
"Can't create UNIX socket (%d)",
- "Can't connect to local MySQL server through socket '%-.100s' (%M)",
- "Can't connect to MySQL server on '%-.100s' (%M)",
+ "Can't connect to local server through socket '%-.100s' (%M)",
+ "Can't connect to server on '%-.100s' (%M)",
"Can't create TCP/IP socket (%M)",
- "Unknown MySQL server host '%-.100s' (%d)",
- "MySQL server has gone away",
+ "Unknown server host '%-.100s' (%d)",
+ "Server has gone away",
"Protocol mismatch; server version = %d, client version = %d",
- "MySQL client ran out of memory",
+ "MariaDB client ran out of memory",
"Wrong host info",
"Localhost via UNIX socket",
"%-.100s via TCP/IP",
"Error in server handshake",
- "Lost connection to MySQL server during query",
+ "Lost connection to server during query",
"Commands out of sync; you can't run this command now",
"Named pipe: %-.32s",
"Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
@@ -53,7 +54,7 @@ const char *client_errors[]=
"Error connecting to master:",
"SSL connection error: %-.100s",
"Malformed packet",
- "This client library is licensed only for use with MySQL servers having '%s' license",
+ "This client library is licensed only for use with servers having '%s' license",
"Invalid use of null pointer",
"Statement not prepared",
"No data supplied for parameters in prepared statement",
@@ -80,7 +81,7 @@ const char *client_errors[]=
"Prepared statement contains no metadata",
"Attempt to read a row while there is no result set associated with the statement",
"This feature is not implemented yet",
- "Lost connection to MySQL server at '%s', system error: %M",
+ "Lost connection to server at '%s', system error: %M",
"Statement closed indirectly because of a preceding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
"This handle is already connected. Use a separate handle for each connection.",
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 5c14b8071a3..96674723b34 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -1454,23 +1454,161 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
/*
- Helper function for datetime formatting.
- Format number as string, left-padded with 0.
+ A formatting routine to print a 2 digit zero padded number.
+ It prints 2 digits at a time, which gives a performance improvement.
+ The idea is taken from "class TwoDigitWriter" in MySQL.
+
+ The old implementation printed one digit at a time, using the division
+ and the remainder operators, which appeared to be slow.
+ It's cheaper to have a cached array of 2-digit numbers
+ in their string representation.
+
+ Benchmark results showed a 10% to 23% time reduce for these queries:
+ SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30'));
+ SELECT BENCHMARK(10*1000*1000,CONCAT(DATE'2001-01-01'));
+ SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30'));
+ SELECT BENCHMARK(10*1000*1000,CONCAT(TIME'10:20:30.123456'));
+ SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30.123456'));
+ (depending on the exact data type and fractional precision).
+
+ The array has extra elements for values 100..255.
+ This is done for safety. If the caller passes a value
+ outside of the expected range 0..99, the value will be printed as "XX".
+
+ Part2:
+
+ As an additional improvement over "class TwoDigitWriter", we store
+ the string representations of the numbers in an array uint16[256]
+ instead of char[512]. This allows to copy data using int2store(),
+ which copies two bytes at a time on x86 and gives an additional
+ 7% to 26% time reduce over copying the two bytes separately.
+
+ The total time reduce is 15% to 38% on the above queries.
+
+ The bytes in the following array are swapped:
+ e.g. 0x3130 in two_digit_numbers[1] means the following:
+ - 0x31 is '1' (the left byte, the right digit)
+ - 0x30 is '0' (the right byte, the left digit)
+ int2store() puts the lower byte first, so the output string becomes '01'.
+*/
+static const uint16 two_digit_numbers[256]=
+{
+ /* 0..99 */
+ 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730,0x3830,0x3930,
+ 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731,0x3831,0x3931,
+ 0x3032,0x3132,0x3232,0x3332,0x3432,0x3532,0x3632,0x3732,0x3832,0x3932,
+ 0x3033,0x3133,0x3233,0x3333,0x3433,0x3533,0x3633,0x3733,0x3833,0x3933,
+ 0x3034,0x3134,0x3234,0x3334,0x3434,0x3534,0x3634,0x3734,0x3834,0x3934,
+ 0x3035,0x3135,0x3235,0x3335,0x3435,0x3535,0x3635,0x3735,0x3835,0x3935,
+ 0x3036,0x3136,0x3236,0x3336,0x3436,0x3536,0x3636,0x3736,0x3836,0x3936,
+ 0x3037,0x3137,0x3237,0x3337,0x3437,0x3537,0x3637,0x3737,0x3837,0x3937,
+ 0x3038,0x3138,0x3238,0x3338,0x3438,0x3538,0x3638,0x3738,0x3838,0x3938,
+ 0x3039,0x3139,0x3239,0x3339,0x3439,0x3539,0x3639,0x3739,0x3839,0x3939,
+ /* 100..199 - safety */
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ /* 200..255 - safety */
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+ 0x5858,0x5858,0x5858,0x5858,0x5858,0x5858,
+};
+
+static inline char* fmt_number2(uint8 val, char *out)
+{
+ int2store(out, two_digit_numbers[val]);
+ return out + 2;
+}
+
+
+/*
+ We tried the same trick with a char array of 16384 zerofill 4-digit numbers,
+ with 10000 elements with numbers 0000..9999, and a tail filled with "XXXX".
+
+ Benchmark results for a RelWithDebInfo build:
+
+ SELECT BENCHMARK(10*1000*1000,CONCAT(TIMESTAMP'2001-01-01 10:20:30.123456'));
+ - 0.379 sec (current)
+ - 0.369 sec (array)
+
+ SELECT BENCHMARK(10*1000*1000,CONCAT(DATE'2001-01-01'));
+ - 0.225 sec (current)
+ - 0.219 sec (array)
+
+ It demonstrated an additional 3% performance imrovement one these queries.
+ However, as the array size is too huge, we afraid that it will flush data
+ from the CPU memory cache, which under real load may affect negatively.
+
+ Let's keep using the fmt_number4() version with division and remainder
+ for now. This can be revised later. We could try some smaller array,
+ e.g. for YEARs in the range 1970..2098 (fitting into a 256 element array).
+*/
+/*
+static inline char* fmt_number4(uint16 val, char *out)
+{
+ const char *src= four_digit_numbers + (val & 0x3FFF) * 4;
+ memcpy(out, src, 4);
+ return out + 4;
+}
+*/
- The reason to use own formatting rather than sprintf() is performance - in a
- datetime benchmark it helped to reduced the datetime formatting overhead
- from ~30% down to ~4%.
+
+/*
+ A formatting routine to print a 4 digit zero padded number.
*/
+static inline char* fmt_number4(uint16 val, char *out)
+{
+ out= fmt_number2((uint8) (val / 100), out);
+ out= fmt_number2((uint8) (val % 100), out);
+ return out;
+}
+
+
+/*
+ A formatting routine to print a 6 digit zero padded number.
+*/
+static inline char* fmt_number6(uint val, char *out)
+{
+ out= fmt_number2((uint8) (val / 10000), out);
+ val%= 10000;
+ out= fmt_number2((uint8) (val / 100), out);
+ out= fmt_number2((uint8) (val % 100), out);
+ return out;
+}
+
-static char* fmt_number(uint val, char *out, uint digits)
+static char* fmt_usec(uint val, char *out, uint digits)
{
- uint i;
- for(i= 0; i < digits; i++)
+ switch (digits)
{
- out[digits-i-1]= '0' + val%10;
- val/=10;
+ case 1:
+ *out++= '0' + (val % 10);
+ return out;
+ case 2:
+ return fmt_number2((uint8) val, out);
+ case 3:
+ *out++= '0' + (val / 100) % 10;
+ return fmt_number2((uint8) (val % 100), out);
+ case 4:
+ return fmt_number4((uint16) val, out);
+ case 5:
+ *out++= '0' + (val / 10000) % 10;
+ return fmt_number4((uint16) (val % 10000), out);
+ case 6:
+ return fmt_number6(val, out);
}
- return out + digits;
+ DBUG_ASSERT(0);
+ return out;
}
@@ -1480,13 +1618,13 @@ static int my_mmssff_to_str(const MYSQL_TIME *ltime, char *to, uint fsp)
if (fsp == AUTO_SEC_PART_DIGITS)
fsp= ltime->second_part ? TIME_SECOND_PART_DIGITS : 0;
DBUG_ASSERT(fsp <= TIME_SECOND_PART_DIGITS);
- pos= fmt_number(ltime->minute, pos, 2);
+ pos= fmt_number2((uint8) ltime->minute, pos);
*pos++= ':';
- pos= fmt_number(ltime->second, pos, 2);
+ pos= fmt_number2((uint8) ltime->second, pos);
if (fsp)
{
*pos++= '.';
- pos= fmt_number((uint)sec_part_shift(ltime->second_part, fsp), pos, fsp);
+ pos= fmt_usec((uint)sec_part_shift(ltime->second_part, fsp), pos, fsp);
}
return (int) (pos - to);
}
@@ -1506,7 +1644,7 @@ int my_interval_DDhhmmssff_to_str(const MYSQL_TIME *ltime, char *to, uint fsp)
pos= longlong10_to_str((longlong) hour / 24, pos, 10);
*pos++= ' ';
}
- pos= fmt_number(hour % 24, pos, 2);
+ pos= fmt_number2((uint8) (hour % 24), pos);
*pos++= ':';
pos+= my_mmssff_to_str(ltime, pos, fsp);
*pos= 0;
@@ -1538,7 +1676,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
/* Need more than 2 digits for hours in string representation. */
pos= longlong10_to_str((longlong)hour, pos, 10);
else
- pos= fmt_number(hour, pos, 2);
+ pos= fmt_number2((uint8) hour, pos);
*pos++= ':';
pos+= my_mmssff_to_str(l_time, pos, digits);
@@ -1550,11 +1688,11 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
{
char *pos=to;
- pos= fmt_number(l_time->year, pos, 4);
+ pos= fmt_number4((uint16) l_time->year, pos);
*pos++='-';
- pos= fmt_number(l_time->month, pos, 2);
+ pos= fmt_number2((uint8) l_time->month, pos);
*pos++='-';
- pos= fmt_number(l_time->day, pos, 2);
+ pos= fmt_number2((uint8) l_time->day, pos);
*pos= 0;
return (int)(pos - to);
}
@@ -1563,13 +1701,13 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to)
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
{
char *pos= to;
- pos= fmt_number(l_time->year, pos, 4);
+ pos= fmt_number4((uint16) l_time->year, pos);
*pos++='-';
- pos= fmt_number(l_time->month, pos, 2);
+ pos= fmt_number2((uint8) l_time->month, pos);
*pos++='-';
- pos= fmt_number(l_time->day, pos, 2);
+ pos= fmt_number2((uint8) l_time->day, pos);
*pos++=' ';
- pos= fmt_number(l_time->hour, pos, 2);
+ pos= fmt_number2((uint8) l_time->hour, pos);
*pos++= ':';
pos+= my_mmssff_to_str(l_time, pos, digits);
*pos= 0;
@@ -1625,7 +1763,7 @@ int my_timeval_to_str(const struct timeval *tm, char *to, uint dec)
if (dec)
{
*pos++= '.';
- pos= fmt_number((uint) sec_part_shift(tm->tv_usec, dec), pos, dec);
+ pos= fmt_usec((uint) sec_part_shift(tm->tv_usec, dec), pos, dec);
}
*pos= '\0';
return (int) (pos - to);