Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
c8948b0d
Commit
c8948b0d
authored
Apr 15, 2016
by
Oleksandr Byelkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-8931: (server part of) session state tracking
System variables tracking
parent
e7608a78
Changes
22
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1483 additions
and
153 deletions
+1483
-153
include/mysql_com.h
include/mysql_com.h
+4
-4
mysql-test/r/mysqld--help.result
mysql-test/r/mysqld--help.result
+3
-0
mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result
...te/sys_vars/r/session_track_system_variables_basic.result
+162
-0
mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
...l-test/suite/sys_vars/r/sysvars_server_notembedded.result
+14
-0
mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test
...uite/sys_vars/t/session_track_system_variables_basic.test
+133
-0
sql/mysqld.cc
sql/mysqld.cc
+19
-1
sql/mysqld.h
sql/mysqld.h
+1
-0
sql/protocol.cc
sql/protocol.cc
+0
-1
sql/session_tracker.cc
sql/session_tracker.cc
+757
-8
sql/session_tracker.h
sql/session_tracker.h
+19
-1
sql/set_var.cc
sql/set_var.cc
+30
-1
sql/set_var.h
sql/set_var.h
+7
-0
sql/share/errmsg-utf8.txt
sql/share/errmsg-utf8.txt
+15
-15
sql/sql_class.cc
sql/sql_class.cc
+4
-0
sql/sql_class.h
sql/sql_class.h
+2
-0
sql/sql_plugin.cc
sql/sql_plugin.cc
+43
-11
sql/sql_plugin.h
sql/sql_plugin.h
+2
-0
sql/sql_show.cc
sql/sql_show.cc
+134
-96
sql/sql_show.h
sql/sql_show.h
+6
-0
sql/sql_string.h
sql/sql_string.h
+3
-1
sql/sys_vars.cc
sql/sys_vars.cc
+10
-0
sql/sys_vars.ic
sql/sys_vars.ic
+115
-14
No files found.
include/mysql_com.h
View file @
c8948b0d
mysql-test/r/mysqld--help.result
View file @
c8948b0d
...
...
@@ -908,6 +908,8 @@ The following options may be given as the first argument:
(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.
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
...
...
@@ -1392,6 +1394,7 @@ secure-file-priv (No default value)
server-id 1
session-track-schema TRUE
session-track-state-change FALSE
session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone
show-slave-auth-info FALSE
silent-startup FALSE
skip-grant-tables TRUE
...
...
mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result
0 → 100644
View file @
c8948b0d
#
# Variable name : session_track_system_variables
# Scope : Global & Session
#
# Global - default
SELECT @@global.session_track_system_variables;
@@global.session_track_system_variables
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# Session - default
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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 autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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 autocommit,character_set_client,character_set_connection,character_set_results,time_zone
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
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
SELECT @@session.session_track_system_variables;
@@session.session_track_system_variables
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
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
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
# 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.
mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
View file @
c8948b0d
...
...
@@ -3817,6 +3817,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES
SESSION_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
GLOBAL_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
VARIABLE_SCOPE SESSION
VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Track changes in registered system variables.
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 SKIP_EXTERNAL_LOCKING
SESSION_VALUE NULL
GLOBAL_VALUE ON
...
...
mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test
0 → 100644
View file @
c8948b0d
--
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
--
disable_warnings
SELECT
*
FROM
INFORMATION_SCHEMA
.
GLOBAL_VARIABLES
WHERE
VARIABLE_NAME
LIKE
'session_track%'
ORDER
BY
VARIABLE_NAME
;
--
enable_warnings
--
echo
# via INFORMATION_SCHEMA.SESSION_VARIABLES
--
disable_warnings
SELECT
*
FROM
INFORMATION_SCHEMA
.
SESSION_VARIABLES
WHERE
VARIABLE_NAME
LIKE
'session_track%'
ORDER
BY
VARIABLE_NAME
;
--
enable_warnings
# 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.
sql/mysqld.cc
View file @
c8948b0d
...
...
@@ -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 */
{
Session_tracker
session_track_system_variables_check
;
if
(
session_track_system_variables_check
.
server_boot_verify
(
system_charset_info
))
{
sql_print_error
(
"The variable session_track_system_variables has "
"invalid values."
);
unireg_abort
(
1
);
}
}
/* we do want to exit if there are any other unknown options */
if
(
remaining_argc
>
1
)
{
...
...
sql/mysqld.h
View file @
c8948b0d
...
...
@@ -135,6 +135,7 @@ extern my_bool lower_case_file_system;
extern
my_bool
opt_enable_named_pipe
,
opt_sync_frm
,
opt_allow_suspicious_udfs
;
extern
my_bool
opt_secure_auth
;
extern
const
char
*
current_dbug_option
;
extern
const
char
*
current_session_track_system_variables
;
extern
char
*
opt_secure_file_priv
;
extern
char
*
opt_secure_backup_file_priv
;
extern
size_t
opt_secure_backup_file_priv_len
;
...
...
sql/protocol.cc
View file @
c8948b0d
...
...
@@ -276,7 +276,6 @@ net_send_ok(THD *thd,
/* the info field */
if
(
state_changed
||
(
message
&&
message
[
0
]))
{
DBUG_ASSERT
(
strlen
(
message
)
<=
MYSQL_ERRMSG_SIZE
);
store
.
q_net_store_data
((
uchar
*
)
message
,
message
?
strlen
(
message
)
:
0
);
}
...
...
sql/session_tracker.cc
View file @
c8948b0d
...
...
@@ -15,6 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "sql_plugin.h"
#include "session_tracker.h"
#include "hash.h"
...
...
@@ -23,6 +24,7 @@
#include "sql_class.h"
#include "sql_show.h"
#include "sql_plugin.h"
#include "set_var.h"
class
Not_implemented_tracker
:
public
State_tracker
{
...
...
@@ -40,6 +42,182 @@ class Not_implemented_tracker : public State_tracker
};
static
my_bool
name_array_filler
(
void
*
ptr
,
void
*
data_ptr
);
/**
Session_sysvars_tracker
This is a tracker class that enables & manages the tracking of session
system variables. It internally maintains a hash of user supplied variable
references and a boolean field to store if the variable was changed by the
last statement.
*/
class
Session_sysvars_tracker
:
public
State_tracker
{
private:
struct
sysvar_node_st
{
sys_var
*
m_svar
;
bool
*
test_load
;
bool
m_changed
;
};
class
vars_list
{
private:
/**
Registered system variables. (@@session_track_system_variables)
A hash to store the name of all the system variables specified by the
user.
*/
HASH
m_registered_sysvars
;
/** Size of buffer for string representation */
size_t
buffer_length
;
myf
m_mem_flag
;
/**
If TRUE then we want to check all session variable.
*/
bool
track_all
;
void
init
()
{
my_hash_init
(
&
m_registered_sysvars
,
&
my_charset_bin
,
4
,
0
,
0
,
(
my_hash_get_key
)
sysvars_get_key
,
my_free
,
MYF
(
HASH_UNIQUE
|
((
m_mem_flag
&
MY_THREAD_SPECIFIC
)
?
HASH_THREAD_SPECIFIC
:
0
)));
}
void
free_hash
()
{
if
(
my_hash_inited
(
&
m_registered_sysvars
))
{
my_hash_free
(
&
m_registered_sysvars
);
}
}
uchar
*
search
(
const
sys_var
*
svar
)
{
return
(
my_hash_search
(
&
m_registered_sysvars
,
(
const
uchar
*
)
&
svar
,
sizeof
(
sys_var
*
)));
}
public:
vars_list
()
:
buffer_length
(
0
)
{
m_mem_flag
=
current_thd
?
MY_THREAD_SPECIFIC
:
0
;
init
();
}
size_t
get_buffer_length
()
{
DBUG_ASSERT
(
buffer_length
!=
0
);
// asked earlier then should
return
buffer_length
;
}
~
vars_list
()
{
/* free the allocated hash. */
if
(
my_hash_inited
(
&
m_registered_sysvars
))
{
my_hash_free
(
&
m_registered_sysvars
);
}
}
uchar
*
search
(
sysvar_node_st
*
node
,
const
sys_var
*
svar
)
{
uchar
*
res
;
res
=
search
(
svar
);
if
(
!
res
)
{
if
(
track_all
)
{
insert
(
node
,
svar
,
m_mem_flag
);
return
search
(
svar
);
}
}
return
res
;
}
uchar
*
operator
[](
ulong
idx
)
{
return
my_hash_element
(
&
m_registered_sysvars
,
idx
);
}
bool
insert
(
sysvar_node_st
*
node
,
const
sys_var
*
svar
,
myf
mem_flag
);
void
reset
();
void
copy
(
vars_list
*
from
,
THD
*
thd
);
bool
parse_var_list
(
THD
*
thd
,
LEX_STRING
var_list
,
bool
throw_error
,
const
CHARSET_INFO
*
char_set
,
bool
session_created
);
bool
construct_var_list
(
char
*
buf
,
size_t
buf_len
);
};
/**
Two objects of vars_list type are maintained to manage
various operations.
*/
vars_list
*
orig_list
,
*
tool_list
;
public:
Session_sysvars_tracker
()
{
orig_list
=
new
(
std
::
nothrow
)
vars_list
();
tool_list
=
new
(
std
::
nothrow
)
vars_list
();
}
~
Session_sysvars_tracker
()
{
if
(
orig_list
)
delete
orig_list
;
if
(
tool_list
)
delete
tool_list
;
}
size_t
get_buffer_length
()
{
return
orig_list
->
get_buffer_length
();
}
bool
construct_var_list
(
char
*
buf
,
size_t
buf_len
)
{
return
orig_list
->
construct_var_list
(
buf
,
buf_len
);
}
/**
Method used to check the validity of string provided
for session_track_system_variables during the server
startup.
*/
static
bool
server_init_check
(
THD
*
thd
,
const
CHARSET_INFO
*
char_set
,
LEX_STRING
var_list
)
{
vars_list
dummy
;
bool
result
;
result
=
dummy
.
parse_var_list
(
thd
,
var_list
,
false
,
char_set
,
false
);
return
result
;
}
static
bool
server_init_process
(
THD
*
thd
,
const
CHARSET_INFO
*
char_set
,
LEX_STRING
var_list
)
{
vars_list
dummy
;
bool
result
;
result
=
dummy
.
parse_var_list
(
thd
,
var_list
,
false
,
char_set
,
false
);
if
(
!
result
)
dummy
.
construct_var_list
(
var_list
.
str
,
var_list
.
length
+
1
);
return
result
;
}
void
reset
();
bool
enable
(
THD
*
thd
);
bool
check
(
THD
*
thd
,
set_var
*
var
);
bool
check_str
(
THD
*
thd
,
LEX_STRING
val
);
bool
update
(
THD
*
thd
);
bool
store
(
THD
*
thd
,
String
*
buf
);
void
mark_as_changed
(
THD
*
thd
,
LEX_CSTRING
*
tracked_item_name
);
/* callback */
static
uchar
*
sysvars_get_key
(
const
char
*
entry
,
size_t
*
length
,
my_bool
not_used
__attribute__
((
unused
)));
friend
my_bool
name_array_filler
(
void
*
ptr
,
void
*
data_ptr
);
};
/**
Current_schema_tracker,
...
...
@@ -108,6 +286,540 @@ class Session_state_change_tracker : public State_tracker
/* To be used in expanding the buffer. */
static
const
unsigned
int
EXTRA_ALLOC
=
1024
;
void
Session_sysvars_tracker
::
vars_list
::
reset
()
{
buffer_length
=
0
;
track_all
=
0
;
if
(
m_registered_sysvars
.
records
)
my_hash_reset
(
&
m_registered_sysvars
);
}
/**
Copy the given list.
@param from Source vars_list object.
@param thd THD handle to retrive the charset in use.
@retval true there is something to track
@retval false nothing to track
*/
void
Session_sysvars_tracker
::
vars_list
::
copy
(
vars_list
*
from
,
THD
*
thd
)
{
reset
();
track_all
=
from
->
track_all
;
free_hash
();
buffer_length
=
from
->
buffer_length
;
m_registered_sysvars
=
from
->
m_registered_sysvars
;
from
->
init
();
}
/**
Inserts the variable to be tracked into m_registered_sysvars hash.
@param node Node to be inserted.
@param svar address of the system variable
@retval false success
@retval true error
*/
bool
Session_sysvars_tracker
::
vars_list
::
insert
(
sysvar_node_st
*
node
,
const
sys_var
*
svar
,
myf
mem_flag
)
{
if
(
!
node
)
{
if
(
!
(
node
=
(
sysvar_node_st
*
)
my_malloc
(
sizeof
(
sysvar_node_st
),
MYF
(
MY_WME
|
mem_flag
))))
{
reset
();
return
true
;
}
}
node
->
m_svar
=
(
sys_var
*
)
svar
;
node
->
test_load
=
node
->
m_svar
->
test_load
;
node
->
m_changed
=
false
;
if
(
my_hash_insert
(
&
m_registered_sysvars
,
(
uchar
*
)
node
))
{
my_free
(
node
);
if
(
!
search
((
sys_var
*
)
svar
))
{
//EOF (error is already reported)
reset
();
return
true
;
}
}
return
false
;
}
/**
Parse the specified system variables list.
@Note In case of invalid entry a warning is raised per invalid entry.
This is done in order to handle 'potentially' valid system
variables from uninstalled plugins which might get installed in
future.
@param thd [IN] The thd handle.
@param var_list [IN] System variable list.
@param throw_error [IN] bool when set to true, returns an error
in case of invalid/duplicate values.
@param char_set [IN] charecter set information used for string
manipulations.
@param session_created [IN] bool variable which says if the parse is
already executed once. The mutex on variables
is not acquired if this variable is false.
@return
true Error
false Success
*/
bool
Session_sysvars_tracker
::
vars_list
::
parse_var_list
(
THD
*
thd
,
LEX_STRING
var_list
,
bool
throw_error
,
const
CHARSET_INFO
*
char_set
,
bool
session_created
)
{
const
char
separator
=
','
;
char
*
token
,
*
lasts
=
NULL
;
size_t
rest
=
var_list
.
length
;
if
(
!
var_list
.
str
||
var_list
.
length
==
0
)
{
buffer_length
=
1
;
return
false
;
}
if
(
!
strcmp
(
var_list
.
str
,(
const
char
*
)
"*"
))
{
track_all
=
true
;
buffer_length
=
2
;
return
false
;
}
buffer_length
=
var_list
.
length
+
1
;
token
=
var_list
.
str
;
track_all
=
false
;
/*
If Lock to the plugin mutex is not acquired here itself, it results
in having to acquire it multiple times in find_sys_var_ex for each
token value. Hence the mutex is handled here to avoid a performance
overhead.
*/
if
(
!
thd
||
session_created
)
mysql_mutex_lock
(
&
LOCK_plugin
);
for
(;;)
{
sys_var
*
svar
;
LEX_STRING
var
;
lasts
=
(
char
*
)
memchr
(
token
,
separator
,
rest
);
var
.
str
=
token
;
if
(
lasts
)
{
var
.
length
=
(
lasts
-
token
);
rest
-=
var
.
length
+
1
;
}
else
var
.
length
=
rest
;
/* Remove leading/trailing whitespace. */
trim_whitespace
(
char_set
,
&
var
);
if
((
svar
=
find_sys_var_ex
(
thd
,
var
.
str
,
var
.
length
,
throw_error
,
true
)))
{
if
(
insert
(
NULL
,
svar
,
m_mem_flag
)
==
TRUE
)
goto
error
;
}
else
if
(
throw_error
&&
session_created
&&
thd
)
{
push_warning_printf
(
thd
,
Sql_condition
::
WARN_LEVEL_WARN
,
ER_WRONG_VALUE_FOR_VAR
,
"%.*s is not a valid system variable and will"
"be ignored."
,
(
int
)
var
.
length
,
token
);
}
else
goto
error
;
if
(
lasts
)
token
=
lasts
+
1
;
else
break
;
}
if
(
!
thd
||
session_created
)
mysql_mutex_unlock
(
&
LOCK_plugin
);
return
false
;
error:
if
(
!
thd
||
session_created
)
mysql_mutex_unlock
(
&
LOCK_plugin
);
return
true
;
}
struct
name_array_filler_data
{
LEX_CSTRING
**
names
;
uint
idx
;
};
/** Collects variable references into array */
static
my_bool
name_array_filler
(
void
*
ptr
,
void
*
data_ptr
)
{
Session_sysvars_tracker
::
sysvar_node_st
*
node
=
(
Session_sysvars_tracker
::
sysvar_node_st
*
)
ptr
;
name_array_filler_data
*
data
=
(
struct
name_array_filler_data
*
)
data_ptr
;
if
(
*
node
->
test_load
)
data
->
names
[
data
->
idx
++
]
=
&
node
->
m_svar
->
name
;
return
FALSE
;
}
/* Sorts variable references array */
static
int
name_array_sorter
(
const
void
*
a
,
const
void
*
b
)
{
LEX_CSTRING
**
an
=
(
LEX_CSTRING
**
)
a
,
**
bn
=
(
LEX_CSTRING
**
)
b
;
size_t
min
=
MY_MIN
((
*
an
)
->
length
,
(
*
bn
)
->
length
);
int
res
=
strncmp
((
*
an
)
->
str
,
(
*
bn
)
->
str
,
min
);
if
(
res
==
0
)
res
=
((
int
)(
*
bn
)
->
length
)
-
((
int
)(
*
an
)
->
length
);
return
res
;
}
/**
Construct variable list by internal hash with references
*/
bool
Session_sysvars_tracker
::
vars_list
::
construct_var_list
(
char
*
buf
,
size_t
buf_len
)
{
struct
name_array_filler_data
data
;
size_t
left
=
buf_len
;
size_t
names_size
=
m_registered_sysvars
.
records
*
sizeof
(
LEX_CSTRING
*
);
const
char
separator
=
','
;
if
(
unlikely
(
buf_len
<
1
))
return
true
;
if
(
unlikely
(
track_all
))
{
if
(
buf_len
<
2
)
return
true
;
buf
[
0
]
=
'*'
;
buf
[
1
]
=
'\0'
;
return
false
;
}
if
(
m_registered_sysvars
.
records
==
0
)
{
buf
[
0
]
=
'\0'
;
return
false
;
}
data
.
names
=
(
LEX_CSTRING
**
)
my_safe_alloca
(
names_size
);
if
(
unlikely
(
!
data
.
names
))
return
true
;
data
.
idx
=
0
;
mysql_mutex_lock
(
&
LOCK_plugin
);
my_hash_iterate
(
&
m_registered_sysvars
,
&
name_array_filler
,
&
data
);
DBUG_ASSERT
(
data
.
idx
<=
m_registered_sysvars
.
records
);
if
(
m_registered_sysvars
.
records
==
0
)
{
mysql_mutex_unlock
(
&
LOCK_plugin
);
buf
[
0
]
=
'\0'
;
return
false
;
}
my_qsort
(
data
.
names
,
data
.
idx
,
sizeof
(
LEX_CSTRING
*
),
&
name_array_sorter
);
for
(
uint
i
=
0
;
i
<
data
.
idx
;
i
++
)
{
LEX_CSTRING
*
nm
=
data
.
names
[
i
];
size_t
ln
=
nm
->
length
+
1
;
if
(
ln
>
left
)
{
mysql_mutex_unlock
(
&
LOCK_plugin
);
my_safe_afree
(
data
.
names
,
names_size
);
return
true
;
}
memcpy
(
buf
,
nm
->
str
,
nm
->
length
);
buf
[
nm
->
length
]
=
separator
;
buf
+=
ln
;
left
-=
ln
;
}
mysql_mutex_unlock
(
&
LOCK_plugin
);
buf
--
;
buf
[
0
]
=
'\0'
;
my_safe_afree
(
data
.
names
,
names_size
);
return
false
;
}
/**
Enable session tracker by parsing global value of tracked variables.
@param thd [IN] The thd handle.
@retval true Error
@retval false Success
*/
bool
Session_sysvars_tracker
::
enable
(
THD
*
thd
)
{
sys_var
*
svar
;
mysql_mutex_lock
(
&
LOCK_plugin
);
svar
=
find_sys_var_ex
(
thd
,
SESSION_TRACK_SYSTEM_VARIABLES_NAME
.
str
,
SESSION_TRACK_SYSTEM_VARIABLES_NAME
.
length
,
false
,
true
);
DBUG_ASSERT
(
svar
);
set_var
tmp
(
thd
,
SHOW_OPT_GLOBAL
,
svar
,
&
null_lex_str
,
NULL
);
svar
->
session_save_default
(
thd
,
&
tmp
);
if
(
tool_list
->
parse_var_list
(
thd
,
tmp
.
save_result
.
string_value
,
true
,
thd
->
charset
(),
false
)
==
true
)
{
mysql_mutex_unlock
(
&
LOCK_plugin
);
return
true
;
}
mysql_mutex_unlock
(
&
LOCK_plugin
);
orig_list
->
copy
(
tool_list
,
thd
);
m_enabled
=
true
;
return
false
;
}
/**
Check system variable name(s).
@note This function is called from the ON_CHECK() function of the
session_track_system_variables' sys_var class.
@param thd [IN] The thd handle.
@param var [IN] A pointer to set_var holding the specified list of
system variable names.
@retval true Error
@retval false Success
*/
inline
bool
Session_sysvars_tracker
::
check
(
THD
*
thd
,
set_var
*
var
)
{
return
check_str
(
thd
,
var
->
save_result
.
string_value
);
}
inline
bool
Session_sysvars_tracker
::
check_str
(
THD
*
thd
,
LEX_STRING
val
)
{
tool_list
->
reset
();
return
tool_list
->
parse_var_list
(
thd
,
val
,
true
,
thd
->
charset
(),
true
);
}
/**
Once the value of the @@session_track_system_variables has been
successfully updated, this function calls
Session_sysvars_tracker::vars_list::copy updating the hash in orig_list
which represents the system variables to be tracked.
@note This function is called from the ON_UPDATE() function of the
session_track_system_variables' sys_var class.
@param thd [IN] The thd handle.
@retval true Error
@retval false Success
*/
bool
Session_sysvars_tracker
::
update
(
THD
*
thd
)
{
orig_list
->
copy
(
tool_list
,
thd
);
return
false
;
}
/**
Store the data for changed system variables in the specified buffer.
Once the data is stored, we reset the flags related to state-change
(see reset()).
@param thd [IN] The thd handle.
@paran buf [INOUT] Buffer to store the information to.
@retval true Error
@retval false Success
*/
bool
Session_sysvars_tracker
::
store
(
THD
*
thd
,
String
*
buf
)
{
char
val_buf
[
SHOW_VAR_FUNC_BUFF_SIZE
];
SHOW_VAR
show
;
const
char
*
value
;
sysvar_node_st
*
node
;
const
CHARSET_INFO
*
charset
;
size_t
val_length
,
length
;
int
idx
=
0
;
/* As its always system variable. */
show
.
type
=
SHOW_SYS
;
while
((
node
=
(
sysvar_node_st
*
)
(
*
orig_list
)[
idx
]))
{
if
(
node
->
m_changed
)
{
mysql_mutex_lock
(
&
LOCK_plugin
);
if
(
!*
node
->
test_load
)
{
mysql_mutex_unlock
(
&
LOCK_plugin
);
continue
;
}
sys_var
*
svar
=
node
->
m_svar
;
show
.
name
=
svar
->
name
.
str
;
show
.
value
=
(
char
*
)
svar
;
value
=
get_one_variable
(
thd
,
&
show
,
OPT_SESSION
,
SHOW_SYS
,
NULL
,
&
charset
,
val_buf
,
&
val_length
);
mysql_mutex_unlock
(
&
LOCK_plugin
);
length
=
net_length_size
(
svar
->
name
.
length
)
+
svar
->
name
.
length
+
net_length_size
(
val_length
)
+
val_length
;
compile_time_assert
(
SESSION_TRACK_SYSTEM_VARIABLES
<
251
);
buf
->
prep_alloc
(
1
+
net_length_size
(
length
)
+
length
,
EXTRA_ALLOC
);
/* Session state type (SESSION_TRACK_SYSTEM_VARIABLES) */
buf
->
q_net_store_length
((
ulonglong
)
SESSION_TRACK_SYSTEM_VARIABLES
);
/* Length of the overall entity. */
buf
->
q_net_store_length
((
ulonglong
)
length
);
/* System variable's name (length-encoded string). */
buf
->
q_net_store_data
((
const
uchar
*
)
svar
->
name
.
str
,
svar
->
name
.
length
);
/* System variable's value (length-encoded string). */
buf
->
q_net_store_data
((
const
uchar
*
)
value
,
val_length
);
}
++
idx
;
}
reset
();
return
false
;
}
/**
Mark the system variable as changed.
@param [IN] pointer on a variable
*/
void
Session_sysvars_tracker
::
mark_as_changed
(
THD
*
thd
,
LEX_CSTRING
*
var
)
{
sysvar_node_st
*
node
=
NULL
;
sys_var
*
svar
=
(
sys_var
*
)
var
;
/*
Check if the specified system variable is being tracked, if so
mark it as changed and also set the class's m_changed flag.
*/
if
((
node
=
(
sysvar_node_st
*
)
(
orig_list
->
search
(
node
,
svar
))))
{
node
->
m_changed
=
true
;
m_changed
=
true
;
/* do not cache the statement when there is change in session state */
thd
->
lex
->
safe_to_cache_query
=
0
;
thd
->
server_status
|=
SERVER_SESSION_STATE_CHANGED
;
}
}
/**
Supply key to a hash.
@param entry [IN] A single entry.
@param length [OUT] Length of the key.
@param not_used Unused.
@return Pointer to the key buffer.
*/
uchar
*
Session_sysvars_tracker
::
sysvars_get_key
(
const
char
*
entry
,
size_t
*
length
,
my_bool
not_used
__attribute__
((
unused
)))
{
*
length
=
sizeof
(
sys_var
*
);
return
(
uchar
*
)
&
(((
sysvar_node_st
*
)
entry
)
->
m_svar
);
}
/**
Prepare/reset the m_registered_sysvars hash for next statement.
*/
void
Session_sysvars_tracker
::
reset
()
{
sysvar_node_st
*
node
;
int
idx
=
0
;
while
((
node
=
(
sysvar_node_st
*
)
(
*
orig_list
)[
idx
]))
{
node
->
m_changed
=
false
;
++
idx
;
}
m_changed
=
false
;
}
static
Session_sysvars_tracker
*
sysvar_tracker
(
THD
*
thd
)
{
return
(
Session_sysvars_tracker
*
)
thd
->
session_tracker
.
get_tracker
(
SESSION_SYSVARS_TRACKER
);
}
bool
sysvartrack_validate_value
(
THD
*
thd
,
const
char
*
str
,
size_t
len
)
{
LEX_STRING
tmp
=
{(
char
*
)
str
,
len
};
if
(
thd
&&
sysvar_tracker
(
thd
)
->
is_enabled
())
return
sysvar_tracker
(
thd
)
->
check_str
(
thd
,
tmp
);
return
Session_sysvars_tracker
::
server_init_check
(
thd
,
system_charset_info
,
tmp
);
}
bool
sysvartrack_reprint_value
(
THD
*
thd
,
char
*
str
,
size_t
len
)
{
LEX_STRING
tmp
=
{
str
,
len
};
return
Session_sysvars_tracker
::
server_init_process
(
thd
,
system_charset_info
,
tmp
);
}
bool
sysvartrack_update
(
THD
*
thd
)
{
return
sysvar_tracker
(
thd
)
->
update
(
thd
);
}
size_t
sysvartrack_value_len
(
THD
*
thd
)
{
return
sysvar_tracker
(
thd
)
->
get_buffer_length
();
}
bool
sysvartrack_value_construct
(
THD
*
thd
,
char
*
val
,
size_t
len
)
{
return
sysvar_tracker
(
thd
)
->
construct_var_list
(
val
,
len
);
}
///////////////////////////////////////////////////////////////////////////////
/**
...
...
@@ -282,8 +994,29 @@ bool Session_state_change_tracker::is_state_changed(THD *)
Session_tracker
::
Session_tracker
()
{
for
(
int
i
=
0
;
i
<=
SESSION_TRACKER_END
;
i
++
)
m_trackers
[
i
]
=
NULL
;
}
/**
@brief Enables the tracker objects.
@param thd [IN] The thread handle.
@return void
*/
void
Session_tracker
::
enable
(
THD
*
thd
)
{
/*
Originally and correctly this allocation was in the constructor and
deallocation in the destructor, but in this case memory counting
system works incorrectly (for example in INSERT DELAYED thread)
*/
deinit
();
m_trackers
[
SESSION_SYSVARS_TRACKER
]
=
new
(
std
::
nothrow
)
Not_implemented_tracker
;
new
(
std
::
nothrow
)
Session_sysvars_tracker
()
;
m_trackers
[
CURRENT_SCHEMA_TRACKER
]
=
new
(
std
::
nothrow
)
Current_schema_tracker
;
m_trackers
[
SESSION_STATE_CHANGE_TRACKER
]
=
...
...
@@ -292,19 +1025,35 @@ Session_tracker::Session_tracker()
new
(
std
::
nothrow
)
Not_implemented_tracker
;
m_trackers
[
TRANSACTION_INFO_TRACKER
]
=
new
(
std
::
nothrow
)
Not_implemented_tracker
;
for
(
int
i
=
0
;
i
<=
SESSION_TRACKER_END
;
i
++
)
m_trackers
[
i
]
->
enable
(
thd
);
}
/**
@brief Enables the tracker objects.
@param thd [IN] The thread handle.
/**
Method called during the server startup to verify the contents
of @@session_track_system_variables.
@return void
@retval false Success
@retval true Failure
*/
void
Session_tracker
::
enable
(
THD
*
thd
)
bool
Session_tracker
::
server_boot_verify
(
const
CHARSET_INFO
*
char_set
)
{
for
(
int
i
=
0
;
i
<=
SESSION_TRACKER_END
;
i
++
)
m_trackers
[
i
]
->
enable
(
thd
);
Session_sysvars_tracker
*
server_tracker
;
bool
result
;
sys_var
*
svar
=
find_sys_var_ex
(
NULL
,
SESSION_TRACK_SYSTEM_VARIABLES_NAME
.
str
,
SESSION_TRACK_SYSTEM_VARIABLES_NAME
.
length
,
false
,
true
);
DBUG_ASSERT
(
svar
);
set_var
tmp
(
NULL
,
SHOW_OPT_GLOBAL
,
svar
,
&
null_lex_str
,
NULL
);
svar
->
session_save_default
(
NULL
,
&
tmp
);
server_tracker
=
new
(
std
::
nothrow
)
Session_sysvars_tracker
();
result
=
server_tracker
->
server_init_check
(
NULL
,
char_set
,
tmp
.
save_result
.
string_value
);
delete
server_tracker
;
return
result
;
}
...
...
sql/session_tracker.h
View file @
c8948b0d
...
...
@@ -104,6 +104,12 @@ class State_tracker
virtual
void
mark_as_changed
(
THD
*
thd
,
LEX_CSTRING
*
name
)
=
0
;
};
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
);
size_t
sysvartrack_value_len
(
THD
*
thd
);
bool
sysvartrack_value_construct
(
THD
*
thd
,
char
*
val
,
size_t
len
);
/**
Session_tracker
...
...
@@ -133,11 +139,23 @@ class Session_tracker
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
);
bool
server_boot_verify
(
const
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
...
...
sql/set_var.cc
View file @
c8948b0d
...
...
@@ -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
)
...
...
@@ -215,13 +220,14 @@ bool sys_var::update(THD *thd, set_var *var)
*/
if
((
var
->
type
==
OPT_SESSION
)
&&
(
!
ret
))
{
thd
->
session_tracker
.
mark_as_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
*/
thd
->
session_tracker
.
mark_as_changed
(
thd
,
SESSION_STATE_CHANGE_TRACKER
,
NULL
);
}
return
ret
;
...
...
@@ -995,7 +1001,30 @@ 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 */
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
);
thd
->
protocol_text
.
init
(
thd
);
thd
->
protocol_binary
.
init
(
thd
);
return
0
;
...
...
sql/set_var.h
View file @
c8948b0d
...
...
@@ -48,6 +48,9 @@ struct sys_var_chain
int
mysql_add_sys_var_chain
(
sys_var
*
chain
);
int
mysql_del_sys_var_chain
(
sys_var
*
chain
);
extern
const
LEX_CSTRING
SESSION_TRACK_SYSTEM_VARIABLES_NAME
;
/**
A class representing one system variable - that is something
that can be accessed as @@global.variable_name or @@session.variable_name,
...
...
@@ -60,6 +63,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 +244,9 @@ class sys_var: protected Value_source // for double_from_string_with_check
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 */
...
...
sql/share/errmsg-utf8.txt
View file @
c8948b0d
...
...
@@ -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á '%-.
64
s'"
dan "Ukendt systemvariabel '%-.
64
s'"
nla "Onbekende systeem variabele '%-.
64
s'"
eng "Unknown system variable '%-.
64
s'"
est "Tundmatu süsteemne muutuja '%-.
64
s'"
fre "Variable système '%-.
64
s' inconnue"
ger "Unbekannte Systemvariable '%-.
64
s'"
ita "Variabile di sistema '%-.
64
s' sconosciuta"
jpn "'%-.
64
s' は不明なシステム変数です。"
por "Variável de sistema '%-.
64
s' desconhecida"
rus "Неизвестная системная переменная '%-.
64
s'"
serbian "Nepoznata sistemska promenljiva '%-.
64
s'"
spa "Desconocida variable de sistema '%-.
64
s'"
swe "Okänd systemvariabel: '%-.
64
s'"
ukr "Невідома системна змінна '%-.
64
s'"
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"
...
...
sql/sql_class.cc
View file @
c8948b0d
...
...
@@ -1766,6 +1766,10 @@ 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 */
session_tracker
.
deinit
();
if
(
status_var
.
local_memory_used
!=
0
)
{
DBUG_PRINT
(
"error"
,
(
"memory_used: %lld"
,
status_var
.
local_memory_used
));
...
...
sql/sql_class.h
View file @
c8948b0d
...
...
@@ -691,6 +691,8 @@ typedef struct system_variables
my_bool
session_track_schema
;
my_bool
session_track_state_change
;
char
*
session_track_system_variables
;
}
SV
;
/**
...
...
sql/sql_plugin.cc
View file @
c8948b0d
...
...
@@ -269,6 +269,7 @@ struct st_bookmark
uint
name_len
;
int
offset
;
uint
version
;
bool
loaded
;
char
key
[
1
];
};
...
...
@@ -322,6 +323,8 @@ static void unlock_variables(THD *thd, struct system_variables *vars);
static
void
cleanup_variables
(
struct
system_variables
*
vars
);
static
void
plugin_vars_free_values
(
sys_var
*
vars
);
static
void
restore_ptr_backup
(
uint
n
,
st_ptr_backup
*
backup
);
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
static
plugin_ref
intern_plugin_lock
(
LEX
*
lex
,
plugin_ref
plugin
);
static
void
intern_plugin_unlock
(
LEX
*
lex
,
plugin_ref
plugin
);
static
void
reap_plugins
(
void
);
...
...
@@ -1175,6 +1178,13 @@ static bool plugin_add(MEM_ROOT *tmp_root,
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 +1236,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 +1456,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 +2789,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
,
size_t
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
))
&&
...
...
@@ -2795,7 +2806,7 @@ sys_var *find_sys_var(THD *thd, const char *str, size_t length)
{
mysql_rwlock_unlock
(
&
LOCK_system_variables_hash
);
LEX
*
lex
=
thd
?
thd
->
lex
:
0
;
if
(
!
(
plugin
=
intern_plugin_lock
(
lex
,
plugin_int_to_ref
(
pi
->
plugin
))))
if
(
!
(
plugin
=
my_
intern_plugin_lock
(
lex
,
plugin_int_to_ref
(
pi
->
plugin
))))
var
=
NULL
;
/* failed to lock it, it must be uninstalling */
else
if
(
!
(
plugin_state
(
plugin
)
&
PLUGIN_IS_READY
))
...
...
@@ -2807,14 +2818,20 @@ sys_var *find_sys_var(THD *thd, const char *str, size_t 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 +3957,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 +4042,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 +4056,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
...
...
sql/sql_plugin.h
View file @
c8948b0d
...
...
@@ -192,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
sql/sql_show.cc
View file @
c8948b0d
...
...
@@ -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
;
...
...
sql/sql_show.h
View file @
c8948b0d
...
...
@@ -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
);
...
...
sql/sql_string.h
View file @
c8948b0d
...
...
@@ -359,7 +359,9 @@ class String
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
);
...
...
sql/sys_vars.cc
View file @
c8948b0d
...
...
@@ -5375,6 +5375,16 @@ static Sys_var_ulong Sys_log_tc_size(
BLOCK_SIZE
(
my_getpagesize
()));
#endif
const
LEX_CSTRING
SESSION_TRACK_SYSTEM_VARIABLES_NAME
=
{
STRING_WITH_LEN
(
"session_track_system_variables"
)};
static
Sys_var_sesvartrack
Sys_track_session_sys_vars
(
SESSION_TRACK_SYSTEM_VARIABLES_NAME
.
str
,
"Track changes in registered system variables."
,
CMD_LINE
(
REQUIRED_ARG
),
IN_SYSTEM_CHARSET
,
DEFAULT
(
"autocommit,character_set_client,character_set_connection,"
"character_set_results,time_zone"
),
NO_MUTEX_GUARD
);
static
bool
update_session_track_schema
(
sys_var
*
self
,
THD
*
thd
,
enum_var_type
type
)
...
...
sql/sys_vars.ic
View file @
c8948b0d
...
...
@@ -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,105 @@ 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); }
};
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);
}
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= 0;
char *buf= (char *)my_safe_alloca(len);
if (buf && !sysvartrack_value_construct(thd, buf, len))
{
size_t len= strlen(buf) + 1;
res= (char*) thd->alloc(len + sizeof(char *));
if (res)
memcpy((*((char**) res)= res + sizeof(char *)), buf, len);
my_safe_afree(buf, len);
}
return (uchar *)res;
}
};
class Sys_var_proxy_user: public sys_var
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment