Loading sql/sp_head.cc +71 −4 Original line number Diff line number Diff line Loading @@ -696,6 +696,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) sp_rcontext *nctx = NULL; uint i; int ret; MEM_ROOT *old_mem_root, call_mem_root; Item *old_free_list, *call_free_list; if (argcount != params) { Loading @@ -706,6 +708,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) DBUG_RETURN(-1); } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); old_mem_root= thd->mem_root; thd->mem_root= &call_mem_root; old_free_list= thd->free_list; // Keep the old list thd->free_list= NULL; // Start a new one // QQ Should have some error checking here? (types, etc...) nctx= new sp_rcontext(csize, hmax, cmax); for (i= 0 ; i < params && i < argcount ; i++) Loading Loading @@ -736,13 +744,20 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) ret= execute(thd); // Partially restore context now. // We still need the call mem root and free list for processing // of the result. call_free_list= thd->free_list; thd->free_list= old_free_list; thd->mem_root= old_mem_root; if (m_type == TYPE_ENUM_FUNCTION && ret == 0) { /* We need result only in function but not in trigger */ Item *it= nctx->get_result(); if (it) *resp= it; *resp= sp_eval_func_item(thd, &it, m_returns, NULL); else { my_error(ER_SP_NORETURNEND, MYF(0), m_name.str); Loading @@ -752,6 +767,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) nctx->pop_all_cursors(); // To avoid memory leaks after an error thd->spcont= octx; // Now get rid of the rest of the callee context cleanup_items(call_free_list); free_items(call_free_list); free_root(&call_mem_root, MYF(0)); DBUG_RETURN(ret); } Loading Loading @@ -781,6 +802,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx MEM_ROOT *old_mem_root, call_mem_root; Item *old_free_list, *call_free_list; if (args->elements != params) { Loading @@ -789,6 +812,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) DBUG_RETURN(-1); } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); old_mem_root= thd->mem_root; thd->mem_root= &call_mem_root; old_free_list= thd->free_list; // Keep the old list thd->free_list= NULL; // Start a new one if (csize > 0 || hmax > 0 || cmax > 0) { Item_null *nit= NULL; // Re-use this, and only create if needed Loading Loading @@ -854,9 +883,16 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (! ret) ret= execute(thd); // Partially restore context now. // We still need the call mem root and free list for processing // of out parameters. call_free_list= thd->free_list; thd->free_list= old_free_list; thd->mem_root= old_mem_root; if (!ret && csize > 0) { List_iterator_fast<Item> li(*args); List_iterator<Item> li(*args); Item *it; // Copy back all OUT or INOUT values to the previous frame, or Loading @@ -868,8 +904,34 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (pvar->mode != sp_param_in) { if (it->is_splocal()) octx->set_item(static_cast<Item_splocal *>(it)->get_offset(), nctx->get_item(i)); { // Have to copy the item to the caller's mem_root Item *copy; uint offset= static_cast<Item_splocal *>(it)->get_offset(); Item *val= nctx->get_item(i); Item *orig= octx->get_item(offset); Item *o_item_next; Item *o_free_list= thd->free_list; LINT_INIT(o_item_next); if (orig) o_item_next= orig->next; copy= sp_eval_func_item(thd, &val, pvar->type, orig); // Copy if (!copy) { ret= -1; break; } if (copy != orig) octx->set_item(offset, copy); if (orig && copy == orig) { // A reused item slot, where the constructor put it in the // free_list, so we have to restore the list. thd->free_list= o_free_list; copy->next= o_item_next; } } else { Item_func_get_user_var *guv= item_is_user_var(it); Loading Loading @@ -900,6 +962,11 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) nctx->pop_all_cursors(); // To avoid memory leaks after an error thd->spcont= octx; // Now get rid of the rest of the callee context cleanup_items(call_free_list); free_items(call_free_list); free_root(&call_mem_root, MYF(0)); DBUG_RETURN(ret); } Loading Loading
sql/sp_head.cc +71 −4 Original line number Diff line number Diff line Loading @@ -696,6 +696,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) sp_rcontext *nctx = NULL; uint i; int ret; MEM_ROOT *old_mem_root, call_mem_root; Item *old_free_list, *call_free_list; if (argcount != params) { Loading @@ -706,6 +708,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) DBUG_RETURN(-1); } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); old_mem_root= thd->mem_root; thd->mem_root= &call_mem_root; old_free_list= thd->free_list; // Keep the old list thd->free_list= NULL; // Start a new one // QQ Should have some error checking here? (types, etc...) nctx= new sp_rcontext(csize, hmax, cmax); for (i= 0 ; i < params && i < argcount ; i++) Loading Loading @@ -736,13 +744,20 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) ret= execute(thd); // Partially restore context now. // We still need the call mem root and free list for processing // of the result. call_free_list= thd->free_list; thd->free_list= old_free_list; thd->mem_root= old_mem_root; if (m_type == TYPE_ENUM_FUNCTION && ret == 0) { /* We need result only in function but not in trigger */ Item *it= nctx->get_result(); if (it) *resp= it; *resp= sp_eval_func_item(thd, &it, m_returns, NULL); else { my_error(ER_SP_NORETURNEND, MYF(0), m_name.str); Loading @@ -752,6 +767,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) nctx->pop_all_cursors(); // To avoid memory leaks after an error thd->spcont= octx; // Now get rid of the rest of the callee context cleanup_items(call_free_list); free_items(call_free_list); free_root(&call_mem_root, MYF(0)); DBUG_RETURN(ret); } Loading Loading @@ -781,6 +802,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx MEM_ROOT *old_mem_root, call_mem_root; Item *old_free_list, *call_free_list; if (args->elements != params) { Loading @@ -789,6 +812,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) DBUG_RETURN(-1); } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); old_mem_root= thd->mem_root; thd->mem_root= &call_mem_root; old_free_list= thd->free_list; // Keep the old list thd->free_list= NULL; // Start a new one if (csize > 0 || hmax > 0 || cmax > 0) { Item_null *nit= NULL; // Re-use this, and only create if needed Loading Loading @@ -854,9 +883,16 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (! ret) ret= execute(thd); // Partially restore context now. // We still need the call mem root and free list for processing // of out parameters. call_free_list= thd->free_list; thd->free_list= old_free_list; thd->mem_root= old_mem_root; if (!ret && csize > 0) { List_iterator_fast<Item> li(*args); List_iterator<Item> li(*args); Item *it; // Copy back all OUT or INOUT values to the previous frame, or Loading @@ -868,8 +904,34 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (pvar->mode != sp_param_in) { if (it->is_splocal()) octx->set_item(static_cast<Item_splocal *>(it)->get_offset(), nctx->get_item(i)); { // Have to copy the item to the caller's mem_root Item *copy; uint offset= static_cast<Item_splocal *>(it)->get_offset(); Item *val= nctx->get_item(i); Item *orig= octx->get_item(offset); Item *o_item_next; Item *o_free_list= thd->free_list; LINT_INIT(o_item_next); if (orig) o_item_next= orig->next; copy= sp_eval_func_item(thd, &val, pvar->type, orig); // Copy if (!copy) { ret= -1; break; } if (copy != orig) octx->set_item(offset, copy); if (orig && copy == orig) { // A reused item slot, where the constructor put it in the // free_list, so we have to restore the list. thd->free_list= o_free_list; copy->next= o_item_next; } } else { Item_func_get_user_var *guv= item_is_user_var(it); Loading Loading @@ -900,6 +962,11 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) nctx->pop_all_cursors(); // To avoid memory leaks after an error thd->spcont= octx; // Now get rid of the rest of the callee context cleanup_items(call_free_list); free_items(call_free_list); free_root(&call_mem_root, MYF(0)); DBUG_RETURN(ret); } Loading