void get_partition_set(const TABLE *table, uchar *buf, const uint index,
                       const key_range *key_spec, part_id_range *part_spec)
{
  partition_info *part_info= table->part_info;
  uint num_parts= part_info->get_tot_partitions();
  uint i, part_id;
  uint sub_part= num_parts;
  uint32 part_part= num_parts;
  KEY *key_info= NULL;
  bool found_part_field= FALSE;
  DBUG_ENTER("get_partition_set");

  part_spec->start_part= 0;
  part_spec->end_part= num_parts - 1;
  if ((index < MAX_KEY) && 
       key_spec && key_spec->flag == (uint)HA_READ_KEY_EXACT &&
       part_info->some_fields_in_PF.is_set(index))
  {
    key_info= table->key_info+index;
    /*
      The index can potentially provide at least one PF-field (field in the
      partition function). Thus it is interesting to continue our probe.
    */
    if (key_spec->length == key_info->key_length)
    {
      /*
        The entire key is set so we can check whether we can immediately
        derive either the complete PF or if we can derive either
        the top PF or the subpartitioning PF. This can be established by
        checking precalculated bits on each index.
      */
      if (part_info->all_fields_in_PF.is_set(index))
      {
        /*
          We can derive the exact partition to use, no more than this one
          is needed.
        */
        get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
        /*
          Check if range can be adjusted by looking in read_partitions
        */
        prune_partition_set(table, part_spec);
        DBUG_VOID_RETURN;
      }
      else if (part_info->is_sub_partitioned())
      {
        if (part_info->all_fields_in_SPF.is_set(index))
        {
          if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
          {
            part_spec->start_part= num_parts;
            DBUG_VOID_RETURN;
          }
        }
        else if (part_info->all_fields_in_PPF.is_set(index))
        {
          if (get_part_id_from_key(table,buf,key_info,
                                   key_spec,(uint32*)&part_part))
          {
            /*
              The value of the RANGE or LIST partitioning was outside of
              allowed values. Thus it is certain that the result of this
              scan will be empty.
            */
            part_spec->start_part= num_parts;
            DBUG_VOID_RETURN;
          }
        }
      }
    }
    else
    {
      /*
        Set an indicator on all partition fields that are bound.
        If at least one PF-field was bound it pays off to check whether
        the PF or PPF or SPF has been bound.
        (PF = Partition Function, SPF = Subpartition Function and
         PPF = Partition Function part of subpartitioning)
      */
      if ((found_part_field= set_PF_fields_in_key(key_info,
                                                  key_spec->length)))
      {
        if (check_part_func_bound(part_info->full_part_field_array))
        {
          /*
            We were able to bind all fields in the partition function even
            by using only a part of the key. Calculate the partition to use.
          */
          get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
          clear_indicator_in_key_fields(key_info);
          /*
            Check if range can be adjusted by looking in read_partitions
          */
          prune_partition_set(table, part_spec);
          DBUG_VOID_RETURN; 
        }
        else if (part_info->is_sub_partitioned())
        {
          if (check_part_func_bound(part_info->subpart_field_array))
          {
            if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
            {
              part_spec->start_part= num_parts;
              clear_indicator_in_key_fields(key_info);
              DBUG_VOID_RETURN;
            }
          }
          else if (check_part_func_bound(part_info->part_field_array))
          {
            if (get_part_id_from_key(table,buf,key_info,key_spec,&part_part))
            {
              part_spec->start_part= num_parts;
              clear_indicator_in_key_fields(key_info);
              DBUG_VOID_RETURN;
            }
          }
        }
      }
    }
  }
  {
    /*
      The next step is to analyse the table condition to see whether any
      information about which partitions to scan can be derived from there.
      Currently not implemented.
    */
  }
  /*
    If we come here we have found a range of sorts we have either discovered
    nothing or we have discovered a range of partitions with possible holes
    in it. We need a bitvector to further the work here.
  */
  if (!(part_part == num_parts && sub_part == num_parts))
  {
    /*
      We can only arrive here if we are using subpartitioning.
    */
    if (part_part != num_parts)
    {
      /*
        We know the top partition and need to scan all underlying
        subpartitions. This is a range without holes.
      */
      DBUG_ASSERT(sub_part == num_parts);
      part_spec->start_part= part_part * part_info->num_subparts;
      part_spec->end_part= part_spec->start_part+part_info->num_subparts - 1;
    }
    else
    {
      DBUG_ASSERT(sub_part != num_parts);
      part_spec->start_part= sub_part;
      part_spec->end_part=sub_part+
                           (part_info->num_subparts*(part_info->num_parts-1));
      for (i= 0, part_id= sub_part; i < part_info->num_parts;
           i++, part_id+= part_info->num_subparts)
        ; //Set bit part_id in bit array
    }
  }
  if (found_part_field)
    clear_indicator_in_key_fields(key_info);
  /*
    Check if range can be adjusted by looking in read_partitions
  */
  prune_partition_set(table, part_spec);
  DBUG_VOID_RETURN;
}