mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/opt/local/work/mysql-4.1-16365 sql/mysql_priv.h: Auto merged sql/sql_class.h: Auto merged mysql-test/r/ps.result: Manual merge mysql-test/t/ps.test: Manual merge
This commit is contained in:
@ -107,6 +107,9 @@ set @fvar= 123.4567;
|
|||||||
prepare stmt1 from @fvar;
|
prepare stmt1 from @fvar;
|
||||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '123.4567' at line 1
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '123.4567' at line 1
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
deallocate prepare stmt3;
|
||||||
|
deallocate prepare stmt4;
|
||||||
|
deallocate prepare stmt5;
|
||||||
PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
|
PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
|
||||||
set @var='A';
|
set @var='A';
|
||||||
EXECUTE stmt1 USING @var;
|
EXECUTE stmt1 USING @var;
|
||||||
@ -252,6 +255,7 @@ set names latin1;
|
|||||||
execute `<60>`;
|
execute `<60>`;
|
||||||
1234
|
1234
|
||||||
1234
|
1234
|
||||||
|
deallocate prepare `<60>`;
|
||||||
set names default;
|
set names default;
|
||||||
create table t1 (a varchar(10)) charset=utf8;
|
create table t1 (a varchar(10)) charset=utf8;
|
||||||
insert into t1 (a) values ('yahoo');
|
insert into t1 (a) values ('yahoo');
|
||||||
@ -767,3 +771,107 @@ execute stmt using @a,@b;
|
|||||||
col1 col2
|
col1 col2
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
set @old_max_prepared_stmt_count= @@max_prepared_stmt_count;
|
||||||
|
show variables like 'max_prepared_stmt_count';
|
||||||
|
Variable_name Value
|
||||||
|
max_prepared_stmt_count 16382
|
||||||
|
show variables like 'prepared_stmt_count';
|
||||||
|
Variable_name Value
|
||||||
|
prepared_stmt_count 0
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count @@prepared_stmt_count
|
||||||
|
16382 0
|
||||||
|
set global max_prepared_stmt_count=-1;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count
|
||||||
|
0
|
||||||
|
set global max_prepared_stmt_count=10000000000000000;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count
|
||||||
|
1048576
|
||||||
|
set global max_prepared_stmt_count=default;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count
|
||||||
|
16382
|
||||||
|
set @@max_prepared_stmt_count=1;
|
||||||
|
ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
set max_prepared_stmt_count=1;
|
||||||
|
ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
set local max_prepared_stmt_count=1;
|
||||||
|
ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
set local prepared_stmt_count=0;
|
||||||
|
ERROR HY000: Variable 'prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
set @@prepared_stmt_count=0;
|
||||||
|
ERROR HY000: Variable 'prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
set global prepared_stmt_count=1;
|
||||||
|
ERROR 42000: Incorrect argument type to variable 'prepared_stmt_count'
|
||||||
|
set global max_prepared_stmt_count=1;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count
|
||||||
|
1
|
||||||
|
set global max_prepared_stmt_count=0;
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count @@prepared_stmt_count
|
||||||
|
0 0
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
0
|
||||||
|
set global max_prepared_stmt_count=1;
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
1
|
||||||
|
prepare stmt1 from "select 1";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
1
|
||||||
|
deallocate prepare stmt;
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
0
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
1
|
||||||
|
prepare stmt from "select 2";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
1
|
||||||
|
select @@prepared_stmt_count, @@max_prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count @@max_prepared_stmt_count
|
||||||
|
1 1
|
||||||
|
set global max_prepared_stmt_count=0;
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
execute stmt;
|
||||||
|
ERROR HY000: Unknown prepared statement handler (stmt) given to EXECUTE
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
0
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
@@prepared_stmt_count
|
||||||
|
0
|
||||||
|
set global max_prepared_stmt_count=3;
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count @@prepared_stmt_count
|
||||||
|
3 0
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
prepare stmt from "select 2";
|
||||||
|
prepare stmt1 from "select 3";
|
||||||
|
prepare stmt2 from "select 4";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
prepare stmt2 from "select 4";
|
||||||
|
ERROR HY000: Unknown error
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count @@prepared_stmt_count
|
||||||
|
3 3
|
||||||
|
deallocate prepare stmt;
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
@@max_prepared_stmt_count @@prepared_stmt_count
|
||||||
|
3 0
|
||||||
|
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
|
||||||
|
@ -111,6 +111,9 @@ set @fvar= 123.4567;
|
|||||||
prepare stmt1 from @fvar;
|
prepare stmt1 from @fvar;
|
||||||
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
deallocate prepare stmt3;
|
||||||
|
deallocate prepare stmt4;
|
||||||
|
deallocate prepare stmt5;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug #4105: Server crash on attempt to prepare a statement with character
|
# Bug #4105: Server crash on attempt to prepare a statement with character
|
||||||
@ -254,6 +257,7 @@ prepare `ü` from 'select 1234';
|
|||||||
execute `ü` ;
|
execute `ü` ;
|
||||||
set names latin1;
|
set names latin1;
|
||||||
execute `<60>`;
|
execute `<60>`;
|
||||||
|
deallocate prepare `<60>`;
|
||||||
set names default;
|
set names default;
|
||||||
|
|
||||||
|
|
||||||
@ -803,4 +807,123 @@ execute stmt using @a,@b;
|
|||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#16365 Prepared Statements: DoS with too many open statements
|
||||||
|
# Check that the limit @@max_prpeared_stmt_count works.
|
||||||
|
#
|
||||||
|
# Save the old value
|
||||||
|
set @old_max_prepared_stmt_count= @@max_prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# Disable prepared statement protocol: in this test we set
|
||||||
|
# @@max_prepared_stmt_count to 0 or 1 and would like to test the limit
|
||||||
|
# manually.
|
||||||
|
#
|
||||||
|
--disable_ps_protocol
|
||||||
|
#
|
||||||
|
# A. Check that the new variables are present in SHOW VARIABLES list.
|
||||||
|
#
|
||||||
|
show variables like 'max_prepared_stmt_count';
|
||||||
|
show variables like 'prepared_stmt_count';
|
||||||
|
#
|
||||||
|
# B. Check that the new variables are selectable.
|
||||||
|
#
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# C. Check that max_prepared_stmt_count is settable (global only),
|
||||||
|
# whereas prepared_stmt_count is readonly.
|
||||||
|
#
|
||||||
|
set global max_prepared_stmt_count=-1;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
set global max_prepared_stmt_count=10000000000000000;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
set global max_prepared_stmt_count=default;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
--error 1229 # ER_GLOBAL_VARIABLE
|
||||||
|
set @@max_prepared_stmt_count=1;
|
||||||
|
--error 1229 # ER_GLOBAL_VARIABLE
|
||||||
|
set max_prepared_stmt_count=1;
|
||||||
|
--error 1229 # ER_GLOBAL_VARIABLE
|
||||||
|
set local max_prepared_stmt_count=1;
|
||||||
|
--error 1229 # ER_GLOBAL_VARIABLE
|
||||||
|
set local prepared_stmt_count=0;
|
||||||
|
--error 1229 # ER_GLOBAL_VARIABLE
|
||||||
|
set @@prepared_stmt_count=0;
|
||||||
|
--error 1232 # ER_WRONG_TYPE_FOR_VAR
|
||||||
|
set global prepared_stmt_count=1;
|
||||||
|
# set to a reasonable limit works
|
||||||
|
set global max_prepared_stmt_count=1;
|
||||||
|
select @@max_prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# D. Check that the variables actually work.
|
||||||
|
#
|
||||||
|
set global max_prepared_stmt_count=0;
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
set global max_prepared_stmt_count=1;
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt1 from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# E. Check that we can prepare a statement with the same name
|
||||||
|
# successfully, without hitting the limit.
|
||||||
|
#
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
prepare stmt from "select 2";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# F. We can set the max below the current count. In this case no new
|
||||||
|
# statements should be allowed to prepare.
|
||||||
|
#
|
||||||
|
select @@prepared_stmt_count, @@max_prepared_stmt_count;
|
||||||
|
set global max_prepared_stmt_count=0;
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
# Result: the old statement is deallocated, the new is not created.
|
||||||
|
--error 1243 # ER_UNKNOWN_STMT_HANDLER
|
||||||
|
execute stmt;
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
select @@prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# G. Show that the variables are up to date even after a connection with all
|
||||||
|
# statements in it was terminated.
|
||||||
|
#
|
||||||
|
set global max_prepared_stmt_count=3;
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
prepare stmt from "select 1";
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
connection con1;
|
||||||
|
prepare stmt from "select 2";
|
||||||
|
prepare stmt1 from "select 3";
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt2 from "select 4";
|
||||||
|
connection default;
|
||||||
|
--error 1105 # ER_UNKNOWN_ERROR
|
||||||
|
prepare stmt2 from "select 4";
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
disconnect con1;
|
||||||
|
connection default;
|
||||||
|
# Wait for the connection to die: deal with a possible race
|
||||||
|
deallocate prepare stmt;
|
||||||
|
let $count= `select @@prepared_stmt_count`;
|
||||||
|
if ($count)
|
||||||
|
{
|
||||||
|
--sleep 2
|
||||||
|
let $count= `select @@prepared_stmt_count`;
|
||||||
|
}
|
||||||
|
select @@max_prepared_stmt_count, @@prepared_stmt_count;
|
||||||
|
#
|
||||||
|
# Restore the old value.
|
||||||
|
#
|
||||||
|
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
|
||||||
|
--enable_ps_protocol
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@ -918,6 +918,7 @@ extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
|
|||||||
extern ulong max_connections,max_connect_errors, connect_timeout;
|
extern ulong max_connections,max_connect_errors, connect_timeout;
|
||||||
extern ulong slave_net_timeout, slave_trans_retries;
|
extern ulong slave_net_timeout, slave_trans_retries;
|
||||||
extern ulong max_user_connections;
|
extern ulong max_user_connections;
|
||||||
|
extern ulong max_prepared_stmt_count, prepared_stmt_count;
|
||||||
extern ulong long_query_count, what_to_log,flush_time;
|
extern ulong long_query_count, what_to_log,flush_time;
|
||||||
extern ulong query_buff_size, thread_stack,thread_stack_min;
|
extern ulong query_buff_size, thread_stack,thread_stack_min;
|
||||||
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
|
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
|
||||||
@ -961,7 +962,8 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
|
|||||||
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
||||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
||||||
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
|
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
|
||||||
LOCK_global_system_variables, LOCK_user_conn;
|
LOCK_global_system_variables, LOCK_user_conn,
|
||||||
|
LOCK_prepared_stmt_count;
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
extern pthread_mutex_t LOCK_des_key_file;
|
extern pthread_mutex_t LOCK_des_key_file;
|
||||||
#endif
|
#endif
|
||||||
|
@ -336,6 +336,22 @@ ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
|
|||||||
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
|
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
|
||||||
ulong max_connections,max_used_connections,
|
ulong max_connections,max_used_connections,
|
||||||
max_connect_errors, max_user_connections = 0;
|
max_connect_errors, max_user_connections = 0;
|
||||||
|
/*
|
||||||
|
Limit of the total number of prepared statements in the server.
|
||||||
|
Is necessary to protect the server against out-of-memory attacks.
|
||||||
|
*/
|
||||||
|
ulong max_prepared_stmt_count;
|
||||||
|
/*
|
||||||
|
Current total number of prepared statements in the server. This number
|
||||||
|
is exact, and therefore may not be equal to the difference between
|
||||||
|
`com_stmt_prepare' and `com_stmt_close' (global status variables), as
|
||||||
|
the latter ones account for all registered attempts to prepare
|
||||||
|
a statement (including unsuccessful ones). Prepared statements are
|
||||||
|
currently connection-local: if the same SQL query text is prepared in
|
||||||
|
two different connections, this counts as two distinct prepared
|
||||||
|
statements.
|
||||||
|
*/
|
||||||
|
ulong prepared_stmt_count=0;
|
||||||
ulong thread_id=1L,current_pid;
|
ulong thread_id=1L,current_pid;
|
||||||
ulong slow_launch_threads = 0, sync_binlog_period;
|
ulong slow_launch_threads = 0, sync_binlog_period;
|
||||||
ulong expire_logs_days = 0;
|
ulong expire_logs_days = 0;
|
||||||
@ -421,6 +437,14 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
|
|||||||
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
|
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
|
||||||
LOCK_global_system_variables,
|
LOCK_global_system_variables,
|
||||||
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
|
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
|
||||||
|
/*
|
||||||
|
The below lock protects access to two global server variables:
|
||||||
|
max_prepared_stmt_count and prepared_stmt_count. These variables
|
||||||
|
set the limit and hold the current total number of prepared statements
|
||||||
|
in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
|
||||||
|
server may be fairly high, we need a dedicated lock.
|
||||||
|
*/
|
||||||
|
pthread_mutex_t LOCK_prepared_stmt_count;
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
pthread_mutex_t LOCK_des_key_file;
|
pthread_mutex_t LOCK_des_key_file;
|
||||||
#endif
|
#endif
|
||||||
@ -1118,6 +1142,7 @@ static void clean_up_mutexes()
|
|||||||
(void) rwlock_destroy(&LOCK_sys_init_connect);
|
(void) rwlock_destroy(&LOCK_sys_init_connect);
|
||||||
(void) rwlock_destroy(&LOCK_sys_init_slave);
|
(void) rwlock_destroy(&LOCK_sys_init_slave);
|
||||||
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
|
(void) pthread_mutex_destroy(&LOCK_global_system_variables);
|
||||||
|
(void) pthread_mutex_destroy(&LOCK_prepared_stmt_count);
|
||||||
(void) pthread_cond_destroy(&COND_thread_count);
|
(void) pthread_cond_destroy(&COND_thread_count);
|
||||||
(void) pthread_cond_destroy(&COND_refresh);
|
(void) pthread_cond_destroy(&COND_refresh);
|
||||||
(void) pthread_cond_destroy(&COND_thread_cache);
|
(void) pthread_cond_destroy(&COND_thread_cache);
|
||||||
@ -2635,6 +2660,7 @@ static int init_thread_environment()
|
|||||||
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
|
||||||
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
||||||
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
|
||||||
|
(void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
|
||||||
(void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
(void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
|
(void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
|
||||||
@ -4238,7 +4264,8 @@ enum options_mysqld
|
|||||||
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
|
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
|
||||||
OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
|
OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
|
||||||
OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
|
OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
|
||||||
OPT_MAX_JOIN_SIZE, OPT_MAX_RELAY_LOG_SIZE, OPT_MAX_SORT_LENGTH,
|
OPT_MAX_JOIN_SIZE, OPT_MAX_PREPARED_STMT_COUNT,
|
||||||
|
OPT_MAX_RELAY_LOG_SIZE, OPT_MAX_SORT_LENGTH,
|
||||||
OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
|
OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
|
||||||
OPT_MAX_LENGTH_FOR_SORT_DATA,
|
OPT_MAX_LENGTH_FOR_SORT_DATA,
|
||||||
OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
|
OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
|
||||||
@ -5225,6 +5252,10 @@ The minimum value for this variable is 4096.",
|
|||||||
(gptr*) &global_system_variables.max_length_for_sort_data,
|
(gptr*) &global_system_variables.max_length_for_sort_data,
|
||||||
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
|
(gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
|
||||||
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
|
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
|
||||||
|
{"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT,
|
||||||
|
"Maximum numbrer of prepared statements in the server.",
|
||||||
|
(gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count,
|
||||||
|
0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0},
|
||||||
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
|
{"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
|
||||||
"If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
|
"If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
|
||||||
(gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG,
|
(gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG,
|
||||||
|
@ -118,6 +118,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length);
|
|||||||
void fix_sql_mode_var(THD *thd, enum_var_type type);
|
void fix_sql_mode_var(THD *thd, enum_var_type type);
|
||||||
static byte *get_error_count(THD *thd);
|
static byte *get_error_count(THD *thd);
|
||||||
static byte *get_warning_count(THD *thd);
|
static byte *get_warning_count(THD *thd);
|
||||||
|
static byte *get_prepared_stmt_count(THD *thd);
|
||||||
static byte *get_have_innodb(THD *thd);
|
static byte *get_have_innodb(THD *thd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -239,6 +240,10 @@ sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size",
|
|||||||
&SV::max_join_size,
|
&SV::max_join_size,
|
||||||
fix_max_join_size);
|
fix_max_join_size);
|
||||||
#endif
|
#endif
|
||||||
|
static sys_var_long_ptr_global
|
||||||
|
sys_max_prepared_stmt_count("max_prepared_stmt_count",
|
||||||
|
&max_prepared_stmt_count,
|
||||||
|
&LOCK_prepared_stmt_count);
|
||||||
sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size",
|
sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size",
|
||||||
&max_relay_log_size,
|
&max_relay_log_size,
|
||||||
fix_max_relay_log_size);
|
fix_max_relay_log_size);
|
||||||
@ -472,6 +477,9 @@ static sys_var_readonly sys_warning_count("warning_count",
|
|||||||
OPT_SESSION,
|
OPT_SESSION,
|
||||||
SHOW_LONG,
|
SHOW_LONG,
|
||||||
get_warning_count);
|
get_warning_count);
|
||||||
|
static sys_var_readonly sys_prepared_stmt_count("prepared_stmt_count",
|
||||||
|
OPT_GLOBAL, SHOW_LONG,
|
||||||
|
get_prepared_stmt_count);
|
||||||
|
|
||||||
/* alias for last_insert_id() to be compatible with Sybase */
|
/* alias for last_insert_id() to be compatible with Sybase */
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
@ -569,6 +577,7 @@ sys_var *sys_variables[]=
|
|||||||
&sys_max_heap_table_size,
|
&sys_max_heap_table_size,
|
||||||
&sys_max_join_size,
|
&sys_max_join_size,
|
||||||
&sys_max_length_for_sort_data,
|
&sys_max_length_for_sort_data,
|
||||||
|
&sys_max_prepared_stmt_count,
|
||||||
&sys_max_relay_log_size,
|
&sys_max_relay_log_size,
|
||||||
&sys_max_seeks_for_key,
|
&sys_max_seeks_for_key,
|
||||||
&sys_max_sort_length,
|
&sys_max_sort_length,
|
||||||
@ -589,6 +598,7 @@ sys_var *sys_variables[]=
|
|||||||
&sys_new_mode,
|
&sys_new_mode,
|
||||||
&sys_old_passwords,
|
&sys_old_passwords,
|
||||||
&sys_preload_buff_size,
|
&sys_preload_buff_size,
|
||||||
|
&sys_prepared_stmt_count,
|
||||||
&sys_pseudo_thread_id,
|
&sys_pseudo_thread_id,
|
||||||
&sys_query_alloc_block_size,
|
&sys_query_alloc_block_size,
|
||||||
&sys_query_cache_size,
|
&sys_query_cache_size,
|
||||||
@ -801,6 +811,8 @@ struct show_var_st init_vars[]= {
|
|||||||
{sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS},
|
{sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS},
|
||||||
{sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data,
|
{sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data,
|
||||||
SHOW_SYS},
|
SHOW_SYS},
|
||||||
|
{sys_max_prepared_stmt_count.name, (char*) &sys_max_prepared_stmt_count,
|
||||||
|
SHOW_SYS},
|
||||||
{sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
|
{sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
|
||||||
{sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS},
|
{sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS},
|
||||||
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
|
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
|
||||||
@ -838,6 +850,7 @@ struct show_var_st init_vars[]= {
|
|||||||
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
|
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
|
||||||
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
|
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
|
||||||
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
|
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
|
||||||
|
{sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS},
|
||||||
{"port", (char*) &mysqld_port, SHOW_INT},
|
{"port", (char*) &mysqld_port, SHOW_INT},
|
||||||
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
|
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
|
||||||
{"protocol_version", (char*) &protocol_version, SHOW_INT},
|
{"protocol_version", (char*) &protocol_version, SHOW_INT},
|
||||||
@ -1251,29 +1264,40 @@ static void fix_server_id(THD *thd, enum_var_type type)
|
|||||||
server_id_supplied = 1;
|
server_id_supplied = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sys_var_long_ptr::check(THD *thd, set_var *var)
|
|
||||||
|
sys_var_long_ptr::
|
||||||
|
sys_var_long_ptr(const char *name_arg, ulong *value_ptr,
|
||||||
|
sys_after_update_func after_update_arg)
|
||||||
|
:sys_var_long_ptr_global(name_arg, value_ptr,
|
||||||
|
&LOCK_global_system_variables, after_update_arg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
longlong v= var->value->val_int();
|
longlong v= var->value->val_int();
|
||||||
var->save_result.ulonglong_value= v < 0 ? 0 : v;
|
var->save_result.ulonglong_value= v < 0 ? 0 : v;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sys_var_long_ptr::update(THD *thd, set_var *var)
|
bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
ulonglong tmp= var->save_result.ulonglong_value;
|
ulonglong tmp= var->save_result.ulonglong_value;
|
||||||
pthread_mutex_lock(&LOCK_global_system_variables);
|
pthread_mutex_lock(guard);
|
||||||
if (option_limits)
|
if (option_limits)
|
||||||
*value= (ulong) getopt_ull_limit_value(tmp, option_limits);
|
*value= (ulong) getopt_ull_limit_value(tmp, option_limits);
|
||||||
else
|
else
|
||||||
*value= (ulong) tmp;
|
*value= (ulong) tmp;
|
||||||
pthread_mutex_unlock(&LOCK_global_system_variables);
|
pthread_mutex_unlock(guard);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sys_var_long_ptr::set_default(THD *thd, enum_var_type type)
|
void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(guard);
|
||||||
*value= (ulong) option_limits->def_value;
|
*value= (ulong) option_limits->def_value;
|
||||||
|
pthread_mutex_unlock(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2642,6 +2666,14 @@ static byte *get_have_innodb(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static byte *get_prepared_stmt_count(THD *thd)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
||||||
|
thd->sys_var_tmp.ulong_value= prepared_stmt_count;
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
return (byte*) &thd->sys_var_tmp.ulong_value;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Main handling of variables:
|
Main handling of variables:
|
||||||
- Initialisation
|
- Initialisation
|
||||||
|
@ -47,13 +47,7 @@ public:
|
|||||||
#if MYSQL_VERSION_ID < 50000
|
#if MYSQL_VERSION_ID < 50000
|
||||||
bool no_support_one_shot;
|
bool no_support_one_shot;
|
||||||
#endif
|
#endif
|
||||||
sys_var(const char *name_arg)
|
sys_var(const char *name_arg, sys_after_update_func func= NULL)
|
||||||
:name(name_arg), after_update(0)
|
|
||||||
#if MYSQL_VERSION_ID < 50000
|
|
||||||
, no_support_one_shot(1)
|
|
||||||
#endif
|
|
||||||
{}
|
|
||||||
sys_var(const char *name_arg,sys_after_update_func func)
|
|
||||||
:name(name_arg), after_update(func)
|
:name(name_arg), after_update(func)
|
||||||
#if MYSQL_VERSION_ID < 50000
|
#if MYSQL_VERSION_ID < 50000
|
||||||
, no_support_one_shot(1)
|
, no_support_one_shot(1)
|
||||||
@ -79,15 +73,35 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class sys_var_long_ptr :public sys_var
|
/*
|
||||||
|
A base class for all variables that require its access to
|
||||||
|
be guarded with a mutex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sys_var_global: public sys_var
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
pthread_mutex_t *guard;
|
||||||
|
public:
|
||||||
|
sys_var_global(const char *name_arg, sys_after_update_func after_update_arg,
|
||||||
|
pthread_mutex_t *guard_arg)
|
||||||
|
:sys_var(name_arg, after_update_arg), guard(guard_arg) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A global-only ulong variable that requires its access to be
|
||||||
|
protected with a mutex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sys_var_long_ptr_global: public sys_var_global
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ulong *value;
|
ulong *value;
|
||||||
sys_var_long_ptr(const char *name_arg, ulong *value_ptr)
|
sys_var_long_ptr_global(const char *name_arg, ulong *value_ptr,
|
||||||
:sys_var(name_arg),value(value_ptr) {}
|
pthread_mutex_t *guard_arg,
|
||||||
sys_var_long_ptr(const char *name_arg, ulong *value_ptr,
|
sys_after_update_func after_update_arg= NULL)
|
||||||
sys_after_update_func func)
|
:sys_var_global(name_arg, after_update_arg, guard_arg), value(value_ptr) {}
|
||||||
:sys_var(name_arg,func), value(value_ptr) {}
|
|
||||||
bool check(THD *thd, set_var *var);
|
bool check(THD *thd, set_var *var);
|
||||||
bool update(THD *thd, set_var *var);
|
bool update(THD *thd, set_var *var);
|
||||||
void set_default(THD *thd, enum_var_type type);
|
void set_default(THD *thd, enum_var_type type);
|
||||||
@ -97,6 +111,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A global ulong variable that is protected by LOCK_global_system_variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
class sys_var_long_ptr :public sys_var_long_ptr_global
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sys_var_long_ptr(const char *name_arg, ulong *value_ptr,
|
||||||
|
sys_after_update_func after_update_arg= NULL);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class sys_var_ulonglong_ptr :public sys_var
|
class sys_var_ulonglong_ptr :public sys_var
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -175,7 +201,7 @@ class sys_var_const_str :public sys_var
|
|||||||
public:
|
public:
|
||||||
char *value; // Pointer to const value
|
char *value; // Pointer to const value
|
||||||
sys_var_const_str(const char *name_arg, const char *value_arg)
|
sys_var_const_str(const char *name_arg, const char *value_arg)
|
||||||
:sys_var(name_arg), value((char*) value_arg)
|
:sys_var(name_arg),value((char*) value_arg)
|
||||||
{}
|
{}
|
||||||
bool check(THD *thd, set_var *var)
|
bool check(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
@ -221,10 +247,7 @@ public:
|
|||||||
class sys_var_thd :public sys_var
|
class sys_var_thd :public sys_var
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
sys_var_thd(const char *name_arg)
|
sys_var_thd(const char *name_arg, sys_after_update_func func= NULL)
|
||||||
:sys_var(name_arg)
|
|
||||||
{}
|
|
||||||
sys_var_thd(const char *name_arg, sys_after_update_func func)
|
|
||||||
:sys_var(name_arg,func)
|
:sys_var(name_arg,func)
|
||||||
{}
|
{}
|
||||||
bool check_type(enum_var_type type) { return 0; }
|
bool check_type(enum_var_type type) { return 0; }
|
||||||
|
119
sql/sql_class.cc
119
sql/sql_class.cc
@ -1616,27 +1616,128 @@ Statement_map::Statement_map() :
|
|||||||
NULL,MYF(0));
|
NULL,MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Statement_map::insert(Statement *statement)
|
/*
|
||||||
|
Insert a new statement to the thread-local statement map.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
If there was an old statement with the same name, replace it with the
|
||||||
|
new one. Otherwise, check if max_prepared_stmt_count is not reached yet,
|
||||||
|
increase prepared_stmt_count, and insert the new statement. It's okay
|
||||||
|
to delete an old statement and fail to insert the new one.
|
||||||
|
|
||||||
|
POSTCONDITIONS
|
||||||
|
All named prepared statements are also present in names_hash.
|
||||||
|
Statement names in names_hash are unique.
|
||||||
|
The statement is added only if prepared_stmt_count < max_prepard_stmt_count
|
||||||
|
last_found_statement always points to a valid statement or is 0
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
0 success
|
||||||
|
1 error: out of resources or max_prepared_stmt_count limit has been
|
||||||
|
reached. An error is sent to the client, the statement is deleted.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Statement_map::insert(THD *thd, Statement *statement)
|
||||||
{
|
{
|
||||||
int rc= my_hash_insert(&st_hash, (byte *) statement);
|
if (my_hash_insert(&st_hash, (byte*) statement))
|
||||||
if (rc == 0)
|
{
|
||||||
last_found_statement= statement;
|
/*
|
||||||
|
Delete is needed only in case of an insert failure. In all other
|
||||||
|
cases hash_delete will also delete the statement.
|
||||||
|
*/
|
||||||
|
delete statement;
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
goto err_st_hash;
|
||||||
|
}
|
||||||
if (statement->name.str)
|
if (statement->name.str)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If there is a statement with the same name, remove it. It is ok to
|
If there is a statement with the same name, remove it. It is ok to
|
||||||
remove old and fail to insert new one at the same time.
|
remove old and fail to insert new one at the same time.
|
||||||
*/
|
*/
|
||||||
Statement *old_stmt;
|
Statement *old_stmt;
|
||||||
if ((old_stmt= find_by_name(&statement->name)))
|
if ((old_stmt= find_by_name(&statement->name)))
|
||||||
erase(old_stmt);
|
erase(old_stmt);
|
||||||
if ((rc= my_hash_insert(&names_hash, (byte*)statement)))
|
if (my_hash_insert(&names_hash, (byte*) statement))
|
||||||
hash_delete(&st_hash, (byte*)statement);
|
{
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
goto err_names_hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
||||||
|
/*
|
||||||
|
We don't check that prepared_stmt_count is <= max_prepared_stmt_count
|
||||||
|
because we would like to allow to lower the total limit
|
||||||
|
of prepared statements below the current count. In that case
|
||||||
|
no new statements can be added until prepared_stmt_count drops below
|
||||||
|
the limit.
|
||||||
|
*/
|
||||||
|
if (prepared_stmt_count >= max_prepared_stmt_count)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
my_error(ER_UNKNOWN_ERROR, MYF(0));
|
||||||
|
goto err_max;
|
||||||
|
}
|
||||||
|
prepared_stmt_count++;
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
|
||||||
|
last_found_statement= statement;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_max:
|
||||||
|
if (statement->name.str)
|
||||||
|
hash_delete(&names_hash, (byte*) statement);
|
||||||
|
err_names_hash:
|
||||||
|
hash_delete(&st_hash, (byte*) statement);
|
||||||
|
err_st_hash:
|
||||||
|
send_error(thd);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Statement_map::erase(Statement *statement)
|
||||||
|
{
|
||||||
|
if (statement == last_found_statement)
|
||||||
|
last_found_statement= 0;
|
||||||
|
if (statement->name.str)
|
||||||
|
{
|
||||||
|
hash_delete(&names_hash, (byte *) statement);
|
||||||
|
}
|
||||||
|
hash_delete(&st_hash, (byte *) statement);
|
||||||
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
||||||
|
DBUG_ASSERT(prepared_stmt_count > 0);
|
||||||
|
prepared_stmt_count--;
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Statement_map::reset()
|
||||||
|
{
|
||||||
|
/* Must be first, hash_free will reset st_hash.records */
|
||||||
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
||||||
|
DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
|
||||||
|
prepared_stmt_count-= st_hash.records;
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
|
||||||
|
my_hash_reset(&names_hash);
|
||||||
|
my_hash_reset(&st_hash);
|
||||||
|
last_found_statement= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Statement_map::~Statement_map()
|
||||||
|
{
|
||||||
|
/* Must go first, hash_free will reset st_hash.records */
|
||||||
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
||||||
|
DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
|
||||||
|
prepared_stmt_count-= st_hash.records;
|
||||||
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
||||||
|
|
||||||
|
hash_free(&names_hash);
|
||||||
|
hash_free(&st_hash);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool select_dumpvar::send_data(List<Item> &items)
|
bool select_dumpvar::send_data(List<Item> &items)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Item_func_set_user_var> li(vars);
|
List_iterator_fast<Item_func_set_user_var> li(vars);
|
||||||
|
@ -620,7 +620,7 @@ class Statement_map
|
|||||||
public:
|
public:
|
||||||
Statement_map();
|
Statement_map();
|
||||||
|
|
||||||
int insert(Statement *statement);
|
int insert(THD *thd, Statement *statement);
|
||||||
|
|
||||||
Statement *find_by_name(LEX_STRING *name)
|
Statement *find_by_name(LEX_STRING *name)
|
||||||
{
|
{
|
||||||
@ -642,29 +642,10 @@ public:
|
|||||||
}
|
}
|
||||||
return last_found_statement;
|
return last_found_statement;
|
||||||
}
|
}
|
||||||
void erase(Statement *statement)
|
void erase(Statement *statement);
|
||||||
{
|
|
||||||
if (statement == last_found_statement)
|
|
||||||
last_found_statement= 0;
|
|
||||||
if (statement->name.str)
|
|
||||||
{
|
|
||||||
hash_delete(&names_hash, (byte *) statement);
|
|
||||||
}
|
|
||||||
hash_delete(&st_hash, (byte *) statement);
|
|
||||||
}
|
|
||||||
/* Erase all statements (calls Statement destructor) */
|
/* Erase all statements (calls Statement destructor) */
|
||||||
void reset()
|
void reset();
|
||||||
{
|
~Statement_map();
|
||||||
my_hash_reset(&names_hash);
|
|
||||||
my_hash_reset(&st_hash);
|
|
||||||
last_found_statement= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Statement_map()
|
|
||||||
{
|
|
||||||
hash_free(&names_hash);
|
|
||||||
hash_free(&st_hash);
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
HASH st_hash;
|
HASH st_hash;
|
||||||
HASH names_hash;
|
HASH names_hash;
|
||||||
@ -932,6 +913,7 @@ public:
|
|||||||
{
|
{
|
||||||
my_bool my_bool_value;
|
my_bool my_bool_value;
|
||||||
long long_value;
|
long long_value;
|
||||||
|
ulong ulong_value;
|
||||||
} sys_var_tmp;
|
} sys_var_tmp;
|
||||||
|
|
||||||
THD();
|
THD();
|
||||||
|
@ -1593,10 +1593,12 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->stmt_map.insert(stmt))
|
if (thd->stmt_map.insert(thd, stmt))
|
||||||
{
|
{
|
||||||
delete stmt;
|
/*
|
||||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
The error is sent in the insert. The statement itself
|
||||||
|
will be also deleted there (this is how the hash works).
|
||||||
|
*/
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user