aboutsummaryrefslogtreecommitdiff
path: root/mysql/sql
diff options
context:
space:
mode:
Diffstat (limited to 'mysql/sql')
-rw-r--r--mysql/sql/atomic_class.h117
-rw-r--r--mysql/sql/auth/password.c378
-rw-r--r--mysql/sql/my_decimal.h538
-rw-r--r--mysql/sql/mysqld.h979
-rw-r--r--mysql/sql/net_serv.cpp1059
-rw-r--r--mysql/sql/sql_alloc.h51
-rw-r--r--mysql/sql/sql_cmd.h96
-rw-r--r--mysql/sql/thr_malloc.h38
8 files changed, 3256 insertions, 0 deletions
diff --git a/mysql/sql/atomic_class.h b/mysql/sql/atomic_class.h
new file mode 100644
index 0000000..04d3492
--- /dev/null
+++ b/mysql/sql/atomic_class.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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 the Free Software Foundation; version 2 of the
+ License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA */
+
+
+#ifndef ATOMIC_CLASS_H_INCLUDED
+#define ATOMIC_CLASS_H_INCLUDED
+
+#include "my_atomic.h"
+
+/**
+ Wrapper class to use C++ syntax to access atomic integers.
+*/
+#define DEFINE_ATOMIC_CLASS(NAME, SUFFIX, TYPE) \
+ class Atomic_##NAME \
+ { \
+public: \
+ /* Create a new Atomic_* object. */ \
+ Atomic_##NAME(TYPE n= 0) \
+ { \
+ my_atomic_store##SUFFIX(&value, n); \
+ } \
+ /* Atomically read the value. */ \
+ TYPE atomic_get() \
+ { \
+ return my_atomic_load##SUFFIX(&value); \
+ } \
+ /* Atomically set the value. */ \
+ void atomic_set(TYPE n) \
+ { \
+ my_atomic_store##SUFFIX(&value, n); \
+ } \
+ /* Atomically add to the value, and return the old value. */ \
+ TYPE atomic_add(TYPE n) \
+ { \
+ return my_atomic_add##SUFFIX(&value, n); \
+ } \
+ /* Atomically set the value and return the old value. */ \
+ TYPE atomic_get_and_set(TYPE n) \
+ { \
+ return my_atomic_fas##SUFFIX(&value, n); \
+ } \
+ /* If the old value is equal to *old, set the value to new and */ \
+ /* return true. Otherwise, store the old value in '*old' and */ \
+ /* return false. */ \
+ bool atomic_compare_and_swap(TYPE *old, TYPE n) \
+ { \
+ return my_atomic_cas##SUFFIX(&value, old, n); \
+ } \
+ /* Read the value *non-atomically*. */ \
+ TYPE non_atomic_get() \
+ { \
+ return value; \
+ } \
+ /* Set the value *non-atomically*. */ \
+ void non_atomic_set(TYPE n) \
+ { \
+ value= n; \
+ } \
+ /* Add to the value *non-atomically*. */ \
+ TYPE non_atomic_add(TYPE n) \
+ { \
+ TYPE ret= value; \
+ value+= n; \
+ return ret; \
+ } \
+ /* Set the value to the greatest of (old, n). */ \
+ \
+ /* The function will internally requires multiple atomic */ \
+ /* operations. If the old value is known (or guessed), and less */ \
+ /* than n, it requires one atomic operation less. Therefore, */ \
+ /* the caller should set *guess to whatever is the likely value */ \
+ /* that the variable currently has, if such a guess is known. */ \
+ \
+ /* @return If the new value is changed to n, *guess is set to */ \
+ /* the old value and the the function returns true. Otherwise, */ \
+ /* *guess is set to the current value (which is greater than or */ \
+ /* equal to n), and the function returns false. */ \
+ bool atomic_set_to_max(TYPE n, TYPE *guess= NULL) \
+ { \
+ TYPE _guess; \
+ if (guess == NULL) \
+ { \
+ _guess= n - 1; \
+ guess= &_guess; \
+ } \
+ else \
+ DBUG_ASSERT(*guess < n); \
+ bool ret; \
+ do { \
+ ret= atomic_compare_and_swap(guess, n); \
+ } while (!ret && *guess < n); \
+ return ret; \
+ } \
+ \
+private: \
+ TYPE value; \
+ }
+
+DEFINE_ATOMIC_CLASS(int32, 32, int32);
+DEFINE_ATOMIC_CLASS(int64, 64, int64);
+//DEFINE_ATOMIC_CLASS(pointer, ptr, void *);
+
+#endif //ifndef ATOMIC_CLASS_H_INCLUDED
diff --git a/mysql/sql/auth/password.c b/mysql/sql/auth/password.c
new file mode 100644
index 0000000..1f93350
--- /dev/null
+++ b/mysql/sql/auth/password.c
@@ -0,0 +1,378 @@
+/*
+ Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* password checking routines */
+/*****************************************************************************
+ The main idea is that no password are sent between client & server on
+ connection and that no password are saved in mysql in a decodable form.
+
+ On connection a random string is generated and sent to the client.
+ The client generates a new string with a random generator inited with
+ the hash values from the password and the sent string.
+ This 'check' string is sent to the server where it is compared with
+ a string generated from the stored hash_value of the password and the
+ random string.
+
+ The password is saved (in user.password) by using the PASSWORD() function in
+ mysql.
+
+ This is .c file because it's used in libmysqlclient, which is entirely in C.
+ (we need it to be portable to a variety of systems).
+ Example:
+ update user set password=PASSWORD("hello") where user="test"
+ This saves a hashed number as a string in the password field.
+
+ The new authentication is performed in following manner:
+
+ SERVER: public_seed=generate_user_salt()
+ send(public_seed)
+
+ CLIENT: recv(public_seed)
+ hash_stage1=sha1("password")
+ hash_stage2=sha1(hash_stage1)
+ reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
+
+ // this three steps are done in scramble()
+
+ send(reply)
+
+
+ SERVER: recv(reply)
+ hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
+ candidate_hash2=sha1(hash_stage1)
+ check(candidate_hash2==hash_stage2)
+
+ // this three steps are done in check_scramble()
+
+*****************************************************************************/
+
+#include <password.h>
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <sha1.h>
+#include <my_rnd.h>
+#include "mysql.h"
+#include "crypt_genhash_impl.h"
+
+void randominit(struct rand_struct *rand_st, ulong seed1, ulong seed2)
+{ /* For mysql 3.21.# */
+ rand_st->max_value= 0x3FFFFFFFL;
+ rand_st->max_value_dbl=(double) rand_st->max_value;
+ rand_st->seed1=seed1%rand_st->max_value ;
+ rand_st->seed2=seed2%rand_st->max_value;
+}
+
+/*
+ Generate binary hash from raw text string
+ Used for Pre-4.1 password handling
+ SYNOPSIS
+ hash_password()
+ result OUT store hash in this location
+ password IN plain text password to build hash
+ password_len IN password length (password may be not null-terminated)
+*/
+
+void hash_password(ulong *result, const char *password, uint password_len)
+{
+ ulong nr=1345345333L, add=7, nr2=0x12345671L;
+ ulong tmp;
+ const char *password_end= password + password_len;
+ for (; password < password_end; password++)
+ {
+ if (*password == ' ' || *password == '\t')
+ continue; /* skip space in password */
+ tmp= (ulong) (uchar) *password;
+ nr^= (((nr & 63)+add)*tmp)+ (nr << 8);
+ nr2+=(nr2 << 8) ^ nr;
+ add+=tmp;
+ }
+ result[0]=nr & (((ulong) 1L << 31) -1L); /* Don't use sign bit (str2int) */;
+ result[1]=nr2 & (((ulong) 1L << 31) -1L);
+}
+
+static inline uint8 char_val(uint8 X)
+{
+ return (uint) (X >= '0' && X <= '9' ? X - '0' :
+ X >= 'A' && X <= 'Z' ? X - 'A' + 10 : X - 'a' + 10);
+}
+
+/* Character to use as version identifier for version 4.1 */
+
+#define PVERSION41_CHAR '*'
+
+
+/*
+ Convert given octet sequence to asciiz string of hex characters;
+ str..str+len and 'to' may not overlap.
+ SYNOPSIS
+ octet2hex()
+ buf OUT output buffer. Must be at least 2*len+1 bytes
+ str, len IN the beginning and the length of the input string
+
+ RETURN
+ buf+len*2
+*/
+
+char *octet2hex(char *to, const char *str, uint len)
+{
+ const char *str_end= str + len;
+ for (; str != str_end; ++str)
+ {
+ *to++= _dig_vec_upper[((uchar) *str) >> 4];
+ *to++= _dig_vec_upper[((uchar) *str) & 0x0F];
+ }
+ *to= '\0';
+ return to;
+}
+
+
+/*
+ Convert given asciiz string of hex (0..9 a..f) characters to octet
+ sequence.
+ SYNOPSIS
+ hex2octet()
+ to OUT buffer to place result; must be at least len/2 bytes
+ str, len IN begin, length for character string; str and to may not
+ overlap; len % 2 == 0
+*/
+
+static void
+hex2octet(uint8 *to, const char *str, uint len)
+{
+ const char *str_end= str + len;
+ while (str < str_end)
+ {
+ char tmp= char_val(*str++);
+ *to++= (tmp << 4) | char_val(*str++);
+ }
+}
+
+
+/*
+ Encrypt/Decrypt function used for password encryption in authentication.
+ Simple XOR is used here but it is OK as we crypt random strings. Note,
+ that XOR(s1, XOR(s1, s2)) == s2, XOR(s1, s2) == XOR(s2, s1)
+ SYNOPSIS
+ my_crypt()
+ to OUT buffer to hold crypted string; must be at least len bytes
+ long; to and s1 (or s2) may be the same.
+ s1, s2 IN input strings (of equal length)
+ len IN length of s1 and s2
+*/
+
+static void
+my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
+{
+ const uint8 *s1_end= s1 + len;
+ while (s1 < s1_end)
+ *to++= *s1++ ^ *s2++;
+}
+
+#if defined(HAVE_OPENSSL)
+void my_make_scrambled_password(char *to, const char *password,
+ size_t pass_len)
+{
+
+ char salt[CRYPT_SALT_LENGTH + 1];
+
+ generate_user_salt(salt, CRYPT_SALT_LENGTH + 1);
+ my_crypt_genhash(to,
+ CRYPT_MAX_PASSWORD_SIZE,
+ password,
+ pass_len,
+ salt,
+ 0);
+
+}
+#endif
+/**
+ Compute two stage SHA1 hash of the password :
+
+ hash_stage1=sha1("password")
+ hash_stage2=sha1(hash_stage1)
+
+ @param password [IN] Password string.
+ @param pass_len [IN] Length of the password.
+ @param hash_stage1 [OUT] sha1(password)
+ @param hash_stage2 [OUT] sha1(hash_stage1)
+*/
+
+inline static
+void compute_two_stage_sha1_hash(const char *password, size_t pass_len,
+ uint8 *hash_stage1, uint8 *hash_stage2)
+{
+ /* Stage 1: hash password */
+ compute_sha1_hash(hash_stage1, password, pass_len);
+
+ /* Stage 2 : hash first stage's output. */
+ compute_sha1_hash(hash_stage2, (const char *) hash_stage1, SHA1_HASH_SIZE);
+}
+
+
+/*
+ MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
+ applied to the password string, and then produced octet sequence is
+ converted to hex string.
+ The result of this function is used as return value from PASSWORD() and
+ is stored in the database.
+ SYNOPSIS
+ my_make_scrambled_password_sha1()
+ buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
+ password IN password string
+ pass_len IN length of password string
+*/
+
+void my_make_scrambled_password_sha1(char *to, const char *password,
+ size_t pass_len)
+{
+ uint8 hash_stage2[SHA1_HASH_SIZE];
+
+ /* Two stage SHA1 hash of the password. */
+ compute_two_stage_sha1_hash(password, pass_len, (uint8 *) to, hash_stage2);
+
+ /* convert hash_stage2 to hex string */
+ *to++= PVERSION41_CHAR;
+ octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
+}
+
+
+/*
+ Wrapper around my_make_scrambled_password() to maintain client lib ABI
+ compatibility.
+ In server code usage of my_make_scrambled_password() is preferred to
+ avoid strlen().
+ SYNOPSIS
+ make_scrambled_password()
+ buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
+ password IN NULL-terminated password string
+*/
+
+void make_scrambled_password(char *to, const char *password)
+{
+ my_make_scrambled_password_sha1(to, password, strlen(password));
+}
+
+
+/*
+ Produce an obscure octet sequence from password and random
+ string, received from the server. This sequence corresponds to the
+ password, but password can not be easily restored from it. The sequence
+ is then sent to the server for validation. Trailing zero is not stored
+ in the buf as it is not needed.
+ This function is used by client to create authenticated reply to the
+ server's greeting.
+ SYNOPSIS
+ scramble()
+ buf OUT store scrambled string here. The buf must be at least
+ SHA1_HASH_SIZE bytes long.
+ message IN random message, must be exactly SCRAMBLE_LENGTH long and
+ NULL-terminated.
+ password IN users' password
+*/
+
+void
+scramble(char *to, const char *message, const char *password)
+{
+ uint8 hash_stage1[SHA1_HASH_SIZE];
+ uint8 hash_stage2[SHA1_HASH_SIZE];
+
+ /* Two stage SHA1 hash of the password. */
+ compute_two_stage_sha1_hash(password, strlen(password), hash_stage1,
+ hash_stage2);
+
+ /* create crypt string as sha1(message, hash_stage2) */;
+ compute_sha1_hash_multi((uint8 *) to, message, SCRAMBLE_LENGTH,
+ (const char *) hash_stage2, SHA1_HASH_SIZE);
+ my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
+}
+
+
+/*
+ Check that scrambled message corresponds to the password; the function
+ is used by server to check that received reply is authentic.
+ This function does not check lengths of given strings: message must be
+ null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
+ long (if not, something fishy is going on).
+ SYNOPSIS
+ check_scramble_sha1()
+ scramble clients' reply, presumably produced by scramble()
+ message original random string, previously sent to client
+ (presumably second argument of scramble()), must be
+ exactly SCRAMBLE_LENGTH long and NULL-terminated.
+ hash_stage2 hex2octet-decoded database entry
+ All params are IN.
+
+ RETURN VALUE
+ 0 password is correct
+ !0 password is invalid
+*/
+
+my_bool
+check_scramble_sha1(const uchar *scramble_arg, const char *message,
+ const uint8 *hash_stage2)
+{
+ uint8 buf[SHA1_HASH_SIZE];
+ uint8 hash_stage2_reassured[SHA1_HASH_SIZE];
+
+ /* create key to encrypt scramble */
+ compute_sha1_hash_multi(buf, message, SCRAMBLE_LENGTH,
+ (const char *) hash_stage2, SHA1_HASH_SIZE);
+ /* encrypt scramble */
+ my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
+
+ /* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
+ compute_sha1_hash(hash_stage2_reassured, (const char *) buf, SHA1_HASH_SIZE);
+
+ return MY_TEST(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
+}
+
+my_bool
+check_scramble(const uchar *scramble_arg, const char *message,
+ const uint8 *hash_stage2)
+{
+ return check_scramble_sha1(scramble_arg, message, hash_stage2);
+}
+
+/*
+ Convert scrambled password from asciiz hex string to binary form.
+
+ SYNOPSIS
+ get_salt_from_password()
+ res OUT buf to hold password. Must be at least SHA1_HASH_SIZE
+ bytes long.
+ password IN 4.1.1 version value of user.password
+*/
+
+void get_salt_from_password(uint8 *hash_stage2, const char *password)
+{
+ hex2octet(hash_stage2, password+1 /* skip '*' */, SHA1_HASH_SIZE * 2);
+}
+
+/*
+ Convert scrambled password from binary form to asciiz hex string.
+ SYNOPSIS
+ make_password_from_salt()
+ to OUT store resulting string here, 2*SHA1_HASH_SIZE+2 bytes
+ salt IN password in salt format
+*/
+
+void make_password_from_salt(char *to, const uint8 *hash_stage2)
+{
+ *to++= PVERSION41_CHAR;
+ octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
+}
+
diff --git a/mysql/sql/my_decimal.h b/mysql/sql/my_decimal.h
new file mode 100644
index 0000000..d964484
--- /dev/null
+++ b/mysql/sql/my_decimal.h
@@ -0,0 +1,538 @@
+/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef MY_DECIMAL_INCLUDED
+#define MY_DECIMAL_INCLUDED
+
+/**
+ @file
+
+ It is interface module to fixed precision decimals library.
+
+ Most functions use 'uint mask' as parameter, if during operation error
+ which fit in this mask is detected then it will be processed automatically
+ here. (errors are E_DEC_* constants, see include/decimal.h)
+
+ Most function are just inline wrappers around library calls
+*/
+
+#if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+#include "sql_string.h" /* String */
+#endif
+
+C_MODE_START
+#include <decimal.h>
+C_MODE_END
+
+class String;
+typedef struct st_mysql_time MYSQL_TIME;
+
+#define DECIMAL_LONGLONG_DIGITS 22
+#define DECIMAL_LONG_DIGITS 10
+#define DECIMAL_LONG3_DIGITS 8
+
+/** maximum length of buffer in our big digits (uint32). */
+#define DECIMAL_BUFF_LENGTH 9
+
+/* the number of digits that my_decimal can possibly contain */
+#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
+
+
+/**
+ maximum guaranteed precision of number in decimal digits (number of our
+ digits * number of decimal digits in one our big digit - number of decimal
+ digits in one our big digit decreased by 1 (because we always put decimal
+ point on the border of our big digits))
+*/
+#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
+#define DECIMAL_MAX_SCALE 30
+#define DECIMAL_NOT_SPECIFIED 31
+
+/**
+ maximum length of string representation (number of maximum decimal
+ digits + 1 position for sign + 1 position for decimal point, no terminator)
+*/
+#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
+
+/**
+ maximum size of packet length.
+*/
+#define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION
+
+
+inline uint my_decimal_size(uint precision, uint scale)
+{
+ /*
+ Always allocate more space to allow library to put decimal point
+ where it want
+ */
+ return decimal_size(precision, scale) + 1;
+}
+
+
+inline int my_decimal_int_part(uint precision, uint decimals)
+{
+ return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
+}
+
+
+/**
+ my_decimal class limits 'decimal_t' type to what we need in MySQL.
+
+ It contains internally all necessary space needed by the instance so
+ no extra memory is needed. Objects should be moved using copy CTOR
+ or assignment operator, rather than memcpy/memmove.
+*/
+
+class my_decimal :public decimal_t
+{
+ /*
+ Several of the routines in strings/decimal.c have had buffer
+ overrun/underrun problems. These are *not* caught by valgrind.
+ To catch them, we allocate dummy fields around the buffer,
+ and test that their values do not change.
+ */
+#if !defined(DBUG_OFF)
+ int foo1;
+#endif
+
+ decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
+
+#if !defined(DBUG_OFF)
+ int foo2;
+ static const int test_value= 123;
+#endif
+
+public:
+
+ my_decimal(const my_decimal &rhs) : decimal_t(rhs)
+ {
+ rhs.sanity_check();
+#if !defined(DBUG_OFF)
+ foo1= test_value;
+ foo2= test_value;
+#endif
+ for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
+ buffer[i]= rhs.buffer[i];
+ buf= buffer;
+ }
+
+ my_decimal& operator=(const my_decimal &rhs)
+ {
+ sanity_check();
+ rhs.sanity_check();
+ if (this == &rhs)
+ return *this;
+ decimal_t::operator=(rhs);
+ for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++)
+ buffer[i]= rhs.buffer[i];
+ buf= buffer;
+ return *this;
+ }
+
+ void init()
+ {
+#if !defined(DBUG_OFF)
+ foo1= test_value;
+ foo2= test_value;
+#endif
+ /*
+ Do not initialize more of the base class,
+ we want to catch uninitialized use.
+ */
+ len= DECIMAL_BUFF_LENGTH;
+ buf= buffer;
+ }
+
+ my_decimal()
+ {
+ init();
+ }
+ ~my_decimal()
+ {
+ sanity_check();
+ }
+
+ void sanity_check() const
+ {
+ DBUG_ASSERT(foo1 == test_value);
+ DBUG_ASSERT(foo2 == test_value);
+ DBUG_ASSERT(buf == buffer);
+ }
+
+ bool sign() const { return decimal_t::sign; }
+ void sign(bool s) { decimal_t::sign= s; }
+ uint precision() const { return intg + frac; }
+
+ /** Swap two my_decimal values */
+ void swap(my_decimal &rhs)
+ {
+ swap_variables(my_decimal, *this, rhs);
+ }
+
+ // Error reporting in server code only.
+ int check_result(uint mask, int result) const
+#ifdef MYSQL_CLIENT
+ {
+ return result;
+ }
+#endif
+ ;
+};
+
+
+#ifndef DBUG_OFF
+void print_decimal(const my_decimal *dec);
+void print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length);
+const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
+#else
+#define dbug_decimal_as_string(A) NULL
+#endif
+
+bool str_set_decimal(uint mask, const my_decimal *val, uint fixed_prec,
+ uint fixed_dec, char filler, String *str,
+ const CHARSET_INFO *cs);
+
+extern my_decimal decimal_zero;
+
+
+inline
+void max_my_decimal(my_decimal *to, int precision, int frac)
+{
+ DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION)&&
+ (frac <= DECIMAL_MAX_SCALE));
+ max_decimal(precision, frac, to);
+}
+
+inline void max_internal_decimal(my_decimal *to)
+{
+ max_my_decimal(to, DECIMAL_MAX_PRECISION, 0);
+}
+
+inline int check_result_and_overflow(uint mask, int result, my_decimal *val)
+{
+ if (val->check_result(mask, result) & E_DEC_OVERFLOW)
+ {
+ bool sign= val->sign();
+ val->sanity_check();
+ max_internal_decimal(val);
+ val->sign(sign);
+ }
+ /*
+ Avoid returning negative zero, cfr. decimal_cmp()
+ For result == E_DEC_DIV_ZERO *val has not been assigned.
+ */
+ if (result != E_DEC_DIV_ZERO && val->sign() && decimal_is_zero(val))
+ val->sign(false);
+ return result;
+}
+
+inline uint my_decimal_length_to_precision(uint length, uint scale,
+ bool unsigned_flag)
+{
+ /* Precision can't be negative thus ignore unsigned_flag when length is 0. */
+ DBUG_ASSERT(length || !scale);
+ uint retval= (uint) (length - (scale>0 ? 1:0) -
+ (unsigned_flag || !length ? 0:1));
+ return retval;
+}
+
+inline uint32 my_decimal_precision_to_length_no_truncation(uint precision,
+ uint8 scale,
+ bool unsigned_flag)
+{
+ /*
+ When precision is 0 it means that original length was also 0. Thus
+ unsigned_flag is ignored in this case.
+ */
+ DBUG_ASSERT(precision || !scale);
+ uint32 retval= (uint32)(precision + (scale > 0 ? 1 : 0) +
+ (unsigned_flag || !precision ? 0 : 1));
+ return retval;
+}
+
+inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
+ bool unsigned_flag)
+{
+ /*
+ When precision is 0 it means that original length was also 0. Thus
+ unsigned_flag is ignored in this case.
+ */
+ DBUG_ASSERT(precision || !scale);
+ set_if_smaller(precision, DECIMAL_MAX_PRECISION);
+ return my_decimal_precision_to_length_no_truncation(precision, scale,
+ unsigned_flag);
+}
+
+inline
+int my_decimal_string_length(const my_decimal *d)
+{
+ /* length of string representation including terminating '\0' */
+ return decimal_string_size(d);
+}
+
+
+inline
+int my_decimal_max_length(const my_decimal *d)
+{
+ /* -1 because we do not count \0 */
+ return decimal_string_size(d) - 1;
+}
+
+
+inline
+int my_decimal_get_binary_size(uint precision, uint scale)
+{
+ return decimal_bin_size((int)precision, (int)scale);
+}
+
+
+inline
+void my_decimal2decimal(const my_decimal *from, my_decimal *to)
+{
+ *to= *from;
+}
+
+
+int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
+ int scale);
+
+
+inline
+int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec,
+ int scale)
+{
+ return d->check_result(mask, bin2decimal(bin, d, prec, scale));
+}
+
+
+inline
+int my_decimal_set_zero(my_decimal *d)
+{
+ /*
+ We need the up-cast here, since my_decimal has sign() member functions,
+ which conflicts with decimal_t::size
+ (and decimal_make_zero is a macro, rather than a funcion).
+ */
+ decimal_make_zero(static_cast<decimal_t*>(d));
+ return 0;
+}
+
+
+inline
+bool my_decimal_is_zero(const my_decimal *decimal_value)
+{
+ return decimal_is_zero(decimal_value);
+}
+
+
+inline
+int my_decimal_round(uint mask, const my_decimal *from, int scale,
+ bool truncate, my_decimal *to)
+{
+ return
+ from->check_result(mask, decimal_round(from, to, scale,
+ (truncate ? TRUNCATE : HALF_UP)));
+}
+
+
+inline
+int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
+{
+ return from->check_result(mask, decimal_round(from, to, 0, FLOOR));
+}
+
+
+inline
+int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
+{
+ return from->check_result(mask, decimal_round(from, to, 0, CEILING));
+}
+
+
+inline bool str_set_decimal(const my_decimal *val, String *str,
+ const CHARSET_INFO *cs)
+{
+ return str_set_decimal(E_DEC_FATAL_ERROR, val, 0, 0, 0, str, cs);
+}
+
+#ifndef MYSQL_CLIENT
+class String;
+int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
+ uint fixed_dec, char filler, String *str);
+#endif
+
+inline
+int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
+ longlong *l)
+{
+ my_decimal rounded;
+ /* decimal_round can return only E_DEC_TRUNCATED */
+ decimal_round(d, &rounded, 0, HALF_UP);
+ return d->check_result(mask, (unsigned_flag ?
+ decimal2ulonglong(&rounded, (ulonglong *)l) :
+ decimal2longlong(&rounded, l)));
+}
+
+
+inline
+int my_decimal2double(uint, const my_decimal *d, double *result)
+{
+ /* No need to call check_result as this will always succeed */
+ return decimal2double(d, result);
+}
+
+
+inline int my_decimal2lldiv_t(uint mask, const my_decimal *d, lldiv_t *to)
+{
+ return d->check_result(mask, decimal2lldiv_t(d, to));
+}
+
+
+inline int str2my_decimal(uint mask, const char *str,
+ my_decimal *d, char **end)
+{
+ return check_result_and_overflow(mask, string2decimal(str, d, end), d);
+}
+
+
+int str2my_decimal(uint mask, const char *from, size_t length,
+ const CHARSET_INFO *charset, my_decimal *decimal_value);
+
+#if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
+inline
+int string2my_decimal(uint mask, const String *str, my_decimal *d)
+{
+ return str2my_decimal(mask, str->ptr(), (uint)str->length(), str->charset(), d);
+}
+
+
+my_decimal *date2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
+my_decimal *time2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec);
+my_decimal *timeval2my_decimal(const struct timeval *tm, my_decimal *dec);
+
+#endif /*defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) */
+
+inline
+int double2my_decimal(uint mask, double val, my_decimal *d)
+{
+ return check_result_and_overflow(mask, double2decimal(val, d), d);
+}
+
+
+inline
+int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
+{
+ return d->check_result(mask, (unsigned_flag ?
+ ulonglong2decimal((ulonglong)i, d) :
+ longlong2decimal(i, d)));
+}
+
+
+inline
+void my_decimal_neg(decimal_t *arg)
+{
+ // Avoid returning negative zero, cfr. decimal_cmp()
+ if (decimal_is_zero(arg))
+ {
+ arg->sign= 0;
+ return;
+ }
+ arg->sign^= 1;
+}
+
+
+inline
+int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result_and_overflow(mask,
+ decimal_add(a, b, res),
+ res);
+}
+
+
+inline
+int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result_and_overflow(mask,
+ decimal_sub(a, b, res),
+ res);
+}
+
+
+inline
+int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result_and_overflow(mask,
+ decimal_mul(a, b, res),
+ res);
+}
+
+
+inline
+int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b, int div_scale_inc)
+{
+ return check_result_and_overflow(mask,
+ decimal_div(a, b, res, div_scale_inc),
+ res);
+}
+
+
+inline
+int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
+ const my_decimal *b)
+{
+ return check_result_and_overflow(mask,
+ decimal_mod(a, b, res),
+ res);
+}
+
+
+/**
+ @return
+ -1 if a<b, 1 if a>b and 0 if a==b
+*/
+inline
+int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
+{
+ return decimal_cmp(a, b);
+}
+
+inline
+bool operator<(const my_decimal &lhs, const my_decimal &rhs)
+{
+ return my_decimal_cmp(&lhs, &rhs) < 0;
+}
+
+inline
+bool operator!=(const my_decimal &lhs, const my_decimal &rhs)
+{
+ return my_decimal_cmp(&lhs, &rhs) != 0;
+}
+
+inline
+int my_decimal_intg(const my_decimal *a)
+{
+ return decimal_intg(a);
+}
+
+
+void my_decimal_trim(ulong *precision, uint *scale);
+
+#endif // MY_DECIMAL_INCLUDED
diff --git a/mysql/sql/mysqld.h b/mysql/sql/mysqld.h
new file mode 100644
index 0000000..4639fd3
--- /dev/null
+++ b/mysql/sql/mysqld.h
@@ -0,0 +1,979 @@
+/* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef MYSQLD_INCLUDED
+#define MYSQLD_INCLUDED
+
+#include "my_global.h" /* MYSQL_PLUGIN_IMPORT, FN_REFLEN, FN_EXTLEN */
+#include "my_bitmap.h" /* MY_BITMAP */
+#include "my_decimal.h" /* my_decimal */
+#include "mysql_com.h" /* SERVER_VERSION_LENGTH */
+#include "my_atomic.h" /* my_atomic_add64 */
+#include "sql_cmd.h" /* SQLCOM_END */
+#include "my_thread_local.h" /* my_get_thread_local */
+#include "my_thread.h" /* my_thread_attr_t */
+#include "atomic_class.h" /* Atomic_int32 */
+
+class THD;
+struct handlerton;
+class Time_zone;
+template <uint default_width> class Bitmap;
+
+typedef struct st_mysql_const_lex_string LEX_CSTRING;
+typedef struct st_mysql_show_var SHOW_VAR;
+
+/*
+ This forward declaration is used from C files where the real
+ definition is included before. Since C does not allow repeated
+ typedef declarations, even when identical, the definition may not be
+ repeated.
+*/
+#ifndef CHARSET_INFO_DEFINED
+typedef struct charset_info_st CHARSET_INFO;
+#endif /* CHARSET_INFO_DEFINED */
+
+#if MAX_INDEXES <= 64
+typedef Bitmap<64> key_map; /* Used for finding keys */
+#elif MAX_INDEXES > 255
+#error "MAX_INDEXES values greater than 255 is not supported."
+#else
+typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
+#endif
+
+ /* Bits from testflag */
+#define TEST_PRINT_CACHED_TABLES 1
+#define TEST_NO_KEY_GROUP 2
+#define TEST_MIT_THREAD 4
+/*
+ TEST_BLOCKING is made obsolete and is not used any
+ where in the code base and is retained here so that
+ the other bit flag values are not changed.
+*/
+#define OBSOLETE_TEST_BLOCKING 8
+#define TEST_KEEP_TMP_TABLES 16
+#define TEST_READCHECK 64 /**< Force use of readcheck */
+#define TEST_NO_EXTRA 128
+#define TEST_CORE_ON_SIGNAL 256 /**< Give core if signal */
+#define TEST_NO_STACKTRACE 512
+#define TEST_SIGINT 1024 /**< Allow sigint on threads */
+#define TEST_SYNCHRONIZATION 2048 /**< get server to do sleep in
+ some places */
+#define TEST_DO_QUICK_LEAK_CHECK 4096 /**< Do Valgrind leak check for
+ each command. */
+
+#define SPECIAL_NO_NEW_FUNC 2 /* Skip new functions */
+#define SPECIAL_SKIP_SHOW_DB 4 /* Don't allow 'show db' */
+#define SPECIAL_NO_RESOLVE 64 /* Don't use gethostname */
+#define SPECIAL_NO_HOST_CACHE 512 /* Don't cache hosts */
+#define SPECIAL_SHORT_LOG_FORMAT 1024
+
+/* Function prototypes */
+#ifndef EMBEDDED_LIBRARY
+void kill_mysql(void);
+#endif
+void refresh_status(THD *thd);
+bool is_secure_file_path(char *path);
+int handle_early_options();
+void adjust_related_options(ulong *requested_open_files);
+ulong sql_rnd_with_mutex();
+
+// These are needed for unit testing.
+void set_remaining_args(int argc, char **argv);
+int init_common_variables();
+void my_init_signals();
+bool gtid_server_init();
+void gtid_server_cleanup();
+const char *fixup_enforce_gtid_consistency_command_line(char *value_arg);
+
+extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
+extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ;
+extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *national_charset_info;
+extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset;
+
+enum enum_server_operational_state
+{
+ SERVER_BOOTING, /* Server is not operational. It is starting */
+ SERVER_OPERATING, /* Server is fully initialized and operating */
+ SERVER_SHUTTING_DOWN /* erver is shutting down */
+};
+enum_server_operational_state get_server_state();
+
+/**
+ Character set of the buildin error messages loaded from errmsg.sys.
+*/
+extern CHARSET_INFO *error_message_charset_info;
+
+extern CHARSET_INFO *character_set_filesystem;
+
+extern MY_BITMAP temp_pool;
+extern bool opt_large_files, server_id_supplied;
+extern bool opt_update_log, opt_bin_log;
+extern my_bool opt_log_slave_updates;
+extern my_bool opt_log_unsafe_statements;
+extern bool opt_general_log, opt_slow_log, opt_general_log_raw;
+extern my_bool opt_backup_history_log;
+extern my_bool opt_backup_progress_log;
+extern ulonglong log_output_options;
+extern ulong log_backup_output_options;
+extern my_bool opt_log_queries_not_using_indexes;
+extern ulong opt_log_throttle_queries_not_using_indexes;
+extern bool opt_disable_networking, opt_skip_show_db;
+extern bool opt_skip_name_resolve;
+extern my_bool opt_help;
+extern my_bool opt_verbose;
+extern bool opt_ignore_builtin_innodb;
+extern my_bool opt_character_set_client_handshake;
+extern MYSQL_PLUGIN_IMPORT bool volatile abort_loop;
+extern my_bool opt_bootstrap, opt_initialize;
+extern my_bool opt_safe_user_create;
+extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
+extern my_bool opt_slave_compressed_protocol, use_temp_pool;
+extern ulong slave_exec_mode_options;
+extern ulonglong slave_type_conversions_options;
+extern my_bool read_only, opt_readonly;
+extern my_bool super_read_only, opt_super_readonly;
+extern my_bool lower_case_file_system;
+extern ulonglong slave_rows_search_algorithms_options;
+extern my_bool opt_require_secure_transport;
+
+#ifdef HAVE_REPLICATION
+extern my_bool opt_slave_preserve_commit_order;
+#endif
+
+#ifndef DBUG_OFF
+extern uint slave_rows_last_search_algorithm_used;
+#endif
+extern ulong mts_parallel_option;
+extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
+extern my_bool opt_secure_auth;
+extern char* opt_secure_file_priv;
+extern char* opt_secure_backup_file_priv;
+extern size_t opt_secure_backup_file_priv_len;
+extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements;
+extern my_bool sp_automatic_privileges, opt_noacl;
+extern my_bool opt_old_style_user_limits, trust_function_creators;
+extern my_bool check_proxy_users, mysql_native_password_proxy_users, sha256_password_proxy_users;
+extern uint opt_crash_binlog_innodb;
+extern char *shared_memory_base_name, *mysqld_unix_port;
+extern my_bool opt_enable_shared_memory;
+extern char *default_tz_name;
+extern Time_zone *default_tz;
+extern char *default_storage_engine;
+extern char *default_tmp_storage_engine;
+extern ulong internal_tmp_disk_storage_engine;
+extern bool opt_endinfo, using_udf_functions;
+extern my_bool locked_in_memory;
+extern bool opt_using_transactions;
+extern ulong max_long_data_size;
+extern ulong current_pid;
+extern ulong expire_logs_days;
+extern my_bool relay_log_recovery;
+extern uint sync_binlog_period, sync_relaylog_period,
+ sync_relayloginfo_period, sync_masterinfo_period,
+ opt_mts_checkpoint_period, opt_mts_checkpoint_group;
+extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size;
+extern ulong tc_log_page_waits;
+extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
+extern my_bool relay_log_recovery;
+extern my_bool offline_mode;
+extern my_bool opt_log_builtin_as_identified_by_password;
+extern uint test_flags,select_errors,ha_open_options;
+extern uint protocol_version, mysqld_port, dropping_tables;
+extern ulong delay_key_write_options;
+extern ulong opt_log_timestamps;
+extern const char *timestamp_type_names[];
+extern char *opt_general_logname, *opt_slow_logname, *opt_bin_logname,
+ *opt_relay_logname;
+extern char *opt_backup_history_logname, *opt_backup_progress_logname,
+ *opt_backup_settings_name;
+extern const char *log_output_str;
+extern const char *log_backup_output_str;
+extern char *mysql_home_ptr, *pidfile_name_ptr;
+extern char *default_auth_plugin;
+extern uint default_password_lifetime;
+extern char *my_bind_addr_str;
+extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
+extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
+extern char default_logfile_name[FN_REFLEN];
+extern char *opt_tc_log_file;
+/*Move UUID_LENGTH from item_strfunc.h*/
+#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
+extern char server_uuid[UUID_LENGTH+1];
+extern const char *server_uuid_ptr;
+extern const double log_10[309];
+extern ulonglong keybuff_size;
+extern ulonglong thd_startup_options;
+extern ulong binlog_cache_use, binlog_cache_disk_use;
+extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use;
+extern ulong aborted_threads;
+extern ulong delayed_insert_timeout;
+extern ulong delayed_insert_limit, delayed_queue_size;
+extern ulong delayed_insert_threads, delayed_insert_writes;
+extern ulong delayed_rows_in_use,delayed_insert_errors;
+extern Atomic_int32 slave_open_temp_tables;
+extern ulong query_cache_size, query_cache_min_res_unit;
+extern ulong slow_launch_time;
+extern ulong table_cache_size, table_def_size;
+extern ulong table_cache_size_per_instance, table_cache_instances;
+extern MYSQL_PLUGIN_IMPORT ulong max_connections;
+extern ulong max_digest_length;
+extern ulong max_connect_errors, connect_timeout;
+extern my_bool opt_slave_allow_batching;
+extern my_bool allow_slave_start;
+extern LEX_CSTRING reason_slave_blocked;
+extern ulong slave_trans_retries;
+extern uint slave_net_timeout;
+extern ulong opt_mts_slave_parallel_workers;
+extern ulonglong opt_mts_pending_jobs_size_max;
+extern uint max_user_connections;
+extern ulong rpl_stop_slave_timeout;
+extern my_bool log_bin_use_v1_row_events;
+extern ulong what_to_log,flush_time;
+extern ulong max_prepared_stmt_count, prepared_stmt_count;
+extern ulong open_files_limit;
+extern ulong binlog_cache_size, binlog_stmt_cache_size;
+extern ulonglong max_binlog_cache_size, max_binlog_stmt_cache_size;
+extern int32 opt_binlog_max_flush_queue_time;
+extern ulong opt_binlog_group_commit_sync_delay;
+extern ulong opt_binlog_group_commit_sync_no_delay_count;
+extern ulong max_binlog_size, max_relay_log_size;
+extern ulong slave_max_allowed_packet;
+extern ulong opt_binlog_rows_event_max_size;
+extern ulong binlog_checksum_options;
+extern const char *binlog_checksum_type_names[];
+extern my_bool opt_master_verify_checksum;
+extern my_bool opt_slave_sql_verify_checksum;
+extern uint32 gtid_executed_compression_period;
+extern my_bool binlog_gtid_simple_recovery;
+extern ulong binlog_error_action;
+extern ulong locked_account_connection_count;
+enum enum_binlog_error_action
+{
+ /// Ignore the error and let server continue without binlogging
+ IGNORE_ERROR= 0,
+ /// Abort the server
+ ABORT_SERVER= 1
+};
+extern const char *binlog_error_action_list[];
+
+extern ulong stored_program_cache_size;
+extern ulong back_log;
+extern char language[FN_REFLEN];
+extern "C" MYSQL_PLUGIN_IMPORT ulong server_id;
+extern time_t server_start_time, flush_status_time;
+extern char *opt_mysql_tmpdir, mysql_charsets_dir[];
+extern size_t mysql_unpacked_real_data_home_len;
+extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
+extern const char *show_comp_option_name[];
+extern const char *first_keyword, *binary_keyword;
+extern MYSQL_PLUGIN_IMPORT const char *my_localhost;
+extern const char *myisam_recover_options_str;
+extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
+extern SHOW_VAR status_vars[];
+extern struct system_variables max_system_variables;
+extern struct system_status_var global_status_var;
+extern struct rand_struct sql_rand;
+extern const char *opt_date_time_formats[];
+extern handlerton *myisam_hton;
+extern handlerton *heap_hton;
+extern handlerton *innodb_hton;
+extern uint opt_server_id_bits;
+extern ulong opt_server_id_mask;
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
+/* engine specific hook, to be made generic */
+extern int(*ndb_wait_setup_func)(ulong);
+extern ulong opt_ndb_wait_setup;
+#endif
+extern const char *load_default_groups[];
+extern struct my_option my_long_options[];
+extern struct my_option my_long_early_options[];
+extern bool mysqld_server_started;
+extern "C" MYSQL_PLUGIN_IMPORT int orig_argc;
+extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv;
+extern my_thread_attr_t connection_attrib;
+extern my_bool old_mode;
+extern my_bool avoid_temporal_upgrade;
+extern LEX_STRING opt_init_connect, opt_init_slave;
+extern char err_shared_dir[];
+extern my_decimal decimal_zero;
+#ifndef EMBEDDED_LIBRARY
+extern ulong connection_errors_internal;
+extern ulong connection_errors_peer_addr;
+#endif
+extern ulong log_warnings;
+extern bool opt_log_syslog_enable;
+extern char *opt_log_syslog_tag;
+#ifndef _WIN32
+extern bool opt_log_syslog_include_pid;
+extern char *opt_log_syslog_facility;
+#endif
+/** The size of the host_cache. */
+extern uint host_cache_size;
+extern ulong log_error_verbosity;
+
+/** System variable show_compatibility_56. */
+extern my_bool show_compatibility_56;
+
+#if defined(EMBEDDED_LIBRARY)
+extern ulong max_allowed_packet;
+extern ulong net_buffer_length;
+#endif
+
+extern LEX_CSTRING sql_statement_names[(uint) SQLCOM_END + 1];
+
+/*
+ THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
+ using my_set_thread_local()/my_get_thread_local().
+*/
+extern thread_local_key_t THR_MALLOC;
+extern bool THR_MALLOC_initialized;
+
+static inline MEM_ROOT ** my_thread_get_THR_MALLOC()
+{
+ DBUG_ASSERT(THR_MALLOC_initialized);
+ return (MEM_ROOT**) my_get_thread_local(THR_MALLOC);
+}
+
+static inline int my_thread_set_THR_MALLOC(MEM_ROOT ** hdl)
+{
+ DBUG_ASSERT(THR_MALLOC_initialized);
+ return my_set_thread_local(THR_MALLOC, hdl);
+}
+
+/*
+ THR_THD is a key which will be used to set/get THD* for a thread,
+ using my_set_thread_local()/my_get_thread_local().
+*/
+extern MYSQL_PLUGIN_IMPORT thread_local_key_t THR_THD;
+extern bool THR_THD_initialized;
+
+static inline THD * my_thread_get_THR_THD()
+{
+ DBUG_ASSERT(THR_THD_initialized);
+ return (THD*)my_get_thread_local(THR_THD);
+}
+
+static inline int my_thread_set_THR_THD(THD *thd)
+{
+ DBUG_ASSERT(THR_THD_initialized);
+ return my_set_thread_local(THR_THD, thd);
+}
+
+#ifdef HAVE_PSI_INTERFACE
+
+C_MODE_START
+
+extern PSI_mutex_key key_LOCK_tc;
+
+#ifdef HAVE_OPENSSL
+extern PSI_mutex_key key_LOCK_des_key_file;
+#endif
+
+extern PSI_mutex_key key_BINLOG_LOCK_commit;
+extern PSI_mutex_key key_BINLOG_LOCK_commit_queue;
+extern PSI_mutex_key key_BINLOG_LOCK_done;
+extern PSI_mutex_key key_BINLOG_LOCK_flush_queue;
+extern PSI_mutex_key key_BINLOG_LOCK_index;
+extern PSI_mutex_key key_BINLOG_LOCK_log;
+extern PSI_mutex_key key_BINLOG_LOCK_binlog_end_pos;
+extern PSI_mutex_key key_BINLOG_LOCK_sync;
+extern PSI_mutex_key key_BINLOG_LOCK_sync_queue;
+extern PSI_mutex_key key_BINLOG_LOCK_xids;
+extern PSI_mutex_key
+ key_hash_filo_lock,
+ key_LOCK_crypt, key_LOCK_error_log,
+ key_LOCK_gdl, key_LOCK_global_system_variables,
+ key_LOCK_lock_db, key_LOCK_logger, key_LOCK_manager,
+ key_LOCK_prepared_stmt_count,
+ key_LOCK_server_started, key_LOCK_status,
+ key_LOCK_sql_slave_skip_counter,
+ key_LOCK_slave_net_timeout,
+ key_LOCK_table_share, key_LOCK_thd_data, key_LOCK_thd_sysvar,
+ key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
+ key_master_info_data_lock, key_master_info_run_lock,
+ key_master_info_sleep_lock, key_master_info_thd_lock,
+ key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
+ key_relay_log_info_sleep_lock, key_relay_log_info_thd_lock,
+ key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
+ key_mutex_slave_parallel_pend_jobs, key_mutex_mts_temp_tables_lock,
+ key_mutex_slave_parallel_worker,
+ key_mutex_slave_parallel_worker_count,
+ key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
+ key_LOCK_error_messages,
+ key_LOCK_log_throttle_qni, key_LOCK_query_plan, key_LOCK_thd_query,
+ key_LOCK_cost_const, key_LOCK_current_cond;
+extern PSI_mutex_key key_RELAYLOG_LOCK_commit;
+extern PSI_mutex_key key_RELAYLOG_LOCK_commit_queue;
+extern PSI_mutex_key key_RELAYLOG_LOCK_done;
+extern PSI_mutex_key key_RELAYLOG_LOCK_flush_queue;
+extern PSI_mutex_key key_RELAYLOG_LOCK_index;
+extern PSI_mutex_key key_RELAYLOG_LOCK_log;
+extern PSI_mutex_key key_RELAYLOG_LOCK_sync;
+extern PSI_mutex_key key_RELAYLOG_LOCK_sync_queue;
+extern PSI_mutex_key key_RELAYLOG_LOCK_xids;
+extern PSI_mutex_key key_LOCK_sql_rand;
+extern PSI_mutex_key key_gtid_ensure_index_mutex;
+extern PSI_mutex_key key_mts_temp_table_LOCK;
+extern PSI_mutex_key key_LOCK_reset_gtid_table;
+extern PSI_mutex_key key_LOCK_compress_gtid_table;
+extern PSI_mutex_key key_mts_gaq_LOCK;
+extern PSI_mutex_key key_thd_timer_mutex;
+extern PSI_mutex_key key_LOCK_offline_mode;
+extern PSI_mutex_key key_LOCK_default_password_lifetime;
+extern PSI_mutex_key key_LOCK_group_replication_handler;
+
+#ifdef HAVE_REPLICATION
+extern PSI_mutex_key key_commit_order_manager_mutex;
+extern PSI_mutex_key key_mutex_slave_worker_hash;
+#endif
+
+extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
+ key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
+ key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
+ key_rwlock_global_sid_lock, key_rwlock_gtid_mode_lock,
+ key_rwlock_channel_map_lock, key_rwlock_channel_lock;
+
+extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
+extern PSI_cond_key key_BINLOG_update_cond,
+ key_COND_cache_status_changed, key_COND_manager,
+ key_COND_server_started,
+ key_item_func_sleep_cond, key_master_info_data_cond,
+ key_master_info_start_cond, key_master_info_stop_cond,
+ key_master_info_sleep_cond,
+ key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
+ key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
+ key_relay_log_info_sleep_cond, key_cond_slave_parallel_pend_jobs,
+ key_cond_slave_parallel_worker, key_cond_mts_gaq,
+ key_TABLE_SHARE_cond, key_user_level_lock_cond;
+extern PSI_cond_key key_BINLOG_COND_done;
+extern PSI_cond_key key_RELAYLOG_COND_done;
+extern PSI_cond_key key_RELAYLOG_update_cond;
+extern PSI_cond_key key_BINLOG_prep_xids_cond;
+extern PSI_cond_key key_RELAYLOG_prep_xids_cond;
+extern PSI_cond_key key_gtid_ensure_index_cond;
+extern PSI_cond_key key_COND_compress_gtid_table;
+extern PSI_cond_key key_COND_thr_lock;
+
+#ifdef HAVE_REPLICATION
+extern PSI_cond_key key_cond_slave_worker_hash;
+extern PSI_cond_key key_commit_order_manager_cond;
+#endif
+extern PSI_thread_key key_thread_bootstrap,
+ key_thread_handle_manager, key_thread_main,
+ key_thread_one_connection, key_thread_signal_hand,
+ key_thread_compress_gtid_table, key_thread_parser_service;
+extern PSI_thread_key key_thread_timer_notifier;
+
+extern PSI_file_key key_file_map;
+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_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_general_log, key_file_slow_log;
+extern PSI_file_key key_file_relaylog, key_file_relaylog_cache, key_file_relaylog_index, key_file_relaylog_index_cache;
+extern PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;
+
+void init_server_psi_keys();
+
+C_MODE_END
+
+#endif /* HAVE_PSI_INTERFACE */
+
+C_MODE_START
+
+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;
+
+C_MODE_END
+
+/*
+ MAINTAINER: Please keep this list in order, to limit merge collisions.
+ Hint: grep PSI_stage_info | sort -u
+*/
+extern PSI_stage_info stage_after_create;
+extern PSI_stage_info stage_allocating_local_table;
+extern PSI_stage_info stage_alter_inplace_prepare;
+extern PSI_stage_info stage_alter_inplace;
+extern PSI_stage_info stage_alter_inplace_commit;
+extern PSI_stage_info stage_changing_master;
+extern PSI_stage_info stage_checking_master_version;
+extern PSI_stage_info stage_checking_permissions;
+extern PSI_stage_info stage_checking_privileges_on_cached_query;
+extern PSI_stage_info stage_checking_query_cache_for_query;
+extern PSI_stage_info stage_cleaning_up;
+extern PSI_stage_info stage_closing_tables;
+extern PSI_stage_info stage_compressing_gtid_table;
+extern PSI_stage_info stage_connecting_to_master;
+extern PSI_stage_info stage_converting_heap_to_ondisk;
+extern PSI_stage_info stage_copying_to_group_table;
+extern PSI_stage_info stage_copying_to_tmp_table;
+extern PSI_stage_info stage_copy_to_tmp_table;
+extern PSI_stage_info stage_creating_sort_index;
+extern PSI_stage_info stage_creating_table;
+extern PSI_stage_info stage_creating_tmp_table;
+extern PSI_stage_info stage_deleting_from_main_table;
+extern PSI_stage_info stage_deleting_from_reference_tables;
+extern PSI_stage_info stage_discard_or_import_tablespace;
+extern PSI_stage_info stage_end;
+extern PSI_stage_info stage_executing;
+extern PSI_stage_info stage_execution_of_init_command;
+extern PSI_stage_info stage_explaining;
+extern PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog;
+extern PSI_stage_info stage_flushing_relay_log_and_master_info_repository;
+extern PSI_stage_info stage_flushing_relay_log_info_file;
+extern PSI_stage_info stage_freeing_items;
+extern PSI_stage_info stage_fulltext_initialization;
+extern PSI_stage_info stage_got_handler_lock;
+extern PSI_stage_info stage_got_old_table;
+extern PSI_stage_info stage_init;
+extern PSI_stage_info stage_insert;
+extern PSI_stage_info stage_invalidating_query_cache_entries_table;
+extern PSI_stage_info stage_invalidating_query_cache_entries_table_list;
+extern PSI_stage_info stage_killing_slave;
+extern PSI_stage_info stage_logging_slow_query;
+extern PSI_stage_info stage_making_temp_file_append_before_load_data;
+extern PSI_stage_info stage_making_temp_file_create_before_load_data;
+extern PSI_stage_info stage_manage_keys;
+extern PSI_stage_info stage_master_has_sent_all_binlog_to_slave;
+extern PSI_stage_info stage_opening_tables;
+extern PSI_stage_info stage_optimizing;
+extern PSI_stage_info stage_preparing;
+extern PSI_stage_info stage_purging_old_relay_logs;
+extern PSI_stage_info stage_query_end;
+extern PSI_stage_info stage_queueing_master_event_to_the_relay_log;
+extern PSI_stage_info stage_reading_event_from_the_relay_log;
+extern PSI_stage_info stage_registering_slave_on_master;
+extern PSI_stage_info stage_removing_duplicates;
+extern PSI_stage_info stage_removing_tmp_table;
+extern PSI_stage_info stage_rename;
+extern PSI_stage_info stage_rename_result_table;
+extern PSI_stage_info stage_requesting_binlog_dump;
+extern PSI_stage_info stage_reschedule;
+extern PSI_stage_info stage_searching_rows_for_update;
+extern PSI_stage_info stage_sending_binlog_event_to_slave;
+extern PSI_stage_info stage_sending_cached_result_to_client;
+extern PSI_stage_info stage_sending_data;
+extern PSI_stage_info stage_setup;
+extern PSI_stage_info stage_slave_has_read_all_relay_log;
+extern PSI_stage_info stage_slave_waiting_event_from_coordinator;
+extern PSI_stage_info stage_slave_waiting_for_workers_to_process_queue;
+extern PSI_stage_info stage_slave_waiting_worker_queue;
+extern PSI_stage_info stage_slave_waiting_worker_to_free_events;
+extern PSI_stage_info stage_slave_waiting_worker_to_release_partition;
+extern PSI_stage_info stage_slave_waiting_workers_to_exit;
+extern PSI_stage_info stage_sorting_for_group;
+extern PSI_stage_info stage_sorting_for_order;
+extern PSI_stage_info stage_sorting_result;
+extern PSI_stage_info stage_sql_thd_waiting_until_delay;
+extern PSI_stage_info stage_statistics;
+extern PSI_stage_info stage_storing_result_in_query_cache;
+extern PSI_stage_info stage_storing_row_into_queue;
+extern PSI_stage_info stage_system_lock;
+extern PSI_stage_info stage_update;
+extern PSI_stage_info stage_updating;
+extern PSI_stage_info stage_updating_main_table;
+extern PSI_stage_info stage_updating_reference_tables;
+extern PSI_stage_info stage_upgrading_lock;
+extern PSI_stage_info stage_user_sleep;
+extern PSI_stage_info stage_verifying_table;
+extern PSI_stage_info stage_waiting_for_gtid_to_be_committed;
+extern PSI_stage_info stage_waiting_for_handler_insert;
+extern PSI_stage_info stage_waiting_for_handler_lock;
+extern PSI_stage_info stage_waiting_for_handler_open;
+extern PSI_stage_info stage_waiting_for_insert;
+extern PSI_stage_info stage_waiting_for_master_to_send_event;
+extern PSI_stage_info stage_waiting_for_master_update;
+extern PSI_stage_info stage_waiting_for_relay_log_space;
+extern PSI_stage_info stage_waiting_for_slave_mutex_on_exit;
+extern PSI_stage_info stage_waiting_for_slave_thread_to_start;
+extern PSI_stage_info stage_waiting_for_query_cache_lock;
+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_worker_waiting_for_its_turn_to_commit;
+extern PSI_stage_info stage_worker_waiting_for_commit_parent;
+extern PSI_stage_info stage_suspending;
+extern PSI_stage_info stage_starting;
+extern PSI_stage_info stage_waiting_for_no_channel_reference;
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
+/**
+ Statement instrumentation keys (sql).
+ The last entry, at [SQLCOM_END], is for parsing errors.
+*/
+extern PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1];
+
+/**
+ Statement instrumentation keys (com).
+ The last entry, at [COM_END], is for packet errors.
+*/
+extern PSI_statement_info com_statement_info[(uint) COM_END + 1];
+
+/**
+ Statement instrumentation key for replication.
+*/
+extern PSI_statement_info stmt_info_rpl;
+
+void init_sql_statement_info();
+void init_com_statement_info();
+#endif /* HAVE_PSI_STATEMENT_INTERFACE */
+
+#ifndef _WIN32
+extern my_thread_t signal_thread;
+#endif
+
+#ifdef HAVE_OPENSSL
+extern struct st_VioSSLFd * ssl_acceptor_fd;
+#endif /* HAVE_OPENSSL */
+
+/*
+ The following variables were under INNODB_COMPABILITY_HOOKS
+ */
+extern my_bool opt_large_pages;
+extern uint opt_large_page_size;
+extern char lc_messages_dir[FN_REFLEN];
+extern char *lc_messages_dir_ptr;
+extern const char *log_error_dest;
+extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN];
+extern MYSQL_PLUGIN_IMPORT uint reg_ext_length;
+extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names;
+extern MYSQL_PLUGIN_IMPORT bool mysqld_embedded;
+
+extern long tc_heuristic_recover;
+
+extern ulong specialflag;
+extern size_t mysql_data_home_len;
+extern size_t mysql_real_data_home_len;
+extern const char *mysql_real_data_home_ptr;
+extern MYSQL_PLUGIN_IMPORT char *mysql_data_home;
+extern "C" MYSQL_PLUGIN_IMPORT char server_version[SERVER_VERSION_LENGTH];
+extern MYSQL_PLUGIN_IMPORT char mysql_real_data_home[];
+extern char mysql_unpacked_real_data_home[];
+extern MYSQL_PLUGIN_IMPORT struct system_variables global_system_variables;
+extern char default_logfile_name[FN_REFLEN];
+
+#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
+
+extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty;
+extern MYSQL_PLUGIN_IMPORT key_map key_map_full; /* Should be threaded as const */
+
+/*
+ Server mutex locks and condition variables.
+ */
+extern mysql_mutex_t
+ LOCK_item_func_sleep, LOCK_status,
+ LOCK_uuid_generator,
+ LOCK_crypt, LOCK_timezone,
+ LOCK_slave_list, LOCK_manager,
+ LOCK_global_system_variables, LOCK_user_conn, LOCK_log_throttle_qni,
+ LOCK_prepared_stmt_count, LOCK_error_messages,
+ LOCK_sql_slave_skip_counter, LOCK_slave_net_timeout,
+ LOCK_offline_mode, LOCK_default_password_lifetime;
+#ifdef HAVE_OPENSSL
+extern char* des_key_file;
+extern mysql_mutex_t LOCK_des_key_file;
+#endif
+extern mysql_mutex_t LOCK_server_started;
+extern mysql_cond_t COND_server_started;
+extern mysql_mutex_t LOCK_reset_gtid_table;
+extern mysql_mutex_t LOCK_compress_gtid_table;
+extern mysql_cond_t COND_compress_gtid_table;
+extern mysql_rwlock_t LOCK_sys_init_connect, LOCK_sys_init_slave;
+extern mysql_rwlock_t LOCK_system_variables_hash;
+extern mysql_cond_t COND_manager;
+extern int32 thread_running;
+extern mysql_mutex_t LOCK_group_replication_handler;
+
+extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
+ *opt_ssl_key, *opt_ssl_crl, *opt_ssl_crlpath, *opt_tls_version;
+
+
+extern char *opt_disabled_storage_engines;
+/**
+ only options that need special treatment in get_one_option() deserve
+ to be listed below
+*/
+enum options_mysqld
+{
+ OPT_to_set_the_start_number=256,
+ OPT_BIND_ADDRESS,
+ OPT_BINLOG_CHECKSUM,
+ OPT_BINLOG_DO_DB,
+ OPT_BINLOG_FORMAT,
+ OPT_BINLOG_MAX_FLUSH_QUEUE_TIME,
+ OPT_BINLOG_IGNORE_DB,
+ OPT_BIN_LOG,
+ OPT_BOOTSTRAP,
+ OPT_CONSOLE,
+ OPT_DEBUG_SYNC_TIMEOUT,
+ OPT_DELAY_KEY_WRITE_ALL,
+ OPT_ISAM_LOG,
+ OPT_IGNORE_DB_DIRECTORY,
+ OPT_KEY_BUFFER_SIZE,
+ OPT_KEY_CACHE_AGE_THRESHOLD,
+ OPT_KEY_CACHE_BLOCK_SIZE,
+ OPT_KEY_CACHE_DIVISION_LIMIT,
+ OPT_LC_MESSAGES_DIRECTORY,
+ OPT_LOWER_CASE_TABLE_NAMES,
+ OPT_MASTER_RETRY_COUNT,
+ OPT_MASTER_VERIFY_CHECKSUM,
+ OPT_POOL_OF_THREADS,
+ OPT_REPLICATE_DO_DB,
+ OPT_REPLICATE_DO_TABLE,
+ OPT_REPLICATE_IGNORE_DB,
+ OPT_REPLICATE_IGNORE_TABLE,
+ OPT_REPLICATE_REWRITE_DB,
+ OPT_REPLICATE_WILD_DO_TABLE,
+ OPT_REPLICATE_WILD_IGNORE_TABLE,
+ OPT_SERVER_ID,
+ OPT_SKIP_HOST_CACHE,
+ OPT_SKIP_LOCK,
+ OPT_SKIP_NEW,
+ OPT_SKIP_RESOLVE,
+ OPT_SKIP_STACK_TRACE,
+ OPT_SKIP_SYMLINKS,
+ OPT_SLAVE_SQL_VERIFY_CHECKSUM,
+ OPT_SSL_CA,
+ OPT_SSL_CAPATH,
+ OPT_SSL_CERT,
+ OPT_SSL_CIPHER,
+ OPT_TLS_VERSION,
+ OPT_SSL_KEY,
+ OPT_UPDATE_LOG,
+ OPT_WANT_CORE,
+ OPT_LOG_ERROR,
+ OPT_MAX_LONG_DATA_SIZE,
+ OPT_EARLY_PLUGIN_LOAD,
+ OPT_PLUGIN_LOAD,
+ OPT_PLUGIN_LOAD_ADD,
+ OPT_SSL_CRL,
+ OPT_SSL_CRLPATH,
+ OPT_PFS_INSTRUMENT,
+ OPT_DEFAULT_AUTH,
+ OPT_SECURE_AUTH,
+ OPT_THREAD_CACHE_SIZE,
+ OPT_HOST_CACHE_SIZE,
+ OPT_TABLE_DEFINITION_CACHE,
+ OPT_MDL_CACHE_SIZE,
+ OPT_MDL_HASH_INSTANCES,
+ OPT_SKIP_INNODB,
+ OPT_AVOID_TEMPORAL_UPGRADE,
+ OPT_SHOW_OLD_TEMPORALS,
+ OPT_ENFORCE_GTID_CONSISTENCY,
+ OPT_TRANSACTION_READ_ONLY,
+ OPT_TRANSACTION_ISOLATION
+};
+
+
+/**
+ Query type constants (usable as bitmap flags).
+*/
+enum enum_query_type
+{
+ /// Nothing specific, ordinary SQL query.
+ QT_ORDINARY= 0,
+ /// In utf8.
+ QT_TO_SYSTEM_CHARSET= (1 << 0),
+ /// Without character set introducers.
+ QT_WITHOUT_INTRODUCERS= (1 << 1),
+ /// When printing a SELECT, add its number (select_lex->number)
+ QT_SHOW_SELECT_NUMBER= (1 << 2),
+ /// Don't print a database if it's equal to the connection's database
+ QT_NO_DEFAULT_DB= (1 << 3),
+ /// When printing a derived table, don't print its expression, only alias
+ QT_DERIVED_TABLE_ONLY_ALIAS= (1 << 4),
+ /// Print in charset of Item::print() argument (typically thd->charset()).
+ QT_TO_ARGUMENT_CHARSET= (1 << 5),
+ /// Print identifiers without database's name
+ QT_NO_DB= (1 << 6),
+ /// Print identifiers without table's name
+ QT_NO_TABLE= (1 << 7),
+ /**
+ Change all Item_basic_constant to ? (used by query rewrite to compute
+ digest.) Un-resolved hints will also be printed in this format.
+ */
+ QT_NORMALIZED_FORMAT= (1 << 8),
+ /**
+ If an expression is constant, print the expression, not the value
+ it evaluates to. Should be used for error messages, so that they
+ don't reveal values.
+ */
+ QT_NO_DATA_EXPANSION= (1 << 9),
+};
+
+/* query_id */
+typedef int64 query_id_t;
+extern query_id_t global_query_id;
+
+/* increment query_id and return it. */
+inline MY_ATTRIBUTE((warn_unused_result)) query_id_t next_query_id()
+{
+ query_id_t id= my_atomic_add64(&global_query_id, 1);
+ return (id+1);
+}
+
+/*
+ TODO: Replace this with an inline function.
+ */
+#ifndef EMBEDDED_LIBRARY
+extern "C" void unireg_abort(int exit_code) MY_ATTRIBUTE((noreturn));
+#else
+extern "C" void unireg_clear(int exit_code);
+#define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0)
+#endif
+
+#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32)
+extern "C" THD *_current_thd_noinline();
+#define _current_thd() _current_thd_noinline()
+#else
+static inline THD *_current_thd(void)
+{
+ return my_thread_get_THR_THD();
+}
+#endif
+#define current_thd _current_thd()
+
+#define ER(X) ER_THD(current_thd,X)
+
+#endif /* MYSQLD_INCLUDED */
diff --git a/mysql/sql/net_serv.cpp b/mysql/sql/net_serv.cpp
new file mode 100644
index 0000000..a6bc857
--- /dev/null
+++ b/mysql/sql/net_serv.cpp
@@ -0,0 +1,1059 @@
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file
+
+ This file is the net layer API for the MySQL client/server protocol.
+
+ Write and read of logical packets to/from socket.
+
+ Writes are cached into net_buffer_length big packets.
+ Read packets are reallocated dynamicly when reading big packets.
+ Each logical packet has the following pre-info:
+ 3 byte length & 1 byte package-number.
+
+ This file needs to be written in C as it's used by the libmysql client as a
+ C file.
+*/
+
+/*
+ HFTODO this must be hidden if we don't want client capabilities in
+ embedded library
+ */
+#include <my_global.h>
+#include <mysql.h>
+#include <mysql_com.h>
+#include <mysqld_error.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <violite.h>
+#include <signal.h>
+#include <errno.h>
+#include "probes_mysql.h"
+/* key_memory_NET_buff */
+#include "mysqld.h"
+
+#include <algorithm>
+
+using std::min;
+using std::max;
+
+PSI_memory_key key_memory_NET_buff;
+PSI_memory_key key_memory_NET_compress_packet;
+
+#ifdef EMBEDDED_LIBRARY
+#undef MYSQL_SERVER
+#undef MYSQL_CLIENT
+#define MYSQL_CLIENT
+#endif /*EMBEDDED_LIBRARY */
+
+
+/*
+ The following handles the differences when this is linked between the
+ client and the server.
+
+ This gives an error if a too big packet is found.
+ The server can change this, but because the client can't normally do this
+ the client should have a bigger max_allowed_packet.
+*/
+
+#ifdef MYSQL_SERVER
+/*
+ The following variables/functions should really not be declared
+ extern, but as it's hard to include sql_class.h here, we have to
+ live with this for a while.
+*/
+extern void query_cache_insert(const char *packet, ulong length,
+ unsigned pkt_nr);
+extern void thd_increment_bytes_sent(size_t length);
+extern void thd_increment_bytes_received(size_t length);
+
+/* Additional instrumentation hooks for the server */
+#include "mysql_com_server.h"
+#endif
+
+#define VIO_SOCKET_ERROR ((size_t) -1)
+
+static my_bool net_write_buff(NET *, const uchar *, size_t);
+
+/** Init with packet info. */
+
+my_bool my_net_init(NET *net, Vio* vio)
+{
+ DBUG_ENTER("my_net_init");
+ net->vio = vio;
+ my_net_local_init(net); /* Set some limits */
+ if (!(net->buff=(uchar*) my_malloc(key_memory_NET_buff,
+ (size_t) net->max_packet+
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
+ DBUG_RETURN(1);
+ net->buff_end=net->buff+net->max_packet;
+ net->error=0; net->return_status=0;
+ net->pkt_nr=net->compress_pkt_nr=0;
+ net->write_pos=net->read_pos = net->buff;
+ net->last_error[0]=0;
+ net->compress=0; net->reading_or_writing=0;
+ net->where_b = net->remain_in_buf=0;
+ net->last_errno=0;
+ net->unused= 0;
+#ifdef MYSQL_SERVER
+ net->extension= NULL;
+#endif
+
+ if (vio)
+ {
+ /* For perl DBI/DBD. */
+ net->fd= vio_fd(vio);
+ vio_fastsend(vio);
+ }
+ DBUG_RETURN(0);
+}
+
+
+void net_end(NET *net)
+{
+ DBUG_ENTER("net_end");
+ my_free(net->buff);
+ net->buff=0;
+ DBUG_VOID_RETURN;
+}
+
+void net_claim_memory_ownership(NET *net)
+{
+ my_claim(net->buff);
+}
+
+/** Realloc the packet buffer. */
+
+my_bool net_realloc(NET *net, size_t length)
+{
+ uchar *buff;
+ size_t pkt_length;
+ DBUG_ENTER("net_realloc");
+ DBUG_PRINT("enter",("length: %lu", (ulong) length));
+
+ if (length >= net->max_packet_size)
+ {
+ DBUG_PRINT("error", ("Packet too large. Max size: %lu",
+ net->max_packet_size));
+ /* @todo: 1 and 2 codes are identical. */
+ net->error= 1;
+ net->last_errno= ER_NET_PACKET_TOO_LARGE;
+#ifdef MYSQL_SERVER
+ my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
+#endif
+ DBUG_RETURN(1);
+ }
+ pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
+ /*
+ We must allocate some extra bytes for the end 0 and to be able to
+ read big compressed blocks in
+ net_read_packet() may actually read 4 bytes depending on build flags and
+ platform.
+ */
+ if (!(buff= (uchar*) my_realloc(key_memory_NET_buff,
+ (char*) net->buff, pkt_length +
+ NET_HEADER_SIZE + COMP_HEADER_SIZE,
+ MYF(MY_WME))))
+ {
+ /* @todo: 1 and 2 codes are identical. */
+ net->error= 1;
+ net->last_errno= ER_OUT_OF_RESOURCES;
+ /* In the server the error is reported by MY_WME flag. */
+ DBUG_RETURN(1);
+ }
+ net->buff=net->write_pos=buff;
+ net->buff_end=buff+(net->max_packet= (ulong) pkt_length);
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Clear (reinitialize) the NET structure for a new command.
+
+ @remark Performs debug checking of the socket buffer to
+ ensure that the protocol sequence is correct.
+
+ @param net NET handler
+ @param check_buffer Whether to check the socket buffer.
+*/
+
+void net_clear(NET *net,
+ my_bool check_buffer MY_ATTRIBUTE((unused)))
+{
+ DBUG_ENTER("net_clear");
+
+#if !defined(EMBEDDED_LIBRARY)
+ /* Ensure the socket buffer is empty, except for an EOF (at least 1). */
+ DBUG_ASSERT(!check_buffer || (vio_pending(net->vio) <= 1));
+#endif
+
+ /* Ready for new command */
+ net->pkt_nr= net->compress_pkt_nr= 0;
+ net->write_pos= net->buff;
+
+ DBUG_VOID_RETURN;
+}
+
+
+/** Flush write_buffer if not empty. */
+
+my_bool net_flush(NET *net)
+{
+ my_bool error= 0;
+ DBUG_ENTER("net_flush");
+ if (net->buff != net->write_pos)
+ {
+ error= net_write_packet(net, net->buff,
+ (size_t) (net->write_pos - net->buff));
+ net->write_pos= net->buff;
+ }
+ /* Sync packet number if using compression */
+ if (net->compress)
+ net->pkt_nr=net->compress_pkt_nr;
+ DBUG_RETURN(error);
+}
+
+
+/**
+ Whether a I/O operation should be retried later.
+
+ @param net NET handler.
+ @param retry_count Maximum number of interrupted operations.
+
+ @retval TRUE Operation should be retried.
+ @retval FALSE Operation should not be retried. Fatal error.
+*/
+
+static my_bool
+net_should_retry(NET *net, uint *retry_count MY_ATTRIBUTE((unused)))
+{
+ my_bool retry;
+
+#ifndef MYSQL_SERVER
+ /*
+ In the client library, interrupted I/O operations are always retried.
+ Otherwise, it's either a timeout or an unrecoverable error.
+ */
+ retry= vio_should_retry(net->vio);
+#else
+ /*
+ In the server, interrupted I/O operations are retried up to a limit.
+ In this scenario, pthread_kill can be used to wake up
+ (interrupt) threads waiting for I/O.
+ */
+ retry= vio_should_retry(net->vio) && ((*retry_count)++ < net->retry_count);
+#endif
+
+ return retry;
+}
+
+
+/*****************************************************************************
+** Write something to server/client buffer
+*****************************************************************************/
+
+/**
+ Write a logical packet with packet header.
+
+ Format: Packet length (3 bytes), packet number (1 byte)
+ When compression is used, a 3 byte compression length is added.
+
+ @note If compression is used, the original packet is modified!
+*/
+
+my_bool my_net_write(NET *net, const uchar *packet, size_t len)
+{
+ uchar buff[NET_HEADER_SIZE];
+ int rc;
+
+ if (unlikely(!net->vio)) /* nowhere to write */
+ return 0;
+
+ MYSQL_NET_WRITE_START(len);
+
+ DBUG_EXECUTE_IF("simulate_net_write_failure", {
+ my_error(ER_NET_ERROR_ON_WRITE, MYF(0));
+ return 1;
+ };
+ );
+
+ /*
+ Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
+ length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
+ (The last packet may even have a length of 0)
+ */
+ while (len >= MAX_PACKET_LENGTH)
+ {
+ const ulong z_size = MAX_PACKET_LENGTH;
+ int3store(buff, z_size);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
+ net_write_buff(net, packet, z_size))
+ {
+ MYSQL_NET_WRITE_DONE(1);
+ return 1;
+ }
+ packet += z_size;
+ len-= z_size;
+ }
+ /* Write last packet */
+ int3store(buff, static_cast<uint>(len));
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net, buff, NET_HEADER_SIZE))
+ {
+ MYSQL_NET_WRITE_DONE(1);
+ return 1;
+ }
+#ifndef DEBUG_DATA_PACKETS
+ DBUG_DUMP("packet_header", buff, NET_HEADER_SIZE);
+#endif
+ rc= MY_TEST(net_write_buff(net,packet,len));
+ MYSQL_NET_WRITE_DONE(rc);
+ return rc;
+}
+
+
+/**
+ Send a command to the server.
+
+ The reason for having both header and packet is so that libmysql
+ can easy add a header to a special command (like prepared statements)
+ without having to re-alloc the string.
+
+ As the command is part of the first data packet, we have to do some data
+ juggling to put the command in there, without having to create a new
+ packet.
+
+ This function will split big packets into sub-packets if needed.
+ (Each sub packet can only be 2^24 bytes)
+
+ @param net NET handler
+ @param command Command in MySQL server (enum enum_server_command)
+ @param header Header to write after command
+ @param head_len Length of header
+ @param packet Query or parameter to query
+ @param len Length of packet
+
+ @retval
+ 0 ok
+ @retval
+ 1 error
+*/
+
+my_bool
+net_write_command(NET *net,uchar command,
+ const uchar *header, size_t head_len,
+ const uchar *packet, size_t len)
+{
+ size_t length=len+1+head_len; /* 1 extra byte for command */
+ uchar buff[NET_HEADER_SIZE+1];
+ uint header_size=NET_HEADER_SIZE+1;
+ int rc;
+ DBUG_ENTER("net_write_command");
+ DBUG_PRINT("enter",("length: %lu", (ulong) len));
+
+ MYSQL_NET_WRITE_START(length);
+
+ buff[4]=command; /* For first packet */
+
+ if (length >= MAX_PACKET_LENGTH)
+ {
+ /* Take into account that we have the command in the first header */
+ len= MAX_PACKET_LENGTH - 1 - head_len;
+ do
+ {
+ int3store(buff, MAX_PACKET_LENGTH);
+ buff[3]= (uchar) net->pkt_nr++;
+ if (net_write_buff(net, buff, header_size) ||
+ net_write_buff(net, header, head_len) ||
+ net_write_buff(net, packet, len))
+ {
+ MYSQL_NET_WRITE_DONE(1);
+ DBUG_RETURN(1);
+ }
+ packet+= len;
+ length-= MAX_PACKET_LENGTH;
+ len= MAX_PACKET_LENGTH;
+ head_len= 0;
+ header_size= NET_HEADER_SIZE;
+ } while (length >= MAX_PACKET_LENGTH);
+ len=length; /* Data left to be written */
+ }
+ int3store(buff, static_cast<uint>(length));
+ buff[3]= (uchar) net->pkt_nr++;
+ rc= MY_TEST(net_write_buff(net, buff, header_size) ||
+ (head_len && net_write_buff(net, header, head_len)) ||
+ net_write_buff(net, packet, len) || net_flush(net));
+ MYSQL_NET_WRITE_DONE(rc);
+ DBUG_RETURN(rc);
+}
+
+
+/**
+ Caching the data in a local buffer before sending it.
+
+ Fill up net->buffer and send it to the client when full.
+
+ If the rest of the to-be-sent-packet is bigger than buffer,
+ send it in one big block (to avoid copying to internal buffer).
+ If not, copy the rest of the data to the buffer and return without
+ sending data.
+
+ @param net Network handler
+ @param packet Packet to send
+ @param len Length of packet
+
+ @note
+ The cached buffer can be sent as it is with 'net_flush()'.
+ In this code we have to be careful to not send a packet longer than
+ MAX_PACKET_LENGTH to net_write_packet() if we are using the compressed
+ protocol as we store the length of the compressed packet in 3 bytes.
+
+ @retval
+ 0 ok
+ @retval
+ 1
+*/
+
+static my_bool
+net_write_buff(NET *net, const uchar *packet, size_t len)
+{
+ ulong left_length;
+ if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
+ left_length= (ulong) (MAX_PACKET_LENGTH - (net->write_pos - net->buff));
+ else
+ left_length= (ulong) (net->buff_end - net->write_pos);
+
+#ifdef DEBUG_DATA_PACKETS
+ DBUG_DUMP("data", packet, len);
+#endif
+ if (len > left_length)
+ {
+ if (net->write_pos != net->buff)
+ {
+ /* Fill up already used packet and write it */
+ memcpy(net->write_pos, packet, left_length);
+ if (net_write_packet(net, net->buff,
+ (size_t) (net->write_pos - net->buff) + left_length))
+ return 1;
+ net->write_pos= net->buff;
+ packet+= left_length;
+ len-= left_length;
+ }
+ if (net->compress)
+ {
+ /*
+ We can't have bigger packets than 16M with compression
+ Because the uncompressed length is stored in 3 bytes
+ */
+ left_length= MAX_PACKET_LENGTH;
+ while (len > left_length)
+ {
+ if (net_write_packet(net, packet, left_length))
+ return 1;
+ packet+= left_length;
+ len-= left_length;
+ }
+ }
+ if (len > net->max_packet)
+ return net_write_packet(net, packet, len);
+ /* Send out rest of the blocks as full sized blocks */
+ }
+ memcpy(net->write_pos, packet, len);
+ net->write_pos+= len;
+ return 0;
+}
+
+
+/**
+ Write a determined number of bytes to a network handler.
+
+ @param net NET handler.
+ @param buf Buffer containing the data to be written.
+ @param count The length, in bytes, of the buffer.
+
+ @return TRUE on error, FALSE on success.
+*/
+
+static my_bool
+net_write_raw_loop(NET *net, const uchar *buf, size_t count)
+{
+ unsigned int retry_count= 0;
+
+ while (count)
+ {
+ size_t sentcnt= vio_write(net->vio, buf, count);
+
+ /* VIO_SOCKET_ERROR (-1) indicates an error. */
+ if (sentcnt == VIO_SOCKET_ERROR)
+ {
+ /* A recoverable I/O error occurred? */
+ if (net_should_retry(net, &retry_count))
+ continue;
+ else
+ break;
+ }
+
+ count-= sentcnt;
+ buf+= sentcnt;
+#ifdef MYSQL_SERVER
+ thd_increment_bytes_sent(sentcnt);
+#endif
+ }
+
+ /* On failure, propagate the error code. */
+ if (count)
+ {
+ /* Socket should be closed. */
+ net->error= 2;
+
+ /* Interrupted by a timeout? */
+ if (vio_was_timeout(net->vio))
+ net->last_errno= ER_NET_WRITE_INTERRUPTED;
+ else
+ net->last_errno= ER_NET_ERROR_ON_WRITE;
+
+#ifdef MYSQL_SERVER
+ my_error(net->last_errno, MYF(0));
+#endif
+ }
+
+ return MY_TEST(count);
+}
+
+
+/**
+ Compress and encapsulate a packet into a compressed packet.
+
+ @param net NET handler.
+ @param packet The packet to compress.
+ @param[in,out] length Length of the packet.
+
+ A compressed packet header is compromised of the packet
+ length (3 bytes), packet number (1 byte) and the length
+ of the original (uncompressed) packet.
+
+ @return Pointer to the (new) compressed packet.
+*/
+
+static uchar *
+compress_packet(NET *net, const uchar *packet, size_t *length)
+{
+ uchar *compr_packet;
+ size_t compr_length;
+ const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE;
+
+ compr_packet= (uchar *) my_malloc(key_memory_NET_compress_packet,
+ *length + header_length, MYF(MY_WME));
+
+ if (compr_packet == NULL)
+ return NULL;
+
+ memcpy(compr_packet + header_length, packet, *length);
+
+ /* Compress the encapsulated packet. */
+ if (my_compress(compr_packet + header_length, length, &compr_length))
+ {
+ /*
+ If the length of the compressed packet is larger than the
+ original packet, the original packet is sent uncompressed.
+ */
+ compr_length= 0;
+ }
+
+ /* Length of the compressed (original) packet. */
+ int3store(&compr_packet[NET_HEADER_SIZE], static_cast<uint>(compr_length));
+ /* Length of this packet. */
+ int3store(compr_packet, static_cast<uint>(*length));
+ /* Packet number. */
+ compr_packet[3]= (uchar) (net->compress_pkt_nr++);
+
+ *length+= header_length;
+
+ return compr_packet;
+}
+
+
+/**
+ Write a MySQL protocol packet to the network handler.
+
+ @param net NET handler.
+ @param packet The packet to write.
+ @param length Length of the packet.
+
+ @remark The packet might be encapsulated into a compressed packet.
+
+ @return TRUE on error, FALSE on success.
+*/
+
+my_bool
+net_write_packet(NET *net, const uchar *packet, size_t length)
+{
+ my_bool res;
+ DBUG_ENTER("net_write_packet");
+
+#if defined(MYSQL_SERVER)
+ query_cache_insert((char*) packet, length, net->pkt_nr);
+#endif
+
+ /* Socket can't be used */
+ if (net->error == 2)
+ DBUG_RETURN(TRUE);
+
+ net->reading_or_writing= 2;
+
+#ifdef HAVE_COMPRESS
+ const bool do_compress= net->compress;
+ if (do_compress)
+ {
+ if ((packet= compress_packet(net, packet, &length)) == NULL)
+ {
+ net->error= 2;
+ net->last_errno= ER_OUT_OF_RESOURCES;
+ /* In the server, allocation failure raises a error. */
+ net->reading_or_writing= 0;
+ DBUG_RETURN(TRUE);
+ }
+ }
+#endif /* HAVE_COMPRESS */
+
+#ifdef DEBUG_DATA_PACKETS
+ DBUG_DUMP("data", packet, length);
+#endif
+
+ res= net_write_raw_loop(net, packet, length);
+
+#ifdef HAVE_COMPRESS
+ if (do_compress)
+ my_free((void *) packet);
+#endif
+
+ net->reading_or_writing= 0;
+
+ DBUG_RETURN(res);
+}
+
+/*****************************************************************************
+** Read something from server/clinet
+*****************************************************************************/
+
+/**
+ Read a determined number of bytes from a network handler.
+
+ @param net NET handler.
+ @param count The number of bytes to read.
+
+ @return TRUE on error, FALSE on success.
+*/
+
+static my_bool net_read_raw_loop(NET *net, size_t count)
+{
+ bool eof= false;
+ unsigned int retry_count= 0;
+ uchar *buf= net->buff + net->where_b;
+
+ while (count)
+ {
+ size_t recvcnt= vio_read(net->vio, buf, count);
+
+ /* VIO_SOCKET_ERROR (-1) indicates an error. */
+ if (recvcnt == VIO_SOCKET_ERROR)
+ {
+ /* A recoverable I/O error occurred? */
+ if (net_should_retry(net, &retry_count))
+ continue;
+ else
+ break;
+ }
+ /* Zero indicates end of file. */
+ else if (!recvcnt)
+ {
+ eof= true;
+ break;
+ }
+
+ count-= recvcnt;
+ buf+= recvcnt;
+#ifdef MYSQL_SERVER
+ thd_increment_bytes_received(recvcnt);
+#endif
+ }
+
+ /* On failure, propagate the error code. */
+ if (count)
+ {
+ /* Socket should be closed. */
+ net->error= 2;
+
+ /* Interrupted by a timeout? */
+ if (!eof && vio_was_timeout(net->vio))
+ net->last_errno= ER_NET_READ_INTERRUPTED;
+ else
+ net->last_errno= ER_NET_READ_ERROR;
+
+#ifdef MYSQL_SERVER
+ my_error(net->last_errno, MYF(0));
+#endif
+ }
+
+ return MY_TEST(count);
+}
+
+
+/**
+ Read the header of a packet. The MySQL protocol packet header
+ consists of the length, in bytes, of the payload (packet data)
+ and a serial number.
+
+ @remark The encoded length is the length of the packet payload,
+ which does not include the packet header.
+
+ @remark The serial number is used to ensure that the packets are
+ received in order. If the packet serial number does not
+ match the expected value, a error is returned.
+
+ @param net NET handler.
+
+ @return TRUE on error, FALSE on success.
+*/
+
+static my_bool net_read_packet_header(NET *net)
+{
+ uchar pkt_nr;
+ size_t count= NET_HEADER_SIZE;
+ my_bool rc;
+
+ if (net->compress)
+ count+= COMP_HEADER_SIZE;
+
+#ifdef MYSQL_SERVER
+ struct st_net_server *server_extension;
+
+ server_extension= static_cast<st_net_server*> (net->extension);
+
+ if (server_extension != NULL)
+ {
+ void *user_data= server_extension->m_user_data;
+ DBUG_ASSERT(server_extension->m_before_header != NULL);
+ DBUG_ASSERT(server_extension->m_after_header != NULL);
+
+ server_extension->m_before_header(net, user_data, count);
+ rc= net_read_raw_loop(net, count);
+ server_extension->m_after_header(net, user_data, count, rc);
+ }
+ else
+#endif
+ {
+ rc= net_read_raw_loop(net, count);
+ }
+
+ if (rc)
+ return TRUE;
+
+ DBUG_DUMP("packet_header", net->buff + net->where_b, NET_HEADER_SIZE);
+
+ pkt_nr= net->buff[net->where_b + 3];
+
+ /*
+ Verify packet serial number against the truncated packet counter.
+ The local packet counter must be truncated since its not reset.
+ */
+ if (pkt_nr != (uchar) net->pkt_nr)
+ {
+ /* Not a NET error on the client. XXX: why? */
+#if defined(MYSQL_SERVER)
+ my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
+#elif defined(EXTRA_DEBUG)
+ /*
+ We don't make noise server side, since the client is expected
+ to break the protocol for e.g. --send LOAD DATA .. LOCAL where
+ the server expects the client to send a file, but the client
+ may reply with a new command instead.
+ */
+ my_message_local(ERROR_LEVEL,
+ "packets out of order (found %u, expected %u)",
+ (uint) pkt_nr, net->pkt_nr);
+ DBUG_ASSERT(pkt_nr == net->pkt_nr);
+#endif
+ return TRUE;
+ }
+
+ net->pkt_nr++;
+
+ return FALSE;
+}
+
+
+/**
+ Read one (variable-length) MySQL protocol packet.
+ A MySQL packet consists of a header and a payload.
+
+ @remark Reads one packet to net->buff + net->where_b.
+ @remark Long packets are handled by my_net_read().
+ @remark The network buffer is expanded if necessary.
+
+ @return The length of the packet, or @packet_error on error.
+*/
+
+static size_t net_read_packet(NET *net, size_t *complen)
+{
+ size_t pkt_len, pkt_data_len;
+
+ *complen= 0;
+
+ net->reading_or_writing= 1;
+
+ /* Retrieve packet length and number. */
+ if (net_read_packet_header(net))
+ goto error;
+
+ net->compress_pkt_nr= net->pkt_nr;
+
+#ifdef HAVE_COMPRESS
+ if (net->compress)
+ {
+ /*
+ The right-hand expression
+ must match the size of the buffer allocated in net_realloc().
+ */
+ DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
+ net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE);
+
+ /*
+ If the packet is compressed then complen > 0 and contains the
+ number of bytes in the uncompressed packet.
+ */
+ *complen= uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
+ }
+#endif
+
+ /* The length of the packet that follows. */
+ pkt_len= uint3korr(net->buff+net->where_b);
+
+ /* End of big multi-packet. */
+ if (!pkt_len)
+ goto end;
+
+ pkt_data_len = max(pkt_len, *complen) + net->where_b;
+
+ /* Expand packet buffer if necessary. */
+ if ((pkt_data_len >= net->max_packet) && net_realloc(net, pkt_data_len))
+ goto error;
+
+ /* Read the packet data (payload). */
+ if (net_read_raw_loop(net, pkt_len))
+ goto error;
+
+end:
+ net->reading_or_writing= 0;
+ return pkt_len;
+
+error:
+ net->reading_or_writing= 0;
+ return packet_error;
+}
+
+
+/**
+ Read a packet from the client/server and return it without the internal
+ package header.
+
+ If the packet is the first packet of a multi-packet packet
+ (which is indicated by the length of the packet = 0xffffff) then
+ all sub packets are read and concatenated.
+
+ If the packet was compressed, its uncompressed and the length of the
+ uncompressed packet is returned.
+
+ @return
+ The function returns the length of the found packet or packet_error.
+ net->read_pos points to the read data.
+*/
+
+ulong
+my_net_read(NET *net)
+{
+ size_t len, complen;
+
+ MYSQL_NET_READ_START();
+
+#ifdef HAVE_COMPRESS
+ if (!net->compress)
+ {
+#endif
+ len= net_read_packet(net, &complen);
+ if (len == MAX_PACKET_LENGTH)
+ {
+ /* First packet of a multi-packet. Concatenate the packets */
+ ulong save_pos = net->where_b;
+ size_t total_length= 0;
+ do
+ {
+ net->where_b += len;
+ total_length += len;
+ len= net_read_packet(net, &complen);
+ } while (len == MAX_PACKET_LENGTH);
+ if (len != packet_error)
+ len+= total_length;
+ net->where_b = save_pos;
+ }
+ net->read_pos = net->buff + net->where_b;
+ if (len != packet_error)
+ net->read_pos[len]=0; /* Safeguard for mysql_use_result */
+ MYSQL_NET_READ_DONE(0, len);
+ return static_cast<ulong>(len);
+#ifdef HAVE_COMPRESS
+ }
+ else
+ {
+ /* We are using the compressed protocol */
+
+ size_t buf_length;
+ ulong start_of_packet;
+ ulong first_packet_offset;
+ uint read_length, multi_byte_packet=0;
+
+ if (net->remain_in_buf)
+ {
+ buf_length= net->buf_length; /* Data left in old packet */
+ first_packet_offset= start_of_packet= (net->buf_length -
+ net->remain_in_buf);
+ /* Restore the character that was overwritten by the end 0 */
+ net->buff[start_of_packet]= net->save_char;
+ }
+ else
+ {
+ /* reuse buffer, as there is nothing in it that we need */
+ buf_length= start_of_packet= first_packet_offset= 0;
+ }
+ for (;;)
+ {
+ size_t packet_len;
+
+ if (buf_length - start_of_packet >= NET_HEADER_SIZE)
+ {
+ read_length = uint3korr(net->buff+start_of_packet);
+ if (!read_length)
+ {
+ /* End of multi-byte packet */
+ start_of_packet += NET_HEADER_SIZE;
+ break;
+ }
+ if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
+ {
+ if (multi_byte_packet)
+ {
+ /*
+ It's never the buffer on the first loop iteration that will have
+ multi_byte_packet on.
+ Thus there shall never be a non-zero first_packet_offset here.
+ */
+ DBUG_ASSERT(first_packet_offset == 0);
+ /* Remove packet header for second packet */
+ memmove(net->buff + start_of_packet,
+ net->buff + start_of_packet + NET_HEADER_SIZE,
+ buf_length - start_of_packet - NET_HEADER_SIZE);
+ start_of_packet += read_length;
+ buf_length -= NET_HEADER_SIZE;
+ }
+ else
+ start_of_packet+= read_length + NET_HEADER_SIZE;
+
+ if (read_length != MAX_PACKET_LENGTH) /* last package */
+ {
+ multi_byte_packet= 0; /* No last zero len packet */
+ break;
+ }
+ multi_byte_packet= NET_HEADER_SIZE;
+ /* Move data down to read next data packet after current one */
+ if (first_packet_offset)
+ {
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
+ }
+ continue;
+ }
+ }
+ /* Move data down to read next data packet after current one */
+ if (first_packet_offset)
+ {
+ memmove(net->buff,net->buff+first_packet_offset,
+ buf_length-first_packet_offset);
+ buf_length-=first_packet_offset;
+ start_of_packet -= first_packet_offset;
+ first_packet_offset=0;
+ }
+
+ net->where_b=buf_length;
+ if ((packet_len= net_read_packet(net, &complen)) == packet_error)
+ {
+ MYSQL_NET_READ_DONE(1, 0);
+ return packet_error;
+ }
+ if (my_uncompress(net->buff + net->where_b, packet_len,
+ &complen))
+ {
+ net->error= 2; /* caller will close socket */
+ net->last_errno= ER_NET_UNCOMPRESS_ERROR;
+#ifdef MYSQL_SERVER
+ my_error(ER_NET_UNCOMPRESS_ERROR, MYF(0));
+#endif
+ MYSQL_NET_READ_DONE(1, 0);
+ return packet_error;
+ }
+ buf_length+= complen;
+ }
+
+ net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
+ net->buf_length= buf_length;
+ net->remain_in_buf= (ulong) (buf_length - start_of_packet);
+ len = ((ulong) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
+ multi_byte_packet);
+ net->save_char= net->read_pos[len]; /* Must be saved */
+ net->read_pos[len]=0; /* Safeguard for mysql_use_result */
+ }
+#endif /* HAVE_COMPRESS */
+ MYSQL_NET_READ_DONE(0, len);
+ return static_cast<ulong>(len);
+}
+
+
+void my_net_set_read_timeout(NET *net, uint timeout)
+{
+ DBUG_ENTER("my_net_set_read_timeout");
+ DBUG_PRINT("enter", ("timeout: %d", timeout));
+ net->read_timeout= timeout;
+ if (net->vio)
+ vio_timeout(net->vio, 0, timeout);
+ DBUG_VOID_RETURN;
+}
+
+
+void my_net_set_write_timeout(NET *net, uint timeout)
+{
+ DBUG_ENTER("my_net_set_write_timeout");
+ DBUG_PRINT("enter", ("timeout: %d", timeout));
+ net->write_timeout= timeout;
+ if (net->vio)
+ vio_timeout(net->vio, 1, timeout);
+ DBUG_VOID_RETURN;
+}
+
diff --git a/mysql/sql/sql_alloc.h b/mysql/sql/sql_alloc.h
new file mode 100644
index 0000000..629dfe1
--- /dev/null
+++ b/mysql/sql/sql_alloc.h
@@ -0,0 +1,51 @@
+#ifndef SQL_ALLOC_INCLUDED
+#define SQL_ALLOC_INCLUDED
+/* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#include "my_sys.h" // TRASH
+#include "thr_malloc.h" // alloc_root
+
+/**
+ MySQL standard memory allocator class. You have to inherit the class
+ in order to use it.
+*/
+class Sql_alloc
+{
+public:
+ static void *operator new(size_t size) throw ()
+ {
+ return sql_alloc(size);
+ }
+ static void *operator new[](size_t size) throw ()
+ {
+ return sql_alloc(size);
+ }
+ static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
+ { return alloc_root(mem_root, size); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
+ { return alloc_root(mem_root, size); }
+ static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
+ static void operator delete(void *ptr, MEM_ROOT *mem_root)
+ { /* never called */ }
+ static void operator delete[](void *ptr, MEM_ROOT *mem_root)
+ { /* never called */ }
+ static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); }
+
+ inline Sql_alloc() {}
+ inline ~Sql_alloc() {}
+};
+
+#endif // SQL_ALLOC_INCLUDED
diff --git a/mysql/sql/sql_cmd.h b/mysql/sql/sql_cmd.h
new file mode 100644
index 0000000..8656f83
--- /dev/null
+++ b/mysql/sql/sql_cmd.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file Representation of an SQL command.
+*/
+
+#ifndef SQL_CMD_INCLUDED
+#define SQL_CMD_INCLUDED
+
+#include "my_sqlcommand.h"
+#include "sql_alloc.h"
+class THD;
+
+/**
+ @class Sql_cmd - Representation of an SQL command.
+
+ This class is an interface between the parser and the runtime.
+ The parser builds the appropriate derived classes of Sql_cmd
+ to represent a SQL statement in the parsed tree.
+ The execute() method in the derived classes of Sql_cmd contain the runtime
+ implementation.
+ Note that this interface is used for SQL statements recently implemented,
+ the code for older statements tend to load the LEX structure with more
+ attributes instead.
+ Implement new statements by sub-classing Sql_cmd, as this improves
+ code modularity (see the 'big switch' in dispatch_command()), and decreases
+ the total size of the LEX structure (therefore saving memory in stored
+ programs).
+ The recommended name of a derived class of Sql_cmd is Sql_cmd_<derived>.
+
+ Notice that the Sql_cmd class should not be confused with the Statement class.
+ Statement is a class that is used to manage an SQL command or a set
+ of SQL commands. When the SQL statement text is analyzed, the parser will
+ create one or more Sql_cmd objects to represent the actual SQL commands.
+*/
+class Sql_cmd : public Sql_alloc
+{
+private:
+ Sql_cmd(const Sql_cmd &); // No copy constructor wanted
+ void operator=(Sql_cmd &); // No assignment operator wanted
+
+public:
+ /**
+ @brief Return the command code for this statement
+ */
+ virtual enum_sql_command sql_command_code() const = 0;
+
+ /**
+ Execute this SQL statement.
+ @param thd the current thread.
+ @retval false on success.
+ @retval true on error
+ */
+ virtual bool execute(THD *thd) = 0;
+
+ /**
+ Command-specific reinitialization before execution of prepared statement
+
+ @see reinit_stmt_before_use()
+
+ @note Currently this function is overloaded for INSERT/REPLACE stmts only.
+
+ @param thd Current THD.
+ */
+ virtual void cleanup(THD *thd) {}
+
+protected:
+ Sql_cmd()
+ {}
+
+ virtual ~Sql_cmd()
+ {
+ /*
+ Sql_cmd objects are allocated in thd->mem_root.
+ In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is
+ simply destroyed instead.
+ Do not rely on the destructor for any cleanup.
+ */
+ DBUG_ASSERT(FALSE);
+ }
+};
+
+#endif // SQL_CMD_INCLUDED
diff --git a/mysql/sql/thr_malloc.h b/mysql/sql/thr_malloc.h
new file mode 100644
index 0000000..6af9488
--- /dev/null
+++ b/mysql/sql/thr_malloc.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef THR_MALLOC_INCLUDED
+#define THR_MALLOC_INCLUDED
+
+#include "my_global.h"
+
+typedef struct charset_info_st CHARSET_INFO;
+typedef struct st_mem_root MEM_ROOT;
+typedef unsigned int PSI_memory_key;
+
+void init_sql_alloc(PSI_memory_key key,
+ MEM_ROOT *root, size_t block_size, size_t pre_alloc_size);
+
+void *sql_alloc(size_t);
+void *sql_calloc(size_t);
+char *sql_strdup(const char *str);
+char *sql_strmake(const char *str, size_t len);
+void *sql_memdup(const void * ptr, size_t size);
+char *sql_strmake_with_convert(const char *str, size_t arg_length,
+ const CHARSET_INFO *from_cs,
+ size_t max_res_length,
+ const CHARSET_INFO *to_cs, size_t *result_length);
+
+#endif /* THR_MALLOC_INCLUDED */