1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

Merge branch '10.2' of github.com:MariaDB/server into bb-10.2-mdev9864

This commit is contained in:
Igor Babaev
2016-08-31 10:34:21 -07:00
42 changed files with 3406 additions and 220 deletions

View File

@@ -443,7 +443,7 @@ ADD_CUSTOM_TARGET(INFO_BIN ALL
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
INSTALL_DOCUMENTATION(README CREDITS COPYING COPYING.LESSER COPYING.thirdparty
INSTALL_DOCUMENTATION(README.md CREDITS COPYING COPYING.LESSER COPYING.thirdparty
EXCEPTIONS-CLIENT COMPONENT Readme)
# MDEV-6526 these files are not installed anymore
#INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC

View File

@@ -1,3 +1,5 @@
## MariaDB: drop-in replacement for MySQL
MariaDB is designed as a drop-in replacement of MySQL(R) with more
features, new storage engines, fewer bugs, and better performance.
@@ -24,10 +26,17 @@ https://mariadb.com/kb/en/mariadb-versus-mysql-compatibility/
As MariaDB is a full replacement of MySQL, the MySQL manual at
http://dev.mysql.com/doc is generally applicable.
Help:
-----
More help is available from the Maria Discuss mailing list
https://launchpad.net/~maria-discuss
and the #maria IRC channel on Freenode.
License:
--------
***************************************************************************
NOTE:
@@ -42,7 +51,8 @@ and COPYING.thirdparty files.
***************************************************************************
IMPORTANT:
Bug Reports:
------------
Bug and/or error reports regarding MariaDB should be submitted at
http://mariadb.org/jira
@@ -53,3 +63,8 @@ The code for MariaDB, including all revision history, can be found at:
https://github.com/MariaDB/server
***************************************************************************
Code status:
------------
* [![tests status](https://secure.travis-ci.org/MariaDB/server.png?branch=10.2)](https://travis-ci.org/MariaDB/server) travis-ci.org (10.2 branch)

View File

@@ -1,2 +1,2 @@
debian/additions/innotop/changelog.innotop
README
README.md

View File

@@ -87,6 +87,16 @@ enum enum_mysql_set_option
MYSQL_OPTION_MULTI_STATEMENTS_ON,
MYSQL_OPTION_MULTI_STATEMENTS_OFF
};
enum enum_session_state_type
{
SESSION_TRACK_SYSTEM_VARIABLES,
SESSION_TRACK_SCHEMA,
SESSION_TRACK_STATE_CHANGE,
SESSION_TRACK_GTIDS,
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
SESSION_TRACK_TRANSACTION_STATE,
SESSION_TRACK_always_at_the_end
};
my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags);
void my_net_local_init(NET *net);
void net_end(NET *net);

View File

@@ -72,6 +72,14 @@
#define INDEX_COMMENT_MAXLEN 1024
#define TABLE_PARTITION_COMMENT_MAXLEN 1024
/*
Maximum length of protocol packet.
OK packet length limit also restricted to this value as any length greater
than this value will have first byte of OK packet to be 254 thus does not
provide a means to identify if this is OK or EOF packet.
*/
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
/*
USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain
username and hostname parts of the user identifier with trailing zero in
@@ -221,6 +229,14 @@ enum enum_server_command
/* Don't close the connection for a connection with expired password. */
#define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22)
/**
Capable of handling server state change information. Its a hint to the
server to include the state change information in Ok packet.
*/
#define CLIENT_SESSION_TRACK (1UL << 23)
/* Client no longer needs EOF packet */
#define CLIENT_DEPRECATE_EOF (1UL << 24)
#define CLIENT_PROGRESS_OBSOLETE (1UL << 29)
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
/*
@@ -276,6 +292,8 @@ enum enum_server_command
MARIADB_CLIENT_PROGRESS | \
CLIENT_PLUGIN_AUTH | \
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
CLIENT_SESSION_TRACK |\
CLIENT_DEPRECATE_EOF |\
CLIENT_CONNECT_ATTRS |\
MARIADB_CLIENT_COM_MULTI)
@@ -340,6 +358,11 @@ enum enum_server_command
*/
#define SERVER_STATUS_IN_TRANS_READONLY 8192
/**
This status flag, when on, implies that one of the state information has
changed on the server because of the execution of the last statement.
*/
#define SERVER_SESSION_STATE_CHANGED (1UL << 14)
/**
Server status flags that must be cleared when starting
@@ -356,7 +379,8 @@ enum enum_server_command
SERVER_QUERY_WAS_SLOW |\
SERVER_STATUS_DB_DROPPED |\
SERVER_STATUS_CURSOR_EXISTS|\
SERVER_STATUS_LAST_ROW_SENT)
SERVER_STATUS_LAST_ROW_SENT|\
SERVER_SESSION_STATE_CHANGED)
#define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */
@@ -523,6 +547,26 @@ enum enum_mysql_set_option
MYSQL_OPTION_MULTI_STATEMENTS_OFF
};
/*
Type of state change information that the server can include in the Ok
packet.
*/
enum enum_session_state_type
{
SESSION_TRACK_SYSTEM_VARIABLES, /* Session system variables */
SESSION_TRACK_SCHEMA, /* Current schema */
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
SESSION_TRACK_GTIDS,
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */
SESSION_TRACK_always_at_the_end /* must be last */
};
#define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES
#define IS_SESSION_STATE_TYPE(T) \
(((int)(T) >= SESSION_TRACK_BEGIN) && ((T) < SESSION_TRACK_always_at_the_end))
#define net_new_transaction(net) ((net)->pkt_nr=0)
#ifdef __cplusplus
@@ -641,6 +685,7 @@ my_ulonglong net_field_length_ll(uchar **packet);
my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len);
uchar *net_store_length(uchar *pkg, ulonglong length);
uchar *safe_net_store_length(uchar *pkg, size_t pkg_len, ulonglong length);
unsigned int net_length_size(ulonglong num);
#endif
#ifdef __cplusplus

View File

@@ -112,6 +112,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/item_windowfunc.cc ../sql/sql_window.cc
../sql/sql_cte.cc
../sql/temporary_tables.cc
../sql/session_tracker.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)

View File

@@ -1172,7 +1172,7 @@ bool
net_send_ok(THD *thd,
uint server_status, uint statement_warn_count,
ulonglong affected_rows, ulonglong id, const char *message,
bool unused __attribute__((unused)))
bool, bool)
{
DBUG_ENTER("emb_net_send_ok");
MYSQL_DATA *data;

View File

@@ -23,9 +23,9 @@
+ --shared-memory Enable the shared memory
+ --shared-memory-base-name=name
+ Base name of shared memory
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
--session-track-schema
Track changes to the default schema.
(Defaults to on; use --skip-session-track-schema to disable.)
@@ -1015,6 +1018,10 @@
Log slow queries to given log file. Defaults logging to
'hostname'-slow.log. Must be enabled to activate other
@@ -103,12 +103,12 @@
@@ -1387,6 +1381,8 @@
secure-auth TRUE
secure-file-priv (No default value)
server-id 0
server-id 1
+shared-memory FALSE
+shared-memory-base-name MYSQL
show-slave-auth-info FALSE
silent-startup FALSE
skip-grant-tables TRUE
session-track-schema TRUE
session-track-state-change FALSE
session-track-system-variables
@@ -1411,6 +1407,7 @@
slave-type-conversions
slow-launch-time 2

View File

@@ -906,6 +906,26 @@ The following options may be given as the first argument:
files within specified directory
--server-id=# Uniquely identifies the server instance in the community
of replication partners
--session-track-schema
Track changes to the default schema.
(Defaults to on; use --skip-session-track-schema to disable.)
--session-track-state-change
Track changes to the session state.
--session-track-system-variables=name
Track changes in registered system variables. For
compatibility with MySQL defaults this variable should be
set to "autocommit, character_set_client,
character_set_connection, character_set_results,
time_zone"
--session-track-transaction-info=name
Track changes to the transaction attributes. OFF to
disable; STATE to track just transaction state (Is there
an active transaction? Does it have any data? etc.);
CHARACTERISTICS to track transaction state and report all
statements needed to start a transaction withthe same
characteristics (isolation level, read only/read
write,snapshot - but not any work done / data modified
within the transaction).
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
@@ -1392,6 +1412,10 @@ safe-user-create FALSE
secure-auth TRUE
secure-file-priv (No default value)
server-id 1
session-track-schema TRUE
session-track-state-change FALSE
session-track-system-variables
session-track-transaction-info OFF
show-slave-auth-info FALSE
silent-startup FALSE
skip-grant-tables TRUE

View File

@@ -0,0 +1,164 @@
#
# Variable name : session_track_system_variables
# Scope : Global & Session
#
# Global - default
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
# Session - default
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# via INFORMATION_SCHEMA.GLOBAL_VARIABLES
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
VARIABLE_NAME VARIABLE_VALUE
SESSION_TRACK_SCHEMA ON
SESSION_TRACK_STATE_CHANGE OFF
SESSION_TRACK_SYSTEM_VARIABLES
SESSION_TRACK_TRANSACTION_INFO OFF
# via INFORMATION_SCHEMA.SESSION_VARIABLES
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
VARIABLE_NAME VARIABLE_VALUE
SESSION_TRACK_SCHEMA ON
SESSION_TRACK_STATE_CHANGE OFF
SESSION_TRACK_SYSTEM_VARIABLES
SESSION_TRACK_TRANSACTION_INFO OFF
SET @global_saved_tmp = @@global.session_track_system_variables;
# Altering global variable's value
SET @@global.session_track_system_variables='autocommit';
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
autocommit
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# Altering session variable's value
SET @@session.session_track_system_variables='autocommit';
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
autocommit
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit
# Variables' values in a new session.
connect con1,"127.0.0.1",root,,test,$MASTER_MYPORT,;
# Global - expect "autocommit"
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
autocommit
# Session - expect "autocommit"
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit
# Switching to the default connection.
connection default;
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
autocommit
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit
# Test if DEFAULT is working as expected.
SET @@global.session_track_system_variables = DEFAULT;
SET @@session.session_track_system_variables = DEFAULT;
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# Variables' values in a new session (con2).
connect con2,"127.0.0.1",root,,test,$MASTER_MYPORT,;
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# Altering session should not affect global.
SET @@session.session_track_system_variables = 'sql_mode';
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
sql_mode
# Variables' values in a new session (con3).
connect con3,"127.0.0.1",root,,test,$MASTER_MYPORT,;
# Altering global should not affect session.
SET @@global.session_track_system_variables = 'sql_mode';
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
sql_mode
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# Switching to the default connection.
connection default;
# Testing NULL
SET @@global.session_track_system_variables = NULL;
SET @@session.session_track_system_variables = NULL;
# Global - expect "" instead of NULL
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
NULL
# Session - expect "" instead of NULL
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# testing with duplicate entries.
SET @@global.session_track_system_variables= "time_zone";
SET @@session.session_track_system_variables= "time_zone";
SET @@global.session_track_system_variables= "sql_mode,sql_mode";
SET @@session.session_track_system_variables= "sql_mode,sql_mode";
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
sql_mode
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
sql_mode
# testing ordering
SET @@global.session_track_system_variables= "time_zone,sql_mode";
SET @@session.session_track_system_variables= "time_zone,sql_mode";
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
sql_mode,time_zone
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
sql_mode,time_zone
# special values
SET @@global.session_track_system_variables= "*";
SET @@session.session_track_system_variables= "*";
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
*
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
*
SET @@global.session_track_system_variables= "";
SET @@session.session_track_system_variables= "";
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
# Restoring the original values.
SET @@global.session_track_system_variables = @global_saved_tmp;
# End of tests.

View File

@@ -3803,6 +3803,62 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SESSION_TRACK_SCHEMA
SESSION_VALUE ON
GLOBAL_VALUE ON
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE ON
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the default schema.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME SESSION_TRACK_STATE_CHANGE
SESSION_VALUE OFF
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE SESSION
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Track changes to the session state.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES
SESSION_VALUE
GLOBAL_VALUE
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE
VARIABLE_SCOPE SESSION
VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Track changes in registered system variables. For compatibility with MySQL defaults this variable should be set to "autocommit, character_set_client, character_set_connection, character_set_results, time_zone"
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SESSION_TRACK_TRANSACTION_INFO
SESSION_VALUE OFF
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE SESSION
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Track changes to the transaction attributes. OFF to disable; STATE to track just transaction state (Is there an active transaction? Does it have any data? etc.); CHARACTERISTICS to track transaction state and report all statements needed to start a transaction withthe same characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction).
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
SESSION_VALUE NULL
GLOBAL_VALUE ON

View File

@@ -0,0 +1,129 @@
--source include/not_embedded.inc
--echo #
--echo # Variable name : session_track_system_variables
--echo # Scope : Global & Session
--echo #
--echo # Global - default
SELECT @@global.session_track_system_variables;
--echo # Session - default
SELECT @@session.session_track_system_variables;
--echo
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
--echo # via INFORMATION_SCHEMA.SESSION_VARIABLES
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
# Save the global value to be used to restore the original value.
SET @global_saved_tmp = @@global.session_track_system_variables;
--echo
--echo # Altering global variable's value
SET @@global.session_track_system_variables='autocommit';
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Altering session variable's value
SET @@session.session_track_system_variables='autocommit';
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Variables' values in a new session.
connect (con1,"127.0.0.1",root,,test,$MASTER_MYPORT,);
--echo # Global - expect "autocommit"
SELECT @@global.session_track_system_variables;
--echo
--echo # Session - expect "autocommit"
SELECT @@session.session_track_system_variables;
--echo
--echo # Switching to the default connection.
connection default;
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Test if DEFAULT is working as expected.
SET @@global.session_track_system_variables = DEFAULT;
SET @@session.session_track_system_variables = DEFAULT;
--echo
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Variables' values in a new session (con2).
connect (con2,"127.0.0.1",root,,test,$MASTER_MYPORT,);
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Altering session should not affect global.
SET @@session.session_track_system_variables = 'sql_mode';
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Variables' values in a new session (con3).
connect (con3,"127.0.0.1",root,,test,$MASTER_MYPORT,);
--echo # Altering global should not affect session.
SET @@global.session_track_system_variables = 'sql_mode';
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Switching to the default connection.
connection default;
--echo # Testing NULL
SET @@global.session_track_system_variables = NULL;
SET @@session.session_track_system_variables = NULL;
--echo # Global - expect "" instead of NULL
SELECT @@global.session_track_system_variables;
--echo # Session - expect "" instead of NULL
SELECT @@session.session_track_system_variables;
--echo # testing with duplicate entries.
# Lets first set it to some valid value.
SET @@global.session_track_system_variables= "time_zone";
SET @@session.session_track_system_variables= "time_zone";
# Now set with duplicate entries (must pass)
SET @@global.session_track_system_variables= "sql_mode,sql_mode";
SET @@session.session_track_system_variables= "sql_mode,sql_mode";
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # testing ordering
SET @@global.session_track_system_variables= "time_zone,sql_mode";
SET @@session.session_track_system_variables= "time_zone,sql_mode";
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # special values
SET @@global.session_track_system_variables= "*";
SET @@session.session_track_system_variables= "*";
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
SET @@global.session_track_system_variables= "";
SET @@session.session_track_system_variables= "";
SELECT @@global.session_track_system_variables;
SELECT @@session.session_track_system_variables;
--echo
--echo # Restoring the original values.
SET @@global.session_track_system_variables = @global_saved_tmp;
--echo # End of tests.

View File

@@ -186,3 +186,25 @@ uchar *safe_net_store_length(uchar *packet, size_t packet_len, ulonglong length)
return packet+8;
}
/**
The length of space required to store the resulting length-encoded integer
for the given number. This function can be used at places where one needs to
dynamically allocate the buffer for a given number to be stored as length-
encoded integer.
@param num [IN] the input number
@return length of buffer needed to store this number [1, 3, 4, 9].
*/
uint net_length_size(ulonglong num)
{
if (num < (ulonglong) 251LL)
return 1;
if (num < (ulonglong) 65536LL)
return 3;
if (num < (ulonglong) 16777216LL)
return 4;
return 9;
}

View File

@@ -95,7 +95,9 @@ SET (SQL_SOURCE
../sql-common/client_plugin.c
opt_range.cc opt_range.h opt_sum.cc
../sql-common/pack.c parse_file.cc password.c procedure.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
protocol.cc records.cc repl_failsafe.cc rpl_filter.cc
session_tracker.cc
set_var.cc
slave.cc sp.cc sp_cache.cc sp_head.cc sp_pcontext.cc
sp_rcontext.cc spatial.cc sql_acl.cc sql_analyse.cc sql_base.cc
sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h

View File

@@ -90,6 +90,7 @@ extern HASH open_cache;
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
/* Map the return value of thr_lock to an error from errmsg.txt */
static int thr_lock_errno_to_mysql[]=
{ 0, ER_LOCK_ABORTED, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
@@ -243,6 +244,39 @@ void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock)
}
/**
Scan array of tables for access types; update transaction tracker
accordingly.
@param thd The current thread.
@param tables An array of pointers to the tables to lock.
@param count The number of tables to lock.
*/
#ifndef EMBEDDED_LIBRARY
static void track_table_access(THD *thd, TABLE **tables, size_t count)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
while (count--)
{
TABLE *t= tables[count];
if (t)
tst->add_trx_state(thd, t->reginfo.lock_type,
t->file->has_transactions());
}
}
}
#else
#define track_table_access(A,B,C)
#endif //EMBEDDED_LIBRARY
/**
Lock tables.
@@ -280,6 +314,9 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
my_free(sql_lock);
sql_lock= 0;
}
track_table_access(thd, tables, count);
DBUG_RETURN(sql_lock);
}

View File

@@ -690,6 +690,14 @@ THD *next_global_thread(THD *thd)
}
struct system_variables global_system_variables;
/**
Following is just for options parsing, used with a difference against
global_system_variables.
TODO: something should be done to get rid of following variables
*/
const char *current_dbug_option="";
struct system_variables max_system_variables;
struct system_status_var global_status_var;
@@ -1463,7 +1471,6 @@ my_bool plugins_are_initialized= FALSE;
#ifndef DBUG_OFF
static const char* default_dbug_option;
#endif
const char *current_dbug_option="";
#ifdef HAVE_LIBWRAP
const char *libwrapName= NULL;
int allow_severity = LOG_INFO;
@@ -5278,6 +5285,17 @@ static int init_server_components()
}
plugins_are_initialized= TRUE; /* Don't separate from init function */
#ifndef EMBEDDED_LIBRARY
{
if (Session_tracker::server_boot_verify(system_charset_info))
{
sql_print_error("The variable session_track_system_variables has "
"invalid values.");
unireg_abort(1);
}
}
#endif //EMBEDDED_LIBRARY
/* we do want to exit if there are any other unknown options */
if (remaining_argc > 1)
{

View File

@@ -117,7 +117,6 @@ extern my_bool thd_net_is_killed();
#endif
#define TEST_BLOCKING 8
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
static my_bool net_write_buff(NET *, const uchar *, ulong);

View File

@@ -35,7 +35,8 @@ static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
/* Declared non-static only because of the embedded library. */
bool net_send_error_packet(THD *, uint, const char *, const char *);
/* Declared non-static only because of the embedded library. */
bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, bool);
bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *,
bool, bool);
/* Declared non-static only because of the embedded library. */
bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
#ifndef EMBEDDED_LIBRARY
@@ -197,6 +198,7 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err,
@param affected_rows Number of rows changed by statement
@param id Auto_increment id for first row (if used)
@param message Message to send to the client (Used by mysql_status)
@param is_eof this called instead of old EOF packet
@return
@retval FALSE The message was successfully sent
@@ -209,10 +211,14 @@ bool
net_send_ok(THD *thd,
uint server_status, uint statement_warn_count,
ulonglong affected_rows, ulonglong id, const char *message,
bool is_eof,
bool skip_flush)
{
NET *net= &thd->net;
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
StringBuffer<MYSQL_ERRMSG_SIZE + 10> store;
bool state_changed= false;
bool error= FALSE;
DBUG_ENTER("net_send_ok");
@@ -222,9 +228,23 @@ net_send_ok(THD *thd,
DBUG_RETURN(FALSE);
}
buff[0]=0; // No fields
pos=net_store_length(buff+1,affected_rows);
pos=net_store_length(pos, id);
/*
OK send instead of EOF still require 0xFE header, but OK packet content.
*/
if (is_eof)
{
DBUG_ASSERT(thd->client_capabilities & CLIENT_DEPRECATE_EOF);
store.q_append((char)254);
}
else
store.q_append('\0');
/* affected rows */
store.q_net_store_length(affected_rows);
/* last insert id */
store.q_net_store_length(id);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
DBUG_PRINT("info",
@@ -233,27 +253,42 @@ net_send_ok(THD *thd,
(ulong) id,
(uint) (server_status & 0xffff),
(uint) statement_warn_count));
int2store(pos, server_status);
pos+=2;
store.q_append2b(server_status);
/* We can only return up to 65535 warnings in two bytes */
uint tmp= MY_MIN(statement_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
store.q_append2b(tmp);
}
else if (net->return_status) // For 4.0 protocol
{
int2store(pos, server_status);
pos+=2;
store.q_append2b(server_status);
}
thd->get_stmt_da()->set_overwrite_status(true);
if (message && message[0])
pos= net_store_data(pos, (uchar*) message, strlen(message));
error= my_net_write(net, buff, (size_t) (pos-buff));
if (!error && !skip_flush)
state_changed=
(thd->client_capabilities & CLIENT_SESSION_TRACK) &&
(server_status & SERVER_SESSION_STATE_CHANGED);
if (state_changed || (message && message[0]))
{
DBUG_ASSERT(safe_strlen(message) <= MYSQL_ERRMSG_SIZE);
store.q_net_store_data((uchar*) safe_str(message), safe_strlen(message));
}
if (unlikely(state_changed))
{
store.set_charset(thd->variables.collation_database);
thd->session_tracker.store(thd, &store);
}
DBUG_ASSERT(store.length() <= MAX_PACKET_LENGTH);
error= my_net_write(net, (const unsigned char*)store.ptr(), store.length());
if (!error && (!skip_flush || is_eof))
error= net_flush(net);
thd->server_status&= ~SERVER_SESSION_STATE_CHANGED;
thd->get_stmt_da()->set_overwrite_status(false);
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
@@ -261,6 +296,7 @@ net_send_ok(THD *thd,
DBUG_RETURN(error);
}
static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
/**
@@ -292,6 +328,22 @@ net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
NET *net= &thd->net;
bool error= FALSE;
DBUG_ENTER("net_send_eof");
/*
Check if client understand new format packets (OK instead of EOF)
Normally end of statement reply is signaled by OK packet, but in case
of binlog dump request an EOF packet is sent instead. Also, old clients
expect EOF packet instead of OK
*/
if ((thd->client_capabilities & CLIENT_DEPRECATE_EOF) &&
(thd->get_command() != COM_BINLOG_DUMP ))
{
error= net_send_ok(thd, server_status, statement_warn_count, 0, 0, NULL,
true, false);
DBUG_RETURN(error);
}
/* Set to TRUE if no active vio, to work well in case of --init-file */
if (net->vio != 0)
{
@@ -548,7 +600,7 @@ bool Protocol::send_ok(uint server_status, uint statement_warn_count,
DBUG_ENTER("Protocol::send_ok");
const bool retval=
net_send_ok(thd, server_status, statement_warn_count,
affected_rows, last_insert_id, message, skip_flush);
affected_rows, last_insert_id, message, false, skip_flush);
DBUG_RETURN(retval);
}
@@ -562,7 +614,7 @@ bool Protocol::send_ok(uint server_status, uint statement_warn_count,
bool Protocol::send_eof(uint server_status, uint statement_warn_count)
{
DBUG_ENTER("Protocol::send_eof");
const bool retval= net_send_eof(thd, server_status, statement_warn_count);
bool retval= net_send_eof(thd, server_status, statement_warn_count);
DBUG_RETURN(retval);
}
@@ -861,6 +913,10 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
}
if (flags & SEND_EOF)
{
/* if it is new client do not send EOF packet */
if (!(thd->client_capabilities & CLIENT_DEPRECATE_EOF))
{
/*
Mark the end of meta-data result set, and store thd->server_status,
@@ -871,6 +927,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
thd->get_stmt_da()->current_statement_warn_count()))
DBUG_RETURN(1);
}
}
DBUG_RETURN(prepare_for_send(list->elements));
err:
@@ -1505,6 +1562,7 @@ bool Protocol_binary::store_time(MYSQL_TIME *tm, int decimals)
bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
{
bool ret;
if (!(thd->client_capabilities & CLIENT_PS_MULTI_RESULTS))
{
/* The client does not support OUT-parameters. */
@@ -1558,8 +1616,7 @@ bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
/* Restore THD::server_status. */
thd->server_status&= ~SERVER_PS_OUT_PARAMS;
/* Send EOF-packet. */
net_send_eof(thd, thd->server_status, 0);
ret= net_send_eof(thd, thd->server_status, 0);
/*
Reset SERVER_MORE_RESULTS_EXISTS bit, because this is the last packet
@@ -1567,5 +1624,5 @@ bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
*/
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
return FALSE;
return ret ? FALSE : TRUE;
}

1710
sql/session_tracker.cc Normal file

File diff suppressed because it is too large Load Diff

304
sql/session_tracker.h Normal file
View File

@@ -0,0 +1,304 @@
#ifndef SESSION_TRACKER_INCLUDED
#define SESSION_TRACKER_INCLUDED
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2016, MariaDB
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 */
#include "m_string.h"
#include "thr_lock.h"
#ifndef EMBEDDED_LIBRARY
/* forward declarations */
class THD;
class set_var;
class String;
enum enum_session_tracker
{
SESSION_SYSVARS_TRACKER, /* Session system variables */
CURRENT_SCHEMA_TRACKER, /* Current schema */
SESSION_STATE_CHANGE_TRACKER,
SESSION_GTIDS_TRACKER, /* Tracks GTIDs */
TRANSACTION_INFO_TRACKER, /* Transaction state */
SESSION_TRACKER_END /* must be the last */
};
/**
State_tracker
An abstract class that defines the interface for any of the server's
'session state change tracker'. A tracker, however, is a sub- class of
this class which takes care of tracking the change in value of a part-
icular session state type and thus defines various methods listed in this
interface. The change information is later serialized and transmitted to
the client through protocol's OK packet.
Tracker system variables :-
A tracker is normally mapped to a system variable. So in order to enable,
disable or modify the sub-entities of a tracker, the user needs to modify
the respective system variable either through SET command or via command
line option. As required in system variable handling, this interface also
includes two functions to help in the verification of the supplied value
(ON_UPDATE) of the tracker system variable, namely - update().
*/
class State_tracker
{
protected:
/**
Is tracking enabled for a particular session state type ?
@note: it is a cache of the corresponding thd->variables.session_track_xxx
variable
*/
bool m_enabled;
/** Has the session state type changed ? */
bool m_changed;
public:
/** Constructor */
State_tracker() : m_enabled(false), m_changed(false)
{}
/** Destructor */
virtual ~State_tracker()
{}
/** Getters */
bool is_enabled() const
{ return m_enabled; }
bool is_changed() const
{ return m_changed; }
/** Called in the constructor of THD*/
virtual bool enable(THD *thd)= 0;
/** To be invoked when the tracker's system variable is updated (ON_UPDATE).*/
virtual bool update(THD *thd, set_var *var)= 0;
/** Store changed data into the given buffer. */
virtual bool store(THD *thd, String *buf)= 0;
/** Mark the entity as changed. */
virtual void mark_as_changed(THD *thd, LEX_CSTRING *name);
};
bool sysvartrack_validate_value(THD *thd, const char *str, size_t len);
bool sysvartrack_reprint_value(THD *thd, char *str, size_t len);
bool sysvartrack_update(THD *thd, set_var *var);
size_t sysvartrack_value_len(THD *thd);
bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
/**
Session_tracker
This class holds an object each for all tracker classes and provides
methods necessary for systematic detection and generation of session
state change information.
*/
class Session_tracker
{
private:
State_tracker *m_trackers[SESSION_TRACKER_END];
/* The following two functions are private to disable copying. */
Session_tracker(Session_tracker const &other)
{
DBUG_ASSERT(FALSE);
}
Session_tracker& operator= (Session_tracker const &rhs)
{
DBUG_ASSERT(FALSE);
return *this;
}
public:
Session_tracker();
~Session_tracker()
{
deinit();
}
/* trick to make happy memory accounting system */
void deinit()
{
for (int i= 0; i < SESSION_TRACKER_END; i++)
{
if (m_trackers[i])
delete m_trackers[i];
m_trackers[i]= NULL;
}
}
void enable(THD *thd);
static bool server_boot_verify(CHARSET_INFO *char_set);
/** Returns the pointer to the tracker object for the specified tracker. */
inline State_tracker *get_tracker(enum_session_tracker tracker) const
{
return m_trackers[tracker];
}
inline void mark_as_changed(THD *thd, enum enum_session_tracker tracker,
LEX_CSTRING *data)
{
if (m_trackers[tracker]->is_enabled())
m_trackers[tracker]->mark_as_changed(thd, data);
}
void store(THD *thd, String *main_buf);
};
/*
Transaction_state_tracker
*/
/**
Transaction state (no transaction, transaction active, work attached, etc.)
*/
enum enum_tx_state {
TX_EMPTY = 0, ///< "none of the below"
TX_EXPLICIT = 1, ///< an explicit transaction is active
TX_IMPLICIT = 2, ///< an implicit transaction is active
TX_READ_TRX = 4, ///< transactional reads were done
TX_READ_UNSAFE = 8, ///< non-transaction reads were done
TX_WRITE_TRX = 16, ///< transactional writes were done
TX_WRITE_UNSAFE = 32, ///< non-transactional writes were done
TX_STMT_UNSAFE = 64, ///< "unsafe" (non-deterministic like UUID()) stmts
TX_RESULT_SET = 128, ///< result set was sent
TX_WITH_SNAPSHOT= 256, ///< WITH CONSISTENT SNAPSHOT was used
TX_LOCKED_TABLES= 512 ///< LOCK TABLES is active
};
/**
Transaction access mode
*/
enum enum_tx_read_flags {
TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.tx_read_only
TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or tx_read_only=1
TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or tx_read_only=0
};
/**
Transaction isolation level
*/
enum enum_tx_isol_level {
TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.tx_isolation
TX_ISOL_UNCOMMITTED = 1,
TX_ISOL_COMMITTED = 2,
TX_ISOL_REPEATABLE = 3,
TX_ISOL_SERIALIZABLE= 4
};
/**
Transaction tracking level
*/
enum enum_session_track_transaction_info {
TX_TRACK_NONE = 0, ///< do not send tracker items on transaction info
TX_TRACK_STATE = 1, ///< track transaction status
TX_TRACK_CHISTICS = 2 ///< track status and characteristics
};
/**
This is a tracker class that enables & manages the tracking of
current transaction info for a particular connection.
*/
class Transaction_state_tracker : public State_tracker
{
private:
/** Helper function: turn table info into table access flag */
enum_tx_state calc_trx_state(THD *thd, thr_lock_type l, bool has_trx);
public:
/** Constructor */
Transaction_state_tracker();
bool enable(THD *thd)
{ return update(thd, NULL); }
bool update(THD *thd, set_var *var);
bool store(THD *thd, String *buf);
/** Change transaction characteristics */
void set_read_flags(THD *thd, enum enum_tx_read_flags flags);
void set_isol_level(THD *thd, enum enum_tx_isol_level level);
/** Change transaction state */
void clear_trx_state(THD *thd, uint clear);
void add_trx_state(THD *thd, uint add);
void inline add_trx_state(THD *thd, thr_lock_type l, bool has_trx)
{
add_trx_state(thd, calc_trx_state(thd, l, has_trx));
}
void add_trx_state_from_thd(THD *thd);
void end_trx(THD *thd);
private:
enum enum_tx_changed {
TX_CHG_NONE = 0, ///< no changes from previous stmt
TX_CHG_STATE = 1, ///< state has changed from previous stmt
TX_CHG_CHISTICS = 2 ///< characteristics have changed from previous stmt
};
/** any trackable changes caused by this statement? */
uint tx_changed;
/** transaction state */
uint tx_curr_state, tx_reported_state;
/** r/w or r/o set? session default? */
enum enum_tx_read_flags tx_read_flags;
/** isolation level */
enum enum_tx_isol_level tx_isol_level;
void reset();
inline void update_change_flags(THD *thd)
{
tx_changed &= ~TX_CHG_STATE;
tx_changed |= (tx_curr_state != tx_reported_state) ? TX_CHG_STATE : 0;
if (tx_changed != TX_CHG_NONE)
mark_as_changed(thd, NULL);
}
};
#define TRANSACT_TRACKER(X) \
do { if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) \
{((Transaction_state_tracker *) \
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER)) \
->X; } } while(0)
#define SESSION_TRACKER_CHANGED(A,B,C) \
thd->session_tracker.mark_as_changed(A,B,C)
#else
#define TRANSACT_TRACKER(X) do{}while(0)
#define SESSION_TRACKER_CHANGED(A,B,C) do{}while(0)
#endif //EMBEDDED_LIBRARY
#endif /* SESSION_TRACKER_INCLUDED */

View File

@@ -115,6 +115,9 @@ void sys_var_end()
DBUG_VOID_RETURN;
}
static bool static_test_load= TRUE;
/**
sys_var constructor
@@ -184,6 +187,8 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
else
chain->first= this;
chain->last= this;
test_load= &static_test_load;
}
bool sys_var::update(THD *thd, set_var *var)
@@ -204,8 +209,28 @@ bool sys_var::update(THD *thd, set_var *var)
(on_update && on_update(this, thd, OPT_GLOBAL));
}
else
return session_update(thd, var) ||
{
bool ret= session_update(thd, var) ||
(on_update && on_update(this, thd, OPT_SESSION));
/*
Make sure we don't session-track variables that are not actually
part of the session. tx_isolation and and tx_read_only for example
exist as GLOBAL, SESSION, and one-shot ("for next transaction only").
*/
if ((var->type == OPT_SESSION) && (!ret))
{
SESSION_TRACKER_CHANGED(thd, SESSION_SYSVARS_TRACKER,
(LEX_CSTRING*)var->var);
/*
Here MySQL sends variable name to avoid reporting change of
the tracker itself, but we decided that it is not needed
*/
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
return ret;
}
}
uchar *sys_var::session_value_ptr(THD *thd, const LEX_STRING *base)
@@ -867,6 +892,8 @@ int set_var_user::update(THD *thd)
MYF(0));
return -1;
}
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
return 0;
}
@@ -914,7 +941,11 @@ int set_var_role::check(THD *thd)
int set_var_role::update(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
return acl_setrole(thd, role.str, access);
int res= acl_setrole(thd, role.str, access);
if (!res)
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
NULL);
return res;
#else
return 0;
#endif
@@ -968,6 +999,33 @@ int set_var_collation_client::update(THD *thd)
{
thd->update_charset(character_set_client, collation_connection,
character_set_results);
/* Mark client collation variables as changed */
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
sys_var *svar;
mysql_mutex_lock(&LOCK_plugin);
if ((svar= find_sys_var_ex(thd, "character_set_client",
sizeof("character_set_client") - 1,
false, true)))
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)svar);
if ((svar= find_sys_var_ex(thd, "character_set_results",
sizeof("character_set_results") - 1,
false, true)))
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)svar);
if ((svar= find_sys_var_ex(thd, "character_set_connection",
sizeof("character_set_connection") - 1,
false, true)))
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)svar);
mysql_mutex_unlock(&LOCK_plugin);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
thd->protocol_text.init(thd);
thd->protocol_binary.init(thd);
return 0;

View File

@@ -48,6 +48,7 @@ struct sys_var_chain
int mysql_add_sys_var_chain(sys_var *chain);
int mysql_del_sys_var_chain(sys_var *chain);
/**
A class representing one system variable - that is something
that can be accessed as @@global.variable_name or @@session.variable_name,
@@ -60,6 +61,7 @@ class sys_var: protected Value_source // for double_from_string_with_check
public:
sys_var *next;
LEX_CSTRING name;
bool *test_load;
enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023,
READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096,
NO_SET_STATEMENT=8192, AUTO_SET=16384};
@@ -240,6 +242,9 @@ protected:
uchar *global_var_ptr()
{ return ((uchar*)&global_system_variables) + offset; }
friend class Session_sysvars_tracker;
friend class Session_tracker;
};
#include "sql_plugin.h" /* SHOW_HA_ROWS, SHOW_MY_BOOL */
@@ -385,7 +390,7 @@ extern SHOW_COMP_OPTION have_openssl;
SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type);
int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond);
sys_var *find_sys_var(THD *thd, const char *str, uint length=0);
sys_var *find_sys_var(THD *thd, const char *str, size_t length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free);
#define SYSVAR_AUTOSIZE(VAR,VAL) \

View File

@@ -4064,21 +4064,21 @@ ER_LOCK_OR_ACTIVE_TRANSACTION
swe "Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion"
ukr "Не можу виконати подану команду тому, що таблиця заблокована або виконується транзакція"
ER_UNKNOWN_SYSTEM_VARIABLE
cze "Neznámá systémová proměnná '%-.64s'"
dan "Ukendt systemvariabel '%-.64s'"
nla "Onbekende systeem variabele '%-.64s'"
eng "Unknown system variable '%-.64s'"
est "Tundmatu süsteemne muutuja '%-.64s'"
fre "Variable système '%-.64s' inconnue"
ger "Unbekannte Systemvariable '%-.64s'"
ita "Variabile di sistema '%-.64s' sconosciuta"
jpn "'%-.64s' は不明なシステム変数です。"
por "Variável de sistema '%-.64s' desconhecida"
rus "Неизвестная системная переменная '%-.64s'"
serbian "Nepoznata sistemska promenljiva '%-.64s'"
spa "Desconocida variable de sistema '%-.64s'"
swe "Okänd systemvariabel: '%-.64s'"
ukr "Невідома системна змінна '%-.64s'"
cze "Neznámá systémová proměnná '%-.*s'"
dan "Ukendt systemvariabel '%-.*s'"
nla "Onbekende systeem variabele '%-.*s'"
eng "Unknown system variable '%-.*s'"
est "Tundmatu süsteemne muutuja '%-.*s'"
fre "Variable système '%-.*s' inconnue"
ger "Unbekannte Systemvariable '%-.*s'"
ita "Variabile di sistema '%-.*s' sconosciuta"
jpn "'%-.*s' は不明なシステム変数です。"
por "Variável de sistema '%-.*s' desconhecida"
rus "Неизвестная системная переменная '%-.*s'"
serbian "Nepoznata sistemska promenljiva '%-.*s'"
spa "Desconocida variable de sistema '%-.*s'"
swe "Okänd systemvariabel: '%-.*s'"
ukr "Невідома системна змінна '%-.*s'"
ER_CRASHED_ON_USAGE
cze "Tabulka '%-.192s' je označena jako porušená a měla by být opravena"
dan "Tabellen '%-.192s' er markeret med fejl og bør repareres"
@@ -7139,7 +7139,6 @@ ER_KILL_QUERY_DENIED_ERROR
ER_NO_EIS_FOR_FIELD
eng "Engine-independent statistics are not collected for column '%s'"
ukr "Незалежна від типу таблиці статистика не збирається для стовбця '%s'"
#
# Internal errors, not used
#

View File

@@ -2048,6 +2048,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
break;
}
}
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
}
/*
@@ -2977,6 +2979,18 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
reinit_stmt_before_use(thd, m_lex);
#ifndef EMBEDDED_LIBRARY
/*
If there was instruction which changed tracking state,
the result of changed tracking state send to client in OK packed.
So it changes result sent to client and probably can be different
independent on query text. So we can't cache such results.
*/
if ((thd->client_capabilities & CLIENT_SESSION_TRACK) &&
(thd->server_status & SERVER_SESSION_STATE_CHANGED))
thd->lex->safe_to_cache_query= 0;
#endif
if (open_tables)
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
@@ -3053,6 +3067,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
what is needed from the substatement gained
*/
thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table;
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
/*
Unlike for PS we should not call Item's destructors for newly created
items after execution of each instruction in stored routine. This is

View File

@@ -2093,6 +2093,9 @@ Locked_tables_list::init_locked_tables(THD *thd)
return TRUE;
}
}
TRANSACT_TRACKER(add_trx_state(thd, TX_LOCKED_TABLES));
thd->enter_locked_tables_mode(LTM_LOCK_TABLES);
return FALSE;
@@ -2133,6 +2136,8 @@ Locked_tables_list::unlock_locked_tables(THD *thd)
}
thd->leave_locked_tables_mode();
TRANSACT_TRACKER(clear_trx_state(thd, TX_LOCKED_TABLES));
DBUG_ASSERT(thd->transaction.stmt.is_empty());
close_thread_tables(thd);
@@ -4354,6 +4359,13 @@ static bool check_lock_and_start_stmt(THD *thd,
table_list->table->file->print_error(error, MYF(0));
DBUG_RETURN(1);
}
/*
Record in transaction state tracking
*/
TRANSACT_TRACKER(add_trx_state(thd, lock_type,
table_list->table->file->has_transactions()));
DBUG_RETURN(0);
}

View File

@@ -1381,6 +1381,21 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_VOID_RETURN;
}
/*
Do not store queries while tracking transaction state.
The tracker already flags queries that actually have
transaction tracker items, but this will make behavior
more straight forward.
*/
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info != TX_TRACK_NONE)
{
DBUG_PRINT("qcache", ("Do not work with transaction tracking"));
DBUG_VOID_RETURN;
}
#endif //EMBEDDED_LIBRARY
/* The following assert fails if we haven't called send_result_to_client */
DBUG_ASSERT(thd->base_query.is_alloced() ||
thd->base_query.ptr() == thd->query());
@@ -1719,6 +1734,20 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
goto err;
}
/*
Don't allow serving from Query_cache while tracking transaction
state. This is a safeguard in case an otherwise matching query
was added to the cache before tracking was turned on.
*/
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info != TX_TRACK_NONE)
{
DBUG_PRINT("qcache", ("Do not work with transaction tracking"));
goto err;
}
#endif //EMBEDDED_LIBRARY
thd->query_cache_is_applicable= 1;
sql= org_sql; sql_end= sql + query_length;

View File

@@ -1465,6 +1465,11 @@ void THD::init(void)
/* Initialize the Debug Sync Facility. See debug_sync.cc. */
debug_sync_init_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
#ifndef EMBEDDED_LIBRARY
session_tracker.enable(this);
#endif //EMBEDDED_LIBRARY
apc_target.init(&LOCK_thd_data);
DBUG_VOID_RETURN;
}
@@ -1763,6 +1768,12 @@ THD::~THD()
lf_hash_put_pins(xid_hash_pins);
/* Ensure everything is freed */
status_var.local_memory_used-= sizeof(THD);
/* trick to make happy memory accounting system */
#ifndef EMBEDDED_LIBRARY
session_tracker.deinit();
#endif //EMBEDDED_LIBRARY
if (status_var.local_memory_used != 0)
{
DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used));

View File

@@ -45,6 +45,7 @@
#include <mysql/psi/mysql_idle.h>
#include <mysql/psi/mysql_table.h>
#include <mysql_com_server.h>
#include "session_tracker.h"
extern "C"
void set_thd_stage_info(void *thd,
@@ -690,6 +691,11 @@ typedef struct system_variables
my_bool pseudo_slave_mode;
char *session_track_system_variables;
ulong session_track_transaction_info;
my_bool session_track_schema;
my_bool session_track_state_change;
} SV;
/**
@@ -4056,6 +4062,9 @@ private:
LEX_STRING invoker_host;
public:
#ifndef EMBEDDED_LIBRARY
Session_tracker session_tracker;
#endif //EMBEDDED_LIBRARY
/*
Flag, mutex and condition for a thread to wait for a signal from another
thread.
@@ -4289,6 +4298,8 @@ my_eof(THD *thd)
{
thd->set_row_count_func(-1);
thd->get_stmt_da()->set_eof_status(thd);
TRANSACT_TRACKER(add_trx_state(thd, TX_RESULT_SET));
}
#define tmp_disable_binlog(A) \

View File

@@ -1035,7 +1035,10 @@ exit:
it to 0.
*/
if (thd->db && cmp_db_names(thd->db, db) && !error)
{
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
}
my_dirend(dirp);
DBUG_RETURN(error);
}
@@ -1459,7 +1462,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
DBUG_RETURN(FALSE);
goto done;
}
else
{
@@ -1476,8 +1479,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, SELECT_ACL,
system_charset_info);
DBUG_RETURN(FALSE);
goto done;
}
/*
@@ -1564,8 +1566,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
/* The operation succeed. */
DBUG_RETURN(FALSE);
goto done;
}
else
{
@@ -1589,6 +1590,9 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
done:
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
DBUG_RETURN(FALSE);
}

View File

@@ -1476,13 +1476,16 @@ uint maria_multi_check(THD *thd, char *packet, uint packet_length)
DBUG_ENTER("maria_multi_check");
while (packet_length)
{
char *packet_start= packet;
size_t subpacket_length= net_field_length((uchar **)&packet_start);
uint length_length= packet_start - packet;
// length of command + 3 bytes where that length was stored
uint subpacket_length= (uint3korr(packet) + 3);
DBUG_PRINT("info", ("sub-packet length: %d command: %x",
subpacket_length, packet[3]));
DBUG_PRINT("info", ("sub-packet length: %ld + %d command: %x",
(ulong)subpacket_length, length_length,
packet_start[3]));
if (subpacket_length == 3 ||
subpacket_length > packet_length)
if (subpacket_length == 0 ||
(subpacket_length + length_length) > packet_length)
{
my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR),
MYF(0));
@@ -1490,8 +1493,8 @@ uint maria_multi_check(THD *thd, char *packet, uint packet_length)
}
counter++;
packet+= subpacket_length;
packet_length-= subpacket_length;
packet= packet_start + subpacket_length;
packet_length-= (subpacket_length + length_length);
}
DBUG_RETURN(counter);
}
@@ -2231,8 +2234,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
{
char *packet_start= packet;
/* We have to store next length because it will be destroyed by '\0' */
uint next_subpacket_length= uint3korr(packet);
size_t next_subpacket_length= net_field_length((uchar **)&packet_start);
uint next_length_length= packet_start - packet;
unsigned char *readbuff= net->buff;
if (net_allocate_new_packet(net, thd, MYF(0)))
@@ -2246,13 +2251,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
while (packet_length)
{
current_com++;
uint subpacket_length= next_subpacket_length + 3;
size_t subpacket_length= next_subpacket_length + next_length_length;
uint length_length= next_length_length;
if (subpacket_length < packet_length)
next_subpacket_length= uint3korr(packet + subpacket_length);
{
packet_start= packet + subpacket_length;
next_subpacket_length= net_field_length((uchar**)&packet_start);
next_length_length= packet_start - (packet + subpacket_length);
}
/* safety like in do_command() */
packet[subpacket_length]= '\0';
enum enum_server_command subcommand= fetch_command(thd, (packet + 3));
enum enum_server_command subcommand=
fetch_command(thd, (packet + length_length));
if (server_command_flags[subcommand] & CF_NO_COM_MULTI)
{
@@ -2260,8 +2271,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
goto com_multi_end;
}
if (dispatch_command(subcommand, thd, packet + (1 + 3),
subpacket_length - (1 + 3), TRUE,
if (dispatch_command(subcommand, thd, packet + (1 + length_length),
subpacket_length - (1 + length_length), TRUE,
(current_com != counter)))
{
DBUG_ASSERT(thd->is_error());
@@ -3852,6 +3863,12 @@ mysql_execute_command(THD *thd)
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
if (create_info.tmp_table())
thd->variables.option_bits|= OPTION_KEEP_LOG;
/* in case of create temp tables if @@session_track_state_change is
ON then send session state notification in OK packet */
if(create_info.options & HA_LEX_CREATE_TMP_TABLE)
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
my_ok(thd);
}
}
@@ -4608,6 +4625,13 @@ end_with_restore_list:
/* DDL and binlog write order are protected by metadata locks. */
res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table());
/* when dropping temporary tables if @@session_track_state_change is ON then
send the boolean tracker in the OK packet */
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
break;
}
case SQLCOM_SHOW_PROCESSLIST:
@@ -5419,8 +5443,7 @@ end_with_restore_list:
else
{
/* Reset the isolation level and access mode if no chaining transaction.*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
}
/* Disconnect the current client connection. */
if (tx_release)
@@ -5467,8 +5490,7 @@ end_with_restore_list:
else
{
/* Reset the isolation level and access mode if no chaining transaction.*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
}
/* Disconnect the current client connection. */
if (tx_release)
@@ -5953,8 +5975,7 @@ end_with_restore_list:
We've just done a commit, reset transaction
isolation level and access mode to the session default.
*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
my_ok(thd);
break;
}
@@ -5972,8 +5993,7 @@ end_with_restore_list:
We've just done a rollback, reset transaction
isolation level and access mode to the session default.
*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
my_ok(thd);
break;
}
@@ -6191,6 +6211,9 @@ finish:
{
thd->mdl_context.release_statement_locks();
}
TRANSACT_TRACKER(add_trx_state_from_thd(thd));
WSREP_TO_ISOLATION_END;
#ifdef WITH_WSREP

View File

@@ -269,6 +269,7 @@ struct st_bookmark
uint name_len;
int offset;
uint version;
bool loaded;
char key[1];
};
@@ -1175,6 +1176,13 @@ err:
DBUG_RETURN(errs > 0 || oks + dupes == 0);
}
static void plugin_variables_deinit(struct st_plugin_int *plugin)
{
for (sys_var *var= plugin->system_vars; var; var= var->next)
(*var->test_load)= FALSE;
mysql_del_sys_var_chain(plugin->system_vars);
}
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
{
@@ -1226,8 +1234,7 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
if (ref_check && plugin->ref_count)
sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
plugin->name.str, plugin->ref_count);
mysql_del_sys_var_chain(plugin->system_vars);
plugin_variables_deinit(plugin);
}
static void plugin_del(struct st_plugin_int *plugin)
@@ -1447,7 +1454,7 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin,
err:
if (ret)
mysql_del_sys_var_chain(plugin->system_vars);
plugin_variables_deinit(plugin);
mysql_mutex_lock(&LOCK_plugin);
plugin->state= state;
@@ -2780,14 +2787,16 @@ static void update_func_double(THD *thd, struct st_mysql_sys_var *var,
System Variables support
****************************************************************************/
sys_var *find_sys_var(THD *thd, const char *str, uint length)
sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
bool throw_error, bool locked)
{
sys_var *var;
sys_var_pluginvar *pi= NULL;
plugin_ref plugin;
DBUG_ENTER("find_sys_var");
DBUG_ENTER("find_sys_var_ex");
DBUG_PRINT("enter", ("var '%.*s'", (int)length, str));
if (!locked)
mysql_mutex_lock(&LOCK_plugin);
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
if ((var= intern_find_sys_var(str, length)) &&
@@ -2807,14 +2816,20 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length)
}
else
mysql_rwlock_unlock(&LOCK_system_variables_hash);
if (!locked)
mysql_mutex_unlock(&LOCK_plugin);
if (!var)
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
if (!throw_error && !var)
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (int)length, (char*) str);
DBUG_RETURN(var);
}
sys_var *find_sys_var(THD *thd, const char *str, size_t length)
{
return find_sys_var_ex(thd, str, length, false, false);
}
/*
called by register_var, construct_options and test_plugin_options.
Returns the 'bookmark' for the named variable.
@@ -3940,6 +3955,14 @@ my_bool mark_changed(int, const struct my_option *opt, char *)
return 0;
}
/**
It is always false to mark global plugin variable unloaded just to be
safe because we have no way now to know truth about them.
TODO: make correct mechanism for global plugin variables
*/
static bool static_unload= FALSE;
/**
Create and register system variables supplied from the plugin and
assigns initial values from corresponding command line arguments.
@@ -4017,9 +4040,13 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
tmp_backup[tmp->nbackups++].save(&o->name);
if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
{
varname= var->key + 1;
var->loaded= TRUE;
}
else
{
var= NULL;
len= tmp->name.length + strlen(o->name) + 2;
varname= (char*) alloc_root(mem_root, len);
strxmov(varname, tmp->name.str, "-", o->name, NullS);
@@ -4027,6 +4054,9 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
convert_dash_to_underscore(varname, len-1);
}
v= new (mem_root) sys_var_pluginvar(&chain, varname, tmp, o);
v->test_load= (var ? &var->loaded : &static_unload);
DBUG_ASSERT(static_unload == FALSE);
if (!(o->flags & PLUGIN_VAR_NOCMDOPT))
{
// update app_type, used for I_S.SYSTEM_VARIABLES

View File

@@ -120,6 +120,8 @@ struct st_plugin_int
};
extern mysql_mutex_t LOCK_plugin;
/*
See intern_plugin_lock() for the explanation for the
conditionally defined plugin_ref type
@@ -190,4 +192,6 @@ extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
plugin_foreach_func *func, void *arg);
sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
bool throw_error, bool locked);
#endif

View File

@@ -2758,7 +2758,10 @@ void mysql_sql_stmt_prepare(THD *thd)
thd->stmt_map.erase(stmt);
}
else
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
my_ok(thd, 0L, 0L, "Statement prepared");
}
DBUG_VOID_RETURN;
}
@@ -3208,6 +3211,7 @@ void mysql_sql_stmt_close(THD *thd)
else
{
stmt->deallocate();
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
my_ok(thd);
}
}

View File

@@ -3212,6 +3212,132 @@ void remove_status_vars(SHOW_VAR *list)
}
/**
@brief Returns the value of a system or a status variable.
@param thd [in] The handle of the current THD.
@param variable [in] Details of the variable.
@param value_type [in] Variable type.
@param show_type [in] Variable show type.
@param charset [out] Character set of the value.
@param buff [in,out] Buffer to store the value.
(Needs to have enough memory
to hold the value of variable.)
@param length [out] Length of the value.
@return Pointer to the value buffer.
*/
const char* get_one_variable(THD *thd,
const SHOW_VAR *variable,
enum_var_type value_type, SHOW_TYPE show_type,
system_status_var *status_var,
const CHARSET_INFO **charset, char *buff,
size_t *length)
{
void *value= variable->value;
const char *pos= buff;
const char *end= buff;
if (show_type == SHOW_SYS)
{
sys_var *var= (sys_var *) value;
show_type= var->show_type();
value= var->value_ptr(thd, value_type, &null_lex_str);
*charset= var->charset(thd);
}
/*
note that value may be == buff. All SHOW_xxx code below
should still work in this case
*/
switch (show_type) {
case SHOW_DOUBLE_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_DOUBLE:
/* 6 is the default precision for '%f' in sprintf() */
end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
break;
case SHOW_LONG_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_ULONG:
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_ULONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
case SHOW_HA_ROWS:
end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
break;
case SHOW_BOOL:
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_UINT:
end= int10_to_str((long) *(uint*) value, buff, 10);
break;
case SHOW_SINT:
end= int10_to_str((long) *(int*) value, buff, -10);
break;
case SHOW_SLONG:
end= int10_to_str(*(long*) value, buff, -10);
break;
case SHOW_SLONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, -10);
break;
case SHOW_HAVE:
{
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
pos= show_comp_option_name[(int) tmp];
end= strend(pos);
break;
}
case SHOW_CHAR:
{
if (!(pos= (char*)value))
pos= "";
end= strend(pos);
break;
}
case SHOW_CHAR_PTR:
{
if (!(pos= *(char**) value))
pos= "";
end= strend(pos);
break;
}
case SHOW_LEX_STRING:
{
LEX_STRING *ls=(LEX_STRING*)value;
if (!(pos= ls->str))
end= pos= "";
else
end= pos + ls->length;
break;
}
case SHOW_UNDEF:
break; // Return empty string
case SHOW_SYS: // Cannot happen
default:
DBUG_ASSERT(0);
break;
}
*length= (size_t) (end - pos);
return pos;
}
static bool show_status_array(THD *thd, const char *wild,
SHOW_VAR *variables,
enum enum_var_type scope,
@@ -3324,109 +3450,21 @@ static bool show_status_array(THD *thd, const char *wild,
name_buffer, wild))) &&
(!cond || cond->val_int()))
{
void *value=var->value;
const char *pos, *end; // We assign a lot of const's
const char *pos; // We assign a lot of const's
size_t length;
if (show_type == SHOW_SYS)
{
sys_var *var= (sys_var *) value;
show_type= var->show_type();
mysql_mutex_lock(&LOCK_global_system_variables);
value= var->value_ptr(thd, scope, &null_lex_str);
charset= var->charset(thd);
}
pos= get_one_variable(thd, var, scope, show_type, status_var,
&charset, buff, &length);
pos= end= buff;
/*
note that value may be == buff. All SHOW_xxx code below
should still work in this case
*/
switch (show_type) {
case SHOW_DOUBLE_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_DOUBLE:
/* 6 is the default precision for '%f' in sprintf() */
end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
break;
case SHOW_LONG_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_ULONG:
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG_STATUS:
value= ((char *) status_var + (intptr) value);
/* fall through */
case SHOW_ULONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
case SHOW_HA_ROWS:
end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
break;
case SHOW_BOOL:
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_UINT:
end= int10_to_str((long) *(uint*) value, buff, 10);
break;
case SHOW_SINT:
end= int10_to_str((long) *(int*) value, buff, -10);
break;
case SHOW_SLONG:
end= int10_to_str(*(long*) value, buff, -10);
break;
case SHOW_SLONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, -10);
break;
case SHOW_HAVE:
{
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
pos= show_comp_option_name[(int) tmp];
end= strend(pos);
break;
}
case SHOW_CHAR:
{
if (!(pos= (char*)value))
pos= "";
end= strend(pos);
break;
}
case SHOW_CHAR_PTR:
{
if (!(pos= *(char**) value))
pos= "";
end= strend(pos);
break;
}
case SHOW_LEX_STRING:
{
LEX_STRING *ls=(LEX_STRING*)value;
if (!(pos= ls->str))
end= pos= "";
else
end= pos + ls->length;
break;
}
case SHOW_UNDEF:
break; // Return empty string
case SHOW_SYS: // Cannot happen
default:
DBUG_ASSERT(0);
break;
}
table->field[1]->store(pos, (uint32) (end - pos), charset);
table->field[1]->store(pos, (uint32) length, charset);
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
table->field[1]->set_notnull();
if (var->type == SHOW_SYS)
if (show_type == SHOW_SYS)
mysql_mutex_unlock(&LOCK_global_system_variables);
if (schema_table_store_record(thd, table))
{
res= TRUE;

View File

@@ -131,6 +131,12 @@ bool get_schema_tables_result(JOIN *join,
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list);
const char* get_one_variable(THD *thd, const SHOW_VAR *variable,
enum_var_type value_type, SHOW_TYPE show_type,
system_status_var *status_var,
const CHARSET_INFO **charset, char *buff,
size_t *length);
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
THD *find_thread_by_id(longlong id, bool query_id= false);

View File

@@ -1,4 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2016, MariaDB
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
@@ -1157,3 +1158,18 @@ uint convert_to_printable(char *to, size_t to_len,
*t= '\0';
return t - to;
}
void String::q_net_store_length(ulonglong length)
{
DBUG_ASSERT(Alloced_length >= (str_length + net_length_size(length)));
char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length);
str_length= pos - Ptr;
}
void String::q_net_store_data(const uchar *from, size_t length)
{
DBUG_ASSERT(Alloced_length >= (str_length + length +
net_length_size(length)));
q_net_store_length(length);
q_append((const char *)from, length);
}

View File

@@ -359,7 +359,9 @@ public:
if (ALIGN_SIZE(arg_length+1) < Alloced_length)
{
char *new_ptr;
if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0))))
if (!(new_ptr=(char*)
my_realloc(Ptr, arg_length,MYF((thread_specific ?
MY_THREAD_SPECIFIC : 0)))))
{
Alloced_length = 0;
real_alloc(arg_length);
@@ -495,6 +497,11 @@ public:
{
Ptr[str_length++] = c;
}
void q_append2b(const uint32 n)
{
int2store(Ptr + str_length, n);
str_length += 2;
}
void q_append(const uint32 n)
{
int4store(Ptr + str_length, n);
@@ -559,6 +566,7 @@ public:
return Ptr+ old_length; /* Area to use */
}
inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
{
uint32 new_length= arg_length + str_length;
@@ -623,6 +631,8 @@ public:
{
return !sortcmp(this, other, cs);
}
void q_net_store_length(ulonglong length);
void q_net_store_data(const uchar *from, size_t length);
};

View File

@@ -55,6 +55,7 @@
#include "transaction.h"
#include "sql_audit.h"
#ifdef __WIN__
#include <io.h>
#endif
@@ -9228,6 +9229,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
goto err_new_table_cleanup;
}
/* in case of alter temp table send the tracker in OK packet */
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}

View File

@@ -3375,6 +3375,20 @@ bool Sys_var_tx_read_only::session_update(THD *thd, set_var *var)
{
// @see Sys_var_tx_isolation::session_update() above for the rules.
thd->tx_read_only= var->save_result.ulonglong_value;
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
if (var->type == OPT_DEFAULT)
tst->set_read_flags(thd,
thd->tx_read_only ? TX_READ_ONLY : TX_READ_WRITE);
else
tst->set_read_flags(thd, TX_READ_INHERIT);
}
#endif //EMBEDDED_LIBRARY
}
return false;
}
@@ -5386,3 +5400,78 @@ static Sys_var_ulong Sys_log_tc_size(
DEFAULT(my_getpagesize() * 6),
BLOCK_SIZE(my_getpagesize()));
#endif
#ifndef EMBEDDED_LIBRARY
static Sys_var_sesvartrack Sys_track_session_sys_vars(
"session_track_system_variables",
"Track changes in registered system variables. "
"For compatibility with MySQL defaults this variable should be set to "
"\"autocommit, character_set_client, character_set_connection, "
"character_set_results, time_zone\"",
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
DEFAULT(""),
NO_MUTEX_GUARD);
static bool update_session_track_schema(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_schema");
DBUG_RETURN(thd->session_tracker.get_tracker(CURRENT_SCHEMA_TRACKER)->
update(thd, NULL));
}
static Sys_var_mybool Sys_session_track_schema(
"session_track_schema",
"Track changes to the default schema.",
SESSION_VAR(session_track_schema),
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0),
ON_UPDATE(update_session_track_schema));
static bool update_session_track_tx_info(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_tx_info");
DBUG_RETURN(thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER)->
update(thd, NULL));
}
static const char *session_track_transaction_info_names[]=
{ "OFF", "STATE", "CHARACTERISTICS", NullS };
static Sys_var_enum Sys_session_track_transaction_info(
"session_track_transaction_info",
"Track changes to the transaction attributes. OFF to disable; "
"STATE to track just transaction state (Is there an active transaction? "
"Does it have any data? etc.); CHARACTERISTICS to track transaction "
"state and report all statements needed to start a transaction with"
"the same characteristics (isolation level, read only/read write,"
"snapshot - but not any work done / data modified within the "
"transaction).",
SESSION_VAR(session_track_transaction_info),
CMD_LINE(REQUIRED_ARG), session_track_transaction_info_names,
DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_session_track_tx_info));
static bool update_session_track_state_change(sys_var *self, THD *thd,
enum_var_type type)
{
DBUG_ENTER("update_session_track_state_change");
DBUG_RETURN(thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->
update(thd, NULL));
}
static Sys_var_mybool Sys_session_track_state_change(
"session_track_state_change",
"Track changes to the session state.",
SESSION_VAR(session_track_state_change),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0),
ON_UPDATE(update_session_track_state_change));
#endif //EMBEDDED_LIBRARY

View File

@@ -438,10 +438,10 @@ public:
does not destroy individual members of SV, there's no way to free
allocated string variables for every thread.
*/
class Sys_var_charptr: public sys_var
class Sys_var_charptr_base: public sys_var
{
public:
Sys_var_charptr(const char *name_arg,
Sys_var_charptr_base(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off, size_t size,
CMD_LINE getopt,
enum charset_enum is_os_charset_arg,
@@ -463,8 +463,6 @@ public:
*/
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
global_var(const char*)= def_val;
SYSVAR_ASSERT(scope() == GLOBAL);
SYSVAR_ASSERT(size == sizeof(char *));
}
void cleanup()
{
@@ -503,31 +501,35 @@ public:
}
bool do_check(THD *thd, set_var *var)
{ return do_string_check(thd, var, charset(thd)); }
bool session_update(THD *thd, set_var *var)
{
DBUG_ASSERT(FALSE);
return true;
}
bool global_update(THD *thd, set_var *var)
bool session_update(THD *thd, set_var *var)= 0;
char *global_update_prepare(THD *thd, set_var *var)
{
char *new_val, *ptr= var->save_result.string_value.str;
size_t len=var->save_result.string_value.length;
if (ptr)
{
new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
if (!new_val) return true;
if (!new_val) return 0;
new_val[len]=0;
}
else
new_val= 0;
return new_val;
}
void global_update_finish(char *new_val)
{
if (flags & ALLOCATED)
my_free(global_var(char*));
flags|= ALLOCATED;
global_var(char*)= new_val;
return false;
}
void session_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); }
bool global_update(THD *thd, set_var *var)
{
char *new_val= global_update_prepare(thd, var);
global_update_finish(new_val);
return (new_val == 0 && var->save_result.string_value.str != 0);
}
void session_save_default(THD *thd, set_var *var)= 0;
void global_save_default(THD *thd, set_var *var)
{
char *ptr= (char*)(intptr)option.def_value;
@@ -536,6 +538,104 @@ public:
}
};
class Sys_var_charptr: public Sys_var_charptr_base
{
public:
Sys_var_charptr(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off, size_t size,
CMD_LINE getopt,
enum charset_enum is_os_charset_arg,
const char *def_val, PolyLock *lock=0,
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
const char *substitute=0) :
Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt,
is_os_charset_arg, def_val, lock, binlog_status_arg,
on_check_func, on_update_func, substitute)
{
SYSVAR_ASSERT(scope() == GLOBAL);
SYSVAR_ASSERT(size == sizeof(char *));
}
bool session_update(THD *thd, set_var *var)
{
DBUG_ASSERT(FALSE);
return true;
}
void session_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); }
};
#ifndef EMBEDDED_LIBRARY
class Sys_var_sesvartrack: public Sys_var_charptr_base
{
public:
Sys_var_sesvartrack(const char *name_arg,
const char *comment,
CMD_LINE getopt,
enum charset_enum is_os_charset_arg,
const char *def_val, PolyLock *lock) :
Sys_var_charptr_base(name_arg, comment,
SESSION_VAR(session_track_system_variables),
getopt, is_os_charset_arg, def_val, lock,
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
{}
bool do_check(THD *thd, set_var *var)
{
if (Sys_var_charptr_base::do_check(thd, var) ||
sysvartrack_validate_value(thd, var->save_result.string_value.str,
var->save_result.string_value.length))
return TRUE;
return FALSE;
}
bool global_update(THD *thd, set_var *var)
{
char *new_val= global_update_prepare(thd, var);
if (new_val)
{
if (sysvartrack_reprint_value(thd, new_val,
var->save_result.string_value.length))
new_val= 0;
}
global_update_finish(new_val);
return (new_val == 0 && var->save_result.string_value.str != 0);
}
bool session_update(THD *thd, set_var *var)
{
return sysvartrack_update(thd, var);
}
void session_save_default(THD *thd, set_var *var)
{
var->save_result.string_value.str= global_var(char*);
var->save_result.string_value.length=
strlen(var->save_result.string_value.str);
/* parse and feel list with default values */
if (thd)
{
bool res=
sysvartrack_validate_value(thd,
var->save_result.string_value.str,
var->save_result.string_value.length);
DBUG_ASSERT(res == 0);
}
}
uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
{
DBUG_ASSERT(thd != NULL);
size_t len= sysvartrack_value_len(thd);
char *res= (char *)thd->alloc(len + sizeof(char *));
if (res)
{
char *buf= res + sizeof(char *);
*((char**) res)= buf;
sysvartrack_value_construct(thd, buf, len);
}
return (uchar *)res;
}
};
#endif //EMBEDDED_LIBRARY
class Sys_var_proxy_user: public sys_var
{
@@ -1978,7 +2078,47 @@ public:
if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var))
return TRUE;
if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction())
{
#ifndef EMBEDDED_LIBRARY
Transaction_state_tracker *tst= NULL;
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
#endif //EMBEDDED_LIBRARY
thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value;
#ifndef EMBEDDED_LIBRARY
if (var->type == OPT_DEFAULT)
{
enum enum_tx_isol_level l;
switch (thd->tx_isolation) {
case ISO_READ_UNCOMMITTED:
l= TX_ISOL_UNCOMMITTED;
break;
case ISO_READ_COMMITTED:
l= TX_ISOL_COMMITTED;
break;
case ISO_REPEATABLE_READ:
l= TX_ISOL_REPEATABLE;
break;
case ISO_SERIALIZABLE:
l= TX_ISOL_SERIALIZABLE;
break;
default:
DBUG_ASSERT(0);
return TRUE;
}
if (tst)
tst->set_isol_level(thd, l);
}
else if (tst)
{
tst->set_isol_level(thd, TX_ISOL_INHERIT);
}
#endif //EMBEDDED_LIBRARY
}
return FALSE;
}
};

View File

@@ -25,6 +25,43 @@
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_acl.h"
#ifndef EMBEDDED_LIBRARY
/**
Helper: Tell tracker (if any) that transaction ended.
*/
static void trans_track_end_trx(THD *thd)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
((Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER))->end_trx(thd);
}
}
/**
Helper: transaction ended, SET TRANSACTION one-shot variables
revert to session values. Let the transaction state tracker know.
*/
void trans_reset_one_shot_chistics(THD *thd)
{
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
{
Transaction_state_tracker *tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
tst->set_read_flags(thd, TX_READ_INHERIT);
tst->set_isol_level(thd, TX_ISOL_INHERIT);
}
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
}
#else
#define trans_track_end_trx(A) do{}while(0)
#endif //EMBEDDED_LIBRARY
/* Conditions under which the transaction state must not change. */
static bool trans_check(THD *thd)
{
@@ -125,11 +162,20 @@ static bool xa_trans_force_rollback(THD *thd)
bool trans_begin(THD *thd, uint flags)
{
int res= FALSE;
#ifndef EMBEDDED_LIBRARY
Transaction_state_tracker *tst= NULL;
#endif //EMBEDDED_LIBRARY
DBUG_ENTER("trans_begin");
if (trans_check(thd))
DBUG_RETURN(TRUE);
#ifndef EMBEDDED_LIBRARY
if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
tst= (Transaction_state_tracker *)
thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
#endif //EMBEDDED_LIBRARY
thd->locked_tables_list.unlock_locked_tables(thd);
DBUG_ASSERT(!thd->locked_tables_mode);
@@ -172,7 +218,13 @@ bool trans_begin(THD *thd, uint flags)
DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) &&
(flags & MYSQL_START_TRANS_OPT_READ_WRITE)));
if (flags & MYSQL_START_TRANS_OPT_READ_ONLY)
{
thd->tx_read_only= true;
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->set_read_flags(thd, TX_READ_ONLY);
#endif //EMBEDDED_LIBRARY
}
else if (flags & MYSQL_START_TRANS_OPT_READ_WRITE)
{
/*
@@ -189,6 +241,14 @@ bool trans_begin(THD *thd, uint flags)
DBUG_RETURN(true);
}
thd->tx_read_only= false;
/*
This flags that tx_read_only was set explicitly, rather than
just from the session's default.
*/
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->set_read_flags(thd, TX_READ_WRITE);
#endif //EMBEDDED_LIBRARY
}
#ifdef WITH_WSREP
@@ -203,9 +263,20 @@ bool trans_begin(THD *thd, uint flags)
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
DBUG_PRINT("info", ("setting SERVER_STATUS_IN_TRANS"));
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->add_trx_state(thd, TX_EXPLICIT);
#endif //EMBEDDED_LIBRARY
/* ha_start_consistent_snapshot() relies on OPTION_BEGIN flag set. */
if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
{
#ifndef EMBEDDED_LIBRARY
if (tst)
tst->add_trx_state(thd, TX_WITH_SNAPSHOT);
#endif //EMBEDDED_LIBRARY
res= ha_start_consistent_snapshot(thd);
}
DBUG_RETURN(MY_TEST(res));
}
@@ -255,6 +326,8 @@ bool trans_commit(THD *thd)
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->lex->start_transaction_opt= 0;
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@@ -308,8 +381,9 @@ bool trans_commit_implicit(THD *thd)
@@session.completion_type since it's documented
to not have any effect on implicit commit.
*/
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
trans_track_end_trx(thd);
DBUG_RETURN(res);
}
@@ -349,6 +423,8 @@ bool trans_rollback(THD *thd)
thd->transaction.all.m_unsafe_rollback_flags&= ~THD_TRANS::DID_WAIT;
thd->lex->start_transaction_opt= 0;
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@@ -396,6 +472,8 @@ bool trans_rollback_implicit(THD *thd)
/* Rollback should clear transaction_rollback_request flag. */
DBUG_ASSERT(! thd->transaction_rollback_request);
trans_track_end_trx(thd);
DBUG_RETURN(MY_TEST(res));
}
@@ -434,8 +512,7 @@ bool trans_commit_stmt(THD *thd)
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
trans_reset_one_shot_chistics(thd);
if (WSREP_ON)
wsrep_post_commit(thd, FALSE);
}
@@ -487,10 +564,7 @@ bool trans_rollback_stmt(THD *thd)
wsrep_register_hton(thd, FALSE);
ha_rollback_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
{
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
}
trans_reset_one_shot_chistics(thd);
}
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
@@ -912,6 +986,8 @@ bool trans_xa_commit(THD *thd)
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
DBUG_RETURN(res);
}
@@ -968,5 +1044,7 @@ bool trans_xa_rollback(THD *thd)
xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
trans_track_end_trx(thd);
DBUG_RETURN(res);
}

View File

@@ -44,4 +44,10 @@ bool trans_xa_prepare(THD *thd);
bool trans_xa_commit(THD *thd);
bool trans_xa_rollback(THD *thd);
#ifndef EMBEDDED_LIBRARY
void trans_reset_one_shot_chistics(THD *thd);
#else
#define trans_reset_one_shot_chistics(A) do{}while(0)
#endif //EMBEDDED_LIBRARY
#endif /* TRANSACTION_H */