diff --git a/include/my_alloc.h b/include/my_alloc.h
|
index 52c04fe1b7d..4e67f4a1ee3 100644
|
--- a/include/my_alloc.h
|
+++ b/include/my_alloc.h
|
@@ -49,6 +49,9 @@ typedef struct st_mem_root
|
MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list)
|
*/
|
unsigned int first_block_usage;
|
+#ifndef DBUG_OFF
|
+ my_bool read_only;
|
+#endif
|
|
void (*error_handler)(void);
|
} MEM_ROOT;
|
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
|
index 73b9f9f588b..4eea704165f 100644
|
--- a/include/mysql.h.pp
|
+++ b/include/mysql.h.pp
|
@@ -238,6 +238,7 @@ typedef struct st_mem_root
|
size_t block_size;
|
unsigned int block_num;
|
unsigned int first_block_usage;
|
+ my_bool read_only;
|
void (*error_handler)(void);
|
} MEM_ROOT;
|
typedef struct st_typelib {
|
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
|
index d67b8be9bb8..8c09e4bab68 100644
|
--- a/mysys/my_alloc.c
|
+++ b/mysys/my_alloc.c
|
@@ -71,6 +71,9 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
|
mem_root->error_handler= 0;
|
mem_root->block_num= 4; /* We shift this with >>2 */
|
mem_root->first_block_usage= 0;
|
+#ifndef DBUG_OFF
|
+ mem_root->read_only= 0;
|
+#endif
|
|
#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
|
if (pre_alloc_size)
|
@@ -177,6 +180,8 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
|
DBUG_ASSERT(alloc_root_inited(mem_root));
|
|
+ DBUG_ASSERT(mem_root->read_only == 0);
|
+
|
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
{
|
if (mem_root->error_handler)
|
@@ -210,6 +215,8 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
DBUG_PRINT("enter",("root: %p", mem_root));
|
DBUG_ASSERT(alloc_root_inited(mem_root));
|
|
+ DBUG_ASSERT(mem_root->read_only == 0);
|
+
|
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
{
|
/* Avoid reusing an already allocated block */
|
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
|
index 64e4cd30561..726e1634904 100644
|
--- a/sql/sql_prepare.cc
|
+++ b/sql/sql_prepare.cc
|
@@ -167,6 +167,9 @@ class Prepared_statement: public Statement
|
Server_side_cursor *cursor;
|
uchar *packet;
|
uchar *packet_end;
|
+#ifndef DBUG_OFF
|
+ ulong executed_counter;
|
+#endif
|
uint param_count;
|
uint last_errno;
|
uint flags;
|
@@ -3996,6 +3999,9 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
|
cursor(0),
|
packet(0),
|
packet_end(0),
|
+#ifndef DBUG_OFF
|
+ executed_counter(0),
|
+#endif
|
param_count(0),
|
last_errno(0),
|
flags((uint) IS_IN_USE),
|
@@ -4069,8 +4075,8 @@ void Prepared_statement::setup_set_params()
|
Prepared_statement::~Prepared_statement()
|
{
|
DBUG_ENTER("Prepared_statement::~Prepared_statement");
|
- DBUG_PRINT("enter",("stmt: %p cursor: %p",
|
- this, cursor));
|
+ DBUG_PRINT("enter",("stmt: %p cursor: %p, executed: %lu",
|
+ this, cursor, executed_counter));
|
delete cursor;
|
/*
|
We have to call free on the items even if cleanup is called as some items,
|
@@ -4228,6 +4234,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
init_param_array(this);
|
|
lex->set_trg_event_type_for_tables();
|
+#ifndef DBUG_OFF
|
+ executed_counter= 0;
|
+#endif
|
|
/*
|
While doing context analysis of the query (in check_prepared_statement)
|
@@ -4525,6 +4534,16 @@ Prepared_statement::execute_loop(String *expanded_query,
|
goto reexecute;
|
}
|
reset_stmt_params(this);
|
+#ifndef DBUG_OFF
|
+ if (!error)
|
+ {
|
+ if (++executed_counter >= 2)
|
+ {
|
+ mem_root->read_only= 1;
|
+ }
|
+ DBUG_PRINT("XXX", ("execute counter: %lu", executed_counter));
|
+ }
|
+#endif
|
|
return error;
|
}
|