void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
{
  Item *item= *ref;
  if (item->basic_const_item())
    return;                                     // Can't be better

  Item *new_item= NULL;
  Item_result res_type= item_cmp_type(comp_item, item);
  char *name= item->name;                       // Alloced on THD::mem_root
  MEM_ROOT *mem_root= thd->mem_root;

  switch (res_type) {
  case TIME_RESULT:
  {
    enum_field_types type= item->field_type_for_temporal_comparison(comp_item);
    longlong value= item->val_temporal_packed(type);
    if (item->null_value)
      new_item= new (mem_root) Item_null(thd, name);
    else
    {
      Item_cache_temporal *cache= new (mem_root) Item_cache_temporal(thd, type);
      cache->store_packed(value, item);
      new_item= cache;
    }
    break;
  }
  case STRING_RESULT:
  {
    char buff[MAX_FIELD_WIDTH];
    String tmp(buff,sizeof(buff),&my_charset_bin),*result;
    result=item->val_str(&tmp);
    if (item->null_value)
      new_item= new (mem_root) Item_null(thd, name);
    else
    {
      uint length= result->length();
      char *tmp_str= thd->strmake(result->ptr(), length);
      new_item= new (mem_root) Item_string(thd, name, tmp_str, length, result->charset());
    }
    break;
  }
  case INT_RESULT:
  {
    longlong result=item->val_int();
    uint length=item->max_length;
    bool null_value=item->null_value;
    new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) :
               (Item*) new (mem_root) Item_int(thd, name, result, length));
    break;
  }
  case ROW_RESULT:
  if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
  {
    /*
      Substitute constants only in Item_row's. Don't affect other Items
      with ROW_RESULT (eg Item_singlerow_subselect).

      For such Items more optimal is to detect if it is constant and replace
      it with Item_row. This would optimize queries like this:
      SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
    */
    Item_row *item_row= (Item_row*) item;
    Item_row *comp_item_row= (Item_row*) comp_item;
    uint col;
    new_item= 0;
    /*
      If item and comp_item are both Item_row's and have same number of cols
      then process items in Item_row one by one.
      We can't ignore NULL values here as this item may be used with <=>, in
      which case NULL's are significant.
    */
    DBUG_ASSERT(item->result_type() == comp_item->result_type());
    DBUG_ASSERT(item_row->cols() == comp_item_row->cols());
    col= item_row->cols();
    while (col-- > 0)
      resolve_const_item(thd, item_row->addr(col),
                         comp_item_row->element_index(col));
    break;
  }
  /* Fallthrough */
  case REAL_RESULT:
  {						// It must REAL_RESULT
    double result= item->val_real();
    uint length=item->max_length,decimals=item->decimals;
    bool null_value=item->null_value;
    new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) : (Item*)
               new (mem_root) Item_float(thd, name, result, decimals, length));
    break;
  }
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value;
    my_decimal *result= item->val_decimal(&decimal_value);
    uint length= item->max_length, decimals= item->decimals;
    bool null_value= item->null_value;
    new_item= (null_value ?
               (Item*) new (mem_root) Item_null(thd, name) :
               (Item*) new (mem_root) Item_decimal(thd, name, result, length, decimals));
    break;
  }
  }
  if (new_item)
    thd->change_item_tree(ref, new_item);
}