Commit ab1ba134 authored by unknown's avatar unknown
Browse files

Merge pmartin@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/home/pem/work/mysql-5.0

parents 0e4afc24 9c79a9d6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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),
+18 −0
Original line number Diff line number Diff line
@@ -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) {}

@@ -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
+20 −25
Original line number Diff line number Diff line
@@ -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)
@@ -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)) {
@@ -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;
      }
@@ -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
	{
@@ -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;
	}
@@ -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)));
@@ -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;
      }
@@ -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);
}
@@ -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);
@@ -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
@@ -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;
}

@@ -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
+52 −11
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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())
    {
@@ -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
    {
      /*
@@ -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())
+3 −4
Original line number Diff line number Diff line
@@ -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)
@@ -82,7 +82,6 @@ class sp_rcontext : public Sql_alloc
    return m_frame[idx];
  }


  inline Item **
  get_item_addr(uint idx)
  {
Loading