summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ps.result130
-rw-r--r--mysql-test/t/ps.test26
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sql_class.cc25
-rw-r--r--sql/sql_class.h10
-rw-r--r--sql/sql_prepare.cc11
6 files changed, 159 insertions, 45 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 9afbca9dcb1..b29185eaaea 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -108,6 +108,9 @@ set @fvar= 123.4567;
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
drop table t1,t2;
+deallocate prepare stmt3;
+deallocate prepare stmt4;
+deallocate prepare stmt5;
PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
set @var='A';
EXECUTE stmt1 USING @var;
@@ -253,6 +256,7 @@ set names latin1;
execute `ü`;
1234
1234
+deallocate prepare `ü`;
set names default;
create table t1 (a varchar(10)) charset=utf8;
insert into t1 (a) values ('yahoo');
@@ -781,6 +785,7 @@ EXECUTE b12651;
1
DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2;
+DEALLOCATE PREPARE b12651;
prepare stmt from "select @@time_zone";
execute stmt;
@@time_zone
@@ -873,6 +878,130 @@ length(a)
10
drop table t1;
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);
prepare ins_call from "insert into t1 (id) values (1)";
execute ins_call;
@@ -883,6 +1012,7 @@ drop table t1;
create table t1 (a int, b int);
insert into t1 (a,b) values (2,8),(1,9),(3,7);
prepare stmt from "select * from t1 order by ?";
+set @a=NULL;
execute stmt using @a;
a b
2 8
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 23b33156b48..1f5f17fe976 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -827,6 +827,7 @@ EXECUTE b12651;
DROP VIEW b12651_V1;
DROP TABLE b12651_T1, b12651_T2;
+DEALLOCATE PREPARE b12651;
#
# Bug#9359 "Prepared statements take snapshot of system vars at PREPARE
@@ -974,17 +975,17 @@ 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
+--error ER_GLOBAL_VARIABLE
set @@max_prepared_stmt_count=1;
---error 1229 # ER_GLOBAL_VARIABLE
+--error ER_GLOBAL_VARIABLE
set max_prepared_stmt_count=1;
---error 1229 # ER_GLOBAL_VARIABLE
+--error ER_GLOBAL_VARIABLE
set local max_prepared_stmt_count=1;
---error 1229 # ER_GLOBAL_VARIABLE
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set local prepared_stmt_count=0;
---error 1229 # ER_GLOBAL_VARIABLE
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
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 to a reasonable limit works
set global max_prepared_stmt_count=1;
@@ -994,13 +995,13 @@ select @@max_prepared_stmt_count;
#
set global max_prepared_stmt_count=0;
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";
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
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt1 from "select 1";
select @@prepared_stmt_count;
deallocate prepare stmt;
@@ -1019,13 +1020,13 @@ select @@prepared_stmt_count;
#
select @@prepared_stmt_count, @@max_prepared_stmt_count;
set global max_prepared_stmt_count=0;
---error 1105 # ER_UNKNOWN_ERROR
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
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
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1";
select @@prepared_stmt_count;
#
@@ -1039,10 +1040,10 @@ connect (con1,localhost,root,,);
connection con1;
prepare stmt from "select 2";
prepare stmt1 from "select 3";
---error 1105 # ER_UNKNOWN_ERROR
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4";
connection default;
---error 1105 # ER_UNKNOWN_ERROR
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4";
select @@max_prepared_stmt_count, @@prepared_stmt_count;
disconnect con1;
@@ -1087,6 +1088,7 @@ insert into t1 (a,b) values (2,8),(1,9),(3,7);
# Will order by index
prepare stmt from "select * from t1 order by ?";
+set @a=NULL;
execute stmt using @a;
set @a=1;
execute stmt using @a;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 37487c245a9..a1f70fca8df 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5611,3 +5611,5 @@ ER_TABLE_NEEDS_UPGRADE
eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
ER_SP_NO_AGGREGATE 42000
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)"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f0ab4b5c29c..d56f10a7a30 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -421,7 +421,7 @@ THD::~THD()
net_end(&net);
}
#endif
- stmt_map.destroy(); /* close all prepared statements */
+ stmt_map.reset(); /* close all prepared statements */
DBUG_ASSERT(lock_info.n_cursors == 0);
if (!cleanup_done)
cleanup();
@@ -1757,20 +1757,10 @@ int Statement_map::insert(THD *thd, Statement *statement)
my_error(ER_OUT_OF_RESOURCES, MYF(0));
goto err_st_hash;
}
- if (statement->name.str)
+ if (statement->name.str && my_hash_insert(&names_hash, (byte*) statement))
{
- /*
- 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.
- */
- 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;
- }
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ goto err_names_hash;
}
pthread_mutex_lock(&LOCK_prepared_stmt_count);
/*
@@ -1783,7 +1773,8 @@ int Statement_map::insert(THD *thd, Statement *statement)
if (prepared_stmt_count >= max_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;
}
prepared_stmt_count++;
@@ -1817,9 +1808,8 @@ 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);
@@ -1852,7 +1842,6 @@ Statement_map::~Statement_map()
hash_free(&names_hash);
hash_free(&st_hash);
-
}
bool select_dumpvar::send_data(List<Item> &items)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index dd645fcf75e..7c74ff6fa93 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -867,16 +867,6 @@ public:
}
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
engine that has transaction-specific state and therefore can not
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5a15e67da8e..4fa0a2dcb6e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -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)))
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
@@ -2029,14 +2029,15 @@ void mysql_sql_stmt_prepare(THD *thd)
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;
}
- 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;
}