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:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
------------
|
||||
|
||||
* [](https://travis-ci.org/MariaDB/server) travis-ci.org (10.2 branch)
|
||||
2
debian/mariadb-client-10.2.docs
vendored
2
debian/mariadb-client-10.2.docs
vendored
@@ -1,2 +1,2 @@
|
||||
debian/additions/innotop/changelog.innotop
|
||||
README
|
||||
README.md
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
37
sql/lock.cc
37
sql/lock.cc
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
1710
sql/session_tracker.cc
Normal file
File diff suppressed because it is too large
Load Diff
304
sql/session_tracker.h
Normal file
304
sql/session_tracker.h
Normal 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 */
|
||||
@@ -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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
230
sql/sql_show.cc
230
sql/sql_show.cc
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
168
sql/sys_vars.ic
168
sql/sys_vars.ic
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user