Loading sql/item.cc +2 −1 Original line number Diff line number Diff line Loading @@ -298,7 +298,7 @@ longlong Item::val_int_from_decimal() Item::Item(): name(0), orig_name(0), name_length(0), fixed(0), rsize(0), name(0), orig_name(0), name_length(0), fixed(0), collation(&my_charset_bin, DERIVATION_COERCIBLE) { marker= 0; Loading Loading @@ -330,6 +330,7 @@ Item::Item(): tables */ Item::Item(THD *thd, Item *item): rsize(0), str_value(item->str_value), name(item->name), orig_name(item->orig_name), Loading sql/item.h +18 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,21 @@ class Item { static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } /* Special for SP local variable assignment - reusing slots */ static void *operator new(size_t size, Item *reuse, uint *rsize) { if (reuse && size <= reuse->rsize) { reuse->cleanup(); TRASH((void *)reuse, size); if (rsize) (*rsize)= reuse->rsize; return (void *)reuse; } if (rsize) (*rsize)= size; return (void *)sql_alloc((uint)size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} Loading @@ -247,6 +262,9 @@ class Item { enum traverse_order { POSTFIX, PREFIX }; /* Reuse size, only used by SP local variable assignment, otherwize 0 */ uint rsize; /* str_values's main purpose is to be used to cache the value in save_in_field Loading sql/sp_head.cc +20 −25 Original line number Diff line number Diff line Loading @@ -131,10 +131,12 @@ sp_prepare_func_item(THD* thd, Item **it_addr) ** if nothing else. */ Item * sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, Item *reuse) { DBUG_ENTER("sp_eval_func_item"); Item *it= sp_prepare_func_item(thd, it_addr); uint rsize; DBUG_PRINT("info", ("type: %d", type)); if (!it) Loading @@ -144,7 +146,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) /* QQ How do we do this? Is there some better way? */ if (type == MYSQL_TYPE_NULL) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else { switch (sp_map_result_type(type)) { Loading @@ -155,12 +157,12 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("INT_RESULT: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { DBUG_PRINT("info", ("INT_RESULT: %d", i)); it= new Item_int(i); it= new(reuse, &rsize) Item_int(i); } break; } Loading @@ -171,7 +173,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("REAL_RESULT: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { Loading @@ -180,7 +182,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) uint8 decimals= it->decimals; uint32 max_length= it->max_length; DBUG_PRINT("info", ("REAL_RESULT: %g", d)); it= new Item_float(d); it= new(reuse, &rsize) Item_float(d); it->decimals= decimals; it->max_length= max_length; } Loading @@ -190,9 +192,9 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { my_decimal value, *val= it->val_decimal(&value); if (it->null_value) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else it= new Item_decimal(val); it= new(reuse, &rsize) Item_decimal(val); #ifndef DBUG_OFF char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val))); Loading @@ -208,14 +210,16 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("default result: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { DBUG_PRINT("info",("default result: %*s", s->length(), s->c_ptr_quick())); it= new Item_string(thd->strmake(s->ptr(), s->length()), s->length(), it->collation.collation); it= new(reuse, &rsize) Item_string(thd->strmake(s->ptr(), s->length()), s->length(), it->collation.collation); } break; } Loading @@ -224,6 +228,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) DBUG_ASSERT(0); } } it->rsize= rsize; DBUG_RETURN(it); } Loading Loading @@ -708,7 +713,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, argp++, pvar->type); Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL); if (it) nctx->push_item(it); Loading Loading @@ -823,7 +828,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type, NULL); if (it2) nctx->push_item(it2); // IN or INOUT Loading Loading @@ -1466,19 +1471,9 @@ sp_instr_set::execute(THD *thd, uint *nextp) int sp_instr_set::exec_core(THD *thd, uint *nextp) { Item *it; int res; int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else { res= 0; thd->spcont->set_item(m_offset, it); } *nextp = m_ip+1; return res; } Loading Loading @@ -1715,7 +1710,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, &m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type, NULL); if (! it) res= -1; else Loading sql/sp_rcontext.cc +52 −11 Original line number Diff line number Diff line Loading @@ -40,19 +40,39 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) m_saved.empty(); } int sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type) sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr, enum_field_types type) { extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type); Item *it= sp_eval_func_item(current_thd, item_addr, type); extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type, Item *reuse); Item *it; Item *reuse_it; Item *old_item_next; Item *old_free_list= thd->free_list; int res; LINT_INIT(old_item_next); if ((reuse_it= get_item(idx))) old_item_next= reuse_it->next; it= sp_eval_func_item(thd, item_addr, type, reuse_it); if (! it) return -1; res= -1; else { res= 0; if (reuse_it && it == reuse_it) { // A reused item slot, where the constructor put it in the free_list, // so we have to restore the list. thd->free_list= old_free_list; it->next= old_item_next; } set_item(idx, it); return 0; } return res; } bool Loading Loading @@ -111,7 +131,10 @@ void sp_rcontext::save_variables(uint fp) { while (fp < m_count) m_saved.push_front(m_frame[fp++]); { m_saved.push_front(m_frame[fp]); m_frame[fp++]= NULL; // Prevent reuse } } void Loading Loading @@ -230,7 +253,12 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) for (fldcount= 0 ; (pv= li++) ; fldcount++) { Item *it; Item *reuse; uint rsize; Item *old_item_next; Item *old_free_list= thd->free_list; const char *s; LINT_INIT(old_item_next); if (fldcount >= m_prot->get_field_count()) { Loading @@ -238,9 +266,13 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0)); return -1; } if ((reuse= thd->spcont->get_item(pv->offset))) old_item_next= reuse->next; s= row[fldcount]; if (!s) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else { /* Loading @@ -255,23 +287,32 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) len= (*next -s)-1; switch (sp_map_result_type(pv->type)) { case INT_RESULT: it= new Item_int(s); it= new(reuse, &rsize) Item_int(s); break; case REAL_RESULT: it= new Item_float(s, len); it= new(reuse, &rsize) Item_float(s, len); break; case DECIMAL_RESULT: it= new Item_decimal(s, len, thd->db_charset); it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset); break; case STRING_RESULT: /* TODO: Document why we do an extra copy of the string 's' here */ it= new Item_string(thd->strmake(s, len), len, thd->db_charset); it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len, thd->db_charset); break; case ROW_RESULT: default: DBUG_ASSERT(0); } } it->rsize= rsize; if (reuse && it == reuse) { // A reused item slot, where the constructor put it in the free_list, // so we have to restore the list. thd->free_list= old_free_list; it->next= old_item_next; } thd->spcont->set_item(pv->offset, it); } if (fldcount < m_prot->get_field_count()) Loading sql/sp_rcontext.h +3 −4 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class sp_rcontext : public Sql_alloc /* Returns 0 on success, -1 on (eval) failure */ int set_item_eval(uint idx, Item **i, enum_field_types type); set_item_eval(THD *thd, uint idx, Item **i, enum_field_types type); inline Item * get_item(uint idx) Loading @@ -82,7 +82,6 @@ class sp_rcontext : public Sql_alloc return m_frame[idx]; } inline Item ** get_item_addr(uint idx) { Loading Loading
sql/item.cc +2 −1 Original line number Diff line number Diff line Loading @@ -298,7 +298,7 @@ longlong Item::val_int_from_decimal() Item::Item(): name(0), orig_name(0), name_length(0), fixed(0), rsize(0), name(0), orig_name(0), name_length(0), fixed(0), collation(&my_charset_bin, DERIVATION_COERCIBLE) { marker= 0; Loading Loading @@ -330,6 +330,7 @@ Item::Item(): tables */ Item::Item(THD *thd, Item *item): rsize(0), str_value(item->str_value), name(item->name), orig_name(item->orig_name), Loading
sql/item.h +18 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,21 @@ class Item { static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } /* Special for SP local variable assignment - reusing slots */ static void *operator new(size_t size, Item *reuse, uint *rsize) { if (reuse && size <= reuse->rsize) { reuse->cleanup(); TRASH((void *)reuse, size); if (rsize) (*rsize)= reuse->rsize; return (void *)reuse; } if (rsize) (*rsize)= size; return (void *)sql_alloc((uint)size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} Loading @@ -247,6 +262,9 @@ class Item { enum traverse_order { POSTFIX, PREFIX }; /* Reuse size, only used by SP local variable assignment, otherwize 0 */ uint rsize; /* str_values's main purpose is to be used to cache the value in save_in_field Loading
sql/sp_head.cc +20 −25 Original line number Diff line number Diff line Loading @@ -131,10 +131,12 @@ sp_prepare_func_item(THD* thd, Item **it_addr) ** if nothing else. */ Item * sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, Item *reuse) { DBUG_ENTER("sp_eval_func_item"); Item *it= sp_prepare_func_item(thd, it_addr); uint rsize; DBUG_PRINT("info", ("type: %d", type)); if (!it) Loading @@ -144,7 +146,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) /* QQ How do we do this? Is there some better way? */ if (type == MYSQL_TYPE_NULL) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else { switch (sp_map_result_type(type)) { Loading @@ -155,12 +157,12 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("INT_RESULT: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { DBUG_PRINT("info", ("INT_RESULT: %d", i)); it= new Item_int(i); it= new(reuse, &rsize) Item_int(i); } break; } Loading @@ -171,7 +173,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("REAL_RESULT: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { Loading @@ -180,7 +182,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) uint8 decimals= it->decimals; uint32 max_length= it->max_length; DBUG_PRINT("info", ("REAL_RESULT: %g", d)); it= new Item_float(d); it= new(reuse, &rsize) Item_float(d); it->decimals= decimals; it->max_length= max_length; } Loading @@ -190,9 +192,9 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { my_decimal value, *val= it->val_decimal(&value); if (it->null_value) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else it= new Item_decimal(val); it= new(reuse, &rsize) Item_decimal(val); #ifndef DBUG_OFF char dbug_buff[DECIMAL_MAX_STR_LENGTH+1]; DBUG_PRINT("info", ("DECIMAL_RESULT: %s", dbug_decimal_as_string(dbug_buff, val))); Loading @@ -208,14 +210,16 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) if (it->null_value) { DBUG_PRINT("info", ("default result: null")); it= new Item_null(); it= new(reuse, &rsize) Item_null(); } else { DBUG_PRINT("info",("default result: %*s", s->length(), s->c_ptr_quick())); it= new Item_string(thd->strmake(s->ptr(), s->length()), s->length(), it->collation.collation); it= new(reuse, &rsize) Item_string(thd->strmake(s->ptr(), s->length()), s->length(), it->collation.collation); } break; } Loading @@ -224,6 +228,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) DBUG_ASSERT(0); } } it->rsize= rsize; DBUG_RETURN(it); } Loading Loading @@ -708,7 +713,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); Item *it= sp_eval_func_item(thd, argp++, pvar->type); Item *it= sp_eval_func_item(thd, argp++, pvar->type, NULL); if (it) nctx->push_item(it); Loading Loading @@ -823,7 +828,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type, NULL); if (it2) nctx->push_item(it2); // IN or INOUT Loading Loading @@ -1466,19 +1471,9 @@ sp_instr_set::execute(THD *thd, uint *nextp) int sp_instr_set::exec_core(THD *thd, uint *nextp) { Item *it; int res; int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else { res= 0; thd->spcont->set_item(m_offset, it); } *nextp = m_ip+1; return res; } Loading Loading @@ -1715,7 +1710,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; it= sp_eval_func_item(thd, &m_value, m_type); it= sp_eval_func_item(thd, &m_value, m_type, NULL); if (! it) res= -1; else Loading
sql/sp_rcontext.cc +52 −11 Original line number Diff line number Diff line Loading @@ -40,19 +40,39 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) m_saved.empty(); } int sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type) sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr, enum_field_types type) { extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type); Item *it= sp_eval_func_item(current_thd, item_addr, type); extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type, Item *reuse); Item *it; Item *reuse_it; Item *old_item_next; Item *old_free_list= thd->free_list; int res; LINT_INIT(old_item_next); if ((reuse_it= get_item(idx))) old_item_next= reuse_it->next; it= sp_eval_func_item(thd, item_addr, type, reuse_it); if (! it) return -1; res= -1; else { res= 0; if (reuse_it && it == reuse_it) { // A reused item slot, where the constructor put it in the free_list, // so we have to restore the list. thd->free_list= old_free_list; it->next= old_item_next; } set_item(idx, it); return 0; } return res; } bool Loading Loading @@ -111,7 +131,10 @@ void sp_rcontext::save_variables(uint fp) { while (fp < m_count) m_saved.push_front(m_frame[fp++]); { m_saved.push_front(m_frame[fp]); m_frame[fp++]= NULL; // Prevent reuse } } void Loading Loading @@ -230,7 +253,12 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) for (fldcount= 0 ; (pv= li++) ; fldcount++) { Item *it; Item *reuse; uint rsize; Item *old_item_next; Item *old_free_list= thd->free_list; const char *s; LINT_INIT(old_item_next); if (fldcount >= m_prot->get_field_count()) { Loading @@ -238,9 +266,13 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0)); return -1; } if ((reuse= thd->spcont->get_item(pv->offset))) old_item_next= reuse->next; s= row[fldcount]; if (!s) it= new Item_null(); it= new(reuse, &rsize) Item_null(); else { /* Loading @@ -255,23 +287,32 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) len= (*next -s)-1; switch (sp_map_result_type(pv->type)) { case INT_RESULT: it= new Item_int(s); it= new(reuse, &rsize) Item_int(s); break; case REAL_RESULT: it= new Item_float(s, len); it= new(reuse, &rsize) Item_float(s, len); break; case DECIMAL_RESULT: it= new Item_decimal(s, len, thd->db_charset); it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset); break; case STRING_RESULT: /* TODO: Document why we do an extra copy of the string 's' here */ it= new Item_string(thd->strmake(s, len), len, thd->db_charset); it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len, thd->db_charset); break; case ROW_RESULT: default: DBUG_ASSERT(0); } } it->rsize= rsize; if (reuse && it == reuse) { // A reused item slot, where the constructor put it in the free_list, // so we have to restore the list. thd->free_list= old_free_list; it->next= old_item_next; } thd->spcont->set_item(pv->offset, it); } if (fldcount < m_prot->get_field_count()) Loading
sql/sp_rcontext.h +3 −4 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class sp_rcontext : public Sql_alloc /* Returns 0 on success, -1 on (eval) failure */ int set_item_eval(uint idx, Item **i, enum_field_types type); set_item_eval(THD *thd, uint idx, Item **i, enum_field_types type); inline Item * get_item(uint idx) Loading @@ -82,7 +82,6 @@ class sp_rcontext : public Sql_alloc return m_frame[idx]; } inline Item ** get_item_addr(uint idx) { Loading