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.
This commit is contained in:
parent
0bce0c9041
commit
6766c0d676
@ -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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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()
|
|||||||
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()
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
{
|
{
|
||||||
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 @@ public:
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user