bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind)
{
  bool result= TRUE;
  partition_info *part_info= table->part_info;
  enum_column_usage saved_column_usage= thd->column_usage;
  DBUG_ENTER("fix_partition_func");

  if (part_info->fixed)
  {
    DBUG_RETURN(FALSE);
  }
  thd->column_usage= COLUMNS_WRITE;
  DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage));

  if (!is_create_table_ind ||
       thd->lex->sql_command != SQLCOM_CREATE_TABLE)
  {
    if (partition_default_handling(thd, table, part_info,
                                   is_create_table_ind,
                                   table->s->normalized_path.str))
    {
      DBUG_RETURN(TRUE);
    }
  }
  if (part_info->is_sub_partitioned())
  {
    DBUG_ASSERT(part_info->subpart_type == HASH_PARTITION);
    /*
      Subpartition is defined. We need to verify that subpartitioning
      function is correct.
    */
    if (part_info->linear_hash_ind)
      set_linear_hash_mask(part_info, part_info->num_subparts);
    if (part_info->list_of_subpart_fields)
    {
      List_iterator<const char> it(part_info->subpart_field_list);
      if (unlikely(handle_list_of_fields(thd, it, table, part_info, TRUE)))
        goto end;
    }
    else
    {
      if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr,
                                        table, TRUE, is_create_table_ind)))
        goto end;
      if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT))
      {
        part_info->report_part_expr_error(TRUE);
        goto end;
      }
    }
  }
  DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION);
  /*
    Partition is defined. We need to verify that partitioning
    function is correct.
  */
  set_up_partition_func_pointers(part_info);
  if (part_info->part_type == HASH_PARTITION)
  {
    if (part_info->linear_hash_ind)
      set_linear_hash_mask(part_info, part_info->num_parts);
    if (part_info->list_of_part_fields)
    {
      List_iterator<const char> it(part_info->part_field_list);
      if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE)))
        goto end;
    }
    else
    {
      if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
                                        table, FALSE, is_create_table_ind)))
        goto end;
      if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
      {
        part_info->report_part_expr_error(FALSE);
        goto end;
      }
    }
    part_info->fixed= TRUE;
  }
  else
  {
    if (part_info->column_list)
    {
      List_iterator<const char> it(part_info->part_field_list);
      if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE)))
        goto end;
    }
    else
    {
      if (part_info->part_type == VERSIONING_PARTITION &&
        part_info->vers_setup_expression(thd))
        goto end;
      if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
                                        table, FALSE, is_create_table_ind)))
        goto end;
    }
    part_info->fixed= TRUE;
    if (part_info->check_constants(thd, part_info))
      goto end;
    if (unlikely(part_info->num_parts < 1))
    {
      const char *error_str= part_info->part_type == LIST_PARTITION
                             ? "LIST" : "RANGE";
      my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str);
      goto end;
    }
    if (unlikely(!part_info->column_list &&
                  part_info->part_expr->result_type() != INT_RESULT &&
                  part_info->part_expr->result_type() != DECIMAL_RESULT))
    {
      part_info->report_part_expr_error(FALSE);
      goto end;
    }
  }
  if (((part_info->part_type != HASH_PARTITION ||
        part_info->list_of_part_fields == FALSE) &&
       !part_info->column_list &&
       check_part_func_fields(part_info->part_field_array, TRUE)) ||
      (part_info->list_of_subpart_fields == FALSE &&
       part_info->is_sub_partitioned() &&
       check_part_func_fields(part_info->subpart_field_array, TRUE)))
  {
    /*
      Range/List/HASH (but not KEY) and not COLUMNS or HASH subpartitioning
      with columns in the partitioning expression using unallowed charset.
    */
    my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
    goto end;
  }
  if (unlikely(create_full_part_field_array(thd, table, part_info)))
    goto end;
  if (unlikely(check_primary_key(table)))
    goto end;
  if (unlikely((!(table->s->db_type()->partition_flags &&
      (table->s->db_type()->partition_flags() & HA_CAN_PARTITION_UNIQUE))) &&
               check_unique_keys(table)))
    goto end;
  if (unlikely(set_up_partition_bitmaps(thd, part_info)))
    goto end;
  if (unlikely(part_info->set_up_charset_field_preps(thd)))
  {
    my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
    goto end;
  }
  if (unlikely(part_info->check_partition_field_length()))
  {
    my_error(ER_PARTITION_FIELDS_TOO_LONG, MYF(0));
    goto end;
  }
  check_range_capable_PF(table);
  set_up_partition_key_maps(table, part_info);
  set_up_range_analysis_info(part_info);
  table->file->set_part_info(part_info);
  result= FALSE;
end:
  thd->column_usage= saved_column_usage;
  DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage));
  DBUG_RETURN(result);
}