~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2009-09-16 21:56:01 UTC
  • mfrom: (1126.2.5 merge)
  • Revision ID: brian@gaz-20090916215601-o8gy2wmwt0pgfp86
Merge Jay Alter table + Brian dead code

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include <drizzled/replication_services.h>
35
35
#include <drizzled/table_proto.h>
36
36
 
 
37
#include "drizzled/statement/alter_table.h" /* for mysql_create_like_schema_frm, which will die soon */
 
38
 
37
39
#include <algorithm>
38
40
 
39
41
using namespace std;
58
60
 
59
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
60
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
61
 
static int copy_data_between_tables(Table *from,Table *to,
62
 
                                    List<CreateField> &create, bool ignore,
63
 
                                    uint32_t order_num, order_st *order,
64
 
                                    ha_rows *copied,ha_rows *deleted,
65
 
                                    enum enum_enable_or_disable keys_onoff,
66
 
                                    bool error_if_not_empty);
67
63
 
68
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
69
 
static bool check_engine(Session *, const char *, HA_CREATE_INFO *);
70
 
static int
71
 
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
72
 
                           Alter_info *alter_info,
73
 
                           bool tmp_table,
74
 
                               uint32_t *db_options,
75
 
                               handler *file, KEY **key_info_buffer,
76
 
                               uint32_t *key_count, int select_field_count);
77
 
static bool
78
 
mysql_prepare_alter_table(Session *session, Table *table,
79
 
                          HA_CREATE_INFO *create_info,
80
 
                          message::Table *table_proto,
81
 
                          Alter_info *alter_info);
82
65
 
83
 
static void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
 
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
84
67
{
85
68
  /*
86
69
    If the table character set was not given explicitly,
815
798
  }
816
799
}
817
800
 
818
 
 
819
801
/*
820
802
  Prepare a create_table instance for packing
821
803
 
834
816
   0    ok
835
817
   1    Error
836
818
*/
837
 
 
838
819
int prepare_create_field(CreateField *sql_field,
839
820
                         uint32_t *blob_columns,
840
821
                         int *timestamps, int *timestamps_with_niladic,
917
898
  return 0;
918
899
}
919
900
 
920
 
/*
921
 
  Preparation for table creation
922
 
 
923
 
  SYNOPSIS
924
 
    mysql_prepare_create_table()
925
 
      session                       Thread object.
926
 
      create_info               Create information (like MAX_ROWS).
927
 
      alter_info                List of columns and indexes to create
928
 
      tmp_table                 If a temporary table is to be created.
929
 
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
930
 
      file                      The handler for the new table.
931
 
      key_info_buffer     OUT   An array of KEY structs for the indexes.
932
 
      key_count           OUT   The number of elements in the array.
933
 
      select_field_count        The number of fields coming from a select table.
934
 
 
935
 
  DESCRIPTION
936
 
    Prepares the table and key structures for table creation.
937
 
 
938
 
  NOTES
939
 
    sets create_info->varchar if the table has a varchar
940
 
 
941
 
  RETURN VALUES
942
 
    false    OK
943
 
    true     error
944
 
*/
945
 
 
946
 
static int
947
 
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
948
 
                           Alter_info *alter_info,
949
 
                           bool tmp_table,
 
901
int mysql_prepare_create_table(Session *session,
 
902
                               HA_CREATE_INFO *create_info,
 
903
                               AlterInfo *alter_info,
 
904
                               bool tmp_table,
950
905
                               uint32_t *db_options,
951
 
                               handler *file, KEY **key_info_buffer,
952
 
                               uint32_t *key_count, int select_field_count)
 
906
                               handler *file,
 
907
                               KEY **key_info_buffer,
 
908
                               uint32_t *key_count,
 
909
                               int select_field_count)
953
910
{
954
911
  const char    *key_name;
955
912
  CreateField   *sql_field,*dup_field;
1709
1666
                                const char *db, const char *table_name,
1710
1667
                                HA_CREATE_INFO *create_info,
1711
1668
                                message::Table *table_proto,
1712
 
                                Alter_info *alter_info,
 
1669
                                AlterInfo *alter_info,
1713
1670
                                bool internal_tmp_table,
1714
1671
                                uint32_t select_field_count)
1715
1672
{
1909
1866
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1910
1867
                        HA_CREATE_INFO *create_info,
1911
1868
                        message::Table *table_proto,
1912
 
                        Alter_info *alter_info,
 
1869
                        AlterInfo *alter_info,
1913
1870
                        bool internal_tmp_table,
1914
1871
                        uint32_t select_field_count)
1915
1872
{
2005
1962
** Alter a table definition
2006
1963
****************************************************************************/
2007
1964
 
2008
 
 
2009
1965
/*
2010
1966
  Rename a table.
2011
1967
 
2494
2450
                           &handler::ha_optimize));
2495
2451
}
2496
2452
 
2497
 
static bool mysql_create_like_schema_frm(Session* session,
2498
 
                                         TableList* schema_table,
2499
 
                                         HA_CREATE_INFO *create_info,
2500
 
                                         message::Table* table_proto)
2501
 
{
2502
 
  HA_CREATE_INFO local_create_info;
2503
 
  Alter_info alter_info;
2504
 
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
2505
 
  uint32_t keys= schema_table->table->s->keys;
2506
 
  uint32_t db_options= 0;
2507
 
 
2508
 
  memset(&local_create_info, 0, sizeof(local_create_info));
2509
 
  local_create_info.db_type= schema_table->table->s->db_type();
2510
 
  local_create_info.row_type= schema_table->table->s->row_type;
2511
 
  local_create_info.default_table_charset=default_charset_info;
2512
 
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
2513
 
  alter_info.flags.set(ALTER_RECREATE);
2514
 
  schema_table->table->use_all_columns();
2515
 
  if (mysql_prepare_alter_table(session, schema_table->table,
2516
 
                                &local_create_info, table_proto, &alter_info))
2517
 
    return true;
2518
 
 
2519
 
  /* I_S tables are created with MAX_ROWS for some efficiency drive.
2520
 
     When CREATE LIKE, we don't want to keep it coming across */
2521
 
  message::Table::TableOptions *table_options;
2522
 
  table_options= table_proto->mutable_options();
2523
 
  table_options->clear_max_rows();
2524
 
 
2525
 
  if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
2526
 
                                 tmp_table, &db_options,
2527
 
                                 schema_table->table->file,
2528
 
                                 &schema_table->table->s->key_info, &keys, 0))
2529
 
    return true;
2530
 
 
2531
 
  table_proto->set_name("system_stupid_i_s_fix_nonsense");
2532
 
  if(tmp_table)
2533
 
    table_proto->set_type(message::Table::TEMPORARY);
2534
 
  else
2535
 
    table_proto->set_type(message::Table::STANDARD);
2536
 
 
2537
 
  {
2538
 
    message::Table::StorageEngine *protoengine;
2539
 
    protoengine= table_proto->mutable_engine();
2540
 
 
2541
 
    StorageEngine *engine= local_create_info.db_type;
2542
 
 
2543
 
    protoengine->set_name(engine->getName());
2544
 
  }
2545
 
 
2546
 
  if (fill_table_proto(table_proto, "system_stupid_i_s_fix_nonsense",
2547
 
                       alter_info.create_list, &local_create_info,
2548
 
                       keys, schema_table->table->s->key_info))
2549
 
    return true;
2550
 
 
2551
 
  return false;
2552
 
}
2553
 
 
2554
2453
/*
2555
2454
  Create a table identical to the specified table
2556
2455
 
2799
2698
                                &handler::ha_check));
2800
2699
}
2801
2700
 
2802
 
 
2803
 
/* table_list should contain just one table */
2804
 
static int
2805
 
mysql_discard_or_import_tablespace(Session *session,
2806
 
                                   TableList *table_list,
2807
 
                                   enum tablespace_op_type tablespace_op)
2808
 
{
2809
 
  Table *table;
2810
 
  bool discard;
2811
 
  int error;
2812
 
 
2813
 
  /*
2814
 
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
2815
 
    ALTER Table
2816
 
  */
2817
 
 
2818
 
  session->set_proc_info("discard_or_import_tablespace");
2819
 
 
2820
 
  discard= test(tablespace_op == DISCARD_TABLESPACE);
2821
 
 
2822
 
 /*
2823
 
   We set this flag so that ha_innobase::open and ::external_lock() do
2824
 
   not complain when we lock the table
2825
 
 */
2826
 
  session->tablespace_op= true;
2827
 
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
2828
 
  {
2829
 
    session->tablespace_op= false;
2830
 
    return -1;
2831
 
  }
2832
 
 
2833
 
  error= table->file->ha_discard_or_import_tablespace(discard);
2834
 
 
2835
 
  session->set_proc_info("end");
2836
 
 
2837
 
  if (error)
2838
 
    goto err;
2839
 
 
2840
 
  /* The ALTER Table is always in its own transaction */
2841
 
  error = ha_autocommit_or_rollback(session, 0);
2842
 
  if (! session->endActiveTransaction())
2843
 
    error=1;
2844
 
  if (error)
2845
 
    goto err;
2846
 
  write_bin_log(session, false, session->query, session->query_length);
2847
 
 
2848
 
err:
2849
 
  ha_autocommit_or_rollback(session, error);
2850
 
  session->tablespace_op=false;
2851
 
 
2852
 
  if (error == 0)
2853
 
  {
2854
 
    session->my_ok();
2855
 
    return 0;
2856
 
  }
2857
 
 
2858
 
  table->file->print_error(error, MYF(0));
2859
 
 
2860
 
  return -1;
2861
 
}
2862
 
 
2863
 
 
2864
 
/*
2865
 
  Manages enabling/disabling of indexes for ALTER Table
2866
 
 
2867
 
  SYNOPSIS
2868
 
    alter_table_manage_keys()
2869
 
      table                  Target table
2870
 
      indexes_were_disabled  Whether the indexes of the from table
2871
 
                             were disabled
2872
 
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
2873
 
 
2874
 
  RETURN VALUES
2875
 
    false  OK
2876
 
    true   Error
2877
 
*/
2878
 
 
2879
 
static
2880
 
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
2881
 
                             enum enum_enable_or_disable keys_onoff)
2882
 
{
2883
 
  int error= 0;
2884
 
  switch (keys_onoff) {
2885
 
  case ENABLE:
2886
 
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2887
 
    break;
2888
 
  case LEAVE_AS_IS:
2889
 
    if (!indexes_were_disabled)
2890
 
      break;
2891
 
    /* fall-through: disabled indexes */
2892
 
  case DISABLE:
2893
 
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2894
 
  }
2895
 
 
2896
 
  if (error == HA_ERR_WRONG_COMMAND)
2897
 
  {
2898
 
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2899
 
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
2900
 
                        table->s->table_name.str);
2901
 
    error= 0;
2902
 
  } else if (error)
2903
 
    table->file->print_error(error, MYF(0));
2904
 
 
2905
 
  return(error);
2906
 
}
2907
 
 
2908
 
static int
2909
 
create_temporary_table(Session *session,
2910
 
                       Table *table,
2911
 
                       char *new_db,
2912
 
                       char *tmp_name,
2913
 
                       HA_CREATE_INFO *create_info,
2914
 
                       message::Table *create_proto,
2915
 
                       Alter_info *alter_info)
2916
 
{
2917
 
  int error;
2918
 
  StorageEngine *old_db_type, *new_db_type;
2919
 
  old_db_type= table->s->db_type();
2920
 
  new_db_type= create_info->db_type;
2921
 
  /*
2922
 
    Create a table with a temporary name.
2923
 
    We don't log the statement, it will be logged later.
2924
 
  */
2925
 
  create_proto->set_name(tmp_name);
2926
 
  create_proto->set_type(message::Table::TEMPORARY);
2927
 
 
2928
 
  message::Table::StorageEngine *protoengine;
2929
 
  protoengine= create_proto->mutable_engine();
2930
 
  protoengine->set_name(new_db_type->getName());
2931
 
 
2932
 
  error= mysql_create_table(session, new_db, tmp_name,
2933
 
                            create_info, create_proto, alter_info, 1, 0);
2934
 
 
2935
 
  return(error);
2936
 
}
2937
 
 
2938
 
 
2939
 
/**
2940
 
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
2941
 
 
2942
 
  This function transforms parse output of ALTER Table - lists of
2943
 
  columns and keys to add, drop or modify into, essentially,
2944
 
  CREATE TABLE definition - a list of columns and keys of the new
2945
 
  table. While doing so, it also performs some (bug not all)
2946
 
  semantic checks.
2947
 
 
2948
 
  This function is invoked when we know that we're going to
2949
 
  perform ALTER Table via a temporary table -- i.e. fast ALTER Table
2950
 
  is not possible, perhaps because the ALTER statement contains
2951
 
  instructions that require change in table data, not only in
2952
 
  table definition or indexes.
2953
 
 
2954
 
  @param[in,out]  session         thread handle. Used as a memory pool
2955
 
                              and source of environment information.
2956
 
  @param[in]      table       the source table, open and locked
2957
 
                              Used as an interface to the storage engine
2958
 
                              to acquire additional information about
2959
 
                              the original table.
2960
 
  @param[in,out]  create_info A blob with CREATE/ALTER Table
2961
 
                              parameters
2962
 
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
2963
 
                              Originally create_info was used only in
2964
 
                              CREATE TABLE and alter_info only in ALTER Table.
2965
 
                              But since ALTER might end-up doing CREATE,
2966
 
                              this distinction is gone and we just carry
2967
 
                              around two structures.
2968
 
 
2969
 
  @return
2970
 
    Fills various create_info members based on information retrieved
2971
 
    from the storage engine.
2972
 
    Sets create_info->varchar if the table has a VARCHAR column.
2973
 
    Prepares alter_info->create_list and alter_info->key_list with
2974
 
    columns and keys of the new table.
2975
 
  @retval true   error, out of memory or a semantical error in ALTER
2976
 
                 Table instructions
2977
 
  @retval false  success
2978
 
*/
2979
 
 
2980
 
static bool
2981
 
mysql_prepare_alter_table(Session *session, Table *table,
2982
 
                          HA_CREATE_INFO *create_info,
2983
 
                          message::Table *table_proto,
2984
 
                          Alter_info *alter_info)
2985
 
{
2986
 
  /* New column definitions are added here */
2987
 
  List<CreateField> new_create_list;
2988
 
  /* New key definitions are added here */
2989
 
  List<Key> new_key_list;
2990
 
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
2991
 
  List_iterator<CreateField> def_it(alter_info->create_list);
2992
 
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
2993
 
  List_iterator<Key> key_it(alter_info->key_list);
2994
 
  List_iterator<CreateField> find_it(new_create_list);
2995
 
  List_iterator<CreateField> field_it(new_create_list);
2996
 
  List<Key_part_spec> key_parts;
2997
 
  uint32_t used_fields= create_info->used_fields;
2998
 
  KEY *key_info=table->key_info;
2999
 
  bool rc= true;
3000
 
 
3001
 
 
3002
 
  /* Let new create options override the old ones */
3003
 
  message::Table::TableOptions *table_options;
3004
 
  table_options= table_proto->mutable_options();
3005
 
 
3006
 
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3007
 
    create_info->block_size= table->s->block_size;
3008
 
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3009
 
    create_info->default_table_charset= table->s->table_charset;
3010
 
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3011
 
    {
3012
 
    /* Table has an autoincrement, copy value to new table */
3013
 
    table->file->info(HA_STATUS_AUTO);
3014
 
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
3015
 
  }
3016
 
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
3017
 
    create_info->key_block_size= table->s->key_block_size;
3018
 
 
3019
 
  table->restoreRecordAsDefault();     // Empty record for DEFAULT
3020
 
  CreateField *def;
3021
 
 
3022
 
    /*
3023
 
    First collect all fields from table which isn't in drop_list
3024
 
    */
3025
 
  Field **f_ptr,*field;
3026
 
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
3027
 
  {
3028
 
    /* Check if field should be dropped */
3029
 
    Alter_drop *drop;
3030
 
    drop_it.rewind();
3031
 
    while ((drop=drop_it++))
3032
 
    {
3033
 
      if (drop->type == Alter_drop::COLUMN &&
3034
 
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
3035
 
      {
3036
 
        /* Reset auto_increment value if it was dropped */
3037
 
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
3038
 
            !(used_fields & HA_CREATE_USED_AUTO))
3039
 
        {
3040
 
          create_info->auto_increment_value=0;
3041
 
          create_info->used_fields|=HA_CREATE_USED_AUTO;
3042
 
        }
3043
 
        break;
3044
 
      }
3045
 
    }
3046
 
    if (drop)
3047
 
    {
3048
 
      drop_it.remove();
3049
 
      continue;
3050
 
    }
3051
 
    
3052
 
    /* Mark that we will read the field */
3053
 
    field->setReadSet();
3054
 
 
3055
 
    /* Check if field is changed */
3056
 
    def_it.rewind();
3057
 
    while ((def=def_it++))
3058
 
    {
3059
 
      if (def->change &&
3060
 
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
3061
 
        break;
3062
 
    }
3063
 
    if (def)
3064
 
    {                                           // Field is changed
3065
 
      def->field=field;
3066
 
      if (!def->after)
3067
 
      {
3068
 
        new_create_list.push_back(def);
3069
 
        def_it.remove();
3070
 
      }
3071
 
    }
3072
 
    else
3073
 
    {
3074
 
      /*
3075
 
        This field was not dropped and not changed, add it to the list
3076
 
        for the new table.
3077
 
      */
3078
 
      def= new CreateField(field, field);
3079
 
      new_create_list.push_back(def);
3080
 
      alter_it.rewind();                        // Change default if ALTER
3081
 
      Alter_column *alter;
3082
 
      while ((alter=alter_it++))
3083
 
      {
3084
 
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
3085
 
          break;
3086
 
      }
3087
 
      if (alter)
3088
 
      {
3089
 
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
3090
 
        {
3091
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
3092
 
          goto err;
3093
 
        }
3094
 
        if ((def->def=alter->def))              // Use new default
3095
 
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
3096
 
        else
3097
 
          def->flags|= NO_DEFAULT_VALUE_FLAG;
3098
 
        alter_it.remove();
3099
 
      }
3100
 
    }
3101
 
  }
3102
 
  def_it.rewind();
3103
 
  while ((def=def_it++))                        // Add new columns
3104
 
  {
3105
 
    if (def->change && ! def->field)
3106
 
    {
3107
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
3108
 
      goto err;
3109
 
    }
3110
 
    /*
3111
 
      Check that the DATE/DATETIME not null field we are going to add is
3112
 
      either has a default value or the '0000-00-00' is allowed by the
3113
 
      set sql mode.
3114
 
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
3115
 
      flag to allow ALTER Table only if the table to be altered is empty.
3116
 
    */
3117
 
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
3118
 
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
3119
 
        !alter_info->datetime_field &&
3120
 
        !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
3121
 
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
3122
 
    {
3123
 
      alter_info->datetime_field= def;
3124
 
      alter_info->error_if_not_empty= true;
3125
 
    }
3126
 
    if (!def->after)
3127
 
      new_create_list.push_back(def);
3128
 
    else if (def->after == first_keyword)
3129
 
      new_create_list.push_front(def);
3130
 
    else
3131
 
    {
3132
 
      CreateField *find;
3133
 
      find_it.rewind();
3134
 
      while ((find=find_it++))                  // Add new columns
3135
 
      {
3136
 
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
3137
 
          break;
3138
 
      }
3139
 
      if (!find)
3140
 
      {
3141
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
3142
 
        goto err;
3143
 
      }
3144
 
      find_it.after(def);                       // Put element after this
3145
 
      /*
3146
 
        XXX: hack for Bug#28427.
3147
 
        If column order has changed, force OFFLINE ALTER Table
3148
 
        without querying engine capabilities.  If we ever have an
3149
 
        engine that supports online ALTER Table CHANGE COLUMN
3150
 
        <name> AFTER <name1> (Falcon?), this fix will effectively
3151
 
        disable the capability.
3152
 
        TODO: detect the situation in compare_tables, behave based
3153
 
        on engine capabilities.
3154
 
      */
3155
 
      if (alter_info->build_method == HA_BUILD_ONLINE)
3156
 
      {
3157
 
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
3158
 
        goto err;
3159
 
      }
3160
 
      alter_info->build_method= HA_BUILD_OFFLINE;
3161
 
    }
3162
 
  }
3163
 
  if (alter_info->alter_list.elements)
3164
 
  {
3165
 
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
3166
 
             alter_info->alter_list.head()->name, table->s->table_name.str);
3167
 
    goto err;
3168
 
  }
3169
 
  if (!new_create_list.elements)
3170
 
  {
3171
 
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
3172
 
               MYF(0));
3173
 
    goto err;
3174
 
  }
3175
 
 
3176
 
  /*
3177
 
    Collect all keys which isn't in drop list. Add only those
3178
 
    for which some fields exists.
3179
 
  */
3180
 
 
3181
 
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
3182
 
  {
3183
 
    char *key_name= key_info->name;
3184
 
    Alter_drop *drop;
3185
 
    drop_it.rewind();
3186
 
    while ((drop=drop_it++))
3187
 
    {
3188
 
      if (drop->type == Alter_drop::KEY &&
3189
 
          !my_strcasecmp(system_charset_info,key_name, drop->name))
3190
 
        break;
3191
 
    }
3192
 
    if (drop)
3193
 
    {
3194
 
      drop_it.remove();
3195
 
      continue;
3196
 
    }
3197
 
 
3198
 
    KEY_PART_INFO *key_part= key_info->key_part;
3199
 
    key_parts.empty();
3200
 
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
3201
 
    {
3202
 
      if (!key_part->field)
3203
 
        continue;                               // Wrong field (from UNIREG)
3204
 
      const char *key_part_name=key_part->field->field_name;
3205
 
      CreateField *cfield;
3206
 
      field_it.rewind();
3207
 
      while ((cfield=field_it++))
3208
 
      {
3209
 
        if (cfield->change)
3210
 
        {
3211
 
          if (!my_strcasecmp(system_charset_info, key_part_name,
3212
 
                             cfield->change))
3213
 
            break;
3214
 
        }
3215
 
        else if (!my_strcasecmp(system_charset_info,
3216
 
                                key_part_name, cfield->field_name))
3217
 
          break;
3218
 
      }
3219
 
      if (!cfield)
3220
 
        continue;                               // Field is removed
3221
 
      uint32_t key_part_length=key_part->length;
3222
 
      if (cfield->field)                        // Not new field
3223
 
      {
3224
 
        /*
3225
 
          If the field can't have only a part used in a key according to its
3226
 
          new type, or should not be used partially according to its
3227
 
          previous type, or the field length is less than the key part
3228
 
          length, unset the key part length.
3229
 
 
3230
 
          We also unset the key part length if it is the same as the
3231
 
          old field's length, so the whole new field will be used.
3232
 
 
3233
 
          BLOBs may have cfield->length == 0, which is why we test it before
3234
 
          checking whether cfield->length < key_part_length (in chars).
3235
 
         */
3236
 
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
3237
 
            !Field::type_can_have_key_part(cfield->sql_type) ||
3238
 
            (cfield->field->field_length == key_part_length &&
3239
 
             !f_is_blob(key_part->key_type)) ||
3240
 
            (cfield->length && (cfield->length < key_part_length /
3241
 
                                key_part->field->charset()->mbmaxlen)))
3242
 
          key_part_length= 0;                   // Use whole field
3243
 
      }
3244
 
      key_part_length /= key_part->field->charset()->mbmaxlen;
3245
 
      key_parts.push_back(new Key_part_spec(cfield->field_name,
3246
 
                                            strlen(cfield->field_name),
3247
 
                                            key_part_length));
3248
 
    }
3249
 
    if (key_parts.elements)
3250
 
    {
3251
 
      KEY_CREATE_INFO key_create_info;
3252
 
      Key *key;
3253
 
      enum Key::Keytype key_type;
3254
 
      memset(&key_create_info, 0, sizeof(key_create_info));
3255
 
 
3256
 
      key_create_info.algorithm= key_info->algorithm;
3257
 
      if (key_info->flags & HA_USES_BLOCK_SIZE)
3258
 
        key_create_info.block_size= key_info->block_size;
3259
 
      if (key_info->flags & HA_USES_COMMENT)
3260
 
        key_create_info.comment= key_info->comment;
3261
 
 
3262
 
      if (key_info->flags & HA_NOSAME)
3263
 
      {
3264
 
        if (is_primary_key_name(key_name))
3265
 
          key_type= Key::PRIMARY;
3266
 
        else
3267
 
          key_type= Key::UNIQUE;
3268
 
      }
3269
 
      else
3270
 
        key_type= Key::MULTIPLE;
3271
 
 
3272
 
      key= new Key(key_type, key_name, strlen(key_name),
3273
 
                   &key_create_info,
3274
 
                   test(key_info->flags & HA_GENERATED_KEY),
3275
 
                   key_parts);
3276
 
      new_key_list.push_back(key);
3277
 
    }
3278
 
  }
3279
 
  {
3280
 
    Key *key;
3281
 
    while ((key=key_it++))                      // Add new keys
3282
 
    {
3283
 
      if (key->type == Key::FOREIGN_KEY &&
3284
 
          ((Foreign_key *)key)->validate(new_create_list))
3285
 
        goto err;
3286
 
      if (key->type != Key::FOREIGN_KEY)
3287
 
        new_key_list.push_back(key);
3288
 
      if (key->name.str && is_primary_key_name(key->name.str))
3289
 
      {
3290
 
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3291
 
        goto err;
3292
 
      }
3293
 
    }
3294
 
  }
3295
 
 
3296
 
  if (alter_info->drop_list.elements)
3297
 
  {
3298
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3299
 
             alter_info->drop_list.head()->name);
3300
 
    goto err;
3301
 
  }
3302
 
  if (alter_info->alter_list.elements)
3303
 
  {
3304
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3305
 
             alter_info->alter_list.head()->name);
3306
 
    goto err;
3307
 
  }
3308
 
 
3309
 
  if (! table_proto->options().has_comment()
3310
 
      && table->s->hasComment())
3311
 
    table_options->set_comment(table->s->getComment());
3312
 
 
3313
 
  if (table->s->tmp_table)
3314
 
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
3315
 
 
3316
 
  rc= false;
3317
 
  alter_info->create_list.swap(new_create_list);
3318
 
  alter_info->key_list.swap(new_key_list);
3319
 
err:
3320
 
  return(rc);
3321
 
}
3322
 
 
3323
 
 
3324
 
/*
3325
 
  Alter table
3326
 
 
3327
 
  SYNOPSIS
3328
 
    mysql_alter_table()
3329
 
      session              Thread handle
3330
 
      new_db           If there is a RENAME clause
3331
 
      new_name         If there is a RENAME clause
3332
 
      create_info      Information from the parsing phase about new
3333
 
                       table properties.
3334
 
      table_list       The table to change.
3335
 
      alter_info       Lists of fields, keys to be changed, added
3336
 
                       or dropped.
3337
 
      order_num        How many order_st BY fields has been specified.
3338
 
      order            List of fields to order_st BY.
3339
 
      ignore           Whether we have ALTER IGNORE Table
3340
 
 
3341
 
  DESCRIPTION
3342
 
    This is a veery long function and is everything but the kitchen sink :)
3343
 
    It is used to alter a table and not only by ALTER Table but also
3344
 
    CREATE|DROP INDEX are mapped on this function.
3345
 
 
3346
 
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
3347
 
    or both, then this function short cuts its operation by renaming
3348
 
    the table and/or enabling/disabling the keys. In this case, the FRM is
3349
 
    not changed, directly by mysql_alter_table. However, if there is a
3350
 
    RENAME + change of a field, or an index, the short cut is not used.
3351
 
    See how `create_list` is used to generate the new FRM regarding the
3352
 
    structure of the fields. The same is done for the indices of the table.
3353
 
 
3354
 
    Important is the fact, that this function tries to do as little work as
3355
 
    possible, by finding out whether a intermediate table is needed to copy
3356
 
    data into and when finishing the altering to use it as the original table.
3357
 
    For this reason the function compare_tables() is called, which decides
3358
 
    based on all kind of data how similar are the new and the original
3359
 
    tables.
3360
 
 
3361
 
  RETURN VALUES
3362
 
    false  OK
3363
 
    true   Error
3364
 
*/
3365
 
 
3366
 
bool mysql_alter_table(Session *session,
3367
 
                       char *new_db,
3368
 
                       char *new_name,
3369
 
                       HA_CREATE_INFO *create_info,
3370
 
                       message::Table *create_proto,
3371
 
                       TableList *table_list,
3372
 
                       Alter_info *alter_info,
3373
 
                       uint32_t order_num,
3374
 
                       order_st *order,
3375
 
                       bool ignore)
3376
 
{
3377
 
  Table *table;
3378
 
  Table *new_table= NULL;
3379
 
  Table *name_lock= NULL;
3380
 
  string new_name_str;
3381
 
  int error= 0;
3382
 
  char tmp_name[80];
3383
 
  char old_name[32];
3384
 
  char new_name_buff[FN_REFLEN];
3385
 
  char new_alias_buff[FN_REFLEN];
3386
 
  char *table_name;
3387
 
  char *db;
3388
 
  const char *new_alias;
3389
 
  char path[FN_REFLEN];
3390
 
  ha_rows copied= 0;
3391
 
  ha_rows deleted= 0;
3392
 
  StorageEngine *old_db_type;
3393
 
  StorageEngine *new_db_type;
3394
 
  StorageEngine *save_old_db_type;
3395
 
  bitset<32> tmp;
3396
 
 
3397
 
  new_name_buff[0]= '\0';
3398
 
 
3399
 
  if (table_list && table_list->schema_table)
3400
 
  {
3401
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
3402
 
    return true;
3403
 
  }
3404
 
 
3405
 
  session->set_proc_info("init");
3406
 
 
3407
 
  /*
3408
 
    Assign variables table_name, new_name, db, new_db, path
3409
 
    to simplify further comparisons: we want to see if it's a RENAME
3410
 
    later just by comparing the pointers, avoiding the need for strcmp.
3411
 
  */
3412
 
  table_name= table_list->table_name;
3413
 
  db= table_list->db;
3414
 
  if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
3415
 
    new_db= db;
3416
 
 
3417
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3418
 
  {
3419
 
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3420
 
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
3421
 
  }
3422
 
 
3423
 
  build_table_filename(path, sizeof(path), db, table_name, false);
3424
 
 
3425
 
  ostringstream oss;
3426
 
  oss << drizzle_data_home << "/" << db << "/" << table_name;
3427
 
 
3428
 
  (void) unpack_filename(new_name_buff, oss.str().c_str());
3429
 
 
3430
 
  /*
3431
 
    If this is just a rename of a view, short cut to the
3432
 
    following scenario: 1) lock LOCK_open 2) do a RENAME
3433
 
    2) unlock LOCK_open.
3434
 
    This is a copy-paste added to make sure
3435
 
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
3436
 
    as an independent branch in mysql_execute_command. The need
3437
 
    for a copy-paste arose because the main code flow of ALTER Table
3438
 
    ... RENAME tries to use openTableLock, which does not work for views
3439
 
    (openTableLock was never modified to merge table lists of child tables
3440
 
    into the main table list, like open_tables does).
3441
 
    This code is wrong and will be removed, please do not copy.
3442
 
  */
3443
 
 
3444
 
  if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
3445
 
    return true;
3446
 
  
3447
 
  table->use_all_columns();
3448
 
 
3449
 
  /* Check that we are not trying to rename to an existing table */
3450
 
  if (new_name)
3451
 
  {
3452
 
    strcpy(new_name_buff, new_name);
3453
 
    strcpy(new_alias_buff, new_name);
3454
 
    new_alias= new_alias_buff;
3455
 
 
3456
 
    my_casedn_str(files_charset_info, new_name_buff);
3457
 
    new_alias= new_name; // Create lower case table name
3458
 
    my_casedn_str(files_charset_info, new_name);
3459
 
 
3460
 
    if (new_db == db &&
3461
 
        ! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3462
 
    {
3463
 
      /*
3464
 
        Source and destination table names are equal: make later check
3465
 
        easier.
3466
 
      */
3467
 
      new_alias= new_name= table_name;
3468
 
    }
3469
 
    else
3470
 
    {
3471
 
      if (table->s->tmp_table != NO_TMP_TABLE)
3472
 
      {
3473
 
        if (session->find_temporary_table(new_db, new_name_buff))
3474
 
        {
3475
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3476
 
          return true;
3477
 
        }
3478
 
      }
3479
 
      else
3480
 
      {
3481
 
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3482
 
          return true;
3483
 
 
3484
 
        if (! name_lock)
3485
 
        {
3486
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3487
 
          return true;
3488
 
        }
3489
 
 
3490
 
        build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
3491
 
 
3492
 
        if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
3493
 
        {
3494
 
          /* Table will be closed by Session::executeCommand() */
3495
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3496
 
          goto err;
3497
 
        }
3498
 
      }
3499
 
    }
3500
 
  }
3501
 
  else
3502
 
  {
3503
 
    new_alias= table_name;
3504
 
    new_name= table_name;
3505
 
  }
3506
 
 
3507
 
  old_db_type= table->s->db_type();
3508
 
  if (! create_info->db_type)
3509
 
  {
3510
 
    create_info->db_type= old_db_type;
3511
 
  }
3512
 
 
3513
 
  if (table->s->tmp_table != NO_TMP_TABLE)
3514
 
    create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3515
 
 
3516
 
  if (check_engine(session, new_name, create_info))
3517
 
    goto err;
3518
 
 
3519
 
  new_db_type= create_info->db_type;
3520
 
 
3521
 
  if (new_db_type != old_db_type &&
3522
 
      !table->file->can_switch_engines())
3523
 
  {
3524
 
    assert(0);
3525
 
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
3526
 
    goto err;
3527
 
  }
3528
 
 
3529
 
  if (create_info->row_type == ROW_TYPE_NOT_USED)
3530
 
    create_info->row_type= table->s->row_type;
3531
 
 
3532
 
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
3533
 
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
3534
 
  {
3535
 
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
3536
 
    goto err;
3537
 
  }
3538
 
 
3539
 
  session->set_proc_info("setup");
3540
 
  
3541
 
  /*
3542
 
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
3543
 
   */
3544
 
  tmp.set();
3545
 
  tmp.reset(ALTER_RENAME);
3546
 
  tmp.reset(ALTER_KEYS_ONOFF);
3547
 
  tmp&= alter_info->flags;
3548
 
  if (! (tmp.any()) &&
3549
 
      ! table->s->tmp_table) // no need to touch frm
3550
 
  {
3551
 
    switch (alter_info->keys_onoff)
3552
 
    {
3553
 
    case LEAVE_AS_IS:
3554
 
      break;
3555
 
    case ENABLE:
3556
 
      /*
3557
 
        wait_while_table_is_used() ensures that table being altered is
3558
 
        opened only by this thread and that Table::TableShare::version
3559
 
        of Table object corresponding to this table is 0.
3560
 
        The latter guarantees that no DML statement will open this table
3561
 
        until ALTER Table finishes (i.e. until close_thread_tables())
3562
 
        while the fact that the table is still open gives us protection
3563
 
        from concurrent DDL statements.
3564
 
      */
3565
 
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3566
 
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3567
 
      pthread_mutex_unlock(&LOCK_open);
3568
 
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3569
 
      /* COND_refresh will be signaled in close_thread_tables() */
3570
 
      break;
3571
 
    case DISABLE:
3572
 
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3573
 
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3574
 
      pthread_mutex_unlock(&LOCK_open);
3575
 
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3576
 
      /* COND_refresh will be signaled in close_thread_tables() */
3577
 
      break;
3578
 
    default:
3579
 
      assert(false);
3580
 
      error= 0;
3581
 
      break;
3582
 
    }
3583
 
 
3584
 
    if (error == HA_ERR_WRONG_COMMAND)
3585
 
    {
3586
 
      error= 0;
3587
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3588
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3589
 
                          table->alias);
3590
 
    }
3591
 
 
3592
 
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
3593
 
    /*
3594
 
      Unlike to the above case close_cached_table() below will remove ALL
3595
 
      instances of Table from table cache (it will also remove table lock
3596
 
      held by this thread). So to make actual table renaming and writing
3597
 
      to binlog atomic we have to put them into the same critical section
3598
 
      protected by LOCK_open mutex. This also removes gap for races between
3599
 
      access() and mysql_rename_table() calls.
3600
 
    */
3601
 
 
3602
 
    if (error == 0 && 
3603
 
        (new_name != table_name || new_db != db))
3604
 
    {
3605
 
      session->set_proc_info("rename");
3606
 
      /*
3607
 
        Then do a 'simple' rename of the table. First we need to close all
3608
 
        instances of 'source' table.
3609
 
      */
3610
 
      session->close_cached_table(table);
3611
 
      /*
3612
 
        Then, we want check once again that target table does not exist.
3613
 
        Actually the order of these two steps does not matter since
3614
 
        earlier we took name-lock on the target table, so we do them
3615
 
        in this particular order only to be consistent with 5.0, in which
3616
 
        we don't take this name-lock and where this order really matters.
3617
 
        TODO: Investigate if we need this access() check at all.
3618
 
      */
3619
 
      if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
3620
 
      {
3621
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
3622
 
        error= -1;
3623
 
      }
3624
 
      else
3625
 
      {
3626
 
        *fn_ext(new_name)= 0;
3627
 
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3628
 
          error= -1;
3629
 
      }
3630
 
    }
3631
 
 
3632
 
    if (error == HA_ERR_WRONG_COMMAND)
3633
 
    {
3634
 
      error= 0;
3635
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3636
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3637
 
                          table->alias);
3638
 
    }
3639
 
 
3640
 
    if (error == 0)
3641
 
    {
3642
 
      write_bin_log(session, true, session->query, session->query_length);
3643
 
      session->my_ok();
3644
 
    }
3645
 
    else if (error > 0)
3646
 
    {
3647
 
      table->file->print_error(error, MYF(0));
3648
 
      error= -1;
3649
 
    }
3650
 
 
3651
 
    if (name_lock)
3652
 
      session->unlink_open_table(name_lock);
3653
 
 
3654
 
    pthread_mutex_unlock(&LOCK_open);
3655
 
    table_list->table= NULL;
3656
 
    return error;
3657
 
  }
3658
 
 
3659
 
  /* We have to do full alter table. */
3660
 
 
3661
 
  /*
3662
 
    If the old table had partitions and we are doing ALTER Table ...
3663
 
    engine= <new_engine>, the new table must preserve the original
3664
 
    partitioning. That means that the new engine is still the
3665
 
    partitioning engine, not the engine specified in the parser.
3666
 
    This is discovered  in prep_alter_part_table, which in such case
3667
 
    updates create_info->db_type.
3668
 
    Now we need to update the stack copy of create_info->db_type,
3669
 
    as otherwise we won't be able to correctly move the files of the
3670
 
    temporary table to the result table files.
3671
 
  */
3672
 
  new_db_type= create_info->db_type;
3673
 
 
3674
 
  if (mysql_prepare_alter_table(session, table, create_info, create_proto,
3675
 
                                alter_info))
3676
 
      goto err;
3677
 
 
3678
 
  set_table_default_charset(create_info, db);
3679
 
 
3680
 
  alter_info->build_method= HA_BUILD_OFFLINE;
3681
 
 
3682
 
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3683
 
  
3684
 
  /* Safety fix for innodb */
3685
 
  my_casedn_str(files_charset_info, tmp_name);
3686
 
 
3687
 
  /* Create a temporary table with the new format */
3688
 
  error= create_temporary_table(session, table, new_db, tmp_name, create_info, create_proto, alter_info);
3689
 
  if (error != 0)
3690
 
    goto err;
3691
 
 
3692
 
  /* Open the table so we need to copy the data to it. */
3693
 
  if (table->s->tmp_table)
3694
 
  {
3695
 
    TableList tbl;
3696
 
    tbl.db= new_db;
3697
 
    tbl.alias= tmp_name;
3698
 
    tbl.table_name= tmp_name;
3699
 
 
3700
 
    /* Table is in session->temporary_tables */
3701
 
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3702
 
  }
3703
 
  else
3704
 
  {
3705
 
    char tmp_path[FN_REFLEN];
3706
 
    /* table is a normal table: Create temporary table in same directory */
3707
 
    build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
3708
 
    /* Open our intermediate table */
3709
 
    new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3710
 
  }
3711
 
 
3712
 
  if (new_table == NULL)
3713
 
    goto err1;
3714
 
 
3715
 
  /* Copy the data if necessary. */
3716
 
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
3717
 
  session->cuted_fields= 0L;
3718
 
  session->set_proc_info("copy to tmp table");
3719
 
  copied= deleted= 0;
3720
 
 
3721
 
  assert(new_table);
3722
 
 
3723
 
  /* We don't want update TIMESTAMP fields during ALTER Table. */
3724
 
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3725
 
  new_table->next_number_field= new_table->found_next_number_field;
3726
 
  error= copy_data_between_tables(table, 
3727
 
                                  new_table,
3728
 
                                  alter_info->create_list, 
3729
 
                                  ignore,
3730
 
                                  order_num, 
3731
 
                                  order, 
3732
 
                                  &copied, 
3733
 
                                  &deleted,
3734
 
                                  alter_info->keys_onoff,
3735
 
                                  alter_info->error_if_not_empty);
3736
 
 
3737
 
  /* We must not ignore bad input! */
3738
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3739
 
 
3740
 
  if (table->s->tmp_table != NO_TMP_TABLE)
3741
 
  {
3742
 
    /* We changed a temporary table */
3743
 
    if (error)
3744
 
      goto err1;
3745
 
 
3746
 
    /* Close lock if this is a transactional table */
3747
 
    if (session->lock)
3748
 
    {
3749
 
      mysql_unlock_tables(session, session->lock);
3750
 
      session->lock= 0;
3751
 
    }
3752
 
 
3753
 
    /* Remove link to old table and rename the new one */
3754
 
    session->close_temporary_table(table, true, true);
3755
 
 
3756
 
    /* Should pass the 'new_name' as we store table name in the cache */
3757
 
    if (new_table->rename_temporary_table(new_db, new_name))
3758
 
      goto err1;
3759
 
    
3760
 
    goto end_temporary;
3761
 
  }
3762
 
 
3763
 
  if (new_table)
3764
 
  {
3765
 
    /*
3766
 
      Close the intermediate table that will be the new table.
3767
 
      Note that MERGE tables do not have their children attached here.
3768
 
    */
3769
 
    new_table->intern_close_table();
3770
 
    free(new_table);
3771
 
  }
3772
 
 
3773
 
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3774
 
  
3775
 
  if (error)
3776
 
  {
3777
 
    quick_rm_table(new_db_type, new_db, tmp_name, true);
3778
 
    pthread_mutex_unlock(&LOCK_open);
3779
 
    goto err;
3780
 
  }
3781
 
 
3782
 
  /*
3783
 
    Data is copied. Now we:
3784
 
    1) Wait until all other threads close old version of table.
3785
 
    2) Close instances of table open by this thread and replace them
3786
 
       with exclusive name-locks.
3787
 
    3) Rename the old table to a temp name, rename the new one to the
3788
 
       old name.
3789
 
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
3790
 
       we reopen new version of table.
3791
 
    5) Write statement to the binary log.
3792
 
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
3793
 
       remove name-locks from list of open tables and table cache.
3794
 
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
3795
 
       call to remove name-locks from table cache and list of open table.
3796
 
  */
3797
 
 
3798
 
  session->set_proc_info("rename result table");
3799
 
 
3800
 
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3801
 
 
3802
 
  my_casedn_str(files_charset_info, old_name);
3803
 
 
3804
 
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3805
 
  session->close_data_files_and_morph_locks(db, table_name);
3806
 
 
3807
 
  error= 0;
3808
 
  save_old_db_type= old_db_type;
3809
 
 
3810
 
  /*
3811
 
    This leads to the storage engine (SE) not being notified for renames in
3812
 
    mysql_rename_table(), because we just juggle with the FRM and nothing
3813
 
    more. If we have an intermediate table, then we notify the SE that
3814
 
    it should become the actual table. Later, we will recycle the old table.
3815
 
    However, in case of ALTER Table RENAME there might be no intermediate
3816
 
    table. This is when the old and new tables are compatible, according to
3817
 
    compare_table(). Then, we need one additional call to
3818
 
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
3819
 
    actual rename in the SE and the FRM is not touched. Note that, if the
3820
 
    table is renamed and the SE is also changed, then an intermediate table
3821
 
    is created and the additional call will not take place.
3822
 
  */
3823
 
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
3824
 
  {
3825
 
    error= 1;
3826
 
    quick_rm_table(new_db_type, new_db, tmp_name, true);
3827
 
  }
3828
 
  else
3829
 
  {
3830
 
    if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
3831
 
    {
3832
 
      /* Try to get everything back. */
3833
 
      error= 1;
3834
 
      quick_rm_table(new_db_type, new_db, new_alias, false);
3835
 
      quick_rm_table(new_db_type, new_db, tmp_name, true);
3836
 
      mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
3837
 
    }
3838
 
  }
3839
 
 
3840
 
  if (error)
3841
 
  {
3842
 
    /* This shouldn't happen. But let us play it safe. */
3843
 
    goto err_with_placeholders;
3844
 
  }
3845
 
 
3846
 
  quick_rm_table(old_db_type, db, old_name, true);
3847
 
 
3848
 
  pthread_mutex_unlock(&LOCK_open);
3849
 
 
3850
 
  session->set_proc_info("end");
3851
 
 
3852
 
  write_bin_log(session, true, session->query, session->query_length);
3853
 
 
3854
 
  if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
3855
 
  {
3856
 
    /*
3857
 
      For the alter table to be properly flushed to the logs, we
3858
 
      have to open the new table.  If not, we get a problem on server
3859
 
      shutdown. But we do not need to attach MERGE children.
3860
 
    */
3861
 
    char table_path[FN_REFLEN];
3862
 
    Table *t_table;
3863
 
    build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
3864
 
    t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
3865
 
    if (t_table)
3866
 
    {
3867
 
      t_table->intern_close_table();
3868
 
      free(t_table);
3869
 
    }
3870
 
    else
3871
 
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
3872
 
 
3873
 
    ha_flush_logs(old_db_type);
3874
 
  }
3875
 
  table_list->table= NULL;
3876
 
 
3877
 
end_temporary:
3878
 
  /*
3879
 
   * Field::store() may have called my_error().  If this is 
3880
 
   * the case, we must not send an ok packet, since 
3881
 
   * Diagnostics_area::is_set() will fail an assert.
3882
 
   */
3883
 
  if (! session->is_error())
3884
 
  {
3885
 
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
3886
 
            (ulong) (copied + deleted), (ulong) deleted,
3887
 
            (ulong) session->cuted_fields);
3888
 
    session->my_ok(copied + deleted, 0, 0L, tmp_name);
3889
 
    session->some_tables_deleted=0;
3890
 
    return false;
3891
 
  }
3892
 
  else
3893
 
  {
3894
 
    /* my_error() was called.  Return true (which means error...) */
3895
 
    return true;
3896
 
  }
3897
 
 
3898
 
err1:
3899
 
  if (new_table)
3900
 
  {
3901
 
    /* close_temporary_table() frees the new_table pointer. */
3902
 
    session->close_temporary_table(new_table, true, true);
3903
 
  }
3904
 
  else
3905
 
    quick_rm_table(new_db_type, new_db, tmp_name, true);
3906
 
 
3907
 
err:
3908
 
  /*
3909
 
    No default value was provided for a DATE/DATETIME field, the
3910
 
    current sql_mode doesn't allow the '0000-00-00' value and
3911
 
    the table to be altered isn't empty.
3912
 
    Report error here.
3913
 
  */
3914
 
  if (alter_info->error_if_not_empty && session->row_count)
3915
 
  {
3916
 
    const char *f_val= 0;
3917
 
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
3918
 
    switch (alter_info->datetime_field->sql_type)
3919
 
    {
3920
 
      case DRIZZLE_TYPE_DATE:
3921
 
        f_val= "0000-00-00";
3922
 
        t_type= DRIZZLE_TIMESTAMP_DATE;
3923
 
        break;
3924
 
      case DRIZZLE_TYPE_DATETIME:
3925
 
        f_val= "0000-00-00 00:00:00";
3926
 
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
3927
 
        break;
3928
 
      default:
3929
 
        /* Shouldn't get here. */
3930
 
        assert(0);
3931
 
    }
3932
 
    bool save_abort_on_warning= session->abort_on_warning;
3933
 
    session->abort_on_warning= true;
3934
 
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
3935
 
                                 f_val, strlength(f_val), t_type,
3936
 
                                 alter_info->datetime_field->field_name);
3937
 
    session->abort_on_warning= save_abort_on_warning;
3938
 
  }
3939
 
  if (name_lock)
3940
 
  {
3941
 
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
3942
 
    session->unlink_open_table(name_lock);
3943
 
    pthread_mutex_unlock(&LOCK_open);
3944
 
  }
3945
 
  return true;
3946
 
 
3947
 
err_with_placeholders:
3948
 
  /*
3949
 
    An error happened while we were holding exclusive name-lock on table
3950
 
    being altered. To be safe under LOCK TABLES we should remove placeholders
3951
 
    from list of open tables list and table cache.
3952
 
  */
3953
 
  session->unlink_open_table(table);
3954
 
  if (name_lock)
3955
 
    session->unlink_open_table(name_lock);
3956
 
  pthread_mutex_unlock(&LOCK_open);
3957
 
  return true;
3958
 
}
3959
 
/* mysql_alter_table */
3960
 
 
3961
 
static int
3962
 
copy_data_between_tables(Table *from,Table *to,
3963
 
                         List<CreateField> &create,
3964
 
                         bool ignore,
3965
 
                         uint32_t order_num, order_st *order,
3966
 
                         ha_rows *copied,
3967
 
                         ha_rows *deleted,
3968
 
                         enum enum_enable_or_disable keys_onoff,
3969
 
                         bool error_if_not_empty)
3970
 
{
3971
 
  int error;
3972
 
  CopyField *copy,*copy_end;
3973
 
  ulong found_count,delete_count;
3974
 
  Session *session= current_session;
3975
 
  uint32_t length= 0;
3976
 
  SORT_FIELD *sortorder;
3977
 
  READ_RECORD info;
3978
 
  TableList   tables;
3979
 
  List<Item>   fields;
3980
 
  List<Item>   all_fields;
3981
 
  ha_rows examined_rows;
3982
 
  bool auto_increment_field_copied= 0;
3983
 
  uint64_t prev_insert_id;
3984
 
 
3985
 
  /*
3986
 
    Turn off recovery logging since rollback of an alter table is to
3987
 
    delete the new table so there is no need to log the changes to it.
3988
 
 
3989
 
    This needs to be done before external_lock
3990
 
  */
3991
 
  error= ha_enable_transaction(session, false);
3992
 
  if (error)
3993
 
    return -1;
3994
 
 
3995
 
  if (!(copy= new CopyField[to->s->fields]))
3996
 
    return -1;                          /* purecov: inspected */
3997
 
 
3998
 
  if (to->file->ha_external_lock(session, F_WRLCK))
3999
 
    return -1;
4000
 
 
4001
 
  /* We need external lock before we can disable/enable keys */
4002
 
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
4003
 
 
4004
 
  /* We can abort alter table for any table type */
4005
 
  session->abort_on_warning= !ignore;
4006
 
 
4007
 
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
4008
 
  to->file->ha_start_bulk_insert(from->file->stats.records);
4009
 
 
4010
 
  List_iterator<CreateField> it(create);
4011
 
  CreateField *def;
4012
 
  copy_end=copy;
4013
 
  for (Field **ptr=to->field ; *ptr ; ptr++)
4014
 
  {
4015
 
    def=it++;
4016
 
    if (def->field)
4017
 
    {
4018
 
      if (*ptr == to->next_number_field)
4019
 
        auto_increment_field_copied= true;
4020
 
 
4021
 
      (copy_end++)->set(*ptr,def->field,0);
4022
 
    }
4023
 
 
4024
 
  }
4025
 
 
4026
 
  found_count=delete_count=0;
4027
 
 
4028
 
  if (order)
4029
 
  {
4030
 
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
4031
 
    {
4032
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
4033
 
      snprintf(warn_buff, sizeof(warn_buff),
4034
 
               _("order_st BY ignored because there is a user-defined clustered "
4035
 
                 "index in the table '%-.192s'"),
4036
 
               from->s->table_name.str);
4037
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
4038
 
                   warn_buff);
4039
 
    }
4040
 
    else
4041
 
    {
4042
 
      from->sort.io_cache= new IO_CACHE;
4043
 
      memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
4044
 
 
4045
 
      memset(&tables, 0, sizeof(tables));
4046
 
      tables.table= from;
4047
 
      tables.alias= tables.table_name= from->s->table_name.str;
4048
 
      tables.db= from->s->db.str;
4049
 
      error= 1;
4050
 
 
4051
 
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
4052
 
          setup_order(session, session->lex->select_lex.ref_pointer_array,
4053
 
                      &tables, fields, all_fields, order) ||
4054
 
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
4055
 
          (from->sort.found_records= filesort(session, from, sortorder, length,
4056
 
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
4057
 
                                              1, &examined_rows)) ==
4058
 
          HA_POS_ERROR)
4059
 
        goto err;
4060
 
    }
4061
 
  };
4062
 
 
4063
 
  /* Tell handler that we have values for all columns in the to table */
4064
 
  to->use_all_columns();
4065
 
  init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
4066
 
  if (ignore)
4067
 
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
4068
 
  session->row_count= 0;
4069
 
  to->restoreRecordAsDefault();        // Create empty record
4070
 
  while (!(error=info.read_record(&info)))
4071
 
  {
4072
 
    if (session->killed)
4073
 
    {
4074
 
      session->send_kill_message();
4075
 
      error= 1;
4076
 
      break;
4077
 
    }
4078
 
    session->row_count++;
4079
 
    /* Return error if source table isn't empty. */
4080
 
    if (error_if_not_empty)
4081
 
    {
4082
 
      error= 1;
4083
 
      break;
4084
 
    }
4085
 
    if (to->next_number_field)
4086
 
    {
4087
 
      if (auto_increment_field_copied)
4088
 
        to->auto_increment_field_not_null= true;
4089
 
      else
4090
 
        to->next_number_field->reset();
4091
 
    }
4092
 
 
4093
 
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
4094
 
    {
4095
 
      copy_ptr->do_copy(copy_ptr);
4096
 
    }
4097
 
    prev_insert_id= to->file->next_insert_id;
4098
 
    error=to->file->ha_write_row(to->record[0]);
4099
 
    to->auto_increment_field_not_null= false;
4100
 
    if (error)
4101
 
    {
4102
 
      if (!ignore ||
4103
 
          to->file->is_fatal_error(error, HA_CHECK_DUP))
4104
 
      {
4105
 
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
4106
 
         {
4107
 
           uint32_t key_nr= to->file->get_dup_key(error);
4108
 
           if ((int) key_nr >= 0)
4109
 
           {
4110
 
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
4111
 
             if (key_nr == 0 &&
4112
 
                 (to->key_info[0].key_part[0].field->flags &
4113
 
                  AUTO_INCREMENT_FLAG))
4114
 
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
4115
 
             to->file->print_keydup_error(key_nr, err_msg);
4116
 
             break;
4117
 
           }
4118
 
         }
4119
 
 
4120
 
        to->file->print_error(error,MYF(0));
4121
 
        break;
4122
 
      }
4123
 
      to->file->restore_auto_increment(prev_insert_id);
4124
 
      delete_count++;
4125
 
    }
4126
 
    else
4127
 
      found_count++;
4128
 
  }
4129
 
  end_read_record(&info);
4130
 
  from->free_io_cache();
4131
 
  delete [] copy;                               // This is never 0
4132
 
 
4133
 
  if (to->file->ha_end_bulk_insert() && error <= 0)
4134
 
  {
4135
 
    to->file->print_error(my_errno,MYF(0));
4136
 
    error=1;
4137
 
  }
4138
 
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
4139
 
 
4140
 
  if (ha_enable_transaction(session, true))
4141
 
  {
4142
 
    error= 1;
4143
 
    goto err;
4144
 
  }
4145
 
 
4146
 
  /*
4147
 
    Ensure that the new table is saved properly to disk so that we
4148
 
    can do a rename
4149
 
  */
4150
 
  if (ha_autocommit_or_rollback(session, 0))
4151
 
    error=1;
4152
 
  if (! session->endActiveTransaction())
4153
 
    error=1;
4154
 
 
4155
 
 err:
4156
 
  session->abort_on_warning= 0;
4157
 
  from->free_io_cache();
4158
 
  *copied= found_count;
4159
 
  *deleted=delete_count;
4160
 
  to->file->ha_release_auto_increment();
4161
 
  if (to->file->ha_external_lock(session,F_UNLCK))
4162
 
    error=1;
4163
 
  return(error > 0 ? -1 : 0);
4164
 
}
4165
 
 
4166
 
 
4167
2701
/*
4168
2702
  Recreates tables by calling mysql_alter_table().
4169
2703
 
4178
2712
bool mysql_recreate_table(Session *session, TableList *table_list)
4179
2713
{
4180
2714
  HA_CREATE_INFO create_info;
4181
 
  Alter_info alter_info;
 
2715
  AlterInfo alter_info;
4182
2716
  message::Table table_proto;
4183
2717
 
4184
2718
  assert(!table_list->next_global);
4315
2849
  return(true);
4316
2850
}
4317
2851
 
4318
 
static bool check_engine(Session *session, const char *table_name,
 
2852
bool check_engine(Session *session, const char *table_name,
4319
2853
                         HA_CREATE_INFO *create_info)
4320
2854
{
4321
2855
  StorageEngine **new_engine= &create_info->db_type;