bool Aggregator_distinct::setup(THD *thd)
{
  endup_done= FALSE;
  /*
    Setup can be called twice for ROLLUP items. This is a bug.
    Please add DBUG_ASSERT(tree == 0) here when it's fixed.
  */
  if (tree || table || tmp_table_param)
    return FALSE;

  if (item_sum->setup(thd))
    return TRUE;
  if (item_sum->sum_func() == Item_sum::COUNT_FUNC || 
      item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
  {
    List<Item> list;
    SELECT_LEX *select_lex= thd->lex->current_select;

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

    /* Create a table with an unique key over all parameters */
    for (uint i=0; i < item_sum->get_arg_count() ; i++)
    {
      Item *item=item_sum->get_arg(i);
      if (list.push_back(item, thd->mem_root))
        return TRUE;                              // End of memory
      if (item->const_item() && item->is_null())
        always_null= true;
    }
    if (always_null)
      return FALSE;
    count_field_types(select_lex, tmp_table_param, list, 0);
    tmp_table_param->force_copy_fields= item_sum->has_force_copy_fields();
    DBUG_ASSERT(table == 0);
    /*
      Make create_tmp_table() convert BIT columns to BIGINT.
      This is needed because BIT fields store parts of their data in table's
      null bits, and we don't have methods to compare two table records, which
      is needed by Unique which is used when HEAP table is used.
    */
    {
      List_iterator_fast<Item> li(list);
      Item *item;
      while ((item= li++))
      {    
        if (item->type() == Item::FIELD_ITEM &&
            ((Item_field*)item)->field->type() == FIELD_TYPE_BIT)
          item->marker=4;
      }    
    }    
    if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
                                  0,
                                  (select_lex->options | thd->variables.option_bits),
                                  HA_POS_ERROR, const_cast<char*>(""))))
      return TRUE;
    table->file->extra(HA_EXTRA_NO_ROWS);		// Don't update rows
    table->no_rows=1;

    if (table->s->db_type() == heap_hton)
    {
      /*
        No blobs, otherwise it would have been MyISAM: set up a compare
        function and its arguments to use with Unique.
      */
      qsort_cmp2 compare_key;
      void* cmp_arg;
      Field **field= table->field;
      Field **field_end= field + table->s->fields;
      bool all_binary= TRUE;

      for (tree_key_length= 0; field < field_end; ++field)
      {
        Field *f= *field;
        enum enum_field_types type= f->type();
        tree_key_length+= f->pack_length();
        if ((type == MYSQL_TYPE_VARCHAR) ||
            (!f->binary() && (type == MYSQL_TYPE_STRING ||
                             type == MYSQL_TYPE_VAR_STRING)))
        {
          all_binary= FALSE;
          break;
        }
      }
      if (all_binary)
      {
        cmp_arg= (void*) &tree_key_length;
        compare_key= (qsort_cmp2) simple_raw_key_cmp;
      }
      else
      {
        if (table->s->fields == 1)
        {
          /*
            If we have only one field, which is the most common use of
            count(distinct), it is much faster to use a simpler key
            compare method that can take advantage of not having to worry
            about other fields.
          */
          compare_key= (qsort_cmp2) simple_str_key_cmp;
          cmp_arg= (void*) table->field[0];
          /* tree_key_length has been set already */
        }
        else
        {
          uint32 *length;
          compare_key= (qsort_cmp2) composite_key_cmp;
          cmp_arg= (void*) this;
          field_lengths= (uint32*) thd->alloc(table->s->fields * sizeof(uint32));
          for (tree_key_length= 0, length= field_lengths, field= table->field;
               field < field_end; ++field, ++length)
          {
            *length= (*field)->pack_length();
            tree_key_length+= *length;
          }
        }
      }
      DBUG_ASSERT(tree == 0);
      tree= new Unique(compare_key, cmp_arg, tree_key_length,
                       item_sum->ram_limitation(thd));
      /*
        The only time tree_key_length could be 0 is if someone does
        count(distinct) on a char(0) field - stupid thing to do,
        but this has to be handled - otherwise someone can crash
        the server with a DoS attack
      */
      if (! tree)
        return TRUE;
    }
    return FALSE;
  }
  else
  {
    Item *arg;
    DBUG_ENTER("Aggregator_distinct::setup");
    /* It's legal to call setup() more than once when in a subquery */
    if (tree)
      DBUG_RETURN(FALSE);

    /*
      Virtual table and the tree are created anew on each re-execution of
      PS/SP. Hence all further allocations are performed in the runtime
      mem_root.
    */

    item_sum->null_value= item_sum->maybe_null= 1;
    item_sum->quick_group= 0;

    DBUG_ASSERT(item_sum->get_arg(0)->fixed);

    arg= item_sum->get_arg(0);
    if (arg->const_item())
    {
      (void) arg->is_null();
      if (arg->null_value)
        always_null= true;
    }

    if (always_null)
      DBUG_RETURN(FALSE);

    Field *field= arg->make_num_distinct_aggregator_field(thd->mem_root, arg);
    if (!field || !(table= create_virtual_tmp_table(thd, field)))
      DBUG_RETURN(TRUE);

    /* XXX: check that the case of CHAR(0) works OK */
    tree_key_length= table->s->reclength - table->s->null_bytes;

    /*
      Unique handles all unique elements in a tree until they can't fit
      in.  Then the tree is dumped to the temporary file. We can use
      simple_raw_key_cmp because the table contains numbers only; decimals
      are converted to binary representation as well.
    */
    tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
                     item_sum->ram_limitation(thd));

    DBUG_RETURN(tree == 0);
  }
}