summaryrefslogtreecommitdiff
path: root/sql/sql_class.h
diff options
context:
space:
mode:
authorkonstantin@mysql.com <>2004-08-21 02:02:46 +0400
committerkonstantin@mysql.com <>2004-08-21 02:02:46 +0400
commit568c6e8526bded952225a9f4d2b262582091ae78 (patch)
tree687b98d21d388c1958d7cabd22c8c450eecca73e /sql/sql_class.h
parentb9dbef8e239b0ad70d0e4da376736611164bf96d (diff)
downloadmariadb-git-568c6e8526bded952225a9f4d2b262582091ae78.tar.gz
Fix for bug#4912 "mysqld crashs in case a statement is executed
a second time". The bug was caused by incompatibility of negations elimination algorithm and PS: during first statement execute a subtree with negation was replaced with equivalent subtree without NOTs. The problem was that although this transformation was permanent, items of the new subtree were created in execute-local memory. The patch adds means to check if it is the first execute of a prepared statement, and if this is the case, to allocate items in memory of the prepared statement. The implementation: - backports Item_arena from 5.0 - adds Item_arena::is_stmt_prepare(), Item_arena::is_first_stmt_execute(). - deletes THD::allocate_temporary_pool_for_ps_preparing(), THD::free_temporary_pool_for_ps_preparing(); they were redundant. and adds a few invariants: - thd->free_list never contains junk (= freed items) - thd->current_arena is never null. If there is no prepared statement, it points at the thd. The rest of the patch contains mainly mechanical changes and cleanups.
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r--sql/sql_class.h128
1 files changed, 60 insertions, 68 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 59ac8ff0483..61b8a8281da 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -418,6 +418,61 @@ struct system_variables
void free_tmp_table(THD *thd, TABLE *entry);
+class Item_arena
+{
+public:
+ /*
+ List of items created in the parser for this query. Every item puts
+ itself to the list on creation (see Item::Item() for details))
+ */
+ Item *free_list;
+ MEM_ROOT mem_root;
+ static const int INITIALIZED= 0, PREPARED= 1, EXECUTED= 3,
+ CONVENTIONAL_EXECUTION= 2, ERROR= -1;
+ int state;
+
+ /* We build without RTTI, so dynamic_cast can't be used. */
+ enum Type
+ {
+ STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
+ };
+
+ Item_arena(THD *thd);
+ Item_arena();
+ Item_arena(bool init_mem_root);
+ virtual Type type() const;
+ virtual ~Item_arena();
+
+ inline bool is_stmt_prepare() const { return state < PREPARED; }
+ inline bool is_first_stmt_execute() const { return state == PREPARED; }
+ inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
+ inline gptr calloc(unsigned int size)
+ {
+ gptr ptr;
+ if ((ptr=alloc_root(&mem_root,size)))
+ bzero((char*) ptr,size);
+ return ptr;
+ }
+ inline char *strdup(const char *str)
+ { return strdup_root(&mem_root,str); }
+ inline char *strmake(const char *str, uint size)
+ { return strmake_root(&mem_root,str,size); }
+ inline char *memdup(const char *str, uint size)
+ { return memdup_root(&mem_root,str,size); }
+ inline char *memdup_w_gap(const char *str, uint size, uint gap)
+ {
+ gptr ptr;
+ if ((ptr=alloc_root(&mem_root,size+gap)))
+ memcpy(ptr,str,size);
+ return ptr;
+ }
+
+ void set_n_backup_item_arena(Item_arena *set, Item_arena *backup);
+ void restore_backup_item_arena(Item_arena *set, Item_arena *backup);
+ void set_item_arena(Item_arena *set);
+};
+
+
/*
State of a single command executed against this connection.
One connection can contain a lot of simultaneously running statements,
@@ -432,7 +487,7 @@ void free_tmp_table(THD *thd, TABLE *entry);
be used explicitly.
*/
-class Statement
+class Statement: public Item_arena
{
Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */
@@ -474,20 +529,8 @@ public:
*/
char *query;
uint32 query_length; // current query length
- /*
- List of items created in the parser for this query. Every item puts
- itself to the list on creation (see Item::Item() for details))
- */
- Item *free_list;
- MEM_ROOT mem_root;
public:
- /* We build without RTTI, so dynamic_cast can't be used. */
- enum Type
- {
- STATEMENT,
- PREPARED_STATEMENT
- };
/*
This constructor is called when statement is a subobject of THD:
@@ -500,34 +543,10 @@ public:
/* Assign execution context (note: not all members) of given stmt to self */
void set_statement(Statement *stmt);
+ void set_n_backup_statement(Statement *stmt, Statement *backup);
+ void restore_backup_statement(Statement *stmt, Statement *backup);
/* return class type */
virtual Type type() const;
-
- inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
- inline gptr calloc(unsigned int size)
- {
- gptr ptr;
- if ((ptr=alloc_root(&mem_root,size)))
- bzero((char*) ptr,size);
- return ptr;
- }
- inline char *strdup(const char *str)
- { return strdup_root(&mem_root,str); }
- inline char *strmake(const char *str, uint size)
- { return strmake_root(&mem_root,str,size); }
- inline char *memdup(const char *str, uint size)
- { return memdup_root(&mem_root,str,size); }
- inline char *memdup_w_gap(const char *str, uint size, uint gap)
- {
- gptr ptr;
- if ((ptr=alloc_root(&mem_root,size+gap)))
- memcpy(ptr,str,size);
- return ptr;
- }
-
- void set_n_backup_item_arena(Statement *set, Statement *backup);
- void restore_backup_item_arena(Statement *set, Statement *backup);
- void set_item_arena(Statement *set);
};
@@ -760,9 +779,9 @@ public:
Vio* active_vio;
#endif
/*
- Current prepared Statement if there one, or 0
+ Current prepared Item_arena if there one, or 0
*/
- Statement *current_statement;
+ Item_arena *current_arena;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
@@ -983,33 +1002,6 @@ public:
}
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
-
- inline void allocate_temporary_memory_pool_for_ps_preparing()
- {
- DBUG_ASSERT(current_statement!=0);
- /*
- We do not want to have in PS memory all that junk,
- which will be created by preparation => substitute memory
- from original thread pool.
-
- We know that PS memory pool is now copied to THD, we move it back
- to allow some code use it.
- */
- current_statement->set_item_arena(this);
- init_sql_alloc(&mem_root,
- variables.query_alloc_block_size,
- variables.query_prealloc_size);
- free_list= 0;
- }
- inline void free_temporary_memory_pool_for_ps_preparing()
- {
- DBUG_ASSERT(current_statement!=0);
- cleanup_items(current_statement->free_list);
- free_items(free_list);
- close_thread_tables(this); // to close derived tables
- free_root(&mem_root, MYF(0));
- set_item_arena(current_statement);
- }
};
/* Flags for the THD::system_thread (bitmap) variable */