~ubuntu-branches/ubuntu/wily/mysql-5.6/wily

« back to all changes in this revision

Viewing changes to sql/sql_partition.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-04-16 20:07:10 UTC
  • mto: (1.3.9 vivid-proposed)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20150416200710-pcrsa022082zj46k
Tags: upstream-5.6.24
ImportĀ upstreamĀ versionĀ 5.6.24

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
 
1
/* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
4368
4368
    thd->variables.character_set_client;
4369
4369
  LEX *old_lex= thd->lex;
4370
4370
  LEX lex;
 
4371
  sql_digest_state *parent_digest= thd->m_digest;
4371
4372
  PSI_statement_locker *parent_locker= thd->m_statement_psi;
4372
4373
  DBUG_ENTER("mysql_unpack_partition");
4373
4374
 
4399
4400
  part_info= lex.part_info;
4400
4401
  DBUG_PRINT("info", ("Parse: %s", part_buf));
4401
4402
 
 
4403
  thd->m_digest= NULL;
4402
4404
  thd->m_statement_psi= NULL;
4403
4405
  if (parse_sql(thd, & parser_state, NULL) ||
4404
4406
      part_info->fix_parser_data(thd))
4405
4407
  {
4406
4408
    thd->free_items();
 
4409
    thd->m_digest= parent_digest;
4407
4410
    thd->m_statement_psi= parent_locker;
4408
4411
    goto end;
4409
4412
  }
 
4413
  thd->m_digest= parent_digest;
4410
4414
  thd->m_statement_psi= parent_locker;
4411
4415
  /*
4412
4416
    The parsed syntax residing in the frm file can still contain defaults.
4768
4772
  @param[in,out] create_info     Create info for CREATE TABLE
4769
4773
  @param[in]  alter_ctx          ALTER TABLE runtime context
4770
4774
  @param[out] partition_changed  Boolean indicating whether partition changed
4771
 
  @param[out] fast_alter_table   Boolean indicating if fast partition alter is
4772
 
                                 possible.
 
4775
  @param[out] new_part_info      New partition_info object if fast partition
 
4776
                                 alter is possible. (NULL if not possible).
4773
4777
 
4774
4778
  @return Operation status
4775
4779
    @retval TRUE                 Error
4789
4793
                           HA_CREATE_INFO *create_info,
4790
4794
                           Alter_table_ctx *alter_ctx,
4791
4795
                           bool *partition_changed,
4792
 
                           bool *fast_alter_table)
 
4796
                           partition_info **new_part_info)
4793
4797
{
4794
4798
  DBUG_ENTER("prep_alter_part_table");
 
4799
  DBUG_ASSERT(new_part_info);
4795
4800
 
4796
4801
  /* Foreign keys on partitioned tables are not supported, waits for WL#148 */
4797
4802
  if (table->part_info && (alter_info->flags & Alter_info::ADD_FOREIGN_KEY ||
4839
4844
      DBUG_RETURN(TRUE);
4840
4845
    }
4841
4846
 
4842
 
    /*
4843
 
      Open our intermediate table, we will operate on a temporary instance
4844
 
      of the original table, to be able to skip copying all partitions.
4845
 
      Open it as a copy of the original table, and modify its partition_info
4846
 
      object to allow fast_alter_partition_table to perform the changes.
4847
 
    */
4848
4847
    DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
4849
4848
                                               alter_ctx->db,
4850
4849
                                               alter_ctx->table_name,
4851
4850
                                               MDL_INTENTION_EXCLUSIVE));
4852
4851
 
4853
 
    tab_part_info= table->part_info;
 
4852
    /*
 
4853
      We will operate on a cached instance of the original table,
 
4854
      to be able to skip copying all non-changed partitions
 
4855
      while allowing concurrent access.
 
4856
 
 
4857
      We create a new partition_info object which will carry
 
4858
      the new state of the partitions. It will only be temporary
 
4859
      attached to the handler when needed and then detached afterwards
 
4860
      (through handler::set_part_info()). That way it will not get reused
 
4861
      by next statement, even if the table object is reused due to LOCK TABLE.
 
4862
    */
 
4863
    tab_part_info= table->part_info->get_full_clone();
 
4864
    if (!tab_part_info)
 
4865
    {
 
4866
      mem_alloc_error(sizeof(partition_info));
 
4867
      DBUG_RETURN(true);
 
4868
    }
4854
4869
 
4855
4870
    if (alter_info->flags & Alter_info::ALTER_TABLE_REORG)
4856
4871
    {
4879
4894
          without any changes at all.
4880
4895
        */
4881
4896
        flags= table->file->alter_table_flags(alter_info->flags);
 
4897
        DBUG_ASSERT(flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE));
4882
4898
        if (flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE))
4883
4899
        {
4884
 
          *fast_alter_table= true;
 
4900
          *new_part_info= tab_part_info;
4885
4901
          /* Force table re-open for consistency with the main case. */
4886
4902
          table->m_needs_reopen= true;
4887
4903
        }
4888
 
        else
4889
 
        {
4890
 
          /*
4891
 
            Create copy of partition_info to avoid modifying original
4892
 
            TABLE::part_info, to keep it safe for later use.
4893
 
          */
4894
 
          if (!(tab_part_info= tab_part_info->get_clone()))
4895
 
            DBUG_RETURN(TRUE);
4896
 
        }
4897
4904
 
4898
4905
        thd->work_part_info= tab_part_info;
4899
4906
        DBUG_RETURN(FALSE);
4922
4929
      my_error(ER_PARTITION_FUNCTION_FAILURE, MYF(0));
4923
4930
      goto err;
4924
4931
    }
 
4932
    DBUG_ASSERT((flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE)) != 0);
4925
4933
    if ((flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE)) != 0)
4926
4934
    {
4927
4935
      /*
4930
4938
        information to storage engine in this case), so the table
4931
4939
        must be reopened.
4932
4940
      */
4933
 
      *fast_alter_table= true;
 
4941
      *new_part_info= tab_part_info;
4934
4942
      table->m_needs_reopen= true;
4935
4943
    }
4936
 
    else
4937
 
    {
4938
 
      /*
4939
 
        "Fast" changing of partitioning is not supported. Create
4940
 
        a copy of TABLE::part_info object, so we can modify it safely.
4941
 
        Modifying original TABLE::part_info will cause problems when
4942
 
        we read data from old version of table using this TABLE object
4943
 
        while copying them to new version of table.
4944
 
      */
4945
 
      if (!(tab_part_info= tab_part_info->get_clone()))
4946
 
        DBUG_RETURN(TRUE);
4947
 
    }
4948
4944
    DBUG_PRINT("info", ("*fast_alter_table flags: 0x%x", flags));
4949
4945
    if ((alter_info->flags & Alter_info::ALTER_ADD_PARTITION) ||
4950
4946
        (alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION))
5133
5129
and copying and finally the third line after also dropping the partitions
5134
5130
that are reorganised.
5135
5131
*/
5136
 
      if (*fast_alter_table &&
 
5132
      if (*new_part_info &&
5137
5133
          tab_part_info->part_type == HASH_PARTITION)
5138
5134
      {
5139
5135
        uint part_no= 0, start_part= 1, start_sec_part= 1;
5238
5234
        do
5239
5235
        {
5240
5236
          partition_element *part_elem= alt_it++;
5241
 
          if (*fast_alter_table)
 
5237
          if (*new_part_info)
5242
5238
            part_elem->part_state= PART_TO_BE_ADDED;
5243
5239
          if (tab_part_info->partitions.push_back(part_elem))
5244
5240
          {
5325
5321
        my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD");
5326
5322
        goto err;
5327
5323
      }
5328
 
      if (!(*fast_alter_table))
 
5324
      if (!(*new_part_info))
5329
5325
      {
5330
5326
        table->file->print_error(HA_ERR_WRONG_COMMAND, MYF(0));
5331
5327
        goto err;
5388
5384
        uint part_count= 0, start_part= 1, start_sec_part= 1;
5389
5385
        uint end_part= 0, end_sec_part= 0;
5390
5386
        bool all_parts= TRUE;
5391
 
        if (*fast_alter_table &&
 
5387
        if (*new_part_info &&
5392
5388
            tab_part_info->linear_hash_ind)
5393
5389
        {
5394
5390
          uint upper_2n= tab_part_info->linear_hash_mask + 1;
5414
5410
        do
5415
5411
        {
5416
5412
          partition_element *p_elem= part_it++;
5417
 
          if (*fast_alter_table &&
 
5413
          if (*new_part_info &&
5418
5414
              (all_parts ||
5419
5415
              (part_count >= start_part && part_count <= end_part) ||
5420
5416
              (part_count >= start_sec_part && part_count <= end_sec_part)))
5421
5417
            p_elem->part_state= PART_CHANGED;
5422
5418
          if (++part_count > num_parts_remain)
5423
5419
          {
5424
 
            if (*fast_alter_table)
 
5420
            if (*new_part_info)
5425
5421
              p_elem->part_state= PART_REORGED_DROPPED;
5426
5422
            else
5427
5423
              part_it.remove();
5548
5544
            }
5549
5545
            else
5550
5546
              tab_max_range= part_elem->range_value;
5551
 
            if (*fast_alter_table &&
 
5547
            if (*new_part_info &&
5552
5548
                tab_part_info->temp_partitions.push_back(part_elem))
5553
5549
            {
5554
5550
              mem_alloc_error(1);
5555
5551
              goto err;
5556
5552
            }
5557
 
            if (*fast_alter_table)
 
5553
            if (*new_part_info)
5558
5554
              part_elem->part_state= PART_TO_BE_REORGED;
5559
5555
            if (!found_first)
5560
5556
            {
5574
5570
                else
5575
5571
                  alt_max_range= alt_part_elem->range_value;
5576
5572
 
5577
 
                if (*fast_alter_table)
 
5573
                if (*new_part_info)
5578
5574
                  alt_part_elem->part_state= PART_TO_BE_ADDED;
5579
5575
                if (alt_part_count == 0)
5580
5576
                  tab_it.replace(alt_part_elem);
5822
5818
  }
5823
5819
  DBUG_RETURN(FALSE);
5824
5820
err:
5825
 
  *fast_alter_table= false;
 
5821
  *new_part_info= NULL;
5826
5822
  DBUG_RETURN(TRUE);
5827
5823
}
5828
5824
 
5859
5855
  int error;
5860
5856
  handler *file= lpt->table->file;
5861
5857
  THD *thd= lpt->thd;
 
5858
  partition_info *old_part_info= lpt->table->part_info;
5862
5859
  DBUG_ENTER("mysql_change_partitions");
5863
5860
 
5864
5861
  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5868
5865
 
5869
5866
  /* TODO: test if bulk_insert would increase the performance */
5870
5867
 
5871
 
  if ((error= file->ha_change_partitions(lpt->create_info, path, &lpt->copied,
5872
 
                                         &lpt->deleted, lpt->pack_frm_data,
5873
 
                                         lpt->pack_frm_len)))
 
5868
  file->set_part_info(lpt->part_info, false);
 
5869
  error= file->ha_change_partitions(lpt->create_info, path, &lpt->copied,
 
5870
                                    &lpt->deleted, lpt->pack_frm_data,
 
5871
                                    lpt->pack_frm_len);
 
5872
  file->set_part_info(old_part_info, false);
 
5873
  if (error)
5874
5874
  {
5875
5875
    file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
5876
5876
  }
5905
5905
{
5906
5906
  char path[FN_REFLEN+1];
5907
5907
  int error;
 
5908
  partition_info *old_part_info= lpt->table->part_info;
5908
5909
  DBUG_ENTER("mysql_rename_partitions");
5909
5910
 
5910
5911
  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5911
 
  if ((error= lpt->table->file->ha_rename_partitions(path)))
 
5912
  lpt->table->file->set_part_info(lpt->part_info, false);
 
5913
  error= lpt->table->file->ha_rename_partitions(path);
 
5914
  lpt->table->file->set_part_info(old_part_info, false);
 
5915
  if (error)
5912
5916
  {
5913
5917
    if (error != 1)
5914
5918
      lpt->table->file->print_error(error, MYF(0));
5941
5945
static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
5942
5946
{
5943
5947
  char path[FN_REFLEN+1];
5944
 
  partition_info *part_info= lpt->table->part_info;
 
5948
  partition_info *old_part_info= lpt->table->part_info;
 
5949
  partition_info *part_info= lpt->part_info;
5945
5950
  List_iterator<partition_element> part_it(part_info->partitions);
5946
5951
  uint i= 0;
5947
5952
  uint remove_count= 0;
5954
5959
                                                MDL_EXCLUSIVE));
5955
5960
 
5956
5961
  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5957
 
  if ((error= lpt->table->file->ha_drop_partitions(path)))
 
5962
  lpt->table->file->set_part_info(part_info, false);
 
5963
  error= lpt->table->file->ha_drop_partitions(path);
 
5964
  lpt->table->file->set_part_info(old_part_info, false);
 
5965
  if (error)
5958
5966
  {
5959
5967
    lpt->table->file->print_error(error, MYF(0));
5960
5968
    DBUG_RETURN(TRUE);
6724
6732
      }
6725
6733
    }
6726
6734
    /* Ensure the share is destroyed and reopened. */
6727
 
    part_info= lpt->part_info->get_clone();
6728
6735
    close_all_tables_for_name(thd, table->s, false, NULL);
6729
6736
  }
6730
6737
  else
6742
6749
      the table cache.
6743
6750
    */
6744
6751
    mysql_lock_remove(thd, thd->lock, table);
6745
 
    part_info= lpt->part_info->get_clone();
6746
6752
    close_thread_table(thd, &thd->open_tables);
6747
6753
    lpt->table_list->table= NULL;
6748
6754
  }
6889
6895
  previously prepared.
6890
6896
 
6891
6897
  @param thd                           Thread object
6892
 
  @param table                         Original table object with new part_info
 
6898
  @param table                         Original table object
6893
6899
  @param alter_info                    ALTER TABLE info
6894
6900
  @param create_info                   Create info for CREATE TABLE
6895
6901
  @param table_list                    List of the table involved
6896
6902
  @param db                            Database name of new table
6897
6903
  @param table_name                    Table name of new table
 
6904
  @param new_part_info                 New partition_info to use
6898
6905
 
6899
6906
  @return Operation status
6900
6907
    @retval TRUE                          Error
6910
6917
                                HA_CREATE_INFO *create_info,
6911
6918
                                TABLE_LIST *table_list,
6912
6919
                                char *db,
6913
 
                                const char *table_name)
 
6920
                                const char *table_name,
 
6921
                                partition_info *new_part_info)
6914
6922
{
6915
6923
  /* Set-up struct used to write frm files */
6916
6924
  partition_info *part_info;
6923
6931
  DBUG_ENTER("fast_alter_partition_table");
6924
6932
  DBUG_ASSERT(table->m_needs_reopen);
6925
6933
 
6926
 
  part_info= table->part_info;
 
6934
  part_info= new_part_info;
6927
6935
  lpt->thd= thd;
6928
6936
  lpt->table_list= table_list;
6929
6937
  lpt->part_info= part_info;