Commit c49e6f88 authored by konstantin@mysql.com's avatar konstantin@mysql.com

Post-merge fixes. Add a new error message for max_prepared_stmt_count

limit.
parent 75792fc0
...@@ -108,6 +108,9 @@ set @fvar= 123.4567; ...@@ -108,6 +108,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;
...@@ -253,6 +256,7 @@ set names latin1; ...@@ -253,6 +256,7 @@ set names latin1;
execute ``; execute ``;
1234 1234
1234 1234
deallocate prepare ``;
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');
...@@ -781,6 +785,7 @@ EXECUTE b12651; ...@@ -781,6 +785,7 @@ EXECUTE b12651;
1 1
DROP VIEW b12651_V1; DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2; DROP TABLE b12651_T1, b12651_T2;
DEALLOCATE PREPARE b12651;
prepare stmt from "select @@time_zone"; prepare stmt from "select @@time_zone";
execute stmt; execute stmt;
@@time_zone @@time_zone
...@@ -873,6 +878,130 @@ length(a) ...@@ -873,6 +878,130 @@ length(a)
10 10
drop table t1; drop table t1;
deallocate prepare stmt; deallocate prepare stmt;
create table t1 (col1 integer, col2 integer);
insert into t1 values(100,100),(101,101),(102,102),(103,103);
prepare stmt from 'select col1, col2 from t1 where (col1, col2) in ((?,?))';
set @a=100, @b=100;
execute stmt using @a,@b;
col1 col2
100 100
set @a=101, @b=101;
execute stmt using @a,@b;
col1 col2
101 101
set @a=102, @b=102;
execute stmt using @a,@b;
col1 col2
102 102
set @a=102, @b=103;
execute stmt using @a,@b;
col1 col2
deallocate prepare stmt;
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 read only variable
set @@prepared_stmt_count=0;
ERROR HY000: Variable 'prepared_stmt_count' is a read only variable
set global prepared_stmt_count=1;
ERROR HY000: Variable 'prepared_stmt_count' is a read only variable
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 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
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 42000: Can't create more than max_prepared_stmt_count statements (current value: 1)
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 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
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 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
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 42000: Can't create more than max_prepared_stmt_count statements (current value: 3)
prepare stmt2 from "select 4";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 3)
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;
create table t1 (id int); create table t1 (id int);
prepare ins_call from "insert into t1 (id) values (1)"; prepare ins_call from "insert into t1 (id) values (1)";
execute ins_call; execute ins_call;
...@@ -883,6 +1012,7 @@ drop table t1; ...@@ -883,6 +1012,7 @@ drop table t1;
create table t1 (a int, b int); create table t1 (a int, b int);
insert into t1 (a,b) values (2,8),(1,9),(3,7); insert into t1 (a,b) values (2,8),(1,9),(3,7);
prepare stmt from "select * from t1 order by ?"; prepare stmt from "select * from t1 order by ?";
set @a=NULL;
execute stmt using @a; execute stmt using @a;
a b a b
2 8 2 8
......
...@@ -827,6 +827,7 @@ EXECUTE b12651; ...@@ -827,6 +827,7 @@ EXECUTE b12651;
DROP VIEW b12651_V1; DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2; DROP TABLE b12651_T1, b12651_T2;
DEALLOCATE PREPARE b12651;
# #
# Bug#9359 "Prepared statements take snapshot of system vars at PREPARE # Bug#9359 "Prepared statements take snapshot of system vars at PREPARE
...@@ -974,17 +975,17 @@ set global max_prepared_stmt_count=10000000000000000; ...@@ -974,17 +975,17 @@ set global max_prepared_stmt_count=10000000000000000;
select @@max_prepared_stmt_count; select @@max_prepared_stmt_count;
set global max_prepared_stmt_count=default; set global max_prepared_stmt_count=default;
select @@max_prepared_stmt_count; select @@max_prepared_stmt_count;
--error 1229 # ER_GLOBAL_VARIABLE --error ER_GLOBAL_VARIABLE
set @@max_prepared_stmt_count=1; set @@max_prepared_stmt_count=1;
--error 1229 # ER_GLOBAL_VARIABLE --error ER_GLOBAL_VARIABLE
set max_prepared_stmt_count=1; set max_prepared_stmt_count=1;
--error 1229 # ER_GLOBAL_VARIABLE --error ER_GLOBAL_VARIABLE
set local max_prepared_stmt_count=1; set local max_prepared_stmt_count=1;
--error 1229 # ER_GLOBAL_VARIABLE --error ER_INCORRECT_GLOBAL_LOCAL_VAR
set local prepared_stmt_count=0; set local prepared_stmt_count=0;
--error 1229 # ER_GLOBAL_VARIABLE --error ER_INCORRECT_GLOBAL_LOCAL_VAR
set @@prepared_stmt_count=0; set @@prepared_stmt_count=0;
--error 1232 # ER_WRONG_TYPE_FOR_VAR --error ER_INCORRECT_GLOBAL_LOCAL_VAR
set global prepared_stmt_count=1; set global prepared_stmt_count=1;
# set to a reasonable limit works # set to a reasonable limit works
set global max_prepared_stmt_count=1; set global max_prepared_stmt_count=1;
...@@ -994,13 +995,13 @@ select @@max_prepared_stmt_count; ...@@ -994,13 +995,13 @@ select @@max_prepared_stmt_count;
# #
set global max_prepared_stmt_count=0; set global max_prepared_stmt_count=0;
select @@max_prepared_stmt_count, @@prepared_stmt_count; select @@max_prepared_stmt_count, @@prepared_stmt_count;
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1"; prepare stmt from "select 1";
select @@prepared_stmt_count; select @@prepared_stmt_count;
set global max_prepared_stmt_count=1; set global max_prepared_stmt_count=1;
prepare stmt from "select 1"; prepare stmt from "select 1";
select @@prepared_stmt_count; select @@prepared_stmt_count;
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt1 from "select 1"; prepare stmt1 from "select 1";
select @@prepared_stmt_count; select @@prepared_stmt_count;
deallocate prepare stmt; deallocate prepare stmt;
...@@ -1019,13 +1020,13 @@ select @@prepared_stmt_count; ...@@ -1019,13 +1020,13 @@ select @@prepared_stmt_count;
# #
select @@prepared_stmt_count, @@max_prepared_stmt_count; select @@prepared_stmt_count, @@max_prepared_stmt_count;
set global max_prepared_stmt_count=0; set global max_prepared_stmt_count=0;
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1"; prepare stmt from "select 1";
# Result: the old statement is deallocated, the new is not created. # Result: the old statement is deallocated, the new is not created.
--error 1243 # ER_UNKNOWN_STMT_HANDLER --error 1243 # ER_UNKNOWN_STMT_HANDLER
execute stmt; execute stmt;
select @@prepared_stmt_count; select @@prepared_stmt_count;
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1"; prepare stmt from "select 1";
select @@prepared_stmt_count; select @@prepared_stmt_count;
# #
...@@ -1039,10 +1040,10 @@ connect (con1,localhost,root,,); ...@@ -1039,10 +1040,10 @@ connect (con1,localhost,root,,);
connection con1; connection con1;
prepare stmt from "select 2"; prepare stmt from "select 2";
prepare stmt1 from "select 3"; prepare stmt1 from "select 3";
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4"; prepare stmt2 from "select 4";
connection default; connection default;
--error 1105 # ER_UNKNOWN_ERROR --error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4"; prepare stmt2 from "select 4";
select @@max_prepared_stmt_count, @@prepared_stmt_count; select @@max_prepared_stmt_count, @@prepared_stmt_count;
disconnect con1; disconnect con1;
...@@ -1087,6 +1088,7 @@ insert into t1 (a,b) values (2,8),(1,9),(3,7); ...@@ -1087,6 +1088,7 @@ insert into t1 (a,b) values (2,8),(1,9),(3,7);
# Will order by index # Will order by index
prepare stmt from "select * from t1 order by ?"; prepare stmt from "select * from t1 order by ?";
set @a=NULL;
execute stmt using @a; execute stmt using @a;
set @a=1; set @a=1;
execute stmt using @a; execute stmt using @a;
......
...@@ -5611,3 +5611,5 @@ ER_TABLE_NEEDS_UPGRADE ...@@ -5611,3 +5611,5 @@ ER_TABLE_NEEDS_UPGRADE
eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!" eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
ER_SP_NO_AGGREGATE 42000 ER_SP_NO_AGGREGATE 42000
eng "AGGREGATE is not supported for stored functions" eng "AGGREGATE is not supported for stored functions"
ER_MAX_PREPARED_STMT_COUNT_REACHED 42000
eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)"
...@@ -421,7 +421,7 @@ THD::~THD() ...@@ -421,7 +421,7 @@ THD::~THD()
net_end(&net); net_end(&net);
} }
#endif #endif
stmt_map.destroy(); /* close all prepared statements */ stmt_map.reset(); /* close all prepared statements */
DBUG_ASSERT(lock_info.n_cursors == 0); DBUG_ASSERT(lock_info.n_cursors == 0);
if (!cleanup_done) if (!cleanup_done)
cleanup(); cleanup();
...@@ -1757,20 +1757,10 @@ int Statement_map::insert(THD *thd, Statement *statement) ...@@ -1757,20 +1757,10 @@ int Statement_map::insert(THD *thd, Statement *statement)
my_error(ER_OUT_OF_RESOURCES, MYF(0)); my_error(ER_OUT_OF_RESOURCES, MYF(0));
goto err_st_hash; goto err_st_hash;
} }
if (statement->name.str) if (statement->name.str && my_hash_insert(&names_hash, (byte*) statement))
{ {
/* my_error(ER_OUT_OF_RESOURCES, MYF(0));
If there is a statement with the same name, remove it. It is ok to goto err_names_hash;
remove old and fail to insert new one at the same time.
*/
Statement *old_stmt;
if ((old_stmt= find_by_name(&statement->name)))
erase(old_stmt);
if (my_hash_insert(&names_hash, (byte*) statement))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
goto err_names_hash;
}
} }
pthread_mutex_lock(&LOCK_prepared_stmt_count); pthread_mutex_lock(&LOCK_prepared_stmt_count);
/* /*
...@@ -1783,7 +1773,8 @@ int Statement_map::insert(THD *thd, Statement *statement) ...@@ -1783,7 +1773,8 @@ int Statement_map::insert(THD *thd, Statement *statement)
if (prepared_stmt_count >= max_prepared_stmt_count) if (prepared_stmt_count >= max_prepared_stmt_count)
{ {
pthread_mutex_unlock(&LOCK_prepared_stmt_count); pthread_mutex_unlock(&LOCK_prepared_stmt_count);
my_error(ER_UNKNOWN_ERROR, MYF(0)); my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0),
max_prepared_stmt_count);
goto err_max; goto err_max;
} }
prepared_stmt_count++; prepared_stmt_count++;
...@@ -1817,9 +1808,8 @@ void Statement_map::erase(Statement *statement) ...@@ -1817,9 +1808,8 @@ void Statement_map::erase(Statement *statement)
if (statement == last_found_statement) if (statement == last_found_statement)
last_found_statement= 0; last_found_statement= 0;
if (statement->name.str) if (statement->name.str)
{
hash_delete(&names_hash, (byte *) statement); hash_delete(&names_hash, (byte *) statement);
}
hash_delete(&st_hash, (byte *) statement); hash_delete(&st_hash, (byte *) statement);
pthread_mutex_lock(&LOCK_prepared_stmt_count); pthread_mutex_lock(&LOCK_prepared_stmt_count);
DBUG_ASSERT(prepared_stmt_count > 0); DBUG_ASSERT(prepared_stmt_count > 0);
...@@ -1852,7 +1842,6 @@ Statement_map::~Statement_map() ...@@ -1852,7 +1842,6 @@ Statement_map::~Statement_map()
hash_free(&names_hash); hash_free(&names_hash);
hash_free(&st_hash); hash_free(&st_hash);
} }
bool select_dumpvar::send_data(List<Item> &items) bool select_dumpvar::send_data(List<Item> &items)
......
...@@ -867,16 +867,6 @@ class Statement_map ...@@ -867,16 +867,6 @@ class Statement_map
} }
return last_found_statement; return last_found_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);
}
/* /*
Close all cursors of this connection that use tables of a storage Close all cursors of this connection that use tables of a storage
engine that has transaction-specific state and therefore can not engine that has transaction-specific state and therefore can not
......
...@@ -1846,7 +1846,7 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) ...@@ -1846,7 +1846,7 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
if (! (stmt= new Prepared_statement(thd, &thd->protocol_prep))) if (! (stmt= new Prepared_statement(thd, &thd->protocol_prep)))
DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */ DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
if (thd->stmt_map.insert(stmt)) if (thd->stmt_map.insert(thd, stmt))
{ {
/* /*
The error is set in the insert. The statement itself The error is set in the insert. The statement itself
...@@ -2029,14 +2029,15 @@ void mysql_sql_stmt_prepare(THD *thd) ...@@ -2029,14 +2029,15 @@ void mysql_sql_stmt_prepare(THD *thd)
DBUG_VOID_RETURN; /* out of memory */ DBUG_VOID_RETURN; /* out of memory */
} }
if (thd->stmt_map.insert(stmt)) /* Set the name first, insert should know that this statement has a name */
if (stmt->set_name(name))
{ {
/* The statement is deleted and an error is set if insert fails */ delete stmt;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (stmt->set_name(name)) if (thd->stmt_map.insert(thd, stmt))
{ {
thd->stmt_map.erase(stmt); /* The statement is deleted and an error is set if insert fails */
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment