bool Item_func_group_concat::setup(THD *thd)
{
  List<Item> list;
  SELECT_LEX *select_lex= thd->lex->current_select;
  const bool order_or_distinct= MY_TEST(arg_count_order > 0 || distinct);
  DBUG_ENTER("Item_func_group_concat::setup");

  /*
    Currently setup() can be called twice. Please add
    assertion here when this is fixed.
  */
  if (table || tree)
    DBUG_RETURN(FALSE);

  if (!(tmp_table_param= new TMP_TABLE_PARAM))
    DBUG_RETURN(TRUE);

  /* Push all not constant fields to the list and create a temp table */
  always_null= 0;
  for (uint i= 0; i < arg_count_field; i++)
  {
    Item *item= args[i];
    if (list.push_back(item, thd->mem_root))
      DBUG_RETURN(TRUE);
    if (item->const_item())
    {
      if (item->is_null())
      {
        always_null= 1;
        DBUG_RETURN(FALSE);
      }
    }
  }

  List<Item> all_fields(list);
  /*
    Try to find every ORDER expression in the list of GROUP_CONCAT
    arguments. If an expression is not found, prepend it to
    "all_fields". The resulting field list is used as input to create
    tmp table columns.
  */
  if (arg_count_order)
  {
    uint n_elems= arg_count_order + all_fields.elements;
    ref_pointer_array= static_cast<Item**>(thd->alloc(sizeof(Item*) * n_elems));
    if (!ref_pointer_array)
      DBUG_RETURN(TRUE);
    memcpy(ref_pointer_array, args, arg_count * sizeof(Item*));
    if (setup_order(thd, Ref_ptr_array(ref_pointer_array, n_elems),
                    context->table_list, list,  all_fields, *order))
      DBUG_RETURN(TRUE);
    /*
      Prepend the field to store the length of the string representation
      of this row. Used to detect when the tree goes over group_concat_max_len
    */
    Item *item= new (thd->mem_root)
                    Item_uint(thd, thd->variables.group_concat_max_len);
    if (!item || all_fields.push_front(item, thd->mem_root))
      DBUG_RETURN(TRUE);
  }

  count_field_types(select_lex, tmp_table_param, all_fields, 0);
  tmp_table_param->force_copy_fields= force_copy_fields;
  tmp_table_param->hidden_field_count= (arg_count_order > 0);
  DBUG_ASSERT(table == 0);
  if (order_or_distinct)
  {
    /*
      Force the create_tmp_table() to convert BIT columns to INT
      as we cannot compare two table records containing BIT fields
      stored in the the tree used for distinct/order by.
      Moreover we don't even save in the tree record null bits 
      where BIT fields store parts of their data.
    */
    List_iterator_fast<Item> li(all_fields);
    Item *item;
    while ((item= li++))
    {
      if (item->type() == Item::FIELD_ITEM && 
          ((Item_field*) item)->field->type() == FIELD_TYPE_BIT)
        item->marker= 4;
    }
  }

  /*
    We have to create a temporary table to get descriptions of fields
    (types, sizes and so on).

    Note that in the table, we first have the ORDER BY fields, then the
    field list.
  */
  if (!(table= create_tmp_table(thd, tmp_table_param, all_fields,
                                (ORDER*) 0, 0, TRUE,
                                (select_lex->options |
                                 thd->variables.option_bits),
                                HA_POS_ERROR, (char*) "")))
    DBUG_RETURN(TRUE);
  table->file->extra(HA_EXTRA_NO_ROWS);
  table->no_rows= 1;

  /**
    Initialize blob_storage if GROUP_CONCAT is used
    with ORDER BY | DISTINCT and BLOB field count > 0.    
  */
  if (order_or_distinct && table->s->blob_fields)
    table->blob_storage= new Blob_mem_storage();

  /*
     Need sorting or uniqueness: init tree and choose a function to sort.
     Don't reserve space for NULLs: if any of gconcat arguments is NULL,
     the row is not added to the result.
  */
  uint tree_key_length= table->s->reclength - table->s->null_bytes;

  if (arg_count_order)
  {
    tree= &tree_base;
    /*
      Create a tree for sorting. The tree is used to sort (according to the
      syntax of this function). If there is no ORDER BY clause, we don't
      create this tree.
    */
    init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size,
                                   thd->variables.sortbuff_size/16), 0,
              tree_key_length,
              group_concat_key_cmp_with_order, NULL, (void*) this,
              MYF(MY_THREAD_SPECIFIC));
    tree_len= 0;
  }

  if (distinct)
    unique_filter= new Unique(group_concat_key_cmp_with_distinct,
                              (void*)this,
                              tree_key_length,
                              ram_limitation(thd));
  
  DBUG_RETURN(FALSE);
}