Commit 7ce7a818 authored by Tor Didriksen's avatar Tor Didriksen

Backport of

Bug#45523 "Objects of class base_ilist should not be copyable".
               
Suppress the compiler-generated public copy constructor
and assignment operator of class base_ilist; instead, implement
move_elements_to() function which transfers ownership of elements
from one list to another.
parent ec7e7833
...@@ -1171,8 +1171,7 @@ sp_head::execute(THD *thd) ...@@ -1171,8 +1171,7 @@ sp_head::execute(THD *thd)
We should also save Item tree change list to avoid rollback something We should also save Item tree change list to avoid rollback something
too early in the calling query. too early in the calling query.
*/ */
old_change_list= thd->change_list; thd->change_list.move_elements_to(&old_change_list);
thd->change_list.empty();
/* /*
Cursors will use thd->packet, so they may corrupt data which was prepared Cursors will use thd->packet, so they may corrupt data which was prepared
for sending by upper level. OTOH cursors in the same routine can share this for sending by upper level. OTOH cursors in the same routine can share this
...@@ -1318,9 +1317,7 @@ sp_head::execute(THD *thd) ...@@ -1318,9 +1317,7 @@ sp_head::execute(THD *thd)
/* Restore all saved */ /* Restore all saved */
old_packet.swap(thd->packet); old_packet.swap(thd->packet);
DBUG_ASSERT(thd->change_list.is_empty()); DBUG_ASSERT(thd->change_list.is_empty());
thd->change_list= old_change_list; old_change_list.move_elements_to(&thd->change_list);
/* To avoid wiping out thd->change_list on old_change_list destruction */
old_change_list.empty();
thd->lex= old_lex; thd->lex= old_lex;
thd->query_id= old_query_id; thd->query_id= old_query_id;
DBUG_ASSERT(!thd->derived_tables); DBUG_ASSERT(!thd->derived_tables);
......
...@@ -321,7 +321,7 @@ Sensitive_cursor::post_open(THD *thd) ...@@ -321,7 +321,7 @@ Sensitive_cursor::post_open(THD *thd)
lock= thd->lock; lock= thd->lock;
query_id= thd->query_id; query_id= thd->query_id;
free_list= thd->free_list; free_list= thd->free_list;
change_list= thd->change_list; thd->change_list.move_elements_to(&change_list);
reset_thd(thd); reset_thd(thd);
/* Now we have an active cursor and can cause a deadlock */ /* Now we have an active cursor and can cause a deadlock */
thd->lock_info.n_cursors++; thd->lock_info.n_cursors++;
...@@ -437,7 +437,7 @@ Sensitive_cursor::fetch(ulong num_rows) ...@@ -437,7 +437,7 @@ Sensitive_cursor::fetch(ulong num_rows)
thd->open_tables= open_tables; thd->open_tables= open_tables;
thd->lock= lock; thd->lock= lock;
thd->query_id= query_id; thd->query_id= query_id;
thd->change_list= change_list; change_list.move_elements_to(&thd->change_list);
/* save references to memory allocated during fetch */ /* save references to memory allocated during fetch */
thd->set_n_backup_active_arena(this, &backup_arena); thd->set_n_backup_active_arena(this, &backup_arena);
...@@ -459,7 +459,7 @@ Sensitive_cursor::fetch(ulong num_rows) ...@@ -459,7 +459,7 @@ Sensitive_cursor::fetch(ulong num_rows)
/* Grab free_list here to correctly free it in close */ /* Grab free_list here to correctly free it in close */
thd->restore_active_arena(this, &backup_arena); thd->restore_active_arena(this, &backup_arena);
change_list= thd->change_list; thd->change_list.move_elements_to(&change_list);
reset_thd(thd); reset_thd(thd);
for (info= ht_info; info->read_view; info++) for (info= ht_info; info->read_view; info++)
...@@ -506,7 +506,7 @@ Sensitive_cursor::close() ...@@ -506,7 +506,7 @@ Sensitive_cursor::close()
info->ht= 0; info->ht= 0;
} }
thd->change_list= change_list; change_list.move_elements_to(&thd->change_list);
{ {
/* /*
XXX: Another hack: we need to set THD state as if in a fetch to be XXX: Another hack: we need to set THD state as if in a fetch to be
...@@ -532,7 +532,6 @@ Sensitive_cursor::close() ...@@ -532,7 +532,6 @@ Sensitive_cursor::close()
join= 0; join= 0;
stmt_arena= 0; stmt_arena= 0;
free_items(); free_items();
change_list.empty();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -504,15 +504,12 @@ class i_string_pair: public ilink ...@@ -504,15 +504,12 @@ class i_string_pair: public ilink
template <class T> class I_List_iterator; template <class T> class I_List_iterator;
/*
WARNING: copy constructor of this class does not create a usable
copy, as its members may point at each other.
*/
class base_ilist class base_ilist
{ {
struct ilink *first;
struct ilink last;
public: public:
struct ilink *first,last;
inline void empty() { first= &last; last.prev= &first; } inline void empty() { first= &last; last.prev= &first; }
base_ilist() { empty(); } base_ilist() { empty(); }
inline bool is_empty() { return first == &last; } inline bool is_empty() { return first == &last; }
...@@ -540,7 +537,31 @@ class base_ilist ...@@ -540,7 +537,31 @@ class base_ilist
{ {
return (first != &last) ? first : 0; return (first != &last) ? first : 0;
} }
friend class base_list_iterator;
/**
Moves list elements to new owner, and empties current owner (i.e. this).
@param[in,out] new_owner The new owner of the list elements.
Should be empty in input.
*/
void move_elements_to(base_ilist *new_owner)
{
DBUG_ASSERT(new_owner->is_empty());
new_owner->first= first;
new_owner->last= last;
empty();
}
friend class base_ilist_iterator;
private:
/*
We don't want to allow copying of this class, as that would give us
two list heads containing the same elements.
So we declare, but don't define copy CTOR and assignment operator.
*/
base_ilist(const base_ilist&);
void operator=(const base_ilist&);
}; };
...@@ -573,6 +594,9 @@ class I_List :private base_ilist ...@@ -573,6 +594,9 @@ class I_List :private base_ilist
inline void push_back(T* a) { base_ilist::push_back(a); } inline void push_back(T* a) { base_ilist::push_back(a); }
inline T* get() { return (T*) base_ilist::get(); } inline T* get() { return (T*) base_ilist::get(); }
inline T* head() { return (T*) base_ilist::head(); } inline T* head() { return (T*) base_ilist::head(); }
inline void move_elements_to(I_List<T>* new_owner) {
base_ilist::move_elements_to(new_owner);
}
#ifndef _lint #ifndef _lint
friend class I_List_iterator<T>; friend class I_List_iterator<T>;
#endif #endif
......
...@@ -3407,7 +3407,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable) ...@@ -3407,7 +3407,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable)
bool error; bool error;
Query_arena *save_stmt_arena= thd->stmt_arena; Query_arena *save_stmt_arena= thd->stmt_arena;
Item_change_list save_change_list; Item_change_list save_change_list;
thd->change_list= save_change_list; thd->change_list.move_elements_to(&save_change_list);
state= CONVENTIONAL_EXECUTION; state= CONVENTIONAL_EXECUTION;
...@@ -3431,7 +3431,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable) ...@@ -3431,7 +3431,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable)
thd->restore_backup_statement(this, &stmt_backup); thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= save_stmt_arena; thd->stmt_arena= save_stmt_arena;
save_change_list= thd->change_list; save_change_list.move_elements_to(&thd->change_list);
/* Items and memory will freed in destructor */ /* Items and memory will freed in destructor */
......
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